Skip to content

Some Patterns

Video Lecture

Section Video Links
Some Patterns Some Patterns

Description

Note

In this lesson, we also introduce the TSL named imports of fract, step, length, sin, cos, atan.

Now we will use some mathematics to draw some pretty patterns.

You will see at the end, that variations of only a few methods can produce vastly different results.

We will begin by using inline functions, and then move onto TSL functions.

Start Script

./src/main.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import './style.css'
import * as THREE from 'three/webgpu'
import { Fn, positionLocal } from 'three/tsl'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'

const scene = new THREE.Scene()

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  10
)
camera.position.z = 1

const renderer = new THREE.WebGPURenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
renderer.setAnimationLoop(animate)

window.addEventListener('resize', function () {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
})

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

const main = Fn(() => {
  const p = positionLocal.toVar()

  return p
})

const material = new THREE.NodeMaterial()
//material.fragmentNode = main()
material.fragmentNode = positionLocal

const mesh = new THREE.Mesh(new THREE.PlaneGeometry(), material)
scene.add(mesh)

// renderer.debug.getShaderAsync(scene, camera, mesh).then((e) => {
//   //console.log(e.vertexShader)
//   console.log(e.fragmentShader)
// })

function animate() {
  controls.update()

  renderer.render(scene, camera)
}

Example 1 : Checkered Cube

const material = new THREE.NodeMaterial()
material.fragmentNode = positionLocal.mul(4.9999).fract().step(0.5)

const mesh = new THREE.Mesh(new THREE.BoxGeometry(), material)
scene.add(mesh)
<>

Example 2 : Ringed Cube

const material = new THREE.NodeMaterial()
material.fragmentNode = positionLocal.length().mul(15).fract().step(0.5)

const mesh = new THREE.Mesh(new THREE.BoxGeometry(), material)
scene.add(mesh)
<>

Example 3 : Animated Resizing Rings

const main = Fn(() => {
  const p = positionLocal.toVar()

  p.mulAssign(5)
  p.assign(p.fract().sub(0.5))
  p.assign(length(p))
  p.assign(sin(p.mul(10).add(time)))
  p.assign(abs(p))
  p.assign(step(0.5, p))

  return p
})

const material = new THREE.NodeMaterial()
material.fragmentNode = main()

const mesh = new THREE.Mesh(new THREE.PlaneGeometry(), material)
scene.add(mesh)
<>

Example 4 : Psychedelic Swirl

const main = Fn(() => {
  const p = positionLocal.toVar()

  p.assign(rotateUV(p.xy, time, vec2()))

  p.assign(length(p.mul(5)).sub(atan(p.zy, p.zx)).mul(5))
  p.sinAssign()
  p.mulAssign(5)

  p.assign(vec3(p.x.add(sin(time).mul(5)), p.y.add(cos(time).mul(5)), 0))

  return p
})

const material = new THREE.NodeMaterial()
material.fragmentNode = main()

const mesh = new THREE.Mesh(new THREE.PlaneGeometry(), material)
scene.add(mesh)
<>