@tinypoly/gpu-renderer 0.0.3 → 0.0.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 (81) hide show
  1. package/ARCHITECTURE.md +22 -7
  2. package/README.md +1 -1
  3. package/dist/bvh.d.ts +11 -6
  4. package/dist/bvh.d.ts.map +1 -1
  5. package/dist/bvh.js +64 -11
  6. package/dist/bvh.js.map +1 -1
  7. package/dist/denoise.d.ts +7 -2
  8. package/dist/denoise.d.ts.map +1 -1
  9. package/dist/denoise.js +61 -21
  10. package/dist/denoise.js.map +1 -1
  11. package/dist/dispatchScheduler.d.ts +11 -4
  12. package/dist/dispatchScheduler.d.ts.map +1 -1
  13. package/dist/dispatchScheduler.js +14 -7
  14. package/dist/dispatchScheduler.js.map +1 -1
  15. package/dist/frameLayout.d.ts.map +1 -1
  16. package/dist/frameLayout.js +3 -0
  17. package/dist/frameLayout.js.map +1 -1
  18. package/dist/imageResolve.d.ts +26 -0
  19. package/dist/imageResolve.d.ts.map +1 -0
  20. package/dist/imageResolve.js +114 -0
  21. package/dist/imageResolve.js.map +1 -0
  22. package/dist/lights.d.ts +9 -1
  23. package/dist/lights.d.ts.map +1 -1
  24. package/dist/lights.js +9 -0
  25. package/dist/lights.js.map +1 -1
  26. package/dist/renderer.d.ts +1 -0
  27. package/dist/renderer.d.ts.map +1 -1
  28. package/dist/renderer.js +97 -62
  29. package/dist/renderer.js.map +1 -1
  30. package/dist/sceneUpload.d.ts +14 -1
  31. package/dist/sceneUpload.d.ts.map +1 -1
  32. package/dist/sceneUpload.js +21 -3
  33. package/dist/sceneUpload.js.map +1 -1
  34. package/dist/texturePack.d.ts +16 -4
  35. package/dist/texturePack.d.ts.map +1 -1
  36. package/dist/texturePack.js +61 -8
  37. package/dist/texturePack.js.map +1 -1
  38. package/dist/wgsl/bvh.wgsl.d.ts +8 -2
  39. package/dist/wgsl/bvh.wgsl.d.ts.map +1 -1
  40. package/dist/wgsl/bvh.wgsl.js +167 -96
  41. package/dist/wgsl/bvh.wgsl.js.map +1 -1
  42. package/dist/wgsl/common.wgsl.d.ts.map +1 -1
  43. package/dist/wgsl/common.wgsl.js +20 -7
  44. package/dist/wgsl/common.wgsl.js.map +1 -1
  45. package/dist/wgsl/lights.wgsl.d.ts +1 -1
  46. package/dist/wgsl/lights.wgsl.d.ts.map +1 -1
  47. package/dist/wgsl/lights.wgsl.js +3 -2
  48. package/dist/wgsl/lights.wgsl.js.map +1 -1
  49. package/dist/wgsl/pathTrace.wgsl.d.ts +1 -1
  50. package/dist/wgsl/pathTrace.wgsl.d.ts.map +1 -1
  51. package/dist/wgsl/pathTrace.wgsl.js +15 -1
  52. package/dist/wgsl/pathTrace.wgsl.js.map +1 -1
  53. package/dist/wgsl/random.wgsl.d.ts +1 -1
  54. package/dist/wgsl/random.wgsl.d.ts.map +1 -1
  55. package/dist/wgsl/random.wgsl.js +9 -17
  56. package/dist/wgsl/random.wgsl.js.map +1 -1
  57. package/dist/wgsl/surface.wgsl.d.ts +1 -1
  58. package/dist/wgsl/surface.wgsl.d.ts.map +1 -1
  59. package/dist/wgsl/surface.wgsl.js +26 -3
  60. package/dist/wgsl/surface.wgsl.js.map +1 -1
  61. package/dist/wgsl/texture.wgsl.d.ts +1 -1
  62. package/dist/wgsl/texture.wgsl.d.ts.map +1 -1
  63. package/dist/wgsl/texture.wgsl.js +10 -11
  64. package/dist/wgsl/texture.wgsl.js.map +1 -1
  65. package/package.json +1 -1
  66. package/src/bvh.ts +81 -12
  67. package/src/denoise.ts +66 -21
  68. package/src/dispatchScheduler.ts +16 -7
  69. package/src/frameLayout.ts +3 -0
  70. package/src/imageResolve.ts +136 -0
  71. package/src/lights.ts +19 -1
  72. package/src/renderer.ts +123 -77
  73. package/src/sceneUpload.ts +32 -4
  74. package/src/texturePack.ts +80 -13
  75. package/src/wgsl/bvh.wgsl.ts +167 -96
  76. package/src/wgsl/common.wgsl.ts +20 -7
  77. package/src/wgsl/lights.wgsl.ts +3 -2
  78. package/src/wgsl/pathTrace.wgsl.ts +15 -1
  79. package/src/wgsl/random.wgsl.ts +9 -17
  80. package/src/wgsl/surface.wgsl.ts +26 -3
  81. package/src/wgsl/texture.wgsl.ts +10 -11
@@ -1 +1 @@
1
- {"version":3,"file":"sceneUpload.js","sourceRoot":"","sources":["../src/sceneUpload.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAqB,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAuB,MAAM,kBAAkB,CAAC;AAsDjF;;;GAGG;AACH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,cAAc,GAAG,CAAC,CAAC,CAAC;AAEjD,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AAE1D,MAAM,cAAc,GAAG,CAAC,QAAwB,EAAE,EAAE,CAClD,QAAQ,CAAC,OAAO,CAAC,UAAU,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,UAAU,IAAI,CAAC,CAAC;MACxF,CAAC,QAAQ,CAAC,QAAQ,EAAE,UAAU,IAAI,CAAC,CAAC,CAAC;AAEzC,MAAM,UAAU,eAAe,CAC7B,QAAwB,EACxB,GAAc,EACd,SAAuB,UAAU,CAAC,QAAQ,CAAC,EAC3C,WAAyC,EAAE,IAAI,EAAE,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE;IACrE,MAAM,OAAO,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,CAAC;QAC/C,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC3C,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,GAAG,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC;QACpE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,cAAc,GAAG,CAAC,CAAC;QAC1E,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC;QAClC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;QACxC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC;KAC1C,CAAC;IAEF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAEtC,OAAO;QACL,GAAG,OAAO;QACV,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC;QACpD,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;KAC7B,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,aAAa,CAAC,QAAwB;IACpD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,WAAW,CAAC,KAAK,GAAG,cAAc,GAAG,CAAC,CAAC,CAAC;IAE3D,wFAAwF;IACxF,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAAC;IAEnG,GAAG,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,CAAC,kBAAkB,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAEnH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,gBAAgB,CAAC,WAAqC;IACpE,OAAO,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3G,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,MAAiB,EACjB,QAAwB,EACxB,GAAc,EACd,WAA2B,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,EACjF,SAAuB,UAAU,CAAC,QAAQ,CAAC,EAC3C,cAAwC,IAAI,EAC5C,cAAc,GAAG,QAAQ,CAAC,WAAW;IACrC,MAAM,OAAO,GAAG,eAAe,CAAC,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAEjE,MAAM,MAAM,GAAG,CAAC,IAAY,EAAa,EAAE,CACzC,MAAM,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,cAAc,CAAC,OAAO,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC;IAEzF,MAAM,KAAK,GAAG,CAAC,IAAqB,EAAE,IAAY,EAAa,EAAE;QAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAE5B,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QAE1C,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,2FAA2F;IAC3F,MAAM,IAAI,GAAG,CAAC,KAAwB,EAAE,IAAY,EAAa,EAAE;QACjE,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,MAAM,GAAG,CAAC,CAAC;QAEf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,CAAC,UAAU;gBAAE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;YAEpE,MAAM,IAAI,IAAI,CAAC,UAAU,CAAC;QAC5B,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;IAE1D,MAAM,OAAO,GAAG;QACd,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC;QACvD,UAAU,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;QACxF,OAAO,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;QAC/D,SAAS,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;QAC5E,KAAK,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC;QACtD,MAAM,EAAE,KAAK,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC;QAC7D,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC;KACjD,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,OAAO;QACd,GAAG,OAAO;QACV,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM;QACjC,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM;QAC1D,aAAa,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM;QAC5E,SAAS,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC;QAC5B,WAAW,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM;QACtC,aAAa,EAAE,QAAQ,CAAC,aAAa;QACrC,UAAU,EAAE,MAAM,CAAC,KAAK;QACxB,cAAc,EAAE,MAAM,CAAC,SAAS;QAChC,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,WAAW,EAAE;YACX,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,CAAC,CAAC,UAAU;YAC9F,GAAG,EAAE,cAAc;YACnB,KAAK,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;YAC9B,MAAM,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;YAChC,KAAK,EAAE,WAAW,EAAE,KAAK,IAAI,CAAC;YAC9B,IAAI,EAAE,MAAM,CAAC,eAAe;SAC7B;QACD,OAAO;YACL,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;gBAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QAChE,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sceneUpload.js","sourceRoot":"","sources":["../src/sceneUpload.ts"],"names":[],"mappings":"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"}
@@ -9,10 +9,10 @@ import type { SerializedScene, SerializedTexture } from "./upstream.js";
9
9
  */
10
10
  export interface PackedTextures {
11
11
  /**
12
- * One buffer for all of it: `TEXTURE_WORDS` words per texture first, as `TextureInfo` in `wgsl/common.wgsl.ts`, then
13
- * the texels each entry points at. A byte texture takes one word per texel, RGBA in the low to high bytes; a float
14
- * texture takes four, each the bits of one linear channel. Keeping the two in one binding is what holds the shader
15
- * inside the eight storage buffers a WebGPU device has to offer.
12
+ * One buffer for all of it: the lookup tables first (see `TEXTURE_TABLE`), then `TEXTURE_WORDS` words per texture, as
13
+ * `TextureInfo` in `wgsl/common.wgsl.ts`, then the texels each entry points at. A byte texture takes one word per
14
+ * texel, RGBA in the low to high bytes; a float texture takes four, each the bits of one linear channel. Keeping them
15
+ * in one binding is what holds the shader inside the eight storage buffers a WebGPU device has to offer.
16
16
  */
17
17
  data: Uint32Array;
18
18
  count: number;
@@ -28,6 +28,17 @@ export interface TextureExtras {
28
28
  }
29
29
  /** Sixteen words per entry: see `TextureInfo` in `wgsl/common.wgsl.ts`. */
30
30
  export declare const TEXTURE_WORDS = 16;
31
+ /**
32
+ * Lookup tables that lead the buffer, at offsets the shader knows as constants: the second Sobol dimension one byte of
33
+ * the index at a time (four tables of 256), then the linear value of each of the 256 sRGB codes. Both replace work the
34
+ * kernel did on every read with the very numbers it computed, so nothing they feed changes.
35
+ */
36
+ export declare const SOBOL_TABLE = 0;
37
+ export declare const SRGB_TABLE: number;
38
+ /** Where the texture table starts, after the lookup tables. */
39
+ export declare const TEXTURE_TABLE: number;
40
+ /** Where a texture's entry starts in the buffer. */
41
+ export declare const textureEntry: (index: number) => number;
31
42
  /** What a material's map index means when the material has no such map. */
32
43
  export declare const NO_TEXTURE = 4294967295;
33
44
  /** Three's own wrap constants, which the shader compares against. */
@@ -42,6 +53,7 @@ export declare const UV_CHANNELS = 2;
42
53
  export interface TexturePlan {
43
54
  textures: SerializedTexture[];
44
55
  indexOf: Map<string, number>;
56
+ /** The lookup tables and the texture table together: where the texels begin. */
45
57
  tableWords: number;
46
58
  /** Where the words appended after the texels begin. */
47
59
  extraOffset: number;
@@ -1 +1 @@
1
- {"version":3,"file":"texturePack.d.ts","sourceRoot":"","sources":["../src/texturePack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAExE;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,wGAAwG;IACxG,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oHAAoH;AACpH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACxC,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,2EAA2E;AAC3E,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC,2EAA2E;AAC3E,eAAO,MAAM,UAAU,aAAa,CAAC;AASrC,qEAAqE;AACrE,QAAA,MAAM,MAAM,OAAO,CAAC;AACpB,QAAA,MAAM,eAAe,OAAO,CAAC;AAE7B,+FAA+F;AAC/F,eAAO,MAAM,WAAW,IAAI,CAAC;AAY7B;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,aAAa,GAAE,SAAS,iBAAiB,EAAO,GAAG,WAAW,CAalH;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,GAAE,aAAkB,GAAG,cAAc,CAE/F;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,GAAG,cAAc,CAwDxF;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"texturePack.d.ts","sourceRoot":"","sources":["../src/texturePack.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAExE;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;OAKG;IACH,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,wFAAwF;IACxF,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,wGAAwG;IACxG,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oHAAoH;AACpH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACxC,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,2EAA2E;AAC3E,eAAO,MAAM,aAAa,KAAK,CAAC;AAEhC;;;;GAIG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC;AAC7B,eAAO,MAAM,UAAU,QAAwB,CAAC;AAChD,+DAA+D;AAC/D,eAAO,MAAM,aAAa,QAAmB,CAAC;AA6C9C,oDAAoD;AACpD,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,WAA0C,CAAC;AAErF,2EAA2E;AAC3E,eAAO,MAAM,UAAU,aAAa,CAAC;AASrC,qEAAqE;AACrE,QAAA,MAAM,MAAM,OAAO,CAAC;AACpB,QAAA,MAAM,eAAe,OAAO,CAAC;AAE7B,+FAA+F;AAC/F,eAAO,MAAM,WAAW,IAAI,CAAC;AAe7B;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,aAAa,GAAE,SAAS,iBAAiB,EAAO,GAAG,WAAW,CAalH;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,GAAE,aAAkB,GAAG,cAAc,CAE/F;AAED,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,GAAG,cAAc,CA+DxF;AAED,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC"}
@@ -1,5 +1,49 @@
1
1
  /** Sixteen words per entry: see `TextureInfo` in `wgsl/common.wgsl.ts`. */
2
2
  export const TEXTURE_WORDS = 16;
3
+ /**
4
+ * Lookup tables that lead the buffer, at offsets the shader knows as constants: the second Sobol dimension one byte of
5
+ * the index at a time (four tables of 256), then the linear value of each of the 256 sRGB codes. Both replace work the
6
+ * kernel did on every read with the very numbers it computed, so nothing they feed changes.
7
+ */
8
+ export const SOBOL_TABLE = 0;
9
+ export const SRGB_TABLE = SOBOL_TABLE + 4 * 256;
10
+ /** Where the texture table starts, after the lookup tables. */
11
+ export const TEXTURE_TABLE = SRGB_TABLE + 256;
12
+ /** The four byte tables of the Sobol sequence's second dimension, whose generator matrix is Pascal's triangle mod 2. */
13
+ function sobolTables() {
14
+ const directions = [];
15
+ let direction = 0x80000000;
16
+ for (let bit = 0; bit < 32; bit++) {
17
+ directions.push(direction >>> 0);
18
+ direction = (direction ^ (direction >>> 1)) >>> 0;
19
+ }
20
+ const tables = new Uint32Array(4 * 256);
21
+ for (let byte = 0; byte < 4; byte++) {
22
+ for (let value = 0; value < 256; value++) {
23
+ let xor = 0;
24
+ for (let bit = 0; bit < 8; bit++)
25
+ if (value & (1 << bit))
26
+ xor ^= directions[byte * 8 + bit];
27
+ tables[byte * 256 + value] = xor >>> 0;
28
+ }
29
+ }
30
+ return tables;
31
+ }
32
+ /** The linear value of every sRGB code, worked out in double precision and rounded once. */
33
+ function srgbTable() {
34
+ return Float32Array.from({ length: 256 }, (_, code) => {
35
+ const value = Math.fround(code / 255);
36
+ return value <= 0.04045 ? value / 12.92 : ((value + 0.055) / 1.055) ** 2.4;
37
+ });
38
+ }
39
+ const LOOKUP = (() => {
40
+ const words = new Uint32Array(TEXTURE_TABLE);
41
+ words.set(sobolTables(), SOBOL_TABLE);
42
+ words.set(new Uint32Array(srgbTable().buffer), SRGB_TABLE);
43
+ return words;
44
+ })();
45
+ /** Where a texture's entry starts in the buffer. */
46
+ export const textureEntry = (index) => TEXTURE_TABLE + index * TEXTURE_WORDS;
3
47
  /** What a material's map index means when the material has no such map. */
4
48
  export const NO_TEXTURE = 0xffffffff;
5
49
  const TEXTURE_FLOAT = 1;
@@ -13,6 +57,8 @@ const REPEAT = 1000;
13
57
  const MIRRORED_REPEAT = 1002;
14
58
  /** How many UV sets the geometry carries, and so the highest channel a texture may ask for. */
15
59
  export const UV_CHANNELS = 2;
60
+ /** Whether a word's first byte is its lowest, as it is on the device: then RGBA bytes are already RGBA words. */
61
+ const LITTLE_ENDIAN = new Uint8Array(new Uint32Array([1]).buffer)[0] === 1;
16
62
  const texelCount = (texture) => Math.max(0, texture.width) * Math.max(0, texture.height);
17
63
  const isFloat = (texture) => texture.data instanceof Float32Array;
18
64
  /**
@@ -27,7 +73,7 @@ export function planTextures(scene, extraTextures = []) {
27
73
  .filter(texture => texelCount(texture) > 0 && texture.data.length >= texelCount(texture) * 4)
28
74
  .filter(texture => !seen.has(texture.id) && !!seen.add(texture.id));
29
75
  const indexOf = new Map(textures.map((texture, index) => [texture.id, index]));
30
- const tableWords = Math.max(1, textures.length) * TEXTURE_WORDS;
76
+ const tableWords = TEXTURE_TABLE + Math.max(1, textures.length) * TEXTURE_WORDS;
31
77
  const texelWords = textures.reduce((sum, texture) => sum + texelCount(texture) * (isFloat(texture) ? 4 : 1), 0);
32
78
  return { textures, indexOf, tableWords, extraOffset: tableWords + texelWords };
33
79
  }
@@ -42,8 +88,9 @@ export function writeTextures(plan, extraWords) {
42
88
  const words = data;
43
89
  const floats = new Float32Array(data.buffer);
44
90
  let texelAt = tableWords;
91
+ data.set(LOOKUP, 0);
45
92
  textures.forEach((texture, index) => {
46
- const at = index * TEXTURE_WORDS;
93
+ const at = textureEntry(index);
47
94
  const texels = texelCount(texture);
48
95
  const float = isFloat(texture);
49
96
  words[at] = texture.width;
@@ -69,12 +116,18 @@ export function writeTextures(plan, extraWords) {
69
116
  }
70
117
  else {
71
118
  const source = texture.data;
72
- for (let texel = 0; texel < texels; texel++) {
73
- const offset = texel * 4;
74
- words[texelAt + texel] = source[offset]
75
- | (source[offset + 1] << 8)
76
- | (source[offset + 2] << 16)
77
- | (source[offset + 3] << 24);
119
+ if (LITTLE_ENDIAN) {
120
+ // The bytes already sit in the order the words want them: copied whole, as the GPU reads them.
121
+ new Uint8Array(data.buffer, texelAt * 4, texels * 4).set(source.subarray(0, texels * 4));
122
+ }
123
+ else {
124
+ for (let texel = 0; texel < texels; texel++) {
125
+ const offset = texel * 4;
126
+ words[texelAt + texel] = source[offset]
127
+ | (source[offset + 1] << 8)
128
+ | (source[offset + 2] << 16)
129
+ | (source[offset + 3] << 24);
130
+ }
78
131
  }
79
132
  texelAt += texels;
80
133
  }
@@ -1 +1 @@
1
- {"version":3,"file":"texturePack.js","sourceRoot":"","sources":["../src/texturePack.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"texturePack.js","sourceRoot":"","sources":["../src/texturePack.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,9 @@
1
- /** Triangle intersection and the iterative traversal, with the fixed stack the builder caps its depth to. */
2
- export declare const BVH_WGSL = "\nfn triangleVertex(triangle: u32, corner: u32) -> vec3<f32> {\n let base = triangle * 9u + corner * 3u;\n\n return vec3<f32>(positions[base], positions[base + 1u], positions[base + 2u]);\n}\n\n/** Moller-Trumbore. Returns the distance in x and the barycentric coordinates in yz, or a negative distance. */\nfn intersectTriangle(triangle: u32, origin: vec3<f32>, direction: vec3<f32>) -> vec3<f32> {\n let miss = vec3<f32>(-1.0, 0.0, 0.0);\n let a = triangleVertex(triangle, 0u);\n let edge1 = triangleVertex(triangle, 1u) - a;\n let edge2 = triangleVertex(triangle, 2u) - a;\n let p = cross(direction, edge2);\n let determinant = dot(edge1, p);\n\n if (abs(determinant) < 1e-12) {\n return miss;\n }\n\n let inverse = 1.0 / determinant;\n let offset = origin - a;\n let u = dot(offset, p) * inverse;\n\n if (u < 0.0 || u > 1.0) {\n return miss;\n }\n\n let q = cross(offset, edge1);\n let v = dot(direction, q) * inverse;\n\n if (v < 0.0 || u + v > 1.0) {\n return miss;\n }\n\n return vec3<f32>(dot(edge2, q) * inverse, u, v);\n}\n\n/** Where a ray enters a node's box, or 1e30 when it misses it or only meets it past maxDistance. */\nfn enterBox(node: BvhNode, origin: vec3<f32>, inverse: vec3<f32>, maxDistance: f32) -> f32 {\n let first = (node.low - origin) * inverse;\n let second = (node.high - origin) * inverse;\n let near = min(first, second);\n let far = max(first, second);\n let enter = max(max(near.x, near.y), max(near.z, 0.0));\n let exit = min(min(far.x, far.y), min(far.z, maxDistance));\n\n return select(1e30, enter, enter <= exit);\n}\n\n/** The triangles of a leaf, against the closest hit so far. */\nfn intersectLeaf(node: BvhNode, origin: vec3<f32>, direction: vec3<f32>, hit: ptr<function, Hit>) {\n let start = u32(-1 - node.link);\n\n for (var i = 0u; i < u32(node.count); i = i + 1u) {\n let triangle = orderedTriangle(start + i);\n let result = intersectTriangle(triangle, origin, direction);\n\n if (result.x > RAY_EPSILON && result.x < (*hit).distance) {\n (*hit).distance = result.x;\n (*hit).triangle = triangle;\n (*hit).u = result.y;\n (*hit).v = result.z;\n }\n }\n}\n\n/**\n * The closest hit along a ray. Both children of a node are tested together and the nearer one is visited first, so\n * the closest hit shrinks the search early and whole subtrees behind it are skipped; each node remembers where the ray\n * entered it, and one whose entry is already past the closest hit is dropped without being opened.\n */\nfn traceScene(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> Hit {\n var hit: Hit;\n hit.distance = maxDistance;\n hit.triangle = NO_HIT;\n hit.u = 0.0;\n hit.v = 0.0;\n\n if (frame.triangleCount == 0u) {\n return hit;\n }\n\n // A huge finite reciprocal instead of an infinite one: an axis aligned slab would otherwise produce 0 * inf.\n let signs = select(vec3<f32>(-1.0), vec3<f32>(1.0), direction >= vec3<f32>(0.0));\n let inverse = signs / max(abs(direction), vec3<f32>(1e-20));\n let rootEnter = enterBox(nodes[0], origin, inverse, hit.distance);\n\n if (rootEnter >= 1e30) {\n return hit;\n }\n\n var stack: array<u32, 32>;\n var enters: array<f32, 32>;\n var depth = 1u;\n stack[0] = 0u;\n enters[0] = rootEnter;\n\n loop {\n if (depth == 0u) {\n break;\n }\n\n depth = depth - 1u;\n\n // Something closer was found since this node was pushed.\n if (enters[depth] > hit.distance) {\n continue;\n }\n\n let node = nodes[stack[depth]];\n\n if (node.link < 0) {\n intersectLeaf(node, origin, direction, &hit);\n continue;\n }\n\n let leftIndex = u32(node.link);\n let rightIndex = u32(node.count);\n let leftEnter = enterBox(nodes[leftIndex], origin, inverse, hit.distance);\n let rightEnter = enterBox(nodes[rightIndex], origin, inverse, hit.distance);\n let leftHit = leftEnter < 1e30;\n let rightHit = rightEnter < 1e30;\n\n // The builder caps its depth so both children always fit; the guard keeps a malformed tree inside the stack.\n if (depth + 2u > 32u) {\n continue;\n }\n\n if (leftHit && rightHit) {\n // The farther first, so the nearer comes off the stack next.\n let leftNearer = leftEnter <= rightEnter;\n stack[depth] = select(leftIndex, rightIndex, leftNearer);\n enters[depth] = select(leftEnter, rightEnter, leftNearer);\n stack[depth + 1u] = select(rightIndex, leftIndex, leftNearer);\n enters[depth + 1u] = select(rightEnter, leftEnter, leftNearer);\n depth = depth + 2u;\n } else if (leftHit) {\n stack[depth] = leftIndex;\n enters[depth] = leftEnter;\n depth = depth + 1u;\n } else if (rightHit) {\n stack[depth] = rightIndex;\n enters[depth] = rightEnter;\n depth = depth + 1u;\n }\n }\n\n return hit;\n}\n\n/**\n * Whether anything at all lies along a ray before maxDistance, stopping at the first triangle it finds rather than the\n * closest: what a shadow ray asks when every surface it could meet blocks it. Returns that triangle, or NO_HIT.\n */\nfn traceAny(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> u32 {\n if (frame.triangleCount == 0u) {\n return NO_HIT;\n }\n\n let signs = select(vec3<f32>(-1.0), vec3<f32>(1.0), direction >= vec3<f32>(0.0));\n let inverse = signs / max(abs(direction), vec3<f32>(1e-20));\n\n if (enterBox(nodes[0], origin, inverse, maxDistance) >= 1e30) {\n return NO_HIT;\n }\n\n var stack: array<u32, 32>;\n var depth = 1u;\n stack[0] = 0u;\n\n loop {\n if (depth == 0u) {\n break;\n }\n\n depth = depth - 1u;\n\n let node = nodes[stack[depth]];\n\n if (node.link < 0) {\n let start = u32(-1 - node.link);\n\n for (var i = 0u; i < u32(node.count); i = i + 1u) {\n let triangle = orderedTriangle(start + i);\n let result = intersectTriangle(triangle, origin, direction);\n\n if (result.x > RAY_EPSILON && result.x < maxDistance) {\n return triangle;\n }\n }\n\n continue;\n }\n\n let leftIndex = u32(node.link);\n let rightIndex = u32(node.count);\n\n if (depth + 2u > 32u) {\n continue;\n }\n\n if (enterBox(nodes[leftIndex], origin, inverse, maxDistance) < 1e30) {\n stack[depth] = leftIndex;\n depth = depth + 1u;\n }\n\n if (enterBox(nodes[rightIndex], origin, inverse, maxDistance) < 1e30) {\n stack[depth] = rightIndex;\n depth = depth + 1u;\n }\n }\n\n return NO_HIT;\n}\n";
1
+ /**
2
+ * Triangle intersection and the iterative traversal, with the fixed stack the builder caps its depth to.
3
+ *
4
+ * The positions are uploaded in the hierarchy's leaf order, so a leaf is a run of triangles read straight off the
5
+ * buffer; the scene's own triangle number is looked up once, for the hit a trace returns. Every other reader goes the
6
+ * other way, from a triangle number to where its corners sit.
7
+ */
8
+ export declare const BVH_WGSL = "\n/** A corner of the triangle at this position of the hierarchy's leaf order. */\nfn leafVertex(at: u32, corner: u32) -> vec3<f32> {\n let base = at * 9u + corner * 3u;\n\n return vec3<f32>(positions[base], positions[base + 1u], positions[base + 2u]);\n}\n\n/** Where a triangle of the scene sits in the leaf order the positions are stored in. */\nfn leafOf(triangle: u32) -> u32 {\n return indices[frame.leafOffset + triangle];\n}\n\nfn triangleVertex(triangle: u32, corner: u32) -> vec3<f32> {\n return leafVertex(leafOf(triangle), corner);\n}\n\n/** Moller-Trumbore. Returns the distance in x and the barycentric coordinates in yz, or a negative distance. */\nfn intersectTriangle(at: u32, origin: vec3<f32>, direction: vec3<f32>) -> vec3<f32> {\n let miss = vec3<f32>(-1.0, 0.0, 0.0);\n let a = leafVertex(at, 0u);\n let edge1 = leafVertex(at, 1u) - a;\n let edge2 = leafVertex(at, 2u) - a;\n let p = cross(direction, edge2);\n let determinant = dot(edge1, p);\n\n if (abs(determinant) < 1e-12) {\n return miss;\n }\n\n let inverse = 1.0 / determinant;\n let offset = origin - a;\n let u = dot(offset, p) * inverse;\n\n if (u < 0.0 || u > 1.0) {\n return miss;\n }\n\n let q = cross(offset, edge1);\n let v = dot(direction, q) * inverse;\n\n if (v < 0.0 || u + v > 1.0) {\n return miss;\n }\n\n return vec3<f32>(dot(edge2, q) * inverse, u, v);\n}\n\n/** Where a ray enters a box, or 1e30 when it misses it or only meets it past maxDistance. */\nfn enterBox(low: vec3<f32>, high: vec3<f32>, origin: vec3<f32>, inverse: vec3<f32>, maxDistance: f32) -> f32 {\n let first = (low - origin) * inverse;\n let second = (high - origin) * inverse;\n let near = min(first, second);\n let far = max(first, second);\n let enter = max(max(near.x, near.y), max(near.z, 0.0));\n let exit = min(min(far.x, far.y), min(far.z, maxDistance));\n\n return select(1e30, enter, enter <= exit);\n}\n\n/** The triangles of a leaf, against the closest hit so far, which records where in the leaf order it found one. */\nfn intersectLeaf(link: i32, count: i32, origin: vec3<f32>, direction: vec3<f32>, hit: ptr<function, Hit>) {\n let start = u32(-1 - link);\n\n for (var i = 0u; i < u32(count); i = i + 1u) {\n let result = intersectTriangle(start + i, origin, direction);\n\n if (result.x > RAY_EPSILON && result.x < (*hit).distance) {\n (*hit).distance = result.x;\n (*hit).triangle = start + i;\n (*hit).u = result.y;\n (*hit).v = result.z;\n }\n }\n}\n\n/** Whether any triangle of a leaf lies along the ray before maxDistance: its position in the leaf order, or NO_HIT. */\nfn anyInLeaf(link: i32, count: i32, origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> u32 {\n let start = u32(-1 - link);\n\n for (var i = 0u; i < u32(count); i = i + 1u) {\n let result = intersectTriangle(start + i, origin, direction);\n\n if (result.x > RAY_EPSILON && result.x < maxDistance) {\n return start + i;\n }\n }\n\n return NO_HIT;\n}\n\n/** No node to go to: the traversal takes the next entry off the stack. */\nconst NO_NODE: u32 = 0xffffffffu;\n\n/**\n * A stack entry that is a leaf rather than a node: the node holding it and which of its two children it is. A leaf\n * has no node of its own, so this is how one waits its turn.\n */\nconst LEAF_ENTRY: u32 = 0x80000000u;\n\nfn leafEntry(parent: u32, right: bool) -> u32 {\n return LEAF_ENTRY | (parent << 1u) | select(0u, 1u, right);\n}\n\n/** A waiting leaf's link and count, read back from the node that holds it. */\nfn waitingLeaf(entry: u32) -> vec2<i32> {\n let parent = (entry & ~LEAF_ENTRY) >> 1u;\n\n if ((entry & 1u) != 0u) {\n return vec2<i32>(nodes[parent].rightLink, nodes[parent].rightCount);\n }\n\n return vec2<i32>(nodes[parent].leftLink, nodes[parent].leftCount);\n}\n\n/**\n * The closest hit along a ray. A node holds both of its children's boxes, so one read tests them both. The nearer is\n * visited first, so the closest hit shrinks the search early and whole subtrees behind it are skipped; the farther one\n * waits on the stack with where the ray entered it, and is dropped unopened if something closer turned up meanwhile.\n * A leaf is tested at the top of the next step, the one place the loop tests triangles, which keeps the kernel small.\n * This visits what the binary tree's traversal visited, in the same order, so it finds the same hit.\n */\nfn traceScene(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> Hit {\n var hit: Hit;\n hit.distance = maxDistance;\n hit.triangle = NO_HIT;\n hit.u = 0.0;\n hit.v = 0.0;\n\n if (frame.triangleCount == 0u) {\n return hit;\n }\n\n // A huge finite reciprocal instead of an infinite one: an axis aligned slab would otherwise produce 0 * inf.\n let signs = select(vec3<f32>(-1.0), vec3<f32>(1.0), direction >= vec3<f32>(0.0));\n let inverse = signs / max(abs(direction), vec3<f32>(1e-20));\n\n var stack: array<u32, 32>;\n var enters: array<f32, 32>;\n var depth = 0u;\n var current = 0u;\n // A leaf to test before anything else: its link, and its triangle count, zero when there is none.\n var leaf = vec2<i32>(0, 0);\n\n loop {\n if (leaf.y > 0) {\n intersectLeaf(leaf.x, leaf.y, origin, direction, &hit);\n leaf.y = 0;\n }\n\n if (current == NO_NODE) {\n if (depth == 0u) {\n break;\n }\n\n depth = depth - 1u;\n\n // Something closer was found since this was pushed.\n if (enters[depth] > hit.distance) {\n continue;\n }\n\n let entry = stack[depth];\n\n if ((entry & LEAF_ENTRY) != 0u) {\n leaf = waitingLeaf(entry);\n continue;\n }\n\n current = entry;\n }\n\n let node = nodes[current];\n let leftEnter = enterBox(node.leftLow, node.leftHigh, origin, inverse, hit.distance);\n let rightEnter = enterBox(node.rightLow, node.rightHigh, origin, inverse, hit.distance);\n let leftFirst = leftEnter <= rightEnter;\n let nearLink = select(node.rightLink, node.leftLink, leftFirst);\n let farEnter = select(leftEnter, rightEnter, leftFirst);\n let farLink = select(node.leftLink, node.rightLink, leftFirst);\n let parent = current;\n\n current = NO_NODE;\n\n // The nearer child: a miss means both missed.\n if (min(leftEnter, rightEnter) < 1e30) {\n if (nearLink < 0) {\n leaf = vec2<i32>(nearLink, select(node.rightCount, node.leftCount, leftFirst));\n } else {\n current = u32(nearLink);\n }\n }\n\n // The builder caps its depth so the far children always fit; the guard keeps a malformed tree inside the stack.\n if (farEnter < 1e30 && depth < 32u) {\n stack[depth] = select(u32(farLink), leafEntry(parent, leftFirst), farLink < 0);\n enters[depth] = farEnter;\n depth = depth + 1u;\n }\n }\n\n if (hit.triangle != NO_HIT) {\n hit.triangle = orderedTriangle(hit.triangle);\n }\n\n return hit;\n}\n\n/**\n * Whether anything at all lies along a ray before maxDistance, stopping at the first triangle it finds rather than the\n * closest: what a shadow ray asks when every surface it could meet blocks it. Returns that triangle, or NO_HIT. The\n * right child goes first and the left one waits, the order the binary tree's traversal took.\n */\nfn traceAny(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> u32 {\n if (frame.triangleCount == 0u) {\n return NO_HIT;\n }\n\n let signs = select(vec3<f32>(-1.0), vec3<f32>(1.0), direction >= vec3<f32>(0.0));\n let inverse = signs / max(abs(direction), vec3<f32>(1e-20));\n\n var stack: array<u32, 32>;\n var depth = 0u;\n var current = 0u;\n var leaf = vec2<i32>(0, 0);\n\n loop {\n if (leaf.y > 0) {\n let found = anyInLeaf(leaf.x, leaf.y, origin, direction, maxDistance);\n\n if (found != NO_HIT) {\n return orderedTriangle(found);\n }\n\n leaf.y = 0;\n }\n\n if (current == NO_NODE) {\n if (depth == 0u) {\n break;\n }\n\n depth = depth - 1u;\n\n let entry = stack[depth];\n\n if ((entry & LEAF_ENTRY) != 0u) {\n leaf = waitingLeaf(entry);\n continue;\n }\n\n current = entry;\n }\n\n let node = nodes[current];\n let rightHit = enterBox(node.rightLow, node.rightHigh, origin, inverse, maxDistance) < 1e30;\n let leftHit = enterBox(node.leftLow, node.leftHigh, origin, inverse, maxDistance) < 1e30;\n let parent = current;\n\n current = NO_NODE;\n\n // The right child is taken now and the left one waits; with only one of them hit, that one is taken now.\n let takeRight = rightHit;\n let takenLink = select(node.leftLink, node.rightLink, takeRight);\n\n if (rightHit || leftHit) {\n if (takenLink < 0) {\n leaf = vec2<i32>(takenLink, select(node.leftCount, node.rightCount, takeRight));\n } else {\n current = u32(takenLink);\n }\n }\n\n if (rightHit && leftHit && depth < 32u) {\n stack[depth] = select(u32(node.leftLink), leafEntry(parent, false), node.leftLink < 0);\n depth = depth + 1u;\n }\n }\n\n return NO_HIT;\n}\n";
3
9
  //# sourceMappingURL=bvh.wgsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"bvh.wgsl.d.ts","sourceRoot":"","sources":["../../src/wgsl/bvh.wgsl.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,eAAO,MAAM,QAAQ,y4MAuNpB,CAAC"}
1
+ {"version":3,"file":"bvh.wgsl.d.ts","sourceRoot":"","sources":["../../src/wgsl/bvh.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,eAAO,MAAM,QAAQ,+5RAwRpB,CAAC"}
@@ -1,17 +1,33 @@
1
- /** Triangle intersection and the iterative traversal, with the fixed stack the builder caps its depth to. */
1
+ /**
2
+ * Triangle intersection and the iterative traversal, with the fixed stack the builder caps its depth to.
3
+ *
4
+ * The positions are uploaded in the hierarchy's leaf order, so a leaf is a run of triangles read straight off the
5
+ * buffer; the scene's own triangle number is looked up once, for the hit a trace returns. Every other reader goes the
6
+ * other way, from a triangle number to where its corners sit.
7
+ */
2
8
  export const BVH_WGSL = /* wgsl */ `
3
- fn triangleVertex(triangle: u32, corner: u32) -> vec3<f32> {
4
- let base = triangle * 9u + corner * 3u;
9
+ /** A corner of the triangle at this position of the hierarchy's leaf order. */
10
+ fn leafVertex(at: u32, corner: u32) -> vec3<f32> {
11
+ let base = at * 9u + corner * 3u;
5
12
 
6
13
  return vec3<f32>(positions[base], positions[base + 1u], positions[base + 2u]);
7
14
  }
8
15
 
16
+ /** Where a triangle of the scene sits in the leaf order the positions are stored in. */
17
+ fn leafOf(triangle: u32) -> u32 {
18
+ return indices[frame.leafOffset + triangle];
19
+ }
20
+
21
+ fn triangleVertex(triangle: u32, corner: u32) -> vec3<f32> {
22
+ return leafVertex(leafOf(triangle), corner);
23
+ }
24
+
9
25
  /** Moller-Trumbore. Returns the distance in x and the barycentric coordinates in yz, or a negative distance. */
10
- fn intersectTriangle(triangle: u32, origin: vec3<f32>, direction: vec3<f32>) -> vec3<f32> {
26
+ fn intersectTriangle(at: u32, origin: vec3<f32>, direction: vec3<f32>) -> vec3<f32> {
11
27
  let miss = vec3<f32>(-1.0, 0.0, 0.0);
12
- let a = triangleVertex(triangle, 0u);
13
- let edge1 = triangleVertex(triangle, 1u) - a;
14
- let edge2 = triangleVertex(triangle, 2u) - a;
28
+ let a = leafVertex(at, 0u);
29
+ let edge1 = leafVertex(at, 1u) - a;
30
+ let edge2 = leafVertex(at, 2u) - a;
15
31
  let p = cross(direction, edge2);
16
32
  let determinant = dot(edge1, p);
17
33
 
@@ -37,10 +53,10 @@ fn intersectTriangle(triangle: u32, origin: vec3<f32>, direction: vec3<f32>) ->
37
53
  return vec3<f32>(dot(edge2, q) * inverse, u, v);
38
54
  }
39
55
 
40
- /** Where a ray enters a node's box, or 1e30 when it misses it or only meets it past maxDistance. */
41
- fn enterBox(node: BvhNode, origin: vec3<f32>, inverse: vec3<f32>, maxDistance: f32) -> f32 {
42
- let first = (node.low - origin) * inverse;
43
- let second = (node.high - origin) * inverse;
56
+ /** Where a ray enters a box, or 1e30 when it misses it or only meets it past maxDistance. */
57
+ fn enterBox(low: vec3<f32>, high: vec3<f32>, origin: vec3<f32>, inverse: vec3<f32>, maxDistance: f32) -> f32 {
58
+ let first = (low - origin) * inverse;
59
+ let second = (high - origin) * inverse;
44
60
  let near = min(first, second);
45
61
  let far = max(first, second);
46
62
  let enter = max(max(near.x, near.y), max(near.z, 0.0));
@@ -49,27 +65,67 @@ fn enterBox(node: BvhNode, origin: vec3<f32>, inverse: vec3<f32>, maxDistance: f
49
65
  return select(1e30, enter, enter <= exit);
50
66
  }
51
67
 
52
- /** The triangles of a leaf, against the closest hit so far. */
53
- fn intersectLeaf(node: BvhNode, origin: vec3<f32>, direction: vec3<f32>, hit: ptr<function, Hit>) {
54
- let start = u32(-1 - node.link);
68
+ /** The triangles of a leaf, against the closest hit so far, which records where in the leaf order it found one. */
69
+ fn intersectLeaf(link: i32, count: i32, origin: vec3<f32>, direction: vec3<f32>, hit: ptr<function, Hit>) {
70
+ let start = u32(-1 - link);
55
71
 
56
- for (var i = 0u; i < u32(node.count); i = i + 1u) {
57
- let triangle = orderedTriangle(start + i);
58
- let result = intersectTriangle(triangle, origin, direction);
72
+ for (var i = 0u; i < u32(count); i = i + 1u) {
73
+ let result = intersectTriangle(start + i, origin, direction);
59
74
 
60
75
  if (result.x > RAY_EPSILON && result.x < (*hit).distance) {
61
76
  (*hit).distance = result.x;
62
- (*hit).triangle = triangle;
77
+ (*hit).triangle = start + i;
63
78
  (*hit).u = result.y;
64
79
  (*hit).v = result.z;
65
80
  }
66
81
  }
67
82
  }
68
83
 
84
+ /** Whether any triangle of a leaf lies along the ray before maxDistance: its position in the leaf order, or NO_HIT. */
85
+ fn anyInLeaf(link: i32, count: i32, origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> u32 {
86
+ let start = u32(-1 - link);
87
+
88
+ for (var i = 0u; i < u32(count); i = i + 1u) {
89
+ let result = intersectTriangle(start + i, origin, direction);
90
+
91
+ if (result.x > RAY_EPSILON && result.x < maxDistance) {
92
+ return start + i;
93
+ }
94
+ }
95
+
96
+ return NO_HIT;
97
+ }
98
+
99
+ /** No node to go to: the traversal takes the next entry off the stack. */
100
+ const NO_NODE: u32 = 0xffffffffu;
101
+
102
+ /**
103
+ * A stack entry that is a leaf rather than a node: the node holding it and which of its two children it is. A leaf
104
+ * has no node of its own, so this is how one waits its turn.
105
+ */
106
+ const LEAF_ENTRY: u32 = 0x80000000u;
107
+
108
+ fn leafEntry(parent: u32, right: bool) -> u32 {
109
+ return LEAF_ENTRY | (parent << 1u) | select(0u, 1u, right);
110
+ }
111
+
112
+ /** A waiting leaf's link and count, read back from the node that holds it. */
113
+ fn waitingLeaf(entry: u32) -> vec2<i32> {
114
+ let parent = (entry & ~LEAF_ENTRY) >> 1u;
115
+
116
+ if ((entry & 1u) != 0u) {
117
+ return vec2<i32>(nodes[parent].rightLink, nodes[parent].rightCount);
118
+ }
119
+
120
+ return vec2<i32>(nodes[parent].leftLink, nodes[parent].leftCount);
121
+ }
122
+
69
123
  /**
70
- * The closest hit along a ray. Both children of a node are tested together and the nearer one is visited first, so
71
- * the closest hit shrinks the search early and whole subtrees behind it are skipped; each node remembers where the ray
72
- * entered it, and one whose entry is already past the closest hit is dropped without being opened.
124
+ * The closest hit along a ray. A node holds both of its children's boxes, so one read tests them both. The nearer is
125
+ * visited first, so the closest hit shrinks the search early and whole subtrees behind it are skipped; the farther one
126
+ * waits on the stack with where the ray entered it, and is dropped unopened if something closer turned up meanwhile.
127
+ * A leaf is tested at the top of the next step, the one place the loop tests triangles, which keeps the kernel small.
128
+ * This visits what the binary tree's traversal visited, in the same order, so it finds the same hit.
73
129
  */
74
130
  fn traceScene(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> Hit {
75
131
  var hit: Hit;
@@ -85,74 +141,81 @@ fn traceScene(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> Hit
85
141
  // A huge finite reciprocal instead of an infinite one: an axis aligned slab would otherwise produce 0 * inf.
86
142
  let signs = select(vec3<f32>(-1.0), vec3<f32>(1.0), direction >= vec3<f32>(0.0));
87
143
  let inverse = signs / max(abs(direction), vec3<f32>(1e-20));
88
- let rootEnter = enterBox(nodes[0], origin, inverse, hit.distance);
89
-
90
- if (rootEnter >= 1e30) {
91
- return hit;
92
- }
93
144
 
94
145
  var stack: array<u32, 32>;
95
146
  var enters: array<f32, 32>;
96
- var depth = 1u;
97
- stack[0] = 0u;
98
- enters[0] = rootEnter;
147
+ var depth = 0u;
148
+ var current = 0u;
149
+ // A leaf to test before anything else: its link, and its triangle count, zero when there is none.
150
+ var leaf = vec2<i32>(0, 0);
99
151
 
100
152
  loop {
101
- if (depth == 0u) {
102
- break;
153
+ if (leaf.y > 0) {
154
+ intersectLeaf(leaf.x, leaf.y, origin, direction, &hit);
155
+ leaf.y = 0;
103
156
  }
104
157
 
105
- depth = depth - 1u;
158
+ if (current == NO_NODE) {
159
+ if (depth == 0u) {
160
+ break;
161
+ }
106
162
 
107
- // Something closer was found since this node was pushed.
108
- if (enters[depth] > hit.distance) {
109
- continue;
110
- }
163
+ depth = depth - 1u;
111
164
 
112
- let node = nodes[stack[depth]];
165
+ // Something closer was found since this was pushed.
166
+ if (enters[depth] > hit.distance) {
167
+ continue;
168
+ }
113
169
 
114
- if (node.link < 0) {
115
- intersectLeaf(node, origin, direction, &hit);
116
- continue;
117
- }
170
+ let entry = stack[depth];
118
171
 
119
- let leftIndex = u32(node.link);
120
- let rightIndex = u32(node.count);
121
- let leftEnter = enterBox(nodes[leftIndex], origin, inverse, hit.distance);
122
- let rightEnter = enterBox(nodes[rightIndex], origin, inverse, hit.distance);
123
- let leftHit = leftEnter < 1e30;
124
- let rightHit = rightEnter < 1e30;
172
+ if ((entry & LEAF_ENTRY) != 0u) {
173
+ leaf = waitingLeaf(entry);
174
+ continue;
175
+ }
125
176
 
126
- // The builder caps its depth so both children always fit; the guard keeps a malformed tree inside the stack.
127
- if (depth + 2u > 32u) {
128
- continue;
177
+ current = entry;
129
178
  }
130
179
 
131
- if (leftHit && rightHit) {
132
- // The farther first, so the nearer comes off the stack next.
133
- let leftNearer = leftEnter <= rightEnter;
134
- stack[depth] = select(leftIndex, rightIndex, leftNearer);
135
- enters[depth] = select(leftEnter, rightEnter, leftNearer);
136
- stack[depth + 1u] = select(rightIndex, leftIndex, leftNearer);
137
- enters[depth + 1u] = select(rightEnter, leftEnter, leftNearer);
138
- depth = depth + 2u;
139
- } else if (leftHit) {
140
- stack[depth] = leftIndex;
141
- enters[depth] = leftEnter;
142
- depth = depth + 1u;
143
- } else if (rightHit) {
144
- stack[depth] = rightIndex;
145
- enters[depth] = rightEnter;
180
+ let node = nodes[current];
181
+ let leftEnter = enterBox(node.leftLow, node.leftHigh, origin, inverse, hit.distance);
182
+ let rightEnter = enterBox(node.rightLow, node.rightHigh, origin, inverse, hit.distance);
183
+ let leftFirst = leftEnter <= rightEnter;
184
+ let nearLink = select(node.rightLink, node.leftLink, leftFirst);
185
+ let farEnter = select(leftEnter, rightEnter, leftFirst);
186
+ let farLink = select(node.leftLink, node.rightLink, leftFirst);
187
+ let parent = current;
188
+
189
+ current = NO_NODE;
190
+
191
+ // The nearer child: a miss means both missed.
192
+ if (min(leftEnter, rightEnter) < 1e30) {
193
+ if (nearLink < 0) {
194
+ leaf = vec2<i32>(nearLink, select(node.rightCount, node.leftCount, leftFirst));
195
+ } else {
196
+ current = u32(nearLink);
197
+ }
198
+ }
199
+
200
+ // The builder caps its depth so the far children always fit; the guard keeps a malformed tree inside the stack.
201
+ if (farEnter < 1e30 && depth < 32u) {
202
+ stack[depth] = select(u32(farLink), leafEntry(parent, leftFirst), farLink < 0);
203
+ enters[depth] = farEnter;
146
204
  depth = depth + 1u;
147
205
  }
148
206
  }
149
207
 
208
+ if (hit.triangle != NO_HIT) {
209
+ hit.triangle = orderedTriangle(hit.triangle);
210
+ }
211
+
150
212
  return hit;
151
213
  }
152
214
 
153
215
  /**
154
216
  * Whether anything at all lies along a ray before maxDistance, stopping at the first triangle it finds rather than the
155
- * closest: what a shadow ray asks when every surface it could meet blocks it. Returns that triangle, or NO_HIT.
217
+ * closest: what a shadow ray asks when every surface it could meet blocks it. Returns that triangle, or NO_HIT. The
218
+ * right child goes first and the left one waits, the order the binary tree's traversal took.
156
219
  */
157
220
  fn traceAny(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> u32 {
158
221
  if (frame.triangleCount == 0u) {
@@ -162,52 +225,60 @@ fn traceAny(origin: vec3<f32>, direction: vec3<f32>, maxDistance: f32) -> u32 {
162
225
  let signs = select(vec3<f32>(-1.0), vec3<f32>(1.0), direction >= vec3<f32>(0.0));
163
226
  let inverse = signs / max(abs(direction), vec3<f32>(1e-20));
164
227
 
165
- if (enterBox(nodes[0], origin, inverse, maxDistance) >= 1e30) {
166
- return NO_HIT;
167
- }
168
-
169
228
  var stack: array<u32, 32>;
170
- var depth = 1u;
171
- stack[0] = 0u;
229
+ var depth = 0u;
230
+ var current = 0u;
231
+ var leaf = vec2<i32>(0, 0);
172
232
 
173
233
  loop {
174
- if (depth == 0u) {
175
- break;
176
- }
234
+ if (leaf.y > 0) {
235
+ let found = anyInLeaf(leaf.x, leaf.y, origin, direction, maxDistance);
177
236
 
178
- depth = depth - 1u;
237
+ if (found != NO_HIT) {
238
+ return orderedTriangle(found);
239
+ }
179
240
 
180
- let node = nodes[stack[depth]];
241
+ leaf.y = 0;
242
+ }
181
243
 
182
- if (node.link < 0) {
183
- let start = u32(-1 - node.link);
244
+ if (current == NO_NODE) {
245
+ if (depth == 0u) {
246
+ break;
247
+ }
248
+
249
+ depth = depth - 1u;
184
250
 
185
- for (var i = 0u; i < u32(node.count); i = i + 1u) {
186
- let triangle = orderedTriangle(start + i);
187
- let result = intersectTriangle(triangle, origin, direction);
251
+ let entry = stack[depth];
188
252
 
189
- if (result.x > RAY_EPSILON && result.x < maxDistance) {
190
- return triangle;
191
- }
253
+ if ((entry & LEAF_ENTRY) != 0u) {
254
+ leaf = waitingLeaf(entry);
255
+ continue;
192
256
  }
193
257
 
194
- continue;
258
+ current = entry;
195
259
  }
196
260
 
197
- let leftIndex = u32(node.link);
198
- let rightIndex = u32(node.count);
261
+ let node = nodes[current];
262
+ let rightHit = enterBox(node.rightLow, node.rightHigh, origin, inverse, maxDistance) < 1e30;
263
+ let leftHit = enterBox(node.leftLow, node.leftHigh, origin, inverse, maxDistance) < 1e30;
264
+ let parent = current;
199
265
 
200
- if (depth + 2u > 32u) {
201
- continue;
202
- }
266
+ current = NO_NODE;
203
267
 
204
- if (enterBox(nodes[leftIndex], origin, inverse, maxDistance) < 1e30) {
205
- stack[depth] = leftIndex;
206
- depth = depth + 1u;
268
+ // The right child is taken now and the left one waits; with only one of them hit, that one is taken now.
269
+ let takeRight = rightHit;
270
+ let takenLink = select(node.leftLink, node.rightLink, takeRight);
271
+
272
+ if (rightHit || leftHit) {
273
+ if (takenLink < 0) {
274
+ leaf = vec2<i32>(takenLink, select(node.leftCount, node.rightCount, takeRight));
275
+ } else {
276
+ current = u32(takenLink);
277
+ }
207
278
  }
208
279
 
209
- if (enterBox(nodes[rightIndex], origin, inverse, maxDistance) < 1e30) {
210
- stack[depth] = rightIndex;
280
+ if (rightHit && leftHit && depth < 32u) {
281
+ stack[depth] = select(u32(node.leftLink), leafEntry(parent, false), node.leftLink < 0);
211
282
  depth = depth + 1u;
212
283
  }
213
284
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bvh.wgsl.js","sourceRoot":"","sources":["../../src/wgsl/bvh.wgsl.ts"],"names":[],"mappings":"AAAA,6GAA6G;AAC7G,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuNlC,CAAC"}
1
+ {"version":3,"file":"bvh.wgsl.js","sourceRoot":"","sources":["../../src/wgsl/bvh.wgsl.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwRlC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"common.wgsl.d.ts","sourceRoot":"","sources":["../../src/wgsl/common.wgsl.ts"],"names":[],"mappings":"AAGA,6EAA6E;AAC7E,eAAO,MAAM,WAAW,QA4LvB,CAAC"}
1
+ {"version":3,"file":"common.wgsl.d.ts","sourceRoot":"","sources":["../../src/wgsl/common.wgsl.ts"],"names":[],"mappings":"AAIA,6EAA6E;AAC7E,eAAO,MAAM,WAAW,QAwMvB,CAAC"}