@tinypoly/gpu-renderer 0.0.4 → 0.1.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.
Files changed (140) hide show
  1. package/ARCHITECTURE.md +81 -10
  2. package/README.md +53 -5
  3. package/dist/atmosphere.d.ts +21 -0
  4. package/dist/atmosphere.d.ts.map +1 -0
  5. package/dist/atmosphere.js +72 -0
  6. package/dist/atmosphere.js.map +1 -0
  7. package/dist/bvh.d.ts +11 -6
  8. package/dist/bvh.d.ts.map +1 -1
  9. package/dist/bvh.js +64 -11
  10. package/dist/bvh.js.map +1 -1
  11. package/dist/denoise.d.ts +17 -2
  12. package/dist/denoise.d.ts.map +1 -1
  13. package/dist/denoise.js +95 -27
  14. package/dist/denoise.js.map +1 -1
  15. package/dist/dispatchScheduler.d.ts +11 -4
  16. package/dist/dispatchScheduler.d.ts.map +1 -1
  17. package/dist/dispatchScheduler.js +14 -7
  18. package/dist/dispatchScheduler.js.map +1 -1
  19. package/dist/frameLayout.d.ts.map +1 -1
  20. package/dist/frameLayout.js +18 -0
  21. package/dist/frameLayout.js.map +1 -1
  22. package/dist/geometry.d.ts.map +1 -1
  23. package/dist/geometry.js +6 -3
  24. package/dist/geometry.js.map +1 -1
  25. package/dist/index.d.ts +4 -0
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +3 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/lensPass.d.ts +60 -0
  30. package/dist/lensPass.d.ts.map +1 -0
  31. package/dist/lensPass.js +235 -0
  32. package/dist/lensPass.js.map +1 -0
  33. package/dist/lightTree.d.ts +43 -0
  34. package/dist/lightTree.d.ts.map +1 -0
  35. package/dist/lightTree.js +107 -0
  36. package/dist/lightTree.js.map +1 -0
  37. package/dist/lights.d.ts +19 -1
  38. package/dist/lights.d.ts.map +1 -1
  39. package/dist/lights.js +63 -1
  40. package/dist/lights.js.map +1 -1
  41. package/dist/materialLayout.d.ts +24 -0
  42. package/dist/materialLayout.d.ts.map +1 -1
  43. package/dist/materialLayout.js +36 -1
  44. package/dist/materialLayout.js.map +1 -1
  45. package/dist/pathTracePass.d.ts +6 -3
  46. package/dist/pathTracePass.d.ts.map +1 -1
  47. package/dist/pathTracePass.js +16 -10
  48. package/dist/pathTracePass.js.map +1 -1
  49. package/dist/renderer.d.ts +19 -7
  50. package/dist/renderer.d.ts.map +1 -1
  51. package/dist/renderer.js +198 -36
  52. package/dist/renderer.js.map +1 -1
  53. package/dist/sceneUpload.d.ts +19 -1
  54. package/dist/sceneUpload.d.ts.map +1 -1
  55. package/dist/sceneUpload.js +25 -3
  56. package/dist/sceneUpload.js.map +1 -1
  57. package/dist/settings.d.ts +136 -0
  58. package/dist/settings.d.ts.map +1 -0
  59. package/dist/settings.js +100 -0
  60. package/dist/settings.js.map +1 -0
  61. package/dist/subsurface.d.ts +76 -0
  62. package/dist/subsurface.d.ts.map +1 -0
  63. package/dist/subsurface.js +70 -0
  64. package/dist/subsurface.js.map +1 -0
  65. package/dist/texturePack.d.ts +16 -4
  66. package/dist/texturePack.d.ts.map +1 -1
  67. package/dist/texturePack.js +61 -8
  68. package/dist/texturePack.js.map +1 -1
  69. package/dist/volumeContainment.d.ts +17 -0
  70. package/dist/volumeContainment.d.ts.map +1 -0
  71. package/dist/volumeContainment.js +61 -0
  72. package/dist/volumeContainment.js.map +1 -0
  73. package/dist/wgsl/bsdf.wgsl.d.ts +1 -1
  74. package/dist/wgsl/bsdf.wgsl.d.ts.map +1 -1
  75. package/dist/wgsl/bsdf.wgsl.js +35 -3
  76. package/dist/wgsl/bsdf.wgsl.js.map +1 -1
  77. package/dist/wgsl/bvh.wgsl.d.ts +8 -2
  78. package/dist/wgsl/bvh.wgsl.d.ts.map +1 -1
  79. package/dist/wgsl/bvh.wgsl.js +167 -96
  80. package/dist/wgsl/bvh.wgsl.js.map +1 -1
  81. package/dist/wgsl/common.wgsl.d.ts.map +1 -1
  82. package/dist/wgsl/common.wgsl.js +24 -7
  83. package/dist/wgsl/common.wgsl.js.map +1 -1
  84. package/dist/wgsl/lens.wgsl.d.ts +17 -0
  85. package/dist/wgsl/lens.wgsl.d.ts.map +1 -0
  86. package/dist/wgsl/lens.wgsl.js +315 -0
  87. package/dist/wgsl/lens.wgsl.js.map +1 -0
  88. package/dist/wgsl/lights.wgsl.d.ts +1 -1
  89. package/dist/wgsl/lights.wgsl.d.ts.map +1 -1
  90. package/dist/wgsl/lights.wgsl.js +206 -33
  91. package/dist/wgsl/lights.wgsl.js.map +1 -1
  92. package/dist/wgsl/pathTrace.wgsl.d.ts +1 -1
  93. package/dist/wgsl/pathTrace.wgsl.d.ts.map +1 -1
  94. package/dist/wgsl/pathTrace.wgsl.js +410 -25
  95. package/dist/wgsl/pathTrace.wgsl.js.map +1 -1
  96. package/dist/wgsl/random.wgsl.d.ts +1 -1
  97. package/dist/wgsl/random.wgsl.d.ts.map +1 -1
  98. package/dist/wgsl/random.wgsl.js +9 -17
  99. package/dist/wgsl/random.wgsl.js.map +1 -1
  100. package/dist/wgsl/sampling.wgsl.d.ts +1 -1
  101. package/dist/wgsl/sampling.wgsl.d.ts.map +1 -1
  102. package/dist/wgsl/sampling.wgsl.js +25 -0
  103. package/dist/wgsl/sampling.wgsl.js.map +1 -1
  104. package/dist/wgsl/surface.wgsl.d.ts +1 -1
  105. package/dist/wgsl/surface.wgsl.d.ts.map +1 -1
  106. package/dist/wgsl/surface.wgsl.js +47 -4
  107. package/dist/wgsl/surface.wgsl.js.map +1 -1
  108. package/dist/wgsl/texture.wgsl.d.ts +1 -1
  109. package/dist/wgsl/texture.wgsl.d.ts.map +1 -1
  110. package/dist/wgsl/texture.wgsl.js +10 -11
  111. package/dist/wgsl/texture.wgsl.js.map +1 -1
  112. package/package.json +1 -1
  113. package/src/atmosphere.ts +95 -0
  114. package/src/bvh.ts +81 -12
  115. package/src/denoise.ts +110 -27
  116. package/src/dispatchScheduler.ts +16 -7
  117. package/src/frameLayout.ts +18 -0
  118. package/src/geometry.ts +6 -2
  119. package/src/index.ts +13 -0
  120. package/src/lensPass.ts +299 -0
  121. package/src/lightTree.ts +172 -0
  122. package/src/lights.ts +90 -2
  123. package/src/materialLayout.ts +52 -1
  124. package/src/pathTracePass.ts +19 -10
  125. package/src/renderer.ts +258 -43
  126. package/src/sceneUpload.ts +41 -4
  127. package/src/settings.ts +234 -0
  128. package/src/subsurface.ts +153 -0
  129. package/src/texturePack.ts +80 -13
  130. package/src/volumeContainment.ts +81 -0
  131. package/src/wgsl/bsdf.wgsl.ts +35 -3
  132. package/src/wgsl/bvh.wgsl.ts +167 -96
  133. package/src/wgsl/common.wgsl.ts +24 -7
  134. package/src/wgsl/lens.wgsl.ts +314 -0
  135. package/src/wgsl/lights.wgsl.ts +206 -33
  136. package/src/wgsl/pathTrace.wgsl.ts +410 -25
  137. package/src/wgsl/random.wgsl.ts +9 -17
  138. package/src/wgsl/sampling.wgsl.ts +25 -0
  139. package/src/wgsl/surface.wgsl.ts +47 -4
  140. package/src/wgsl/texture.wgsl.ts +10 -11
@@ -21,6 +21,31 @@ fn cosineDirection(normal: vec3<f32>, u: vec2<f32>) -> vec3<f32> {
21
21
  return normalize(orthonormalBasis(normal) * local);
22
22
  }
23
23
 
24
+ /** A direction scattered from forward by the Henyey-Greenstein phase function, which its own sampling cancels. */
25
+ fn sampleHenyeyGreenstein(forward: vec3<f32>, g: f32, u: vec2<f32>) -> vec3<f32> {
26
+ var cosine = 1.0 - 2.0 * u.x;
27
+
28
+ if (abs(g) > 1e-3) {
29
+ let s = (1.0 - g * g) / (1.0 - g + 2.0 * g * u.x);
30
+ cosine = clamp((1.0 + g * g - s * s) / (2.0 * g), -1.0, 1.0);
31
+ }
32
+
33
+ let sine = sqrt(max(0.0, 1.0 - cosine * cosine));
34
+ let angle = 2.0 * PI * u.y;
35
+
36
+ return normalize(orthonormalBasis(forward) * vec3<f32>(sine * cos(angle), sine * sin(angle), cosine));
37
+ }
38
+
39
+ /**
40
+ * The Henyey-Greenstein phase function, per steradian, for a turn whose cosine is given from the direction of travel:
41
+ * the density sampleHenyeyGreenstein draws with.
42
+ */
43
+ fn henyeyGreenstein(cosine: f32, g: f32) -> f32 {
44
+ let denominator = 1.0 + g * g - 2.0 * g * cosine;
45
+
46
+ return (1.0 - g * g) / (4.0 * PI * denominator * sqrt(max(denominator, 1e-12)));
47
+ }
48
+
24
49
  /** The unit normal of the triangle's plane; which side it faces does not matter, every emitter is two sided. */
25
50
  fn triangleNormal(triangle: u32) -> vec3<f32> {
26
51
  let a = triangleVertex(triangle, 0u);
@@ -62,6 +62,8 @@ struct Surface {
62
62
  lightMap: vec3<f32>,
63
63
  blending: u32,
64
64
  material: u32,
65
+ // Share of the diffuse layer that scatters inside the material instead of at its surface.
66
+ subsurface: f32,
65
67
  };
66
68
 
67
69
  /** Barycentric weights of the two trailing vertices, for a point drawn uniformly over a triangle's area. */
@@ -114,6 +116,18 @@ fn isCulled(material: u32, triangle: u32, direction: vec3<f32>) -> bool {
114
116
  /** What the triangle radiates at this point, its emissive map included so direct and indirect light agree on it. */
115
117
  fn emissionAt(triangle: u32, bary: vec2<f32>) -> vec3<f32> {
116
118
  let m = materialIndexOf(triangle);
119
+
120
+ // An unlit material emits its colour as the camera would see it, so a bounce ray finds what a light sample counted.
121
+ if ((materials[m].flags & MATERIAL_UNLIT_LIGHT) != 0u) {
122
+ var color = materials[m].color.rgb * sampleMap(materials[m].map, triangle, bary).rgb;
123
+
124
+ if ((materials[m].flags & MATERIAL_VERTEX_COLORS) != 0u) {
125
+ color = color * triangleColor(triangle, bary).rgb;
126
+ }
127
+
128
+ return color;
129
+ }
130
+
117
131
  let map = sampleMap(materials[m].emissiveMap, triangle, bary);
118
132
 
119
133
  return materials[m].emissive.rgb * materials[m].emissive.w * map.rgb;
@@ -173,8 +187,12 @@ fn onWireframe(triangle: u32, point: vec3<f32>) -> bool {
173
187
 
174
188
  /** Three's diffuseColor.a: opacity, the colour map's alpha, the alpha map's green and the vertex alpha. */
175
189
  fn materialAlpha(m: u32, triangle: u32, bary: vec2<f32>) -> f32 {
176
- var alpha = materials[m].color.w * sampleMap(materials[m].map, triangle, bary).a
177
- * sampleMap(materials[m].alphaMap, triangle, bary).g;
190
+ return materialAlphaFrom(m, triangle, bary, sampleMap(materials[m].map, triangle, bary));
191
+ }
192
+
193
+ /** The same, from the colour map's texel at this point. Multiplied in the order resolveSurface multiplies it. */
194
+ fn materialAlphaFrom(m: u32, triangle: u32, bary: vec2<f32>, base: vec4<f32>) -> f32 {
195
+ var alpha = materials[m].color.w * base.a * sampleMap(materials[m].alphaMap, triangle, bary).g;
178
196
 
179
197
  if ((materials[m].flags & MATERIAL_VERTEX_COLORS) != 0u) {
180
198
  alpha = alpha * triangleColor(triangle, bary).a;
@@ -554,12 +572,31 @@ fn toonRamp(gradientMap: u32, cosine: f32) -> f32 {
554
572
  return sampleTextureRaw(gradientMap, vec2<f32>(coordinate, 0.0)).r;
555
573
  }
556
574
 
575
+ /**
576
+ * Whether a material's coverage can be told from its maps alone, before the rest of the surface is read: no shader that
577
+ * might rewrite the alpha or discard, normal blending, and something that makes it partial at all.
578
+ */
579
+ fn coverageFirst(m: u32) -> bool {
580
+ let flags = materials[m].flags;
581
+ let blending = materials[m].blending;
582
+
583
+ return materials[m].program == NO_PROGRAM
584
+ && (blending == BLEND_NORMAL || blending == BLEND_NONE)
585
+ && (materials[m].alphaTest > 0.0 || (flags & (MATERIAL_ALPHA_HASH | MATERIAL_TRANSPARENT)) != 0u);
586
+ }
587
+
557
588
  /** Everything the lobes need about one point of one triangle. */
558
589
  fn resolveSurface(triangle: u32, bary: vec2<f32>, direction: vec3<f32>) -> Surface {
559
590
  let m = materialIndexOf(triangle);
591
+
592
+ return resolveSurfaceFrom(triangle, bary, direction, sampleMap(materials[m].map, triangle, bary));
593
+ }
594
+
595
+ /** The same, from the colour map's texel at this point, for a caller that already read it. */
596
+ fn resolveSurfaceFrom(triangle: u32, bary: vec2<f32>, direction: vec3<f32>, base: vec4<f32>) -> Surface {
597
+ let m = materialIndexOf(triangle);
560
598
  let flags = materials[m].flags;
561
599
  let kind = materials[m].kind;
562
- let base = sampleMap(materials[m].map, triangle, bary);
563
600
  let facing = interpolatedNormal(m, triangle, bary, direction);
564
601
  let view = -direction;
565
602
  var surface: Surface;
@@ -588,7 +625,12 @@ fn resolveSurface(triangle: u32, bary: vec2<f32>, direction: vec3<f32>) -> Surfa
588
625
 
589
626
  var roughness = materials[m].specular.w * sampleMap(materials[m].roughnessMap, triangle, bary).g;
590
627
  var metalness = materials[m].metalness * sampleMap(materials[m].metalnessMap, triangle, bary).b;
591
- var emissive = emissionAt(triangle, bary);
628
+ var emissive = vec3<f32>(0.0);
629
+
630
+ // An unlit light's colour is added as what it shows, below; emissionAt gives the same colour to light samples.
631
+ if ((flags & MATERIAL_UNLIT_LIGHT) == 0u) {
632
+ emissive = emissionAt(triangle, bary);
633
+ }
592
634
 
593
635
  surface.opacity = 1.0;
594
636
 
@@ -635,6 +677,7 @@ fn resolveSurface(triangle: u32, bary: vec2<f32>, direction: vec3<f32>) -> Surfa
635
677
  surface.ior = max(materials[m].ior, 1.0);
636
678
  surface.thickness = materials[m].thickness * sampleMap(materials[m].thicknessMap, triangle, bary).g;
637
679
  surface.dispersion = materials[m].dispersion;
680
+ surface.subsurface = select(0.0, materials[m].subsurface.w, frame.subsurfaceEnabled != 0u);
638
681
  surface.absorption = absorptionOf(m);
639
682
  surface.shininess = materials[m].shininess;
640
683
  surface.specularStrength = sampleMap(materials[m].specularMap, triangle, bary).r;
@@ -33,10 +33,6 @@ fn wrapIndex(index: i32, size: i32, mode: u32) -> i32 {
33
33
  return clamp(index, 0, size - 1);
34
34
  }
35
35
 
36
- fn srgbChannelToLinear(value: f32) -> f32 {
37
- return select(pow((value + 0.055) / 1.055, 2.4), value / 12.92, value <= 0.04045);
38
- }
39
-
40
36
  /** One texel, in linear light. Alpha is never encoded, as in Three. */
41
37
  fn readTexel(info: TextureInfo, x: i32, y: i32) -> vec4<f32> {
42
38
  let index = u32(y) * info.size.x + u32(x);
@@ -52,18 +48,21 @@ fn readTexel(info: TextureInfo, x: i32, y: i32) -> vec4<f32> {
52
48
  }
53
49
 
54
50
  let word = textures[info.offset + index];
55
- let raw = vec4<f32>(
56
- f32(word & 0xffu),
57
- f32((word >> 8u) & 0xffu),
58
- f32((word >> 16u) & 0xffu),
59
- f32((word >> 24u) & 0xffu)) / 255.0;
60
51
 
52
+ // The decode is a table of the 256 codes rather than a power per channel and per texel: the same values, read.
61
53
  if ((info.flags & TEXTURE_SRGB) != 0u) {
62
54
  return vec4<f32>(
63
- srgbChannelToLinear(raw.r), srgbChannelToLinear(raw.g), srgbChannelToLinear(raw.b), raw.a);
55
+ bitcast<f32>(textures[SRGB_TABLE + (word & 0xffu)]),
56
+ bitcast<f32>(textures[SRGB_TABLE + ((word >> 8u) & 0xffu)]),
57
+ bitcast<f32>(textures[SRGB_TABLE + ((word >> 16u) & 0xffu)]),
58
+ f32((word >> 24u) & 0xffu) / 255.0);
64
59
  }
65
60
 
66
- return raw;
61
+ return vec4<f32>(
62
+ f32(word & 0xffu),
63
+ f32((word >> 8u) & 0xffu),
64
+ f32((word >> 16u) & 0xffu),
65
+ f32((word >> 24u) & 0xffu)) / 255.0;
67
66
  }
68
67
 
69
68
  /** One texture of the table, sampled with its own transform, wrap modes and filter. */