Skip to content
/ tslfx Public

✨ TSLFX • Early-stage collection of VFX, utils, and SDFs for Three.js Shading Language (TSL)

License

Notifications You must be signed in to change notification settings

verekia/tslfx

Repository files navigation

✨ TSLFX ✨

Early-stage collection of VFX shaders, utils, and SDFs for Three.js Shading Language (TSL).

The effects work with the WebGPU renderer and its WebGL backend fallback. To set up your project with WebGPURenderer, check out this repo. The examples use React Three Fiber but the shaders can be used with vanilla Three.js or any other wrapper.

Getting started

Vanilla Three.js

import { MeshBasicNodeMaterial } from 'three/webgpu'
import { impact } from 'tslfx'

const { uniforms, nodes } = impact()

const material = new MeshBasicNodeMaterial()
material.colorNode = nodes.colorNode

const animate = (delta: number) => {
  // Update uniforms in your animation loop
  uniforms.time.value += delta
}

React Three Fiber v9 RC

Somewhere top-level in your project, extend MeshBasicNodeMaterial and declare its type:

import { extend, type ThreeElement } from '@react-three/fiber'
import { MeshBasicNodeMaterial } from 'three/webgpu'

extend({ MeshBasicNodeMaterial })

declare module '@react-three/fiber' {
  interface ThreeElements {
    meshBasicNodeMaterial: ThreeElement<typeof MeshBasicNodeMaterial>
  }
}

Tip

I like to put these in an extend.ts file that I import in my main entry file (_app.tsx in Next.js for example).

You can then use meshBasicNodeMaterial in your scene:

import { useFrame } from '@react-three/fiber'
import { impact } from 'tslfx'

const ImpactVFX = () => {
  const { uniforms, nodes } = useMemo(() => impact(), [])

  useFrame((_, delta) => {
    // Update uniforms here
    uniforms.time.value += delta
  })

  return (
    <mesh>
      <planeGeometry />
      <meshBasicNodeMaterial {...nodes} transparent />
    </mesh>
  )
}

Caution

You should memoize any TSL logic to not re-create nodes on every render.

Primitives and compositions

Primitives are basic single effects. You can combine them together to create more complex effects, which I am calling "compositions" in this library. There is no API to combine them yet, but check out the code of the examples to see how it works.

SDFs

Some Signed Distance Functions (SDFs) ported from Inigo Quilez's website are included in the library:

import { sdCircle, sdVesica, sdHeart } from 'tslfx'

const circle = sdCircle(p, 0.5)
const vesica = sdVesica(p, 0.5, 0.2)
const heart = sdHeart(p)

Timing-based animations

The Timing example shows how to combine multiple effects triggered at different times over a given duration, with delays and durations per effect.

All the effects have a normalized time uniform and a duration of 1, and their timing is relative to the whole animation, making it easier to tweak them all at once and create slow-motion or speed-up effects.

Utils

pipe

TSL functions that take 2 nodes as arguments can be piped together into a single expression without introducing extra variables or reassignments:

import { blendAlpha, pipe } from 'tslfx'

// Simple layering of 3 effects on top of each other
const colorNode = pipe(blendAlpha, effectA.colorNode, effectB.colorNode, effectC.colorNode)

pipe is really just a more readable .reduce() of the arguments, nothing fancy.

blendAlpha

blendAlpha blends two colors together using the alpha channel of the second color.

import { blendAlpha } from 'tslfx'

const colorNode = blendAlpha(effectA.colorNode, effectB.colorNode)

Easing

A few easing functions are included in the library:

  • linear
  • easeInCubic
  • easeOutCubic
  • easeInOutCubic

Noise

Some MaterialX-based noises are directly included in Three.js.

For example, the following code creates a basic water-like effect using mx_noise_vec3:

import { color, float, mix, mx_noise_vec3, time, uv, vec3 } from 'three/tsl'

const blue = color('#3871ff')
const lightBlue = color('#579dff')
const p = uv().sub(0.5).mul(8).add(0.5)

const rawNoise = mx_noise_vec3(vec3(p, time.mul(0.5))).xxx
const adjustedNoise = float(0.5).add(float(0.5).mul(rawNoise))

const colorNode = mix(blue, lightBlue, adjustedNoise)

Resources

About

✨ TSLFX • Early-stage collection of VFX, utils, and SDFs for Three.js Shading Language (TSL)

Topics

Resources

License

Stars

Watchers

Forks