Skip to content

@typegpu/three

TSL (Three.js Shading Language) is a node-based shader composition system for Three.js. Shader logic and control flow is built up by composing special functions, with a focus on composability, intuitive sharing of logic across modules and customizability. TypeGPU fits naturally into this system thanks to the @typegpu/three package. You can choose to write your TSL building blocks in TypeGPU, which has a few benefits:

  • Control-flow like if statements and for loops makes use of familiar JavaScript syntax instead of special functions.
  • The code you write is semantically valid JavaScript, with types flowing through each expression.
  • Unit-testability, since you can call these functions on the CPU

Below are a select few cases comparing TSL and TypeGPU:

TSL:

const simulate = Fn(() => {
//
// ... TSL code ...
//
});

TypeGPU:

const
const simulate: Node
simulate
=
import t3
t3
.
function toTSL(fn: () => unknown): NodeObject<Node>
export toTSL
toTSL
(() => {
'use gpu';
//
// ... TypeGPU code ...
//
});

TSL:

const oscSine = Fn(([t = time]) => {
return t.add(0.75).mul(Math.PI * 2).sin().mul(0.5).add(0.5);
});

TypeGPU:

const
const oscSine: (t: number) => number
oscSine
= (
t: number
t
: number) => {
'use gpu';
return
import std
std
.
function sin(value: number): number (+1 overload)
export sin
sin
((
t: number
t
+ 0.75) *
var Math: Math

An intrinsic object that provides basic mathematics functionality and constants.

Math
.
Math.PI: number

Pi. This is the ratio of the circumference of a circle to its diameter.

PI
* 2) * 0.5 + 0.5;
};

TSL:

If(instanceIndex.greaterThanEqual(uint(vertexCount)), () => {
Return();
});

TypeGPU:

if (
import t3
t3
.
const instanceIndex: t3.TSLAccessor<U32, IndexNode>
instanceIndex
.
TSLAccessor<U32, IndexNode>.$: number
$
>=
const vertexCount: number
vertexCount
) {
return;
}

TSL:

Loop({ start: ptrStart, end: ptrEnd, type: 'uint', condition: '<' }, ({ i }) => {
const springId = springListBuffer.element( i ).toVar( 'springId' );
const springForce = springForceBuffer.element( springId );
const springVertexIds = springVertexIdBuffer.element( springId );
const factor = select( springVertexIds.x.equal( instanceIndex ), 1.0, - 1.0 );
force.addAssign( springForce.mul( factor ) );
});

TypeGPU:

for (let i = ptrStart; i < ptrEnd; i++) {
const springId = springListBuffer.$[i];
const springForce = springForceBuffer.$[springId];
const springVertexIds = springVertexIdBuffer.$[springId];
const factor = std.select(-1, 1, springVertexIds.x === idx);
force = force.add(springForce.mul(d.f32(factor)));
}