Skip to content

Commit 28bd37f

Browse files
authored
refactor: Migrate more examples to use tsover (#2199)
1 parent 40b200c commit 28bd37f

42 files changed

Lines changed: 492 additions & 624 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/typegpu-docs/src/content/docs/ecosystem/typegpu-three/index.mdx

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ const material = new THREE.MeshBasicNodeMaterial();
148148

149149
material.colorNode = t3.toTSL(() => {
150150
'use gpu';
151-
const coords = t3.uv().$.mul(2);
151+
const coords = t3.uv().$ * 2;
152152
const pattern = perlin3d.sample(d.vec3f(coords, t3.time.$ * 0.2));
153153
return d.vec4f(std.tanh(pattern * 5), 0.2, 0.4, 1);
154154
});
@@ -244,12 +244,28 @@ Loop({ start: ptrStart, end: ptrEnd, type: 'uint', condition: '<' }, ({ i }) =>
244244
```
245245

246246
TypeGPU:
247-
```ts
247+
```ts twoslash
248+
'use tsover';
249+
import * as t3 from '@typegpu/three';
250+
import * as THREE from 'three/webgpu';
251+
import { d, std } from 'typegpu';
252+
type TSLStorageAccessor<T extends d.AnyWgslData> = t3.TSLAccessor<
253+
T,
254+
THREE.StorageBufferNode
255+
>;
256+
declare const springListBuffer: TSLStorageAccessor<d.WgslArray<d.U32>>;
257+
declare const springForceBuffer: TSLStorageAccessor<d.WgslArray<d.Vec3f>>;
258+
declare const springVertexIdBuffer: TSLStorageAccessor<d.WgslArray<d.Vec2u>>
259+
declare const ptrStart: number;
260+
declare const ptrEnd: number;
261+
declare const idx: number;
262+
declare let force: d.v3f;
263+
// ---cut---
248264
for (let i = ptrStart; i < ptrEnd; i++) {
249265
const springId = springListBuffer.$[i];
250266
const springForce = springForceBuffer.$[springId];
251267
const springVertexIds = springVertexIdBuffer.$[springId];
252268
const factor = std.select(-1, 1, springVertexIds.x === idx);
253-
force = force.add(springForce.mul(d.f32(factor)));
269+
force += springForce * factor;
254270
}
255271
```

apps/typegpu-docs/src/examples/image-processing/ascii-filter/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ const displayModes = {
3030
* https://www.shadertoy.com/view/lssGDj
3131
*/
3232
const characterFn = tgpu.fn([d.u32, d.vec2f], d.f32)((n, p) => {
33+
'use gpu';
3334
// Transform texture coordinates to character bitmap coordinates (5x5 grid)
34-
const pos = std.floor(p.mul(d.vec2f(-4, 4)).add(2.5));
35+
const pos = std.floor(p * d.vec2f(-4, 4) + 2.5);
3536

3637
// Check if position is outside the 5x5 character bitmap bounds
3738
if (pos.x < 0 || pos.x > 4 || pos.y < 0 || pos.y > 4) {
@@ -58,17 +59,16 @@ const pipeline = root.createRenderPipeline({
5859
*/
5960
fragment: ({ uv }) => {
6061
'use gpu';
61-
const uv2 = std.mul(uvTransformBuffer.$, uv.sub(0.5)).add(0.5);
62+
const uv2 = uvTransformBuffer.$ * (uv - 0.5) + 0.5;
6263
const textureSize = d.vec2f(
6364
std.textureDimensions(layout.$.externalTexture),
6465
);
65-
const pix = uv2.mul(textureSize);
66+
const pix = uv2 * textureSize;
6667

6768
const cellSize = d.f32(glyphSize.$);
6869
const halfCell = cellSize * 0.5;
6970

70-
const blockCoord = std.floor(pix.div(cellSize))
71-
.mul(cellSize).div(textureSize);
71+
const blockCoord = std.floor(pix / cellSize) * cellSize / textureSize;
7272

7373
const color = std.textureSampleBaseClampToEdge(
7474
layout.$.externalTexture,
@@ -77,7 +77,7 @@ const pipeline = root.createRenderPipeline({
7777
);
7878

7979
const rawGray = 0.3 * color.x + 0.59 * color.y + 0.11 * color.z;
80-
const gray = std.pow(rawGray, gammaCorrection.$);
80+
const gray = rawGray ** gammaCorrection.$;
8181

8282
let n = d.u32(4096);
8383
if (charsetExtended.$ === 0) {
@@ -143,7 +143,7 @@ const pipeline = root.createRenderPipeline({
143143
let resultColor = d.vec3f(1);
144144
// Color mode
145145
if (displayMode.$ === displayModes.color) {
146-
resultColor = color.mul(charValue).rgb;
146+
resultColor = color.rgb * charValue;
147147
}
148148
// Grayscale mode
149149
if (displayMode.$ === displayModes.grayscale) {

apps/typegpu-docs/src/examples/image-processing/background-segmentation/shaders.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,24 +49,25 @@ export const computeFn = tgpu.computeFn({
4949
in: { wid: d.builtin.workgroupId, lid: d.builtin.localInvocationId },
5050
workgroupSize: [32, 1, 1],
5151
})(({ wid, lid }) => {
52+
'use gpu';
5253
const filterOffset = d.i32((filterDim - 1) / 2);
5354
const dims = d.vec2i(std.textureDimensions(blurLayout.$.inTexture));
54-
const baseIndex = d.vec2i(
55-
wid.xy.mul(d.vec2u(blockDim, 4)).add(lid.xy.mul(d.vec2u(4, 1))),
56-
).sub(d.vec2i(filterOffset, 0));
55+
const baseIndex =
56+
d.vec2i(wid.xy * d.vec2u(blockDim, 4) + lid.xy * d.vec2u(4, 1)) -
57+
d.vec2i(filterOffset, 0);
5758

5859
// Load a tile of pixels into shared memory
5960
for (const r of tgpu.unroll([0, 1, 2, 3])) {
6061
for (const c of tgpu.unroll([0, 1, 2, 3])) {
61-
let loadIndex = baseIndex.add(d.vec2i(c, r));
62+
let loadIndex = baseIndex + d.vec2i(c, r);
6263
if (flipAccess.$) {
6364
loadIndex = loadIndex.yx;
6465
}
6566

6667
tileData.$[r][lid.x * 4 + d.u32(c)] = std.textureSampleLevel(
6768
blurLayout.$.inTexture,
6869
blurLayout.$.sampler,
69-
d.vec2f(d.vec2f(loadIndex).add(d.vec2f(0.5)).div(d.vec2f(dims))),
70+
(d.vec2f(loadIndex) + 0.5) / d.vec2f(dims),
7071
0,
7172
).rgb;
7273
}
@@ -77,7 +78,7 @@ export const computeFn = tgpu.computeFn({
7778
// Apply the horizontal blur filter and write to the output texture
7879
for (const r of tgpu.unroll([0, 1, 2, 3])) {
7980
for (const c of tgpu.unroll([0, 1, 2, 3])) {
80-
let writeIndex = baseIndex.add(d.vec2i(c, r));
81+
let writeIndex = baseIndex + d.vec2i(c, r);
8182
if (flipAccess.$) {
8283
writeIndex = writeIndex.yx;
8384
}
@@ -91,7 +92,7 @@ export const computeFn = tgpu.computeFn({
9192
let acc = d.vec3f();
9293
for (let f = 0; f < filterDim; f++) {
9394
const i = center + f - filterOffset;
94-
acc = acc.add(tileData.$[r][i].mul(1 / filterDim));
95+
acc += tileData.$[r][i] / filterDim;
9596
}
9697
std.textureStore(blurLayout.$.outTexture, writeIndex, d.vec4f(acc, 1));
9798
}

apps/typegpu-docs/src/examples/rendering/3d-fish/compute.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const simulate = (fishIndex: number) => {
2222
const other = layout.$.currentFishData[i];
2323
const dist = std.distance(fishData.position, other.position);
2424
if (dist < layout.$.fishBehavior.separationDist) {
25-
separation = separation + fishData.position - other.position;
25+
separation += fishData.position - other.position;
2626
}
2727
if (dist < layout.$.fishBehavior.alignmentDist) {
2828
alignment = alignment + other.direction;

apps/typegpu-docs/src/examples/rendering/caustics/index.ts

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ const mainVertex = tgpu.vertexFn({
2222
const tilePattern = (uv: d.v2f): number => {
2323
'use gpu';
2424
const tiledUv = std.fract(uv);
25-
const proximity = std.abs(std.sub(std.mul(tiledUv, 2), 1));
25+
const proximity = std.abs((tiledUv * 2) - 1);
2626
const maxProximity = std.max(proximity.x, proximity.y);
27-
return std.saturate(std.pow(1 - maxProximity, 0.6) * 5);
27+
return std.saturate(((1 - maxProximity) ** 0.6) * 5);
2828
};
2929

3030
const caustics = (uv: d.v2f, time: number, profile: d.v3f): d.v3f => {
3131
'use gpu';
32-
const distortion = perlin3d.sample(d.vec3f(std.mul(uv, 0.5), time * 0.2));
32+
const distortion = perlin3d.sample(d.vec3f(uv * 0.5, time * 0.2));
3333
// Distorting UV coordinates
34-
const uv2 = std.add(uv, distortion);
35-
const noise = std.abs(perlin3d.sample(d.vec3f(std.mul(uv2, 5), time)));
34+
const uv2 = uv + distortion;
35+
const noise = std.abs(perlin3d.sample(d.vec3f(uv2 * 5, time)));
3636
return std.pow(d.vec3f(1 - noise), profile);
3737
};
3838

@@ -65,6 +65,7 @@ const mainFragment = tgpu.fragmentFn({
6565
in: { uv: d.vec2f },
6666
out: d.vec4f,
6767
})(({ uv }) => {
68+
'use gpu';
6869
/**
6970
* A transformation matrix that skews the perspective a bit
7071
* when applied to UV coordinates
@@ -73,8 +74,8 @@ const mainFragment = tgpu.fragmentFn({
7374
d.vec2f(std.cos(angle), std.sin(angle)),
7475
d.vec2f(-std.sin(angle) * 10 + uv.x * 3, std.cos(angle) * 5),
7576
);
76-
const skewedUv = std.mul(skewMat, uv);
77-
const tile = tilePattern(std.mul(skewedUv, tileDensity.$));
77+
const skewedUv = skewMat * uv;
78+
const tile = tilePattern(skewedUv * tileDensity.$);
7879
const albedo = std.mix(d.vec3f(0.1), d.vec3f(1), tile);
7980

8081
// Transforming coordinates to simulate perspective squash
@@ -83,49 +84,38 @@ const mainFragment = tgpu.fragmentFn({
8384
std.pow((uv.y * 1.5 + 0.1) * 1.5, 3) * 1,
8485
);
8586
// Generating two layers of caustics (large scale, and small scale)
86-
const c1 = std.mul(
87-
caustics(cuv, time.$ * 0.2, /* profile */ d.vec3f(4, 4, 1)),
87+
const c1 = caustics(cuv, time.$ * 0.2, /* profile */ d.vec3f(4, 4, 1)) *
8888
// Tinting
89-
d.vec3f(0.4, 0.65, 1),
90-
);
91-
const c2 = std.mul(
92-
caustics(std.mul(cuv, 2), time.$ * 0.4, /* profile */ d.vec3f(16, 1, 4)),
89+
d.vec3f(0.4, 0.65, 1);
90+
const c2 = caustics(cuv * 2, time.$ * 0.4, /* profile */ d.vec3f(16, 1, 4)) *
9391
// Tinting
94-
d.vec3f(0.18, 0.3, 0.5),
95-
);
92+
d.vec3f(0.18, 0.3, 0.5);
9693

9794
// -- BLEND --
9895

99-
const blendCoord = d.vec3f(std.mul(uv, d.vec2f(5, 10)), time.$ * 0.2 + 5);
96+
const blendCoord = d.vec3f(uv * d.vec2f(5, 10), time.$ * 0.2 + 5);
10097
// A smooth blending factor, so that caustics only appear at certain spots
10198
const blend = std.saturate(perlin3d.sample(blendCoord) + 0.3);
10299

103100
// -- FOG --
104101

105-
const noFogColor = std.mul(
106-
albedo,
107-
std.mix(ambientColor, std.add(c1, c2), blend),
108-
);
102+
const noFogColor = albedo * std.mix(ambientColor, c1 + c2, blend);
109103
// Fog blending factor, based on the height of the pixels
110-
const fog = std.min(std.pow(uv.y, 0.5) * 1.2, 1);
104+
const fog = std.min((uv.y ** 0.5) * 1.2, 1);
111105

112106
// -- GOD RAYS --
113107

114-
const godRayUv = std.mul(std.mul(rotateXY(-0.3), uv), d.vec2f(15, 3));
115-
const godRayFactor = std.pow(uv.y, 1);
116-
const godRay1 = std.mul(
117-
std.add(perlin3d.sample(d.vec3f(godRayUv, time.$ * 0.5)), 1),
108+
const godRayUv = rotateXY(-0.3) * uv * d.vec2f(15, 3);
109+
const godRayFactor = uv.y;
110+
const godRay1 = (perlin3d.sample(d.vec3f(godRayUv, time.$ * 0.5)) + 1) *
118111
// Tinting
119-
std.mul(d.vec3f(0.18, 0.3, 0.5), godRayFactor),
120-
);
121-
const godRay2 = std.mul(
122-
std.add(perlin3d.sample(d.vec3f(std.mul(godRayUv, 2), time.$ * 0.3)), 1),
112+
d.vec3f(0.18, 0.3, 0.5) * godRayFactor;
113+
const godRay2 = (perlin3d.sample(d.vec3f(godRayUv * 2, time.$ * 0.3)) + 1) *
123114
// Tinting
124-
std.mul(d.vec3f(0.18, 0.3, 0.5), godRayFactor * 0.4),
125-
);
126-
const godRays = std.add(godRay1, godRay2);
115+
d.vec3f(0.18, 0.3, 0.5) * godRayFactor * 0.4;
116+
const godRays = godRay1 + godRay2;
127117

128-
return d.vec4f(std.add(std.mix(noFogColor, fogColor, fog), godRays), 1);
118+
return d.vec4f(std.mix(noFogColor, fogColor, fog) + godRays, 1);
129119
});
130120

131121
const canvas = document.querySelector('canvas') as HTMLCanvasElement;

apps/typegpu-docs/src/examples/rendering/clouds/index.ts

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -55,47 +55,40 @@ const bindGroup = root.createBindGroup(cloudsLayout, {
5555
sampler,
5656
});
5757

58-
const mainFragment = tgpu.fragmentFn({
59-
in: { uv: d.vec2f },
60-
out: d.vec4f,
61-
})(({ uv }) => {
62-
randf.seed2(uv.mul(cloudsLayout.$.params.time));
63-
const screenRes = resolutionUniform.$;
64-
const aspect = screenRes.x / screenRes.y;
65-
66-
let screenPos = std.mul(std.sub(uv, 0.5), 2.0);
67-
screenPos = d.vec2f(
68-
screenPos.x * std.max(aspect, 1.0),
69-
screenPos.y * std.max(1.0 / aspect, 1.0),
70-
);
71-
72-
const sunDir = std.normalize(SUN_DIRECTION);
73-
const time = cloudsLayout.$.params.time;
74-
const rayOrigin = d.vec3f(
75-
std.sin(time * 0.6) * 0.5,
76-
std.cos(time * 0.8) * 0.5 - 1,
77-
time * WIND_SPEED,
78-
);
79-
const rayDir = std.normalize(d.vec3f(screenPos.x, screenPos.y, FOV_FACTOR));
80-
81-
const sunDot = std.clamp(std.dot(rayDir, sunDir), 0.0, 1.0);
82-
const sunGlow = std.pow(
83-
sunDot,
84-
1.0 / (SUN_BRIGHTNESS * SUN_BRIGHTNESS * SUN_BRIGHTNESS),
85-
);
86-
87-
let skyCol = std.sub(SKY_HORIZON, std.mul(SKY_ZENITH_TINT, rayDir.y * 0.35));
88-
skyCol = std.add(skyCol, std.mul(SUN_GLOW, sunGlow));
89-
90-
const cloudCol = raymarch(rayOrigin, rayDir, sunDir);
91-
const finalCol = std.add(std.mul(skyCol, 1.1 - cloudCol.a), cloudCol.rgb);
92-
93-
return d.vec4f(finalCol, 1.0);
94-
});
95-
9658
const pipeline = root.createRenderPipeline({
9759
vertex: common.fullScreenTriangle,
98-
fragment: mainFragment,
60+
fragment: ({ uv }) => {
61+
'use gpu';
62+
randf.seed2(uv * cloudsLayout.$.params.time);
63+
const screenRes = resolutionUniform.$;
64+
const aspect = screenRes.x / screenRes.y;
65+
66+
let screenPos = (uv - 0.5) * 2;
67+
screenPos = d.vec2f(
68+
screenPos.x * std.max(aspect, 1),
69+
screenPos.y * std.max(1 / aspect, 1),
70+
);
71+
72+
const sunDir = std.normalize(SUN_DIRECTION);
73+
const time = cloudsLayout.$.params.time;
74+
const rayOrigin = d.vec3f(
75+
std.sin(time * 0.6) * 0.5,
76+
std.cos(time * 0.8) * 0.5 - 1,
77+
time * WIND_SPEED,
78+
);
79+
const rayDir = std.normalize(d.vec3f(screenPos.x, screenPos.y, FOV_FACTOR));
80+
81+
const sunDot = std.saturate(std.dot(rayDir, sunDir));
82+
const sunGlow = sunDot ** (1 / SUN_BRIGHTNESS ** 3);
83+
84+
let skyCol = SKY_HORIZON - SKY_ZENITH_TINT * rayDir.y * 0.35;
85+
skyCol += SUN_GLOW * sunGlow;
86+
87+
const cloudCol = raymarch(rayOrigin, rayDir, sunDir);
88+
const finalCol = skyCol * (1.1 - cloudCol.a) + cloudCol.rgb;
89+
90+
return d.vec4f(finalCol, 1.0);
91+
},
9992
targets: { format: presentationFormat },
10093
});
10194

0 commit comments

Comments
 (0)