@multiplekex/shallot 0.2.3 → 0.2.5

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.
Files changed (42) hide show
  1. package/package.json +1 -1
  2. package/src/extras/arrows/index.ts +3 -3
  3. package/src/extras/caustic.ts +37 -0
  4. package/src/extras/gradient/index.ts +63 -69
  5. package/src/extras/index.ts +3 -0
  6. package/src/extras/lines/index.ts +3 -3
  7. package/src/extras/skylab/index.ts +314 -0
  8. package/src/extras/text/font.ts +69 -14
  9. package/src/extras/text/index.ts +15 -7
  10. package/src/extras/text/sdf.ts +13 -2
  11. package/src/extras/water.ts +64 -0
  12. package/src/standard/defaults.ts +2 -0
  13. package/src/standard/index.ts +2 -0
  14. package/src/standard/raster/index.ts +517 -0
  15. package/src/standard/{render → raytracing}/bvh/blas.ts +3 -3
  16. package/src/standard/{render → raytracing}/bvh/tlas.ts +3 -0
  17. package/src/standard/{render → raytracing}/depth.ts +9 -9
  18. package/src/standard/raytracing/index.ts +380 -0
  19. package/src/standard/{render → raytracing}/instance.ts +3 -0
  20. package/src/standard/raytracing/shaders.ts +815 -0
  21. package/src/standard/{render → raytracing}/triangle.ts +1 -1
  22. package/src/standard/render/camera.ts +88 -80
  23. package/src/standard/render/index.ts +68 -208
  24. package/src/standard/render/indirect.ts +9 -10
  25. package/src/standard/render/mesh/index.ts +35 -166
  26. package/src/standard/render/overlay.ts +4 -4
  27. package/src/standard/render/pass.ts +1 -1
  28. package/src/standard/render/postprocess.ts +75 -50
  29. package/src/standard/render/scene.ts +28 -16
  30. package/src/standard/render/surface/compile.ts +6 -8
  31. package/src/standard/render/surface/noise.ts +15 -2
  32. package/src/standard/render/surface/shaders.ts +257 -0
  33. package/src/standard/render/surface/structs.ts +13 -6
  34. package/src/standard/render/forward/index.ts +0 -259
  35. package/src/standard/render/forward/raster.ts +0 -228
  36. package/src/standard/render/shaders.ts +0 -484
  37. package/src/standard/render/surface/wgsl.ts +0 -573
  38. /package/src/standard/{render → raytracing}/bvh/radix.ts +0 -0
  39. /package/src/standard/{render → raytracing}/bvh/structs.ts +0 -0
  40. /package/src/standard/{render → raytracing}/bvh/traverse.ts +0 -0
  41. /package/src/standard/{render → raytracing}/intersection.ts +0 -0
  42. /package/src/standard/{render → raytracing}/ray.ts +0 -0
@@ -0,0 +1,517 @@
1
+ import type { Plugin, State, System } from "../../core";
2
+ import { resource } from "../../core";
3
+ import { Compute } from "../compute";
4
+ import type { ComputeNode, ExecutionContext } from "../compute";
5
+ import { WorldTransform } from "../transforms";
6
+ import { Camera, getClearColor, hasSkyComponent } from "../render/camera";
7
+ import {
8
+ Mesh,
9
+ collectBatches,
10
+ updateBatches,
11
+ MAX_BATCH_SLOTS,
12
+ type Batch,
13
+ type MeshBuffers,
14
+ type BatchEntities,
15
+ } from "../render/mesh";
16
+ import { Surface, SurfaceType, getDefaultAllSurfaces } from "../render/surface";
17
+ import type { SurfaceData } from "../render/surface";
18
+ import { SCENE_STRUCT_WGSL, SKY_STRUCT_WGSL, WGSL_STRUCTS } from "../render/surface/structs";
19
+ import {
20
+ compileVertexBody,
21
+ WGSL_LIGHTING_CALC,
22
+ SKY_WGSL,
23
+ SKY_DIR_WGSL,
24
+ NOISE_WGSL,
25
+ } from "../render/surface/shaders";
26
+ import { COLOR_FORMAT } from "../render/scene";
27
+ import { createIndirectBuffer, INDIRECT_SIZE } from "../render/indirect";
28
+ import { Render, RenderPlugin } from "../render";
29
+
30
+ export { createRasterPipeline, createSkyPipeline, executeRasterPass };
31
+ export type { RasterPassConfig };
32
+
33
+ interface RasterState {
34
+ indirect: GPUBuffer;
35
+ batches: (Batch | null)[];
36
+ batchEntities: BatchEntities;
37
+ buffers: Map<number, MeshBuffers>;
38
+ }
39
+
40
+ export const RasterResource = resource<RasterState>("raster");
41
+
42
+ const RasterUploadSystem: System = {
43
+ group: "draw",
44
+
45
+ update(state: State) {
46
+ const render = Render.from(state);
47
+ const raster = RasterResource.from(state);
48
+ const compute = Compute.from(state);
49
+ if (!render || !raster || !compute) return;
50
+
51
+ const { device } = compute;
52
+ const meshEntities = state.query([Mesh, WorldTransform]);
53
+
54
+ collectBatches(
55
+ meshEntities,
56
+ (eid) => Surface.type[eid] ?? SurfaceType.Default,
57
+ raster.batchEntities
58
+ );
59
+ updateBatches(device, raster.batchEntities, raster, raster.indirect);
60
+ },
61
+ };
62
+
63
+ function compileSurfaceVariant(id: number, data: SurfaceData): string {
64
+ const vertexBody = compileVertexBody(data.vertex);
65
+ const fragmentBody = data.fragment ?? "";
66
+ const lit = data.lit !== false;
67
+
68
+ return `
69
+ fn userVertexTransform_${id}(worldPos: vec3<f32>, normal: vec3<f32>, eid: u32) -> vec3<f32> {
70
+ ${vertexBody}
71
+ }
72
+
73
+ fn userFragment_${id}(surface: ptr<function, SurfaceData>, position: vec4<f32>) {
74
+ ${fragmentBody}
75
+ }
76
+
77
+ fn applyLighting_${id}(surface: SurfaceData) -> vec3<f32> {
78
+ ${
79
+ lit
80
+ ? `${WGSL_LIGHTING_CALC}
81
+ return surface.baseColor * lighting + surface.emission;`
82
+ : "return surface.baseColor;"
83
+ }
84
+ }
85
+ `;
86
+ }
87
+
88
+ function compileDispatchFunctions(surfaceCount: number): string {
89
+ const vertexCases = Array.from(
90
+ { length: surfaceCount },
91
+ (_, i) => ` case ${i}u: { return userVertexTransform_${i}(worldPos, normal, eid); }`
92
+ ).join("\n");
93
+
94
+ const fragmentCases = Array.from(
95
+ { length: surfaceCount },
96
+ (_, i) => ` case ${i}u: { userFragment_${i}(surface, position); }`
97
+ ).join("\n");
98
+
99
+ const lightingCases = Array.from(
100
+ { length: surfaceCount },
101
+ (_, i) => ` case ${i}u: { return applyLighting_${i}(surface); }`
102
+ ).join("\n");
103
+
104
+ return `
105
+ fn dispatchVertexTransform(surfaceId: u32, worldPos: vec3<f32>, normal: vec3<f32>, eid: u32) -> vec3<f32> {
106
+ switch surfaceId {
107
+ ${vertexCases}
108
+ default: { return userVertexTransform_0(worldPos, normal, eid); }
109
+ }
110
+ }
111
+
112
+ fn dispatchFragment(surfaceId: u32, surface: ptr<function, SurfaceData>, position: vec4<f32>) {
113
+ switch surfaceId {
114
+ ${fragmentCases}
115
+ default: { userFragment_0(surface, position); }
116
+ }
117
+ }
118
+
119
+ fn dispatchLighting(surfaceId: u32, surface: SurfaceData) -> vec3<f32> {
120
+ switch surfaceId {
121
+ ${lightingCases}
122
+ default: { return applyLighting_0(surface); }
123
+ }
124
+ }
125
+ `;
126
+ }
127
+
128
+ function compileRasterShader(surfaces: SurfaceData[]): string {
129
+ const surfaceVariants = surfaces.map((s, i) => compileSurfaceVariant(i, s)).join("\n");
130
+ const dispatchFunctions = compileDispatchFunctions(surfaces.length);
131
+
132
+ return /* wgsl */ `
133
+ ${WGSL_STRUCTS}
134
+ ${NOISE_WGSL}
135
+
136
+ ${surfaceVariants}
137
+ ${dispatchFunctions}
138
+
139
+ @vertex
140
+ fn vs(input: VertexInput) -> VertexOutput {
141
+ let eid = entityIds[input.instance];
142
+ let world = matrices[eid];
143
+ let scaledPos = input.position * sizes[eid].xyz;
144
+ let baseWorldPos = (world * vec4<f32>(scaledPos, 1.0)).xyz;
145
+ let worldNormal = normalize((world * vec4<f32>(input.normal, 0.0)).xyz);
146
+ let d = data[eid];
147
+ let surfaceId = d.flags & 0xFFu;
148
+ let finalWorldPos = dispatchVertexTransform(surfaceId, baseWorldPos, worldNormal, eid);
149
+
150
+ var output: VertexOutput;
151
+ output.position = scene.viewProj * vec4<f32>(finalWorldPos, 1.0);
152
+ output.color = d.baseColor;
153
+ output.worldNormal = worldNormal;
154
+ output.entityId = eid;
155
+ output.worldPos = finalWorldPos;
156
+ return output;
157
+ }
158
+
159
+ @fragment
160
+ fn fs(input: VertexOutput) -> FragmentOutput {
161
+ let eid = input.entityId;
162
+ let d = data[eid];
163
+ let surfaceId = d.flags & 0xFFu;
164
+
165
+ var surface: SurfaceData;
166
+ surface.baseColor = input.color.rgb;
167
+ surface.roughness = d.pbr.x;
168
+ surface.metallic = d.pbr.y;
169
+ surface.emission = d.emission.rgb * d.emission.a;
170
+ surface.normal = normalize(input.worldNormal);
171
+ surface.worldPos = input.worldPos;
172
+
173
+ dispatchFragment(surfaceId, &surface, input.position);
174
+
175
+ let litColor = dispatchLighting(surfaceId, surface);
176
+
177
+ var output: FragmentOutput;
178
+ output.color = vec4<f32>(litColor, input.color.a);
179
+ output.entityId = input.entityId;
180
+ return output;
181
+ }
182
+ `;
183
+ }
184
+
185
+ async function createRasterPipeline(
186
+ device: GPUDevice,
187
+ surfaces: SurfaceData[],
188
+ colorFormat: GPUTextureFormat
189
+ ): Promise<GPURenderPipeline> {
190
+ const code = compileRasterShader(surfaces);
191
+ const module = device.createShaderModule({ code });
192
+
193
+ return device.createRenderPipelineAsync({
194
+ layout: "auto",
195
+ vertex: {
196
+ module,
197
+ entryPoint: "vs",
198
+ buffers: [
199
+ {
200
+ arrayStride: 24,
201
+ attributes: [
202
+ { shaderLocation: 0, offset: 0, format: "float32x3" },
203
+ { shaderLocation: 1, offset: 12, format: "float32x3" },
204
+ ],
205
+ },
206
+ ],
207
+ },
208
+ fragment: {
209
+ module,
210
+ entryPoint: "fs",
211
+ targets: [{ format: colorFormat }, { format: "r32uint" }],
212
+ },
213
+ depthStencil: {
214
+ format: "depth24plus",
215
+ depthWriteEnabled: true,
216
+ depthCompare: "less",
217
+ },
218
+ primitive: {
219
+ topology: "triangle-list",
220
+ cullMode: "back",
221
+ },
222
+ });
223
+ }
224
+
225
+ function compileSkyShader(): string {
226
+ return /* wgsl */ `
227
+ ${SCENE_STRUCT_WGSL}
228
+ ${SKY_STRUCT_WGSL}
229
+
230
+ @group(0) @binding(0) var<uniform> scene: Scene;
231
+ @group(0) @binding(1) var<uniform> sky: Sky;
232
+
233
+ ${SKY_DIR_WGSL}
234
+ ${NOISE_WGSL}
235
+ ${SKY_WGSL}
236
+
237
+ struct VertexOutput {
238
+ @builtin(position) position: vec4<f32>,
239
+ @location(0) uv: vec2<f32>,
240
+ }
241
+
242
+ @vertex
243
+ fn vs(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
244
+ var positions = array<vec2<f32>, 3>(
245
+ vec2(-1.0, -1.0),
246
+ vec2(3.0, -1.0),
247
+ vec2(-1.0, 3.0)
248
+ );
249
+ var output: VertexOutput;
250
+ output.position = vec4(positions[vertexIndex], 0.0, 1.0);
251
+ output.uv = (positions[vertexIndex] + 1.0) * 0.5;
252
+ output.uv.y = 1.0 - output.uv.y;
253
+ return output;
254
+ }
255
+
256
+ @fragment
257
+ fn fs(input: VertexOutput) -> @location(0) vec4<f32> {
258
+ let dir = computeSkyDir(input.uv.x, input.uv.y);
259
+ let color = sampleSky(dir);
260
+ return vec4(color, 1.0);
261
+ }
262
+ `;
263
+ }
264
+
265
+ async function createSkyPipeline(
266
+ device: GPUDevice,
267
+ colorFormat: GPUTextureFormat
268
+ ): Promise<GPURenderPipeline> {
269
+ const code = compileSkyShader();
270
+ const module = device.createShaderModule({ code });
271
+
272
+ return device.createRenderPipelineAsync({
273
+ layout: "auto",
274
+ vertex: { module, entryPoint: "vs" },
275
+ fragment: {
276
+ module,
277
+ entryPoint: "fs",
278
+ targets: [{ format: colorFormat }],
279
+ },
280
+ depthStencil: {
281
+ format: "depth24plus",
282
+ depthWriteEnabled: false,
283
+ depthCompare: "always",
284
+ },
285
+ primitive: { topology: "triangle-list" },
286
+ });
287
+ }
288
+
289
+ interface RasterPassConfig {
290
+ scene: GPUBuffer;
291
+ sky: GPUBuffer;
292
+ data: GPUBuffer;
293
+ matrices: GPUBuffer;
294
+ sizes: GPUBuffer;
295
+ indirect: GPUBuffer;
296
+ rasterPipeline: GPURenderPipeline;
297
+ skyPipeline: GPURenderPipeline | null;
298
+ getClearColor: () => { r: number; g: number; b: number };
299
+ getSky: () => boolean;
300
+ batches: () => (Batch | null)[];
301
+ skyBindGroup?: GPUBindGroup | null;
302
+ batchBindGroups?: GPUBindGroup[];
303
+ }
304
+
305
+ function executeRasterPass(ctx: ExecutionContext, config: RasterPassConfig): void {
306
+ const { device, encoder } = ctx;
307
+
308
+ const colorView = ctx.getTextureView("color");
309
+ const eidView = ctx.getTextureView("eid");
310
+ const zView = ctx.getTextureView("z");
311
+
312
+ if (!colorView || !eidView || !zView) {
313
+ return;
314
+ }
315
+
316
+ const batches = config.batches();
317
+ const colorTexture = ctx.getTexture("color");
318
+ if (!colorTexture) return;
319
+
320
+ const clearColor = config.getClearColor();
321
+ const hasSky = config.getSky() && config.skyPipeline;
322
+
323
+ if (hasSky) {
324
+ const skyPass = encoder.beginRenderPass({
325
+ colorAttachments: [
326
+ {
327
+ view: colorView as GPUTextureView,
328
+ clearValue: { r: clearColor.r, g: clearColor.g, b: clearColor.b, a: 1 },
329
+ loadOp: "clear" as const,
330
+ storeOp: "store" as const,
331
+ },
332
+ ],
333
+ depthStencilAttachment: {
334
+ view: zView as GPUTextureView,
335
+ depthClearValue: 1.0,
336
+ depthLoadOp: "clear" as const,
337
+ depthStoreOp: "store" as const,
338
+ },
339
+ });
340
+
341
+ if (!config.skyBindGroup) {
342
+ config.skyBindGroup = device.createBindGroup({
343
+ layout: config.skyPipeline!.getBindGroupLayout(0),
344
+ entries: [
345
+ { binding: 0, resource: { buffer: config.scene } },
346
+ { binding: 1, resource: { buffer: config.sky } },
347
+ ],
348
+ });
349
+ }
350
+
351
+ skyPass.setPipeline(config.skyPipeline!);
352
+ skyPass.setBindGroup(0, config.skyBindGroup);
353
+ skyPass.draw(3);
354
+ skyPass.end();
355
+ }
356
+
357
+ const pass = encoder.beginRenderPass({
358
+ colorAttachments: [
359
+ {
360
+ view: colorView as GPUTextureView,
361
+ clearValue: { r: clearColor.r, g: clearColor.g, b: clearColor.b, a: 1 },
362
+ loadOp: hasSky ? ("load" as const) : ("clear" as const),
363
+ storeOp: "store" as const,
364
+ },
365
+ {
366
+ view: eidView as GPUTextureView,
367
+ clearValue: { r: 0, g: 0, b: 0, a: 0 },
368
+ loadOp: "clear" as const,
369
+ storeOp: "store" as const,
370
+ },
371
+ ],
372
+ depthStencilAttachment: {
373
+ view: zView as GPUTextureView,
374
+ depthClearValue: 1.0,
375
+ depthLoadOp: hasSky ? ("load" as const) : ("clear" as const),
376
+ depthStoreOp: "store" as const,
377
+ },
378
+ });
379
+
380
+ pass.setPipeline(config.rasterPipeline);
381
+
382
+ if (!config.batchBindGroups) {
383
+ config.batchBindGroups = [];
384
+ }
385
+
386
+ for (let i = 0; i < batches.length; i++) {
387
+ const batch = batches[i];
388
+ if (!batch || batch.count === 0) continue;
389
+
390
+ if (!config.batchBindGroups[i]) {
391
+ config.batchBindGroups[i] = device.createBindGroup({
392
+ layout: config.rasterPipeline.getBindGroupLayout(0),
393
+ entries: [
394
+ { binding: 0, resource: { buffer: config.scene } },
395
+ { binding: 1, resource: { buffer: batch.entityIds } },
396
+ { binding: 2, resource: { buffer: config.matrices } },
397
+ { binding: 3, resource: { buffer: config.sizes } },
398
+ { binding: 4, resource: { buffer: config.data } },
399
+ ],
400
+ });
401
+ }
402
+
403
+ pass.setBindGroup(0, config.batchBindGroups[i]);
404
+ pass.setVertexBuffer(0, batch.buffers.vertex);
405
+ pass.setIndexBuffer(batch.buffers.index, "uint16");
406
+ pass.drawIndexedIndirect(config.indirect, i * INDIRECT_SIZE);
407
+ }
408
+
409
+ pass.end();
410
+ }
411
+
412
+ interface RasterForwardConfig {
413
+ scene: GPUBuffer;
414
+ sky: GPUBuffer;
415
+ data: GPUBuffer;
416
+ indirect: GPUBuffer;
417
+ matrices: GPUBuffer;
418
+ sizes: GPUBuffer;
419
+ getSurfaces: () => SurfaceData[];
420
+ getClearColor: () => { r: number; g: number; b: number };
421
+ getSky: () => boolean;
422
+ batches: () => (Batch | null)[];
423
+ }
424
+
425
+ function createRasterForwardNode(config: RasterForwardConfig): ComputeNode {
426
+ let rasterPipeline: GPURenderPipeline | null = null;
427
+ let skyPipeline: GPURenderPipeline | null = null;
428
+ let skyBindGroup: GPUBindGroup | null = null;
429
+ let batchBindGroups: GPUBindGroup[] = [];
430
+
431
+ return {
432
+ id: "forward",
433
+ inputs: [{ id: "data", access: "read" }],
434
+ outputs: [
435
+ { id: "color", access: "write" },
436
+ { id: "eid", access: "write" },
437
+ ],
438
+
439
+ async prepare(device: GPUDevice) {
440
+ const surfaces = config.getSurfaces();
441
+ rasterPipeline = await createRasterPipeline(device, surfaces, COLOR_FORMAT);
442
+ skyPipeline = await createSkyPipeline(device, COLOR_FORMAT);
443
+ },
444
+
445
+ execute(ctx: ExecutionContext) {
446
+ if (!rasterPipeline) return;
447
+ const passConfig: RasterPassConfig = {
448
+ scene: config.scene,
449
+ sky: config.sky,
450
+ data: config.data,
451
+ matrices: config.matrices,
452
+ sizes: config.sizes,
453
+ indirect: config.indirect,
454
+ rasterPipeline,
455
+ skyPipeline,
456
+ getClearColor: config.getClearColor,
457
+ getSky: config.getSky,
458
+ batches: config.batches,
459
+ skyBindGroup,
460
+ batchBindGroups,
461
+ };
462
+ executeRasterPass(ctx, passConfig);
463
+ skyBindGroup = passConfig.skyBindGroup ?? null;
464
+ batchBindGroups = passConfig.batchBindGroups ?? [];
465
+ },
466
+ };
467
+ }
468
+
469
+ export const RasterPlugin: Plugin = {
470
+ systems: [RasterUploadSystem],
471
+ dependencies: [RenderPlugin],
472
+
473
+ async initialize(state: State) {
474
+ const compute = Compute.from(state);
475
+ const render = Render.from(state);
476
+ if (!compute || !render) return;
477
+
478
+ const { device } = compute;
479
+
480
+ const rasterState: RasterState = {
481
+ indirect: createIndirectBuffer(device, MAX_BATCH_SLOTS),
482
+ batches: Array(MAX_BATCH_SLOTS).fill(null),
483
+ batchEntities: Array(MAX_BATCH_SLOTS).fill(null),
484
+ buffers: new Map(),
485
+ };
486
+
487
+ state.setResource(RasterResource, rasterState);
488
+
489
+ const getActiveClearColor = () => {
490
+ for (const eid of state.query([Camera])) {
491
+ if (Camera.active[eid]) return getClearColor(eid);
492
+ }
493
+ return { r: 0, g: 0, b: 0 };
494
+ };
495
+
496
+ const getSky = () => {
497
+ for (const eid of state.query([Camera])) {
498
+ if (Camera.active[eid]) return hasSkyComponent(state, eid);
499
+ }
500
+ return false;
501
+ };
502
+
503
+ const forwardNode = createRasterForwardNode({
504
+ scene: render.scene,
505
+ sky: render.sky,
506
+ data: render.data,
507
+ indirect: rasterState.indirect,
508
+ matrices: render.matrices,
509
+ sizes: render.sizes,
510
+ getSurfaces: getDefaultAllSurfaces,
511
+ getClearColor: getActiveClearColor,
512
+ getSky,
513
+ batches: () => rasterState.batches,
514
+ });
515
+ compute.graph.add(forwardNode);
516
+ },
517
+ };
@@ -1,6 +1,6 @@
1
1
  import type { Vec3, BVHNode, MortonPair, AABB } from "./structs";
2
2
  import { LEAF_FLAG, isLeaf, leafIndex } from "./structs";
3
- import type { MeshData } from "../mesh";
3
+ import type { MeshData } from "../../render/mesh";
4
4
 
5
5
  export interface BLASTriangle {
6
6
  v0: Vec3;
@@ -503,7 +503,7 @@ export function buildShapeBLAS(triangles: BLASTriangle[]): BLASData {
503
503
  };
504
504
  }
505
505
 
506
- export function validateBLASBounds(blas: BLASData, triangles: BLASTriangle[]): boolean {
506
+ function validateBLASBounds(blas: BLASData, triangles: BLASTriangle[]): boolean {
507
507
  if (blas.triCount === 0) return true;
508
508
 
509
509
  const epsilon = 1e-5;
@@ -530,7 +530,7 @@ export function validateBLASBounds(blas: BLASData, triangles: BLASTriangle[]): b
530
530
  return true;
531
531
  }
532
532
 
533
- export function validateBLASNodes(blas: BLASData): { valid: boolean; errors: string[] } {
533
+ function validateBLASNodes(blas: BLASData): { valid: boolean; errors: string[] } {
534
534
  const errors: string[] = [];
535
535
 
536
536
  if (blas.triCount <= 1) {
@@ -721,6 +721,7 @@ export interface TLASConfig {
721
721
  instanceCount: GPUBuffer;
722
722
  tlas: TLASBuffers;
723
723
  getEntityCount: () => number;
724
+ getRaytracing?: () => boolean;
724
725
  }
725
726
 
726
727
  export function createTLASNode(config: TLASConfig): ComputeNode {
@@ -836,6 +837,8 @@ export function createTLASNode(config: TLASConfig): ComputeNode {
836
837
  },
837
838
 
838
839
  execute(ctx: ExecutionContext) {
840
+ if (config.getRaytracing && !config.getRaytracing()) return;
841
+
839
842
  const { device, encoder } = ctx;
840
843
 
841
844
  const workgroups = Math.ceil(MAX_ENTITIES / WORKGROUP_SIZE);
@@ -1,11 +1,11 @@
1
1
  import type { ComputeNode, ExecutionContext } from "../compute";
2
- import { SCENE_STRUCT_WGSL } from "./shaders";
2
+ import { SCENE_STRUCT_WGSL } from "../render/surface/structs";
3
3
 
4
4
  const depthConvertShader = /* wgsl */ `
5
5
  ${SCENE_STRUCT_WGSL}
6
6
 
7
7
  @group(0) @binding(0) var<uniform> scene: Scene;
8
- @group(0) @binding(1) var linearDepthTex: texture_2d<f32>;
8
+ @group(0) @binding(1) var depthTex: texture_2d<f32>;
9
9
 
10
10
  struct VertexOutput {
11
11
  @builtin(position) position: vec4<f32>,
@@ -29,7 +29,7 @@ fn vs(@builtin(vertex_index) vertexIndex: u32) -> VertexOutput {
29
29
  @fragment
30
30
  fn fs(input: VertexOutput) -> @builtin(frag_depth) f32 {
31
31
  let coords = vec2<i32>(input.position.xy);
32
- let t = textureLoad(linearDepthTex, coords, 0).r;
32
+ let t = textureLoad(depthTex, coords, 0).r;
33
33
 
34
34
  let near = scene.near;
35
35
  let far = scene.far;
@@ -59,8 +59,8 @@ export function createDepthConvertNode(config: DepthConvertConfig): ComputeNode
59
59
 
60
60
  return {
61
61
  id: "depth-convert",
62
- inputs: [{ id: "linear-depth", access: "read" }],
63
- outputs: [{ id: "depth", access: "write" }],
62
+ inputs: [{ id: "depth", access: "read" }],
63
+ outputs: [{ id: "z", access: "write" }],
64
64
 
65
65
  async prepare(device: GPUDevice) {
66
66
  const module = device.createShaderModule({ code: depthConvertShader });
@@ -84,10 +84,10 @@ export function createDepthConvertNode(config: DepthConvertConfig): ComputeNode
84
84
 
85
85
  const { device, encoder } = ctx;
86
86
 
87
- const linearDepthView = ctx.getTextureView("linear-depth");
88
87
  const depthView = ctx.getTextureView("depth");
88
+ const zView = ctx.getTextureView("z");
89
89
 
90
- if (!linearDepthView || !depthView) {
90
+ if (!depthView || !zView) {
91
91
  return;
92
92
  }
93
93
 
@@ -95,14 +95,14 @@ export function createDepthConvertNode(config: DepthConvertConfig): ComputeNode
95
95
  layout: pipeline!.getBindGroupLayout(0),
96
96
  entries: [
97
97
  { binding: 0, resource: { buffer: config.scene } },
98
- { binding: 1, resource: linearDepthView },
98
+ { binding: 1, resource: depthView },
99
99
  ],
100
100
  });
101
101
 
102
102
  const pass = encoder.beginRenderPass({
103
103
  colorAttachments: [],
104
104
  depthStencilAttachment: {
105
- view: depthView,
105
+ view: zView,
106
106
  depthClearValue: 1.0,
107
107
  depthLoadOp: "clear",
108
108
  depthStoreOp: "store",