@multiplekex/shallot 0.1.12 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -4
- package/src/core/builder.ts +71 -32
- package/src/core/component.ts +25 -11
- package/src/core/index.ts +14 -13
- package/src/core/math.ts +135 -0
- package/src/core/runtime.ts +0 -1
- package/src/core/state.ts +9 -68
- package/src/core/xml.ts +381 -265
- package/src/editor/format.ts +5 -0
- package/src/editor/index.ts +101 -0
- package/src/extras/arrows/index.ts +28 -69
- package/src/extras/gradient/index.ts +36 -52
- package/src/extras/lines/index.ts +51 -122
- package/src/extras/orbit/index.ts +40 -15
- package/src/extras/text/font.ts +546 -0
- package/src/extras/text/index.ts +158 -204
- package/src/extras/text/sdf.ts +429 -0
- package/src/standard/activity/index.ts +172 -0
- package/src/standard/compute/graph.ts +23 -23
- package/src/standard/compute/index.ts +76 -61
- package/src/standard/defaults.ts +8 -5
- package/src/standard/index.ts +1 -0
- package/src/standard/input/index.ts +30 -19
- package/src/standard/loading/index.ts +18 -13
- package/src/standard/render/bvh/blas.ts +752 -0
- package/src/standard/render/bvh/radix.ts +476 -0
- package/src/standard/render/bvh/structs.ts +167 -0
- package/src/standard/render/bvh/tlas.ts +886 -0
- package/src/standard/render/bvh/traverse.ts +467 -0
- package/src/standard/render/camera.ts +302 -27
- package/src/standard/render/data.ts +93 -0
- package/src/standard/render/depth.ts +117 -0
- package/src/standard/render/forward/index.ts +259 -0
- package/src/standard/render/forward/raster.ts +228 -0
- package/src/standard/render/index.ts +443 -70
- package/src/standard/render/indirect.ts +40 -0
- package/src/standard/render/instance.ts +214 -0
- package/src/standard/render/intersection.ts +72 -0
- package/src/standard/render/light.ts +16 -16
- package/src/standard/render/mesh/index.ts +67 -75
- package/src/standard/render/mesh/unified.ts +96 -0
- package/src/standard/render/{transparent.ts → overlay.ts} +14 -15
- package/src/standard/render/pass.ts +10 -4
- package/src/standard/render/postprocess.ts +142 -64
- package/src/standard/render/ray.ts +61 -0
- package/src/standard/render/scene.ts +38 -164
- package/src/standard/render/shaders.ts +484 -0
- package/src/standard/render/surface/compile.ts +3 -10
- package/src/standard/render/surface/index.ts +60 -30
- package/src/standard/render/surface/noise.ts +45 -0
- package/src/standard/render/surface/structs.ts +60 -19
- package/src/standard/render/surface/wgsl.ts +573 -0
- package/src/standard/render/triangle.ts +84 -0
- package/src/standard/transforms/index.ts +4 -6
- package/src/standard/tween/index.ts +10 -1
- package/src/standard/tween/sequence.ts +24 -16
- package/src/standard/tween/tween.ts +67 -16
- package/src/core/types.ts +0 -37
- package/src/standard/compute/inspect.ts +0 -201
- package/src/standard/compute/pass.ts +0 -23
- package/src/standard/compute/timing.ts +0 -139
- package/src/standard/render/forward.ts +0 -273
|
@@ -1,21 +1,12 @@
|
|
|
1
1
|
import { setTraits } from "../../core/component";
|
|
2
|
+
import { perspective, orthographic, multiply, invert, extractFrustumPlanes } from "../../core/math";
|
|
2
3
|
import { WorldTransform } from "../transforms";
|
|
3
|
-
import { clearColor } from "./forward";
|
|
4
|
-
import { perspective, orthographic, multiply, invert, extractFrustumPlanes } from "./scene";
|
|
5
4
|
|
|
6
5
|
export const RenderMode = {
|
|
7
6
|
Raster: 0,
|
|
8
7
|
Raytracing: 1,
|
|
9
8
|
} as const;
|
|
10
9
|
|
|
11
|
-
export const DebugMode = {
|
|
12
|
-
Color: 0,
|
|
13
|
-
Depth: 1,
|
|
14
|
-
Normal: 2,
|
|
15
|
-
Material: 3,
|
|
16
|
-
Hit: 4,
|
|
17
|
-
} as const;
|
|
18
|
-
|
|
19
10
|
export const CameraMode = {
|
|
20
11
|
Perspective: 0,
|
|
21
12
|
Orthographic: 1,
|
|
@@ -28,7 +19,6 @@ export const Camera = {
|
|
|
28
19
|
active: [] as number[],
|
|
29
20
|
clearColor: [] as number[],
|
|
30
21
|
renderMode: [] as number[],
|
|
31
|
-
debugMode: [] as number[],
|
|
32
22
|
mode: [] as number[],
|
|
33
23
|
size: [] as number[],
|
|
34
24
|
};
|
|
@@ -41,7 +31,6 @@ setTraits(Camera, {
|
|
|
41
31
|
active: 1,
|
|
42
32
|
clearColor: 0x1a1a1a,
|
|
43
33
|
renderMode: RenderMode.Raster,
|
|
44
|
-
debugMode: DebugMode.Color,
|
|
45
34
|
mode: CameraMode.Perspective,
|
|
46
35
|
size: 5,
|
|
47
36
|
}),
|
|
@@ -57,6 +46,8 @@ setTraits(Tonemap, {
|
|
|
57
46
|
|
|
58
47
|
export const FXAA = {};
|
|
59
48
|
|
|
49
|
+
export const Raytracing = {};
|
|
50
|
+
|
|
60
51
|
export const Vignette = {
|
|
61
52
|
strength: [] as number[],
|
|
62
53
|
inner: [] as number[],
|
|
@@ -67,6 +58,152 @@ setTraits(Vignette, {
|
|
|
67
58
|
defaults: () => ({ strength: 0.5, inner: 0.4, outer: 0.8 }),
|
|
68
59
|
});
|
|
69
60
|
|
|
61
|
+
export const Bloom = {
|
|
62
|
+
intensity: [] as number[],
|
|
63
|
+
threshold: [] as number[],
|
|
64
|
+
radius: [] as number[],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
setTraits(Bloom, {
|
|
68
|
+
defaults: () => ({
|
|
69
|
+
intensity: 0.15,
|
|
70
|
+
threshold: 0.0,
|
|
71
|
+
radius: 0.5,
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
export const Quantize = {
|
|
76
|
+
bands: [] as number[],
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
setTraits(Quantize, {
|
|
80
|
+
defaults: () => ({ bands: 8 }),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const Shadows = {
|
|
84
|
+
softness: [] as number[],
|
|
85
|
+
samples: [] as number[],
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
setTraits(Shadows, {
|
|
89
|
+
defaults: () => ({
|
|
90
|
+
softness: 0.5,
|
|
91
|
+
samples: 1,
|
|
92
|
+
}),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export const Reflections = {
|
|
96
|
+
depth: [] as number[],
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
setTraits(Reflections, {
|
|
100
|
+
defaults: () => ({ depth: 1 }),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export const Refractions = {
|
|
104
|
+
depth: [] as number[],
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
setTraits(Refractions, {
|
|
108
|
+
defaults: () => ({ depth: 2 }),
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
export const Haze = {
|
|
112
|
+
density: [] as number[],
|
|
113
|
+
color: [] as number[],
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
setTraits(Haze, {
|
|
117
|
+
defaults: () => ({
|
|
118
|
+
density: 0.005,
|
|
119
|
+
color: 0x4078d0,
|
|
120
|
+
}),
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export const Sky = {
|
|
124
|
+
zenith: [] as number[],
|
|
125
|
+
horizon: [] as number[],
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
setTraits(Sky, {
|
|
129
|
+
defaults: () => ({
|
|
130
|
+
zenith: 0x4078d0,
|
|
131
|
+
horizon: 0x4098d8,
|
|
132
|
+
}),
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
export const Moon = {
|
|
136
|
+
phase: [] as number[],
|
|
137
|
+
glow: [] as number[],
|
|
138
|
+
azimuth: [] as number[],
|
|
139
|
+
elevation: [] as number[],
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
setTraits(Moon, {
|
|
143
|
+
defaults: () => ({
|
|
144
|
+
phase: 0.5,
|
|
145
|
+
glow: 0.3,
|
|
146
|
+
azimuth: 45,
|
|
147
|
+
elevation: 30,
|
|
148
|
+
}),
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
export const Stars = {
|
|
152
|
+
intensity: [] as number[],
|
|
153
|
+
amount: [] as number[],
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
setTraits(Stars, {
|
|
157
|
+
defaults: () => ({
|
|
158
|
+
intensity: 0.8,
|
|
159
|
+
amount: 0.5,
|
|
160
|
+
}),
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
export const Clouds = {
|
|
164
|
+
coverage: [] as number[],
|
|
165
|
+
density: [] as number[],
|
|
166
|
+
height: [] as number[],
|
|
167
|
+
color: [] as number[],
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
setTraits(Clouds, {
|
|
171
|
+
defaults: () => ({
|
|
172
|
+
coverage: 0.7,
|
|
173
|
+
density: 0.8,
|
|
174
|
+
height: 0.5,
|
|
175
|
+
color: 0xffffff,
|
|
176
|
+
}),
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
export const Sun = {
|
|
180
|
+
size: [] as number[],
|
|
181
|
+
glow: [] as number[],
|
|
182
|
+
color: [] as number[],
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
setTraits(Sun, {
|
|
186
|
+
defaults: () => ({
|
|
187
|
+
size: 1.0,
|
|
188
|
+
glow: 0.4,
|
|
189
|
+
color: 0,
|
|
190
|
+
}),
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
export const Viewport = {
|
|
194
|
+
width: [] as number[],
|
|
195
|
+
height: [] as number[],
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
setTraits(Viewport, {
|
|
199
|
+
defaults: () => ({ width: 0, height: 0 }),
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
export interface SkyParams {
|
|
203
|
+
zenith: number;
|
|
204
|
+
horizon: number;
|
|
205
|
+
}
|
|
206
|
+
|
|
70
207
|
export function unpackColor(packed: number): { r: number; g: number; b: number } {
|
|
71
208
|
return {
|
|
72
209
|
r: ((packed >> 16) & 0xff) / 255,
|
|
@@ -75,18 +212,58 @@ export function unpackColor(packed: number): { r: number; g: number; b: number }
|
|
|
75
212
|
};
|
|
76
213
|
}
|
|
77
214
|
|
|
215
|
+
export interface HazeParams {
|
|
216
|
+
density: number;
|
|
217
|
+
color: number;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export interface MoonParams {
|
|
221
|
+
phase: number;
|
|
222
|
+
glow: number;
|
|
223
|
+
azimuth: number;
|
|
224
|
+
elevation: number;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface StarsParams {
|
|
228
|
+
intensity: number;
|
|
229
|
+
amount: number;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface CloudsParams {
|
|
233
|
+
coverage: number;
|
|
234
|
+
density: number;
|
|
235
|
+
height: number;
|
|
236
|
+
color: number;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export interface SunParams {
|
|
240
|
+
size: number;
|
|
241
|
+
glow: number;
|
|
242
|
+
color: number;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const sceneBuffer = new ArrayBuffer(512);
|
|
246
|
+
const scene = new Float32Array(sceneBuffer);
|
|
247
|
+
const sceneU32 = new Uint32Array(sceneBuffer);
|
|
248
|
+
|
|
78
249
|
export function uploadCamera(
|
|
79
250
|
device: GPUDevice,
|
|
80
251
|
buffer: GPUBuffer,
|
|
81
252
|
eid: number,
|
|
82
253
|
width: number,
|
|
83
|
-
height: number
|
|
254
|
+
height: number,
|
|
255
|
+
shadowSoftness: number = 0,
|
|
256
|
+
shadowSamples: number = 1,
|
|
257
|
+
reflectionDepth: number = 0,
|
|
258
|
+
refractionDepth: number = 0,
|
|
259
|
+
instanceCount: number = 0,
|
|
260
|
+
haze?: HazeParams,
|
|
261
|
+
sky?: SkyParams,
|
|
262
|
+
moon?: MoonParams,
|
|
263
|
+
stars?: StarsParams,
|
|
264
|
+
clouds?: CloudsParams,
|
|
265
|
+
sun?: SunParams
|
|
84
266
|
): void {
|
|
85
|
-
const color = unpackColor(Camera.clearColor[eid]);
|
|
86
|
-
clearColor.r = color.r;
|
|
87
|
-
clearColor.g = color.g;
|
|
88
|
-
clearColor.b = color.b;
|
|
89
|
-
|
|
90
267
|
const aspect = width / height;
|
|
91
268
|
const proj =
|
|
92
269
|
Camera.mode[eid] === CameraMode.Orthographic
|
|
@@ -96,16 +273,114 @@ export function uploadCamera(
|
|
|
96
273
|
const view = invert(world);
|
|
97
274
|
const viewProj = multiply(proj, view);
|
|
98
275
|
|
|
99
|
-
|
|
100
|
-
|
|
276
|
+
// viewProj (0-63)
|
|
277
|
+
scene.set(viewProj, 0);
|
|
278
|
+
// world (64-127)
|
|
279
|
+
scene.set(world, 16);
|
|
280
|
+
|
|
281
|
+
// clearColor (176-191) - note: 128-175 is light uniforms, written separately
|
|
282
|
+
const clearColorPacked = Camera.clearColor[eid];
|
|
283
|
+
scene[44] = ((clearColorPacked >> 16) & 0xff) / 255;
|
|
284
|
+
scene[45] = ((clearColorPacked >> 8) & 0xff) / 255;
|
|
285
|
+
scene[46] = (clearColorPacked & 0xff) / 255;
|
|
286
|
+
scene[47] = 1.0;
|
|
287
|
+
|
|
288
|
+
// cameraMode, cameraSize, viewport (192-207)
|
|
289
|
+
scene[48] = Camera.mode[eid];
|
|
290
|
+
scene[49] = Camera.size[eid];
|
|
291
|
+
scene[50] = width;
|
|
292
|
+
scene[51] = height;
|
|
293
|
+
|
|
294
|
+
// fov, near, far, shadowSoftness (208-223)
|
|
295
|
+
scene[52] = Camera.fov[eid];
|
|
296
|
+
scene[53] = Camera.near[eid];
|
|
297
|
+
scene[54] = Camera.far[eid];
|
|
298
|
+
scene[55] = shadowSoftness;
|
|
101
299
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
);
|
|
300
|
+
// shadowSamples, reflectionDepth, refractionDepth, instanceCount (224-239)
|
|
301
|
+
sceneU32[56] = shadowSamples;
|
|
302
|
+
sceneU32[57] = reflectionDepth;
|
|
303
|
+
sceneU32[58] = refractionDepth;
|
|
304
|
+
sceneU32[59] = instanceCount;
|
|
108
305
|
|
|
306
|
+
// hazeDensity (240-255)
|
|
307
|
+
scene[60] = haze?.density ?? 0;
|
|
308
|
+
scene[61] = 0;
|
|
309
|
+
scene[62] = 0;
|
|
310
|
+
scene[63] = 0;
|
|
311
|
+
|
|
312
|
+
// hazeColor (256-271)
|
|
313
|
+
const hazeColorPacked = haze?.color ?? 0x8090b0;
|
|
314
|
+
scene[64] = ((hazeColorPacked >> 16) & 0xff) / 255;
|
|
315
|
+
scene[65] = ((hazeColorPacked >> 8) & 0xff) / 255;
|
|
316
|
+
scene[66] = (hazeColorPacked & 0xff) / 255;
|
|
317
|
+
scene[67] = 1.0;
|
|
318
|
+
|
|
319
|
+
// skyZenith (272-287)
|
|
320
|
+
const zenithPacked = sky?.zenith ?? 0;
|
|
321
|
+
scene[68] = ((zenithPacked >> 16) & 0xff) / 255;
|
|
322
|
+
scene[69] = ((zenithPacked >> 8) & 0xff) / 255;
|
|
323
|
+
scene[70] = (zenithPacked & 0xff) / 255;
|
|
324
|
+
scene[71] = sky ? 1.0 : 0.0;
|
|
325
|
+
|
|
326
|
+
// skyHorizon (288-303)
|
|
327
|
+
const horizonPacked = sky?.horizon ?? 0;
|
|
328
|
+
scene[72] = ((horizonPacked >> 16) & 0xff) / 255;
|
|
329
|
+
scene[73] = ((horizonPacked >> 8) & 0xff) / 255;
|
|
330
|
+
scene[74] = (horizonPacked & 0xff) / 255;
|
|
331
|
+
scene[75] = 1.0;
|
|
332
|
+
|
|
333
|
+
// frustumPlanes (304-399)
|
|
109
334
|
const planes = extractFrustumPlanes(viewProj);
|
|
110
|
-
|
|
335
|
+
scene.set(planes, 76);
|
|
336
|
+
|
|
337
|
+
// moonParams (400-415)
|
|
338
|
+
scene[100] = moon?.phase ?? 0.5;
|
|
339
|
+
scene[101] = moon?.glow ?? 0.3;
|
|
340
|
+
scene[102] = moon ? 1.0 : 0.0;
|
|
341
|
+
scene[103] = 0.0;
|
|
342
|
+
|
|
343
|
+
// moonDirection (416-431)
|
|
344
|
+
const moonAzimuth = ((moon?.azimuth ?? 45) * Math.PI) / 180;
|
|
345
|
+
const moonElevation = ((moon?.elevation ?? 30) * Math.PI) / 180;
|
|
346
|
+
const moonCosEl = Math.cos(moonElevation);
|
|
347
|
+
scene[104] = Math.sin(moonAzimuth) * moonCosEl;
|
|
348
|
+
scene[105] = Math.sin(moonElevation);
|
|
349
|
+
scene[106] = Math.cos(moonAzimuth) * moonCosEl;
|
|
350
|
+
scene[107] = 0.0;
|
|
351
|
+
|
|
352
|
+
// starParams (432-447)
|
|
353
|
+
scene[108] = stars?.intensity ?? 0.8;
|
|
354
|
+
scene[109] = stars?.amount ?? 0.5;
|
|
355
|
+
scene[110] = stars ? 1.0 : 0.0;
|
|
356
|
+
scene[111] = 0.0;
|
|
357
|
+
|
|
358
|
+
// cloudParams (448-463)
|
|
359
|
+
scene[112] = clouds?.coverage ?? 0;
|
|
360
|
+
scene[113] = clouds?.density ?? 0;
|
|
361
|
+
scene[114] = clouds?.height ?? 0;
|
|
362
|
+
scene[115] = clouds ? 1.0 : 0.0;
|
|
363
|
+
|
|
364
|
+
// cloudColor (464-479)
|
|
365
|
+
const cloudColorPacked = clouds?.color ?? 0xffffff;
|
|
366
|
+
scene[116] = ((cloudColorPacked >> 16) & 0xff) / 255;
|
|
367
|
+
scene[117] = ((cloudColorPacked >> 8) & 0xff) / 255;
|
|
368
|
+
scene[118] = (cloudColorPacked & 0xff) / 255;
|
|
369
|
+
scene[119] = 0.0;
|
|
370
|
+
|
|
371
|
+
// sunParams (480-495)
|
|
372
|
+
scene[120] = sun?.size ?? 1.0;
|
|
373
|
+
scene[121] = sun?.glow ?? 0.5;
|
|
374
|
+
scene[122] = sun && sun.color !== 0 ? 1.0 : 0.0;
|
|
375
|
+
scene[123] = 0.0;
|
|
376
|
+
|
|
377
|
+
// sunVisualColor (496-511)
|
|
378
|
+
const sunColorPacked = sun?.color ?? 0xffffff;
|
|
379
|
+
scene[124] = ((sunColorPacked >> 16) & 0xff) / 255;
|
|
380
|
+
scene[125] = ((sunColorPacked >> 8) & 0xff) / 255;
|
|
381
|
+
scene[126] = (sunColorPacked & 0xff) / 255;
|
|
382
|
+
scene[127] = 0.0;
|
|
383
|
+
|
|
384
|
+
device.queue.writeBuffer(buffer, 0, scene, 0, 32);
|
|
385
|
+
device.queue.writeBuffer(buffer, 176, scene, 44, 84);
|
|
111
386
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { ComputeNode, ExecutionContext } from "../compute";
|
|
2
|
+
|
|
3
|
+
const WORKGROUP_SIZE = 64;
|
|
4
|
+
|
|
5
|
+
const shader = /* wgsl */ `
|
|
6
|
+
struct Data {
|
|
7
|
+
baseColor: vec4<f32>,
|
|
8
|
+
pbr: vec4<f32>,
|
|
9
|
+
emission: vec4<f32>,
|
|
10
|
+
flags: u32,
|
|
11
|
+
_pad0: u32,
|
|
12
|
+
_pad1: u32,
|
|
13
|
+
_pad2: u32,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@group(0) @binding(0) var<storage, read> colors: array<vec4<f32>>;
|
|
17
|
+
@group(0) @binding(1) var<storage, read> pbr: array<vec4<f32>>;
|
|
18
|
+
@group(0) @binding(2) var<storage, read> emission: array<vec4<f32>>;
|
|
19
|
+
@group(0) @binding(3) var<storage, read> surfaces: array<u32>;
|
|
20
|
+
@group(0) @binding(4) var<storage, read> entityCount: array<u32>;
|
|
21
|
+
@group(0) @binding(5) var<storage, read_write> data: array<Data>;
|
|
22
|
+
|
|
23
|
+
@compute @workgroup_size(${WORKGROUP_SIZE})
|
|
24
|
+
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
25
|
+
let eid = gid.x;
|
|
26
|
+
let count = entityCount[0];
|
|
27
|
+
if (eid >= count) { return; }
|
|
28
|
+
|
|
29
|
+
var d: Data;
|
|
30
|
+
d.baseColor = colors[eid];
|
|
31
|
+
d.pbr = pbr[eid];
|
|
32
|
+
d.emission = emission[eid];
|
|
33
|
+
d.flags = surfaces[eid];
|
|
34
|
+
d._pad0 = 0u;
|
|
35
|
+
d._pad1 = 0u;
|
|
36
|
+
d._pad2 = 0u;
|
|
37
|
+
data[eid] = d;
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
export interface DataConfig {
|
|
42
|
+
colors: GPUBuffer;
|
|
43
|
+
pbr: GPUBuffer;
|
|
44
|
+
emission: GPUBuffer;
|
|
45
|
+
surfaces: GPUBuffer;
|
|
46
|
+
entityCount: GPUBuffer;
|
|
47
|
+
data: GPUBuffer;
|
|
48
|
+
getEntityCount: () => number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createDataNode(config: DataConfig): ComputeNode {
|
|
52
|
+
let pipeline: GPUComputePipeline | null = null;
|
|
53
|
+
let bindGroup: GPUBindGroup | null = null;
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
id: "data",
|
|
57
|
+
inputs: [],
|
|
58
|
+
outputs: [{ id: "data", access: "write" }],
|
|
59
|
+
|
|
60
|
+
async prepare(device: GPUDevice) {
|
|
61
|
+
const module = device.createShaderModule({ code: shader });
|
|
62
|
+
|
|
63
|
+
pipeline = await device.createComputePipelineAsync({
|
|
64
|
+
layout: "auto",
|
|
65
|
+
compute: { module, entryPoint: "main" },
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
bindGroup = device.createBindGroup({
|
|
69
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
70
|
+
entries: [
|
|
71
|
+
{ binding: 0, resource: { buffer: config.colors } },
|
|
72
|
+
{ binding: 1, resource: { buffer: config.pbr } },
|
|
73
|
+
{ binding: 2, resource: { buffer: config.emission } },
|
|
74
|
+
{ binding: 3, resource: { buffer: config.surfaces } },
|
|
75
|
+
{ binding: 4, resource: { buffer: config.entityCount } },
|
|
76
|
+
{ binding: 5, resource: { buffer: config.data } },
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
execute(ctx: ExecutionContext) {
|
|
82
|
+
if (!pipeline || !bindGroup) return;
|
|
83
|
+
|
|
84
|
+
const workgroups = Math.ceil(config.getEntityCount() / WORKGROUP_SIZE);
|
|
85
|
+
|
|
86
|
+
const pass = ctx.encoder.beginComputePass();
|
|
87
|
+
pass.setPipeline(pipeline);
|
|
88
|
+
pass.setBindGroup(0, bindGroup);
|
|
89
|
+
pass.dispatchWorkgroups(workgroups);
|
|
90
|
+
pass.end();
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type { ComputeNode, ExecutionContext } from "../compute";
|
|
2
|
+
import { SCENE_STRUCT_WGSL } from "./shaders";
|
|
3
|
+
|
|
4
|
+
const depthConvertShader = /* wgsl */ `
|
|
5
|
+
${SCENE_STRUCT_WGSL}
|
|
6
|
+
|
|
7
|
+
@group(0) @binding(0) var<uniform> scene: Scene;
|
|
8
|
+
@group(0) @binding(1) var linearDepthTex: texture_2d<f32>;
|
|
9
|
+
|
|
10
|
+
struct VertexOutput {
|
|
11
|
+
@builtin(position) position: vec4<f32>,
|
|
12
|
+
@location(0) uv: vec2<f32>,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@vertex
|
|
16
|
+
fn vs(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
|
|
17
|
+
var positions = array<vec2<f32>, 3>(
|
|
18
|
+
vec2(-1.0, -1.0),
|
|
19
|
+
vec2(3.0, -1.0),
|
|
20
|
+
vec2(-1.0, 3.0)
|
|
21
|
+
);
|
|
22
|
+
var output: VertexOutput;
|
|
23
|
+
output.position = vec4(positions[vertexIndex], 0.0, 1.0);
|
|
24
|
+
output.uv = (positions[vertexIndex] + 1.0) * 0.5;
|
|
25
|
+
output.uv.y = 1.0 - output.uv.y;
|
|
26
|
+
return output;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@fragment
|
|
30
|
+
fn fs(input: VertexOutput) -> @builtin(frag_depth) f32 {
|
|
31
|
+
let coords = vec2<i32>(input.position.xy);
|
|
32
|
+
let t = textureLoad(linearDepthTex, coords, 0).r;
|
|
33
|
+
|
|
34
|
+
let near = scene.near;
|
|
35
|
+
let far = scene.far;
|
|
36
|
+
|
|
37
|
+
if (t > far) {
|
|
38
|
+
return 1.0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
var ndcDepth: f32;
|
|
42
|
+
if (scene.cameraMode > 0.5) {
|
|
43
|
+
ndcDepth = (t - near) / (far - near);
|
|
44
|
+
} else {
|
|
45
|
+
ndcDepth = (far * (t - near)) / (t * (far - near));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return clamp(ndcDepth, 0.0, 1.0);
|
|
49
|
+
}
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
export interface DepthConvertConfig {
|
|
53
|
+
scene: GPUBuffer;
|
|
54
|
+
getRaytracing?: () => boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function createDepthConvertNode(config: DepthConvertConfig): ComputeNode {
|
|
58
|
+
let pipeline: GPURenderPipeline | null = null;
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
id: "depth-convert",
|
|
62
|
+
inputs: [{ id: "linear-depth", access: "read" }],
|
|
63
|
+
outputs: [{ id: "depth", access: "write" }],
|
|
64
|
+
|
|
65
|
+
async prepare(device: GPUDevice) {
|
|
66
|
+
const module = device.createShaderModule({ code: depthConvertShader });
|
|
67
|
+
pipeline = await device.createRenderPipelineAsync({
|
|
68
|
+
layout: "auto",
|
|
69
|
+
vertex: { module, entryPoint: "vs" },
|
|
70
|
+
fragment: { module, entryPoint: "fs", targets: [] },
|
|
71
|
+
depthStencil: {
|
|
72
|
+
format: "depth24plus",
|
|
73
|
+
depthWriteEnabled: true,
|
|
74
|
+
depthCompare: "always",
|
|
75
|
+
},
|
|
76
|
+
primitive: { topology: "triangle-list" },
|
|
77
|
+
});
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
execute(ctx: ExecutionContext) {
|
|
81
|
+
if (config.getRaytracing && !config.getRaytracing()) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const { device, encoder } = ctx;
|
|
86
|
+
|
|
87
|
+
const linearDepthView = ctx.getTextureView("linear-depth");
|
|
88
|
+
const depthView = ctx.getTextureView("depth");
|
|
89
|
+
|
|
90
|
+
if (!linearDepthView || !depthView) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const bindGroup = device.createBindGroup({
|
|
95
|
+
layout: pipeline!.getBindGroupLayout(0),
|
|
96
|
+
entries: [
|
|
97
|
+
{ binding: 0, resource: { buffer: config.scene } },
|
|
98
|
+
{ binding: 1, resource: linearDepthView },
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const pass = encoder.beginRenderPass({
|
|
103
|
+
colorAttachments: [],
|
|
104
|
+
depthStencilAttachment: {
|
|
105
|
+
view: depthView,
|
|
106
|
+
depthClearValue: 1.0,
|
|
107
|
+
depthLoadOp: "clear",
|
|
108
|
+
depthStoreOp: "store",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
pass.setPipeline(pipeline!);
|
|
112
|
+
pass.setBindGroup(0, bindGroup);
|
|
113
|
+
pass.draw(3);
|
|
114
|
+
pass.end();
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|