Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/typegpu-docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,11 @@ export default defineConfig({
label: '@typegpu/noise',
slug: 'ecosystem/typegpu-noise',
},
{
label: '@typegpu/three',
slug: 'ecosystem/typegpu-three',
badge: { text: 'new' },
},
DEV && {
label: '@typegpu/color',
slug: 'ecosystem/typegpu-color',
Expand Down
101 changes: 101 additions & 0 deletions apps/typegpu-docs/src/content/docs/ecosystem/typegpu-three.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: "@typegpu/three"
---

[TSL (Three.js Shading Language)](https://github.com/mrdoob/three.js/wiki/Three.js-Shading-Language#function) 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:

import { Card, CardGrid } from '@astrojs/starlight/components';

## Node definition

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

TypeGPU:
```ts twoslash
import * as t3 from '@typegpu/three';
// ---cut---
const simulate = t3.toTSL(() => {
'use gpu';
//
// ... TypeGPU code ...
//
});
```

## Function definition

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

TypeGPU:
```ts twoslash
import * as std from 'typegpu/std';
// ---cut---
const oscSine = (t: number) => {
'use gpu';
return std.sin((t + 0.75) * Math.PI * 2) * 0.5 + 0.5;
};
```

## If statements

TSL:
```ts
If(instanceIndex.greaterThanEqual(uint(vertexCount)), () => {
Return();
});
```

TypeGPU:
```ts twoslash
import * as t3 from '@typegpu/three';
declare const vertexCount: number;
const some = () => {
// ---cut-before---
if (t3.instanceIndex.$ >= vertexCount) {
return;
}
// ---cut-after---
};
```

## For loops

TSL:
```ts
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:
```ts
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)));
}
```
Loading