Skip to content

Commit 118e8b1

Browse files
authored
impr: Split the jump flood algorithm example into two and improve the distance painting (#1967)
1 parent cfb5295 commit 118e8b1

16 files changed

Lines changed: 948 additions & 278 deletions

File tree

apps/typegpu-docs/src/examples/algorithms/jump-flood/index.html renamed to apps/typegpu-docs/src/examples/algorithms/jump-flood-distance/index.html

File renamed without changes.

apps/typegpu-docs/src/examples/algorithms/jump-flood-distance/index.ts

Lines changed: 524 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"title": "Jump Flood (Distance)",
3+
"category": "algorithms",
4+
"tags": ["experimental", "compute"]
5+
}
3.97 MB
Loading
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import tgpu, {
2+
type SampledFlag,
3+
type StorageFlag,
4+
type TgpuTexture,
5+
} from 'typegpu';
6+
import * as d from 'typegpu/data';
7+
8+
export const VisualizationParams = d.struct({
9+
showInside: d.u32,
10+
showOutside: d.u32,
11+
});
12+
13+
export const BrushParams = d.struct({
14+
center: d.vec2f,
15+
radius: d.f32,
16+
erasing: d.u32,
17+
});
18+
19+
export const SampleResult = d.struct({
20+
inside: d.vec2f,
21+
outside: d.vec2f,
22+
});
23+
24+
export const paramsAccessor = tgpu['~unstable'].accessor(VisualizationParams);
25+
26+
export const distSampleLayout = tgpu.bindGroupLayout({
27+
distTexture: { texture: d.texture2d() },
28+
sampler: { sampler: 'filtering' },
29+
});
30+
31+
export const initLayout = tgpu.bindGroupLayout({
32+
writeView: {
33+
storageTexture: d.textureStorage2d('rgba16float', 'write-only'),
34+
},
35+
});
36+
37+
export const pingPongLayout = tgpu.bindGroupLayout({
38+
writeView: {
39+
storageTexture: d.textureStorage2d('rgba16float', 'write-only'),
40+
},
41+
readView: {
42+
storageTexture: d.textureStorage2d('rgba16float', 'read-only'),
43+
},
44+
});
45+
46+
export const maskLayout = tgpu.bindGroupLayout({
47+
maskTexture: {
48+
storageTexture: d.textureStorage2d('r32uint', 'write-only'),
49+
},
50+
});
51+
52+
export const distWriteLayout = tgpu.bindGroupLayout({
53+
distTexture: {
54+
storageTexture: d.textureStorage2d('rgba16float', 'write-only'),
55+
},
56+
});
57+
58+
export const initFromMaskLayout = tgpu.bindGroupLayout({
59+
maskTexture: {
60+
storageTexture: d.textureStorage2d('r32uint', 'read-only'),
61+
},
62+
writeView: {
63+
storageTexture: d.textureStorage2d('rgba16float', 'write-only'),
64+
},
65+
});
66+
67+
export type FloodTexture =
68+
& TgpuTexture<{ size: [number, number]; format: 'rgba16float' }>
69+
& StorageFlag;
70+
71+
export type MaskTexture =
72+
& TgpuTexture<{ size: [number, number]; format: 'r32uint' }>
73+
& StorageFlag;
74+
75+
export type DistanceTexture =
76+
& TgpuTexture<{ size: [number, number]; format: 'rgba16float' }>
77+
& SampledFlag
78+
& StorageFlag;
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import tgpu from 'typegpu';
2+
import * as d from 'typegpu/data';
3+
import * as std from 'typegpu/std';
4+
import { distSampleLayout, paramsAccessor } from './types.ts';
5+
6+
const outsideGradient = tgpu.const(d.arrayOf(d.vec3f, 5), [
7+
d.vec3f(0.05, 0.05, 0.15),
8+
d.vec3f(0.2, 0.1, 0.4),
9+
d.vec3f(0.6, 0.2, 0.5),
10+
d.vec3f(0.95, 0.5, 0.3),
11+
d.vec3f(1.0, 0.95, 0.8),
12+
]);
13+
14+
const insideGradient = tgpu.const(d.arrayOf(d.vec3f, 5), [
15+
d.vec3f(0.05, 0.05, 0.15),
16+
d.vec3f(0.1, 0.2, 0.3),
17+
d.vec3f(0.2, 0.45, 0.55),
18+
d.vec3f(0.4, 0.75, 0.7),
19+
d.vec3f(0.9, 1.0, 0.95),
20+
]);
21+
22+
export const distanceFrag = tgpu['~unstable'].fragmentFn({
23+
in: { uv: d.vec2f },
24+
out: d.vec4f,
25+
})(({ uv }) => {
26+
'use gpu';
27+
const size = std.textureDimensions(distSampleLayout.$.distTexture);
28+
let dist = std.textureSample(
29+
distSampleLayout.$.distTexture,
30+
distSampleLayout.$.sampler,
31+
uv,
32+
).x;
33+
34+
if (paramsAccessor.$.showInside === 0 && dist < 0) {
35+
dist = 0;
36+
}
37+
if (paramsAccessor.$.showOutside === 0 && dist > 0) {
38+
dist = 0;
39+
}
40+
41+
const unsigned = std.abs(dist);
42+
43+
const maxDist = d.f32(std.max(size.x, size.y)) * 0.25;
44+
const t = std.saturate(unsigned / maxDist);
45+
46+
const gradientPos = t * 4.0;
47+
const idx = d.u32(gradientPos);
48+
const frac = std.fract(gradientPos);
49+
50+
const outsideBase = std.mix(
51+
outsideGradient.$[std.min(idx, 4)],
52+
outsideGradient.$[std.min(idx + 1, 4)],
53+
frac,
54+
);
55+
56+
const insideBase = std.mix(
57+
insideGradient.$[std.min(idx, 4)],
58+
insideGradient.$[std.min(idx + 1, 4)],
59+
frac,
60+
);
61+
62+
let baseColor = d.vec3f(outsideBase);
63+
if (dist < 0.0) {
64+
baseColor = d.vec3f(insideBase);
65+
}
66+
67+
const contourFreq = maxDist / 12.0;
68+
const contour = std.smoothstep(
69+
0.0,
70+
0.15,
71+
std.abs(std.fract(unsigned / contourFreq) - 0.5),
72+
);
73+
74+
const color = baseColor.mul(0.7 + 0.3 * contour);
75+
return d.vec4f(color, 1.0);
76+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<canvas data-fit-to-container></canvas>

0 commit comments

Comments
 (0)