@woosh/meep-engine 3.14.0 → 3.14.2

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 (220) hide show
  1. package/README.md +33 -64
  2. package/package.json +1 -1
  3. package/src/avif/native/DECISIONS.md +544 -536
  4. package/src/avif/native/heif/parse_avif_file.d.ts.map +1 -1
  5. package/src/avif/native/heif/parse_avif_file.js +384 -383
  6. package/src/avif/native/heif/parse_image_grid.d.ts.map +1 -1
  7. package/src/avif/native/heif/parse_image_grid.js +49 -48
  8. package/src/basis/BasisBitReader.d.ts +77 -0
  9. package/src/basis/BasisBitReader.d.ts.map +1 -0
  10. package/src/basis/BasisBitReader.js +231 -0
  11. package/src/basis/BasisHuffmanTable.d.ts +53 -0
  12. package/src/basis/BasisHuffmanTable.d.ts.map +1 -0
  13. package/src/basis/BasisHuffmanTable.js +263 -0
  14. package/src/basis/basis_read_huffman_table.d.ts +20 -0
  15. package/src/basis/basis_read_huffman_table.d.ts.map +1 -0
  16. package/src/basis/basis_read_huffman_table.js +187 -0
  17. package/src/basis/etc1s/Etc1sSelectorHistory.d.ts +50 -0
  18. package/src/basis/etc1s/Etc1sSelectorHistory.d.ts.map +1 -0
  19. package/src/basis/etc1s/Etc1sSelectorHistory.js +89 -0
  20. package/src/basis/etc1s/etc1s_block_colors.d.ts +14 -0
  21. package/src/basis/etc1s/etc1s_block_colors.d.ts.map +1 -0
  22. package/src/basis/etc1s/etc1s_block_colors.js +75 -0
  23. package/src/basis/etc1s/etc1s_decode_slice.d.ts +57 -0
  24. package/src/basis/etc1s/etc1s_decode_slice.d.ts.map +1 -0
  25. package/src/basis/etc1s/etc1s_decode_slice.js +258 -0
  26. package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts +48 -0
  27. package/src/basis/etc1s/etc1s_read_endpoint_codebook.d.ts.map +1 -0
  28. package/src/basis/etc1s/etc1s_read_endpoint_codebook.js +111 -0
  29. package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts +42 -0
  30. package/src/basis/etc1s/etc1s_read_selector_codebook.d.ts.map +1 -0
  31. package/src/basis/etc1s/etc1s_read_selector_codebook.js +127 -0
  32. package/src/basis/etc1s/etc1s_read_slice_tables.d.ts +54 -0
  33. package/src/basis/etc1s/etc1s_read_slice_tables.d.ts.map +1 -0
  34. package/src/basis/etc1s/etc1s_read_slice_tables.js +47 -0
  35. package/src/basis/transcode/build_range_plan.js +54 -0
  36. package/src/basis/transcode/etc1s_to_bc1.d.ts +24 -0
  37. package/src/basis/transcode/etc1s_to_bc1.d.ts.map +1 -0
  38. package/src/basis/transcode/etc1s_to_bc1.js +205 -0
  39. package/src/basis/transcode/etc1s_to_bc7.d.ts +30 -0
  40. package/src/basis/transcode/etc1s_to_bc7.d.ts.map +1 -0
  41. package/src/basis/transcode/etc1s_to_bc7.js +496 -0
  42. package/src/basis/transcode/fit_endpoints.d.ts +59 -0
  43. package/src/basis/transcode/fit_endpoints.d.ts.map +1 -0
  44. package/src/basis/transcode/fit_endpoints.js +226 -0
  45. package/src/{avif/native/isobmff → core/binary}/ByteCursor.d.ts +19 -6
  46. package/src/core/binary/ByteCursor.d.ts.map +1 -0
  47. package/src/{avif/native/isobmff → core/binary}/ByteCursor.js +41 -14
  48. package/src/engine/EngineHarness.js +1 -1
  49. package/src/engine/asset/codec/Codec.d.ts.map +1 -0
  50. package/src/engine/asset/codec/CodecWithFallback.d.ts.map +1 -0
  51. package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.js +2 -2
  52. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +4 -4
  53. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts +1 -1
  54. package/src/engine/asset/loaders/image/ImageRGBADataLoader.d.ts.map +1 -1
  55. package/src/engine/asset/loaders/image/ImageRGBADataLoader.js +1 -1
  56. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts +1 -1
  57. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.d.ts.map +1 -1
  58. package/src/engine/asset/loaders/image/codec/NativeImageDecoder.js +1 -1
  59. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts +1 -1
  60. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.d.ts.map +1 -1
  61. package/src/engine/asset/loaders/image/codec/ThreadedImageDecoder.js +1 -1
  62. package/src/engine/graphics/texture/atlas/TextureAtlas.d.ts.map +1 -1
  63. package/src/engine/graphics/texture/atlas/TextureAtlas.js +13 -0
  64. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  65. package/src/engine/physics/broadphase/generate_pairs.js +7 -1
  66. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  67. package/src/ktx2/KTX2_IDENTIFIER.d.ts +14 -0
  68. package/src/ktx2/KTX2_IDENTIFIER.d.ts.map +1 -0
  69. package/src/ktx2/KTX2_IDENTIFIER.js +15 -0
  70. package/src/ktx2/KhrDfModel.d.ts +35 -0
  71. package/src/ktx2/KhrDfModel.d.ts.map +1 -0
  72. package/src/ktx2/KhrDfModel.js +49 -0
  73. package/src/ktx2/SupercompressionScheme.d.ts +16 -0
  74. package/src/ktx2/SupercompressionScheme.d.ts.map +1 -0
  75. package/src/ktx2/SupercompressionScheme.js +23 -0
  76. package/src/ktx2/ktx2_read.d.ts +71 -0
  77. package/src/ktx2/ktx2_read.d.ts.map +1 -0
  78. package/src/ktx2/ktx2_read.js +581 -0
  79. package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts +27 -0
  80. package/src/ktx2/ktx2_read_basis_lz_global_data.d.ts.map +1 -0
  81. package/src/ktx2/ktx2_read_basis_lz_global_data.js +189 -0
  82. package/src/ktx2/vk_format_to_texture_format.d.ts +55 -0
  83. package/src/ktx2/vk_format_to_texture_format.d.ts.map +1 -0
  84. package/src/ktx2/vk_format_to_texture_format.js +290 -0
  85. package/src/shade/descriptor/GPUTextureUsage.d.ts +23 -0
  86. package/src/shade/descriptor/GPUTextureUsage.d.ts.map +1 -0
  87. package/src/shade/descriptor/GPUTextureUsage.js +24 -0
  88. package/src/shade/descriptor/WebGPUExtensionType.d.ts +3 -0
  89. package/src/shade/descriptor/WebGPUExtensionType.js +26 -0
  90. package/src/shade/descriptor/texture/TextureDescriptor.d.ts +2 -6
  91. package/src/shade/descriptor/texture/TextureDescriptor.d.ts.map +1 -1
  92. package/src/shade/descriptor/texture/TextureDescriptor.js +24 -40
  93. package/src/shade/descriptor/texture/format/TextureFormat.d.ts +125 -0
  94. package/src/shade/descriptor/texture/format/TextureFormat.d.ts.map +1 -0
  95. package/src/shade/descriptor/texture/format/TextureFormat.js +146 -0
  96. package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts +60 -0
  97. package/src/shade/descriptor/texture/format/gpu_texture_format_info.d.ts.map +1 -1
  98. package/src/shade/descriptor/texture/format/gpu_texture_format_info.js +102 -0
  99. package/src/shade/device/graph/TextureResourceDescriptor.d.ts.map +1 -1
  100. package/src/shade/device/graph/TextureResourceDescriptor.js +160 -155
  101. package/src/shade/device/mock/SoftwareGPUQueue.d.ts +11 -4
  102. package/src/shade/device/mock/SoftwareGPUQueue.d.ts.map +1 -1
  103. package/src/shade/device/mock/SoftwareGPUQueue.js +31 -37
  104. package/src/shade/device/mock/SoftwareGPUTexture.d.ts.map +1 -1
  105. package/src/shade/device/mock/SoftwareGPUTexture.js +8 -4
  106. package/src/shade/device/timing/profile/frame_graph_extract_topology.d.ts.map +1 -1
  107. package/src/shade/device/timing/profile/frame_graph_extract_topology.js +164 -174
  108. package/src/shade/playground/ground_seam/README.md +235 -0
  109. package/src/shade/playground/ground_seam/capture_scene_color.d.ts +45 -0
  110. package/src/shade/playground/ground_seam/capture_scene_color.d.ts.map +1 -0
  111. package/src/shade/playground/ground_seam/capture_scene_color.js +242 -0
  112. package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts +11 -0
  113. package/src/shade/playground/ground_seam/depth_step_across_seam.d.ts.map +1 -0
  114. package/src/shade/playground/ground_seam/depth_step_across_seam.js +185 -0
  115. package/src/shade/playground/ground_seam/index.html +195 -0
  116. package/src/shade/playground/ground_seam/main.d.ts +2 -0
  117. package/src/shade/playground/ground_seam/main.d.ts.map +1 -0
  118. package/src/shade/playground/ground_seam/main.js +879 -0
  119. package/src/shade/playground/ground_seam/make_grid_texture.d.ts +29 -0
  120. package/src/shade/playground/ground_seam/make_grid_texture.d.ts.map +1 -0
  121. package/src/shade/playground/ground_seam/make_grid_texture.js +105 -0
  122. package/src/shade/playground/ground_seam/make_ground.d.ts +70 -0
  123. package/src/shade/playground/ground_seam/make_ground.d.ts.map +1 -0
  124. package/src/shade/playground/ground_seam/make_ground.js +161 -0
  125. package/src/shade/playground/ground_seam/measure_flicker.d.ts +71 -0
  126. package/src/shade/playground/ground_seam/measure_flicker.d.ts.map +1 -0
  127. package/src/shade/playground/ground_seam/measure_flicker.js +531 -0
  128. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  129. package/src/shade/renderer/Renderer.js +2519 -2511
  130. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  131. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +275 -274
  132. package/src/shade/renderer/light/GPULightCollection.d.ts.map +1 -1
  133. package/src/shade/renderer/light/GPULightCollection.js +323 -314
  134. package/src/shade/renderer/lightmap/GPULightMap.js +336 -336
  135. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  136. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +12 -2
  137. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  138. package/src/shade/renderer/material/standard/fragment_gbuffer.js +3 -1
  139. package/src/shade/renderer/material/standard/fragment_gbuffer_vt.js +169 -169
  140. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  141. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +3 -1
  142. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  143. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
  144. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.js +3 -1
  145. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
  146. package/src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.js +3 -1
  147. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts +28 -0
  148. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.d.ts.map +1 -0
  149. package/src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.js +39 -0
  150. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts +45 -0
  151. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.d.ts.map +1 -1
  152. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.js +94 -61
  153. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts +24 -0
  154. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.d.ts.map +1 -0
  155. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_solve.js +43 -0
  156. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +1462 -0
  157. package/src/shade/renderer/texture/TextureManager.d.ts.map +1 -1
  158. package/src/shade/renderer/texture/TextureManager.js +20 -8
  159. package/src/shade/renderer/texture/TextureRole.d.ts +19 -0
  160. package/src/shade/renderer/texture/TextureRole.d.ts.map +1 -0
  161. package/src/shade/renderer/texture/TextureRole.js +26 -0
  162. package/src/shade/renderer/texture/TextureVariantSet.d.ts +71 -0
  163. package/src/shade/renderer/texture/TextureVariantSet.d.ts.map +1 -0
  164. package/src/shade/renderer/texture/TextureVariantSet.js +105 -0
  165. package/src/shade/renderer/texture/download_texture_data.d.ts.map +1 -1
  166. package/src/shade/renderer/texture/download_texture_data.js +22 -0
  167. package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts +15 -0
  168. package/src/shade/renderer/texture/format/gpu_texture_compression_support.d.ts.map +1 -0
  169. package/src/shade/renderer/texture/format/gpu_texture_compression_support.js +50 -0
  170. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts +27 -0
  171. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.d.ts.map +1 -0
  172. package/src/shade/renderer/texture/format/gpu_texture_format_can_generate_mipmaps.js +65 -0
  173. package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts +11 -0
  174. package/src/shade/renderer/texture/format/infer_format_from_parameters.d.ts.map +1 -0
  175. package/src/shade/renderer/texture/format/infer_format_from_parameters.js +88 -0
  176. package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts +24 -0
  177. package/src/shade/renderer/texture/format/texture_format_from_shade_image.d.ts.map +1 -0
  178. package/src/shade/renderer/texture/format/texture_format_from_shade_image.js +71 -0
  179. package/src/shade/renderer/texture/format/texture_format_preference.d.ts +22 -0
  180. package/src/shade/renderer/texture/format/texture_format_preference.d.ts.map +1 -0
  181. package/src/shade/renderer/texture/format/texture_format_preference.js +89 -0
  182. package/src/shade/renderer/texture/format/texture_variant_select.d.ts +24 -0
  183. package/src/shade/renderer/texture/format/texture_variant_select.d.ts.map +1 -0
  184. package/src/shade/renderer/texture/format/texture_variant_select.js +38 -0
  185. package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts +9 -1
  186. package/src/shade/renderer/texture/shade_texture_might_have_alpha.d.ts.map +1 -1
  187. package/src/shade/renderer/texture/shade_texture_might_have_alpha.js +73 -8
  188. package/src/shade/renderer/texture/source/AlphaMode.d.ts +27 -0
  189. package/src/shade/renderer/texture/source/AlphaMode.d.ts.map +1 -0
  190. package/src/shade/renderer/texture/source/AlphaMode.js +52 -0
  191. package/src/shade/renderer/texture/source/ShadeImage.d.ts +33 -0
  192. package/src/shade/renderer/texture/source/ShadeImage.d.ts.map +1 -1
  193. package/src/shade/renderer/texture/source/ShadeImage.js +74 -0
  194. package/src/shade/renderer/texture/source/ShadeTexelData.d.ts +78 -0
  195. package/src/shade/renderer/texture/source/ShadeTexelData.d.ts.map +1 -0
  196. package/src/shade/renderer/texture/source/ShadeTexelData.js +158 -0
  197. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts +0 -10
  198. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.d.ts.map +1 -1
  199. package/src/shade/renderer/texture/texture_descriptor_from_texture_shade.js +73 -175
  200. package/src/shade/renderer/texture/texture_write_level.d.ts +32 -0
  201. package/src/shade/renderer/texture/texture_write_level.d.ts.map +1 -0
  202. package/src/shade/renderer/texture/texture_write_level.js +77 -0
  203. package/src/shade/renderer/texture/texture_write_to_gpu.d.ts +8 -1
  204. package/src/shade/renderer/texture/texture_write_to_gpu.d.ts.map +1 -1
  205. package/src/shade/renderer/texture/texture_write_to_gpu.js +62 -37
  206. package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts +8 -0
  207. package/src/shade/renderer/texture/virtual/source/VTSourceImage.d.ts.map +1 -1
  208. package/src/shade/renderer/texture/virtual/source/VTSourceImage.js +8 -0
  209. package/src/shade/util/texture_mip_extent.d.ts +49 -0
  210. package/src/shade/util/texture_mip_extent.d.ts.map +1 -0
  211. package/src/shade/util/texture_mip_extent.js +87 -0
  212. package/src/avif/native/isobmff/ByteCursor.d.ts.map +0 -1
  213. package/src/engine/asset/loaders/image/codec/Codec.d.ts.map +0 -1
  214. package/src/engine/asset/loaders/image/codec/CodecWithFallback.d.ts.map +0 -1
  215. package/src/shade/util/compute_max_mip_count.d.ts +0 -8
  216. package/src/shade/util/compute_max_mip_count.d.ts.map +0 -1
  217. package/src/shade/util/compute_max_mip_count.js +0 -27
  218. /package/src/engine/asset/{loaders/image/codec → codec}/Codec.d.ts +0 -0
  219. /package/src/engine/asset/{loaders/image/codec → codec}/Codec.js +0 -0
  220. /package/src/engine/asset/{loaders/image/codec → codec}/CodecWithFallback.d.ts +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"GPUResidentMaterialContext.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/resident/GPUResidentMaterialContext.js"],"names":[],"mappings":"AAuDA,sDAAuD;AAEvD,wDAAyD;AAEzD,+DAAiJ;AAEjJ,+DAA+I;AAE/I;IA8GI;;;;OAIG;IACH,0DAoCC;IA3HD;;;OAGG;IACH,6BAEC;IAQD;;;OAGG;IACH,kCAEC;IAQD;;;OAGG;IACH,yCAEC;IAED;;;OAGG;IACH,kCAIC;IA0GD;;;;OAIG;IACH,0CAFa,YAAY,CAIxB;IAgBD;;;;OAIG;IACH,uCAFa,WAAW,CAIvB;IAGD,uBAqHC;IAED,wBA2EC;IAED;;;OAGG;IACH,2CAgBC;IAoCD,eASC;IAGD,gBAGC;;CACJ;kCAnhBiC,oCAAoC;AAOtE;IACI,WAAM;IAEN;;OAEG;IACH,8BAAO;IAEP;;OAEG;IACH,gBAFU,WAAW,CAEP;IAEd;;OAEG;IACH,aAFU,WAAW,CAEV;IAEX;;OAEG;IACH,gBAFU,WAAW,CAEP;IACd;;OAEG;IACH,kBAFU,WAAW,CAEL;CACnB;AAED;IACI,WAAO;IAEP;;OAEG;IACH,qBAAO;CACV"}
1
+ {"version":3,"file":"GPUResidentMaterialContext.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/resident/GPUResidentMaterialContext.js"],"names":[],"mappings":"AAuDA,sDAAuD;AAEvD,wDAAyD;AAEzD,+DAAiJ;AAEjJ,+DAA+I;AAE/I;IA8GI;;;;OAIG;IACH,0DAoCC;IA3HD;;;OAGG;IACH,6BAEC;IAQD;;;OAGG;IACH,kCAEC;IAQD;;;OAGG;IACH,yCAEC;IAED;;;OAGG;IACH,kCAIC;IA0GD;;;;OAIG;IACH,0CAFa,YAAY,CAIxB;IAgBD;;;;OAIG;IACH,uCAFa,WAAW,CAIvB;IAGD,uBA+HC;IAED,wBA2EC;IAED;;;OAGG;IACH,2CAgBC;IAoCD,eASC;IAGD,gBAGC;;CACJ;kCA7hBiC,oCAAoC;AAOtE;IACI,WAAM;IAEN;;OAEG;IACH,8BAAO;IAEP;;OAEG;IACH,gBAFU,WAAW,CAEP;IAEd;;OAEG;IACH,aAFU,WAAW,CAEV;IAEX;;OAEG;IACH,gBAFU,WAAW,CAEP;IACd;;OAEG;IACH,kBAFU,WAAW,CAEL;CACnB;AAED;IACI,WAAO;IAEP;;OAEG;IACH,qBAAO;CACV"}
@@ -322,7 +322,17 @@ export class GPUResidentMaterialContext {
322
322
 
323
323
  const is_square = source_ctx.width === source_ctx.height;
324
324
 
325
- const is_srgb = source.image.color_space === ColorSpace.SRGB;
325
+ /*
326
+ The fast path is a copyTextureToTexture, which requires the two formats to be
327
+ copy-compatible. `!is_srgb` used to stand in for that and was true only by accident: every
328
+ material texture was rgba8unorm, so the only way to differ was the srgb suffix. A BC7
329
+ source would have reached the copy and failed validation.
330
+
331
+ Asking the question directly costs nothing and covers every format at once — a source
332
+ that does not match takes the render path below, which samples it into the atlas and is
333
+ what that path exists for.
334
+ */
335
+ const format_matches = source_ctx.gpu_texture.format === target_texture.gpu_texture.format;
326
336
 
327
337
  const is_pot_w = isPowerOfTwo(source_ctx.width) && isPowerOfTwo(source_ctx.height);
328
338
 
@@ -335,7 +345,7 @@ export class GPUResidentMaterialContext {
335
345
  const texture_slot_y = Math.floor(id_in_slice / RESIDENT_MATERIAL_TEXTURE_SLOT_RESOLUTION);
336
346
  const texture_slot_x = id_in_slice % RESIDENT_MATERIAL_TEXTURE_SLOT_RESOLUTION;
337
347
 
338
- if (is_square && is_pot_w && source_mip_w >= 0 && source_ctx.gpu_texture.mipLevelCount >= source_mip_w && !is_srgb) {
348
+ if (is_square && is_pot_w && source_mip_w >= 0 && source_ctx.gpu_texture.mipLevelCount >= source_mip_w && format_matches) {
339
349
 
340
350
  encoder.copyTextureToTexture(
341
351
  {
@@ -1 +1 @@
1
- {"version":3,"file":"fragment_gbuffer.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/standard/fragment_gbuffer.js"],"names":[],"mappings":"AA4EA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;IAR6B,OAAO,GAAzB,MAAM;IACW,GAAG,EAApB,MAAM;IACW,MAAM,EAAvB,MAAM;IACW,OAAO,EAAxB,MAAM;IACW,QAAQ,EAAzB,MAAM;kBACN,SAAS,EAAE,GACT,SAAS,CAiOrB;AAhRD,oEAA2E;AAI3E,oIAEG;AASH,sIAEG;AAwQH,8CAIE;0BAzSwB,oCAAoC;4CAClB,sDAAsD;iCACjE,kCAAkC"}
1
+ {"version":3,"file":"fragment_gbuffer.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/material/standard/fragment_gbuffer.js"],"names":[],"mappings":"AA6EA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;IAR6B,OAAO,GAAzB,MAAM;IACW,GAAG,EAApB,MAAM;IACW,MAAM,EAAvB,MAAM;IACW,OAAO,EAAxB,MAAM;IACW,QAAQ,EAAzB,MAAM;kBACN,SAAS,EAAE,GACT,SAAS,CAkOrB;AAjRD,oEAA2E;AAI3E,oIAEG;AASH,sIAEG;AAyQH,8CAIE;0BA1SwB,oCAAoC;4CAClB,sDAAsD;iCACjE,kCAAkC"}
@@ -1,4 +1,5 @@
1
1
  import { GPUShaderStage } from "../../../descriptor/GPUShaderStage.js";
2
+ import { chunk_decode_tangent_normal } from "../../shader/chunk/geometry/normal/chunk_decode_tangent_normal.js";
2
3
  import { u32 } from "../../shader/type/WEBGPU_WGSL_PRIMITIVE_TYPES.js";
3
4
  import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
4
5
  import { CAMERA_UNIFORM_STRUCT } from "../../camera/CAMERA_UNIFORM_STRUCT.js";
@@ -308,6 +309,7 @@ fn main(
308
309
  chunk_compute_normal_matrix_from_m4,
309
310
  chunk_anti_alias_roughness_kaplanyan,
310
311
  chunk_build_orthonormal_matrix_nt,
312
+ chunk_decode_tangent_normal,
311
313
  chunk_read_meshlet_triangle_vertices,
312
314
  chunk_decode_meshlet_element,
313
315
  chunk_compute_triangle_face_normal,
@@ -322,7 +324,7 @@ fn main(
322
324
 
323
325
  const body = build_gbuffer_fragment_body({
324
326
  orm: `textureSampleBarycentric(texture_orm, texture_orm_sampler, uv_info)`,
325
- normal: `textureSampleBarycentric(texture_normal, texture_normal_sampler, uv_info).rgb * 2.0 - 1.0`,
327
+ normal: `decode_tangent_normal(textureSampleBarycentric(texture_normal, texture_normal_sampler, uv_info))`,
326
328
  diffuse: `textureSampleBarycentric(texture_diffuse, texture_diffuse_sampler, uv_info)`,
327
329
  emissive: `textureSampleBarycentric(texture_emissive, texture_emissive_sampler, uv_info).rgb`,
328
330
  });
@@ -1,169 +1,169 @@
1
- import { GPUShaderStage } from "../../../descriptor/GPUShaderStage.js";
2
- import { RenderPipelineDescriptor } from "../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
3
- import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
4
- import { G_BUFFER_COLOR_TARGETS } from "../../gbuffer/G_BUFFER_COLOR_TARGETS.js";
5
- import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
6
- import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
7
- import { ShaderResourceGroupDescriptor } from "../../shader/resource/ShaderResourceGroupDescriptor.js";
8
- import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
9
- import { VT_STACK_INFO_STRUCT } from "../../texture/virtual/VT_STACK_INFO_STRUCT.js";
10
- import { MATERIAL_METADATA_STRUCT } from "../MATERIAL_METADATA_STRUCT.js";
11
- import {
12
- build_gbuffer_fragment_body,
13
- g_buffer_scene_resources,
14
- g_buffer_viz_resources,
15
- } from "./fragment_gbuffer.js";
16
- import { material_gbuffer_vertex_shader_code } from "./material_gbuffer_vertex.js";
17
-
18
- /**
19
- * Group 0 of the virtual-texture material variant. Replaces the four
20
- * per-material texture bindings of the standard group with the VT globals:
21
- * the shared page table, the stack info buffer and the physical cache
22
- * layers — identical for every VT material, which is what lets hundreds of
23
- * them share one pipeline and the same feedback/table infrastructure.
24
- * Emissive stays a regular per-material texture (emissive maps are rarely
25
- * the memory problem VT solves).
26
- *
27
- * `material_info` must stay at binding 0 — the shared vertex stage
28
- * ({@link material_gbuffer_vertex_shader_code}) addresses it there.
29
- */
30
- export const SHADING_MATERIAL_VT_RESOURCE_GROUP = new ShaderResourceGroupDescriptor();
31
-
32
- SHADING_MATERIAL_VT_RESOURCE_GROUP.label = "Material VT";
33
-
34
- SHADING_MATERIAL_VT_RESOURCE_GROUP
35
- .addUniform("material_info", MATERIAL_METADATA_STRUCT)
36
- .addTexture("texture_emissive", "float")
37
- .addSampler("texture_emissive_sampler")
38
- .addTexture("vt_page_table", "uint")
39
- .addStorageBuffer("vt_stacks", WebGPUArray.from(VT_STACK_INFO_STRUCT))
40
- .addTexture("vt_cache_albedo", "float")
41
- .addTexture("vt_cache_normal", "float")
42
- .addTexture("vt_cache_orm", "float")
43
- .addSampler("vt_cache_sampler");
44
-
45
- export const vt_gbuffer_shader_resources = new ShaderResourceSetDescriptor();
46
-
47
- // group order mirrors the standard material set — groups 1 and 2 are the
48
- // *same descriptor objects*, so the two pipelines are bind-group compatible
49
- // and the material pass can set viz/scene groups once for both
50
- vt_gbuffer_shader_resources.addGroup(SHADING_MATERIAL_VT_RESOURCE_GROUP);
51
- vt_gbuffer_shader_resources.addGroup(g_buffer_viz_resources);
52
- vt_gbuffer_shader_resources.addGroup(g_buffer_scene_resources);
53
-
54
- vt_gbuffer_shader_resources.addVisibility(GPUShaderStage.FRAGMENT);
55
- vt_gbuffer_shader_resources.getResourceByName("material_info").addVisibility(GPUShaderStage.VERTEX);
56
-
57
- const chunk_vt_sample_layer = new WeakMap();
58
-
59
- /**
60
- * Build the VT variant of the G-buffer material pipeline for a concrete
61
- * cache geometry. Called (and memoized) by the VirtualTextureManager once
62
- * its configuration is frozen.
63
- *
64
- * Sampling model (v1): one page-table fetch per pixel serves all three
65
- * layers — the stack's UV set, wrap mode and residency resolve once, then
66
- * albedo/normal/ORM are three bilinear fetches at the same physical
67
- * coordinate in their respective atlases. Missing layers and not-yet-
68
- * resident cells fall back to per-layer neutral values (albedo falls back
69
- * to the stack's average colour).
70
- *
71
- * @param {CodeChunk} chunk_vt_lookup from {@link build_chunk_vt_lookup}
72
- * @returns {RenderPipelineDescriptor}
73
- */
74
- export function build_vt_material_pipeline_descriptor(chunk_vt_lookup) {
75
-
76
- let sample_chunk = chunk_vt_sample_layer.get(chunk_vt_lookup);
77
-
78
- if (sample_chunk === undefined) {
79
- sample_chunk = CodeChunk.from(
80
- //language=WGSL
81
- `
82
- fn vt_sample_layer(
83
- cache: texture_2d<f32>,
84
- cache_sampler: sampler,
85
- phys: VTPhysical,
86
- available: bool,
87
- fallback: vec4<f32>,
88
- ) -> vec4<f32> {
89
- if (!available) {
90
- return fallback;
91
- }
92
-
93
- // physical atlases are single-mip; virtual mip selection already
94
- // happened through the page table
95
- return textureSampleLevel(cache, cache_sampler, phys.uv, 0.0);
96
- }
97
- `,
98
- [chunk_vt_lookup]
99
- );
100
-
101
- chunk_vt_sample_layer.set(chunk_vt_lookup, sample_chunk);
102
- }
103
-
104
- const body = build_gbuffer_fragment_body(
105
- {
106
- prelude: `
107
- // ── virtual texture resolve, once per pixel for all layers ──────
108
- let vt_info = vt_stacks[material_info.vt_stack];
109
- let vt_layer_mask = vt_info.flags >> 8u;
110
-
111
- if ((vt_info.flags & VT_STACK_FLAG_UV_SET_1) != 0u) {
112
- // stack binds the second UV set — re-interpolate and re-bias
113
- uv_info = barycentric_interpolate_uv(barycentric, vertex_0.uv1, vertex_1.uv1, vertex_2.uv1);
114
- uv_info.ddx *= uv_derivative_bias.x;
115
- uv_info.ddy *= uv_derivative_bias.y;
116
- }
117
-
118
- let vt_uv = vt_stack_wrap_uv(uv_info.uv, vt_info.flags);
119
- let vt_mip = vt_mip_select(vt_info, uv_info.ddx, uv_info.ddy, 0.0);
120
- let vt_entry = vt_page_table_load(vt_page_table, vt_info, vt_uv, vt_mip);
121
-
122
- var vt_phys = VTPhysical(vec2<f32>(0.0), 0.0);
123
-
124
- if (vt_entry.valid) {
125
- vt_phys = vt_physical_uv(vt_entry, vt_info, vt_uv);
126
- }
127
- `,
128
- orm: `vt_sample_layer(vt_cache_orm, vt_cache_sampler, vt_phys, vt_entry.valid && (vt_layer_mask & 4u) != 0u, vec4<f32>(1.0, 1.0, 0.0, 1.0))`,
129
- normal: `vt_sample_layer(vt_cache_normal, vt_cache_sampler, vt_phys, vt_entry.valid && (vt_layer_mask & 2u) != 0u, vec4<f32>(0.5, 0.5, 1.0, 1.0)).rgb * 2.0 - 1.0`,
130
- diffuse: `vt_sample_layer(vt_cache_albedo, vt_cache_sampler, vt_phys, vt_entry.valid && (vt_layer_mask & 1u) != 0u, vt_info.average_color)`,
131
- emissive: `textureSampleBarycentric(texture_emissive, texture_emissive_sampler, uv_info).rgb`,
132
- },
133
- [
134
- sample_chunk,
135
- ]
136
- );
137
-
138
- const shader = ShaderDescriptor.from({
139
- label: "Material / GBuffer laydown (virtual texture)",
140
- resources: vt_gbuffer_shader_resources,
141
- body,
142
- });
143
-
144
- return RenderPipelineDescriptor.from({
145
- label: "VT material / Viz-Buffer to G-Buffer laydown",
146
- layout: vt_gbuffer_shader_resources.generatePipelineLayoutDescriptor(),
147
- vertex: {
148
- module: {
149
- code: material_gbuffer_vertex_shader_code
150
- }
151
- },
152
- fragment: {
153
- module: {
154
- code: shader.source,
155
- },
156
- targets: G_BUFFER_COLOR_TARGETS
157
- },
158
- depthStencil: {
159
- // depth is a material mask — see the standard material pipeline
160
- depthCompare: 'equal',
161
- format: 'depth32float',
162
- depthWriteEnabled: false
163
- },
164
- primitive: {
165
- topology: 'triangle-list',
166
- cullMode: 'none',
167
- }
168
- });
169
- }
1
+ import { GPUShaderStage } from "../../../descriptor/GPUShaderStage.js";
2
+ import { RenderPipelineDescriptor } from "../../../descriptor/pipeline/render/RenderPipelineDescriptor.js";
3
+ import { WebGPUArray } from "../../shader/type/WebGPUArray.js";
4
+ import { G_BUFFER_COLOR_TARGETS } from "../../gbuffer/G_BUFFER_COLOR_TARGETS.js";
5
+ import { CodeChunk } from "../../shader/compiler/CodeChunk.js";
6
+ import { ShaderDescriptor } from "../../shader/ShaderDescriptor.js";
7
+ import { ShaderResourceGroupDescriptor } from "../../shader/resource/ShaderResourceGroupDescriptor.js";
8
+ import { ShaderResourceSetDescriptor } from "../../shader/resource/ShaderResourceSetDescriptor.js";
9
+ import { VT_STACK_INFO_STRUCT } from "../../texture/virtual/VT_STACK_INFO_STRUCT.js";
10
+ import { MATERIAL_METADATA_STRUCT } from "../MATERIAL_METADATA_STRUCT.js";
11
+ import {
12
+ build_gbuffer_fragment_body,
13
+ g_buffer_scene_resources,
14
+ g_buffer_viz_resources,
15
+ } from "./fragment_gbuffer.js";
16
+ import { material_gbuffer_vertex_shader_code } from "./material_gbuffer_vertex.js";
17
+
18
+ /**
19
+ * Group 0 of the virtual-texture material variant. Replaces the four
20
+ * per-material texture bindings of the standard group with the VT globals:
21
+ * the shared page table, the stack info buffer and the physical cache
22
+ * layers — identical for every VT material, which is what lets hundreds of
23
+ * them share one pipeline and the same feedback/table infrastructure.
24
+ * Emissive stays a regular per-material texture (emissive maps are rarely
25
+ * the memory problem VT solves).
26
+ *
27
+ * `material_info` must stay at binding 0 — the shared vertex stage
28
+ * ({@link material_gbuffer_vertex_shader_code}) addresses it there.
29
+ */
30
+ export const SHADING_MATERIAL_VT_RESOURCE_GROUP = new ShaderResourceGroupDescriptor();
31
+
32
+ SHADING_MATERIAL_VT_RESOURCE_GROUP.label = "Material VT";
33
+
34
+ SHADING_MATERIAL_VT_RESOURCE_GROUP
35
+ .addUniform("material_info", MATERIAL_METADATA_STRUCT)
36
+ .addTexture("texture_emissive", "float")
37
+ .addSampler("texture_emissive_sampler")
38
+ .addTexture("vt_page_table", "uint")
39
+ .addStorageBuffer("vt_stacks", WebGPUArray.from(VT_STACK_INFO_STRUCT))
40
+ .addTexture("vt_cache_albedo", "float")
41
+ .addTexture("vt_cache_normal", "float")
42
+ .addTexture("vt_cache_orm", "float")
43
+ .addSampler("vt_cache_sampler");
44
+
45
+ export const vt_gbuffer_shader_resources = new ShaderResourceSetDescriptor();
46
+
47
+ // group order mirrors the standard material set — groups 1 and 2 are the
48
+ // *same descriptor objects*, so the two pipelines are bind-group compatible
49
+ // and the material pass can set viz/scene groups once for both
50
+ vt_gbuffer_shader_resources.addGroup(SHADING_MATERIAL_VT_RESOURCE_GROUP);
51
+ vt_gbuffer_shader_resources.addGroup(g_buffer_viz_resources);
52
+ vt_gbuffer_shader_resources.addGroup(g_buffer_scene_resources);
53
+
54
+ vt_gbuffer_shader_resources.addVisibility(GPUShaderStage.FRAGMENT);
55
+ vt_gbuffer_shader_resources.getResourceByName("material_info").addVisibility(GPUShaderStage.VERTEX);
56
+
57
+ const chunk_vt_sample_layer = new WeakMap();
58
+
59
+ /**
60
+ * Build the VT variant of the G-buffer material pipeline for a concrete
61
+ * cache geometry. Called (and memoized) by the VirtualTextureManager once
62
+ * its configuration is frozen.
63
+ *
64
+ * Sampling model (v1): one page-table fetch per pixel serves all three
65
+ * layers — the stack's UV set, wrap mode and residency resolve once, then
66
+ * albedo/normal/ORM are three bilinear fetches at the same physical
67
+ * coordinate in their respective atlases. Missing layers and not-yet-
68
+ * resident cells fall back to per-layer neutral values (albedo falls back
69
+ * to the stack's average colour).
70
+ *
71
+ * @param {CodeChunk} chunk_vt_lookup from {@link build_chunk_vt_lookup}
72
+ * @returns {RenderPipelineDescriptor}
73
+ */
74
+ export function build_vt_material_pipeline_descriptor(chunk_vt_lookup) {
75
+
76
+ let sample_chunk = chunk_vt_sample_layer.get(chunk_vt_lookup);
77
+
78
+ if (sample_chunk === undefined) {
79
+ sample_chunk = CodeChunk.from(
80
+ //language=WGSL
81
+ `
82
+ fn vt_sample_layer(
83
+ cache: texture_2d<f32>,
84
+ cache_sampler: sampler,
85
+ phys: VTPhysical,
86
+ available: bool,
87
+ fallback: vec4<f32>,
88
+ ) -> vec4<f32> {
89
+ if (!available) {
90
+ return fallback;
91
+ }
92
+
93
+ // physical atlases are single-mip; virtual mip selection already
94
+ // happened through the page table
95
+ return textureSampleLevel(cache, cache_sampler, phys.uv, 0.0);
96
+ }
97
+ `,
98
+ [chunk_vt_lookup]
99
+ );
100
+
101
+ chunk_vt_sample_layer.set(chunk_vt_lookup, sample_chunk);
102
+ }
103
+
104
+ const body = build_gbuffer_fragment_body(
105
+ {
106
+ prelude: `
107
+ // ── virtual texture resolve, once per pixel for all layers ──────
108
+ let vt_info = vt_stacks[material_info.vt_stack];
109
+ let vt_layer_mask = vt_info.flags >> 8u;
110
+
111
+ if ((vt_info.flags & VT_STACK_FLAG_UV_SET_1) != 0u) {
112
+ // stack binds the second UV set — re-interpolate and re-bias
113
+ uv_info = barycentric_interpolate_uv(barycentric, vertex_0.uv1, vertex_1.uv1, vertex_2.uv1);
114
+ uv_info.ddx *= uv_derivative_bias.x;
115
+ uv_info.ddy *= uv_derivative_bias.y;
116
+ }
117
+
118
+ let vt_uv = vt_stack_wrap_uv(uv_info.uv, vt_info.flags);
119
+ let vt_mip = vt_mip_select(vt_info, uv_info.ddx, uv_info.ddy, 0.0);
120
+ let vt_entry = vt_page_table_load(vt_page_table, vt_info, vt_uv, vt_mip);
121
+
122
+ var vt_phys = VTPhysical(vec2<f32>(0.0), 0.0);
123
+
124
+ if (vt_entry.valid) {
125
+ vt_phys = vt_physical_uv(vt_entry, vt_info, vt_uv);
126
+ }
127
+ `,
128
+ orm: `vt_sample_layer(vt_cache_orm, vt_cache_sampler, vt_phys, vt_entry.valid && (vt_layer_mask & 4u) != 0u, vec4<f32>(1.0, 1.0, 0.0, 1.0))`,
129
+ normal: `decode_tangent_normal(vt_sample_layer(vt_cache_normal, vt_cache_sampler, vt_phys, vt_entry.valid && (vt_layer_mask & 2u) != 0u, vec4<f32>(0.5, 0.5, 1.0, 1.0)))`,
130
+ diffuse: `vt_sample_layer(vt_cache_albedo, vt_cache_sampler, vt_phys, vt_entry.valid && (vt_layer_mask & 1u) != 0u, vt_info.average_color)`,
131
+ emissive: `textureSampleBarycentric(texture_emissive, texture_emissive_sampler, uv_info).rgb`,
132
+ },
133
+ [
134
+ sample_chunk,
135
+ ]
136
+ );
137
+
138
+ const shader = ShaderDescriptor.from({
139
+ label: "Material / GBuffer laydown (virtual texture)",
140
+ resources: vt_gbuffer_shader_resources,
141
+ body,
142
+ });
143
+
144
+ return RenderPipelineDescriptor.from({
145
+ label: "VT material / Viz-Buffer to G-Buffer laydown",
146
+ layout: vt_gbuffer_shader_resources.generatePipelineLayoutDescriptor(),
147
+ vertex: {
148
+ module: {
149
+ code: material_gbuffer_vertex_shader_code
150
+ }
151
+ },
152
+ fragment: {
153
+ module: {
154
+ code: shader.source,
155
+ },
156
+ targets: G_BUFFER_COLOR_TARGETS
157
+ },
158
+ depthStencil: {
159
+ // depth is a material mask — see the standard material pipeline
160
+ depthCompare: 'equal',
161
+ format: 'depth32float',
162
+ depthWriteEnabled: false
163
+ },
164
+ primitive: {
165
+ topology: 'triangle-list',
166
+ cullMode: 'none',
167
+ }
168
+ });
169
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_sample_material_data.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js"],"names":[],"mappings":"AA6BA;;;GAGG;AACH,0CAFU,SAAS,CA8FlB;AAED,mDAqHC;0BA9NyB,oCAAoC"}
1
+ {"version":3,"file":"chunk_sample_material_data.d.ts","sourceRoot":"","sources":["../../../../../../src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js"],"names":[],"mappings":"AA8BA;;;GAGG;AACH,0CAFU,SAAS,CA8FlB;AAED,mDAsHC;0BA/NyB,oCAAoC"}
@@ -1,4 +1,5 @@
1
1
  import { chunk_compute_normal_matrix_from_m4 } from "../../shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.js";
2
+ import { chunk_decode_tangent_normal } from "../../shader/chunk/geometry/normal/chunk_decode_tangent_normal.js";
2
3
  import { chunk_F_Hauber } from "../../shader/chunk/brdf/fresnel/chunk_F_Hauber.js";
3
4
  import {
4
5
  chunk_build_orthonormal_matrix_nt
@@ -202,7 +203,7 @@ fn sample_material_data(
202
203
 
203
204
  let world_tangent_frame = build_orthonormal_matrix_nt(world_vertex_normal, vec4(world_tangent, geometry_tangent.w));
204
205
 
205
- var normal_sample = indirect_sample_texture(material.texture_normal, material.sampler_normal, uv).rgb * 2.0 - 1.0;
206
+ var normal_sample = decode_tangent_normal(indirect_sample_texture(material.texture_normal, material.sampler_normal, uv));
206
207
 
207
208
  var output: ${STANDARD_MATERIAL_DATA_STRUCT.wgsl_ref};
208
209
 
@@ -238,6 +239,7 @@ fn sample_material_data(
238
239
  chunk_interpolate_attribute_4f32,
239
240
  chunk_compute_normal_matrix_from_m4,
240
241
  chunk_build_orthonormal_matrix_nt,
242
+ chunk_decode_tangent_normal,
241
243
  chunk_compute_triangle_face_normal,
242
244
  chunk_indirect_sample_texture,
243
245
  chunk_random_vec3,
@@ -49,7 +49,7 @@ export class NSS {
49
49
  * @returns {number}
50
50
  */
51
51
  static recommended_jitter_sequence_size(upscale_ratio: number): number;
52
- static "__#136@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
52
+ static "__#140@#preprocess_tensor_descriptor"(render_w: any, render_h: any): TextureResourceDescriptor;
53
53
  /**
54
54
  * @param {GraphicsContext} graphics
55
55
  */
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_forward_shade_standard_fragment_brick4.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.js"],"names":[],"mappings":"AA2BA,qEAuJC;0BA1JyB,uCAAuC"}
1
+ {"version":3,"file":"chunk_forward_shade_standard_fragment_brick4.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_brick4.js"],"names":[],"mappings":"AA4BA,qEAwJC;0BA3JyB,uCAAuC"}
@@ -1,4 +1,5 @@
1
1
  import { chunk_shade_standard_material_direct } from "../../../deferred/chunk_shade_standard_material_direct.js";
2
+ import { chunk_decode_tangent_normal } from "../../../shader/chunk/geometry/normal/chunk_decode_tangent_normal.js";
2
3
  import { INDIRECT_LIGHT_INTENSITY } from "../../../deferred/INDIRECT_LIGHT_INTENSITY.js";
3
4
  import {
4
5
  chunk_brick4_sample_forward_indirect
@@ -34,7 +35,7 @@ fn forward_shade_standard_fragment(
34
35
  ) -> vec4f {
35
36
  let world_tangent_frame = build_orthonormal_matrix_nt(vert.normal, vert.tangent);
36
37
 
37
- let t_normal = textureSample(texture_normal, texture_normal_sampler, vert.uv).rgb * 2.0 - 1.0;
38
+ let t_normal = decode_tangent_normal(textureSample(texture_normal, texture_normal_sampler, vert.uv));
38
39
  var world_shading_normal:vec3<f32> = normalize( world_tangent_frame * t_normal );
39
40
 
40
41
  // flip normal if fragment is back-facing,
@@ -169,6 +170,7 @@ fn forward_shade_standard_fragment(
169
170
  chunk_dielectric_specular_color,
170
171
  chunk_F_Hauber,
171
172
  chunk_build_orthonormal_matrix_nt,
173
+ chunk_decode_tangent_normal,
172
174
  chunk_anti_alias_roughness_kaplanyan,
173
175
  chunk_shade_standard_material_direct,
174
176
  chunk_get_view_space_depth,
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_forward_shade_standard_fragment_ibl.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.js"],"names":[],"mappings":"AA0BA;;;GAGG;AACH,kEA4IC;0BAnJyB,uCAAuC"}
1
+ {"version":3,"file":"chunk_forward_shade_standard_fragment_ibl.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/rasterize/native/oit/chunk_forward_shade_standard_fragment_ibl.js"],"names":[],"mappings":"AA2BA;;;GAGG;AACH,kEA6IC;0BApJyB,uCAAuC"}
@@ -1,4 +1,5 @@
1
1
  import { chunk_shade_standard_material_direct } from "../../../deferred/chunk_shade_standard_material_direct.js";
2
+ import { chunk_decode_tangent_normal } from "../../../shader/chunk/geometry/normal/chunk_decode_tangent_normal.js";
2
3
  import { chunk_get_ibl_irradiance } from "../../../deferred/indirect/chunk_get_ibl_irradiance.js";
3
4
  import { chunk_get_ibl_radiance } from "../../../deferred/indirect/chunk_get_ibl_radiance.js";
4
5
  import { INDIRECT_LIGHT_INTENSITY } from "../../../deferred/INDIRECT_LIGHT_INTENSITY.js";
@@ -37,7 +38,7 @@ fn forward_shade_standard_fragment(
37
38
  ) -> vec4f {
38
39
  let world_tangent_frame = build_orthonormal_matrix_nt(vert.normal, vert.tangent);
39
40
 
40
- let t_normal = textureSample(texture_normal, texture_normal_sampler, vert.uv).rgb * 2.0 - 1.0;
41
+ let t_normal = decode_tangent_normal(textureSample(texture_normal, texture_normal_sampler, vert.uv));
41
42
  var world_shading_normal:vec3<f32> = normalize( world_tangent_frame * t_normal );
42
43
 
43
44
  // flip normal if fragment is back-facing,
@@ -160,6 +161,7 @@ fn forward_shade_standard_fragment(
160
161
  chunk_dielectric_specular_color,
161
162
  chunk_F_Hauber,
162
163
  chunk_build_orthonormal_matrix_nt,
164
+ chunk_decode_tangent_normal,
163
165
  chunk_anti_alias_roughness_kaplanyan,
164
166
  chunk_shade_standard_material_direct,
165
167
  chunk_get_view_space_depth,
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Decode a tangent-space normal from a normal map sample.
3
+ *
4
+ * **Z is reconstructed, never read.** A tangent-space normal points away from the surface, so its Z
5
+ * is positive by construction and `sqrt(1 - x² - y²)` recovers it exactly for a unit normal. The blue
6
+ * channel of an RGB normal map is therefore redundant, and reconstructing rather than reading it
7
+ * makes this decode correct for two-channel formats as well — `bc5-rg-unorm` and `eac-rg11unorm`
8
+ * spend the same bits on two channels that BC7 spends on three, and are what a normal map should be
9
+ * shipped as.
10
+ *
11
+ * That is the whole reason this exists. A two-channel sample reads `(x, y, 0, 1)`, so the
12
+ * `.rgb * 2.0 - 1.0` this replaces produced `z = -1` — every normal pointing directly into the
13
+ * surface, and no lighting at all. One decode serves both, so nothing downstream branches on the
14
+ * format and no pipeline is compiled twice.
15
+ *
16
+ * {@link chunk_safe_sqrt} guards the root: filtering and lossy compression both produce samples
17
+ * slightly off the unit circle, and `x² + y²` a hair over 1 would otherwise be `NaN` rather than a
18
+ * normal lying in the tangent plane.
19
+ *
20
+ * Object-space normal maps are not this, and would need the sign they do not carry. glTF's
21
+ * `normalTexture` is tangent-space by specification, which is where every normal map in the engine
22
+ * comes from.
23
+ *
24
+ * @type {CodeChunk}
25
+ */
26
+ export const chunk_decode_tangent_normal: CodeChunk;
27
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
28
+ //# sourceMappingURL=chunk_decode_tangent_normal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chunk_decode_tangent_normal.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/geometry/normal/chunk_decode_tangent_normal.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,0CAFU,SAAS,CAYZ;0BAtCmB,gCAAgC"}
@@ -0,0 +1,39 @@
1
+ import { CodeChunk } from "../../../compiler/CodeChunk.js";
2
+ import { chunk_safe_sqrt } from "../../math/chunk_safe_sqrt.js";
3
+
4
+ /**
5
+ * Decode a tangent-space normal from a normal map sample.
6
+ *
7
+ * **Z is reconstructed, never read.** A tangent-space normal points away from the surface, so its Z
8
+ * is positive by construction and `sqrt(1 - x² - y²)` recovers it exactly for a unit normal. The blue
9
+ * channel of an RGB normal map is therefore redundant, and reconstructing rather than reading it
10
+ * makes this decode correct for two-channel formats as well — `bc5-rg-unorm` and `eac-rg11unorm`
11
+ * spend the same bits on two channels that BC7 spends on three, and are what a normal map should be
12
+ * shipped as.
13
+ *
14
+ * That is the whole reason this exists. A two-channel sample reads `(x, y, 0, 1)`, so the
15
+ * `.rgb * 2.0 - 1.0` this replaces produced `z = -1` — every normal pointing directly into the
16
+ * surface, and no lighting at all. One decode serves both, so nothing downstream branches on the
17
+ * format and no pipeline is compiled twice.
18
+ *
19
+ * {@link chunk_safe_sqrt} guards the root: filtering and lossy compression both produce samples
20
+ * slightly off the unit circle, and `x² + y²` a hair over 1 would otherwise be `NaN` rather than a
21
+ * normal lying in the tangent plane.
22
+ *
23
+ * Object-space normal maps are not this, and would need the sign they do not carry. glTF's
24
+ * `normalTexture` is tangent-space by specification, which is where every normal map in the engine
25
+ * comes from.
26
+ *
27
+ * @type {CodeChunk}
28
+ */
29
+ export const chunk_decode_tangent_normal = CodeChunk.from(
30
+ //language=WGSL
31
+ `
32
+ fn decode_tangent_normal(texel: vec4<f32>) -> vec3<f32> {
33
+ let xy = fma(texel.rg, vec2<f32>(2.0), vec2<f32>(-1.0));
34
+
35
+ return vec3<f32>(xy, safe_sqrt(1.0 - dot(xy, xy)));
36
+ }
37
+ `, [
38
+ chunk_safe_sqrt,
39
+ ]);
@@ -1,3 +1,48 @@
1
+ /**
2
+ * Perspective-correct barycentric coordinates for a pixel inside a triangle, with the per-pixel
3
+ * derivatives the texture gradients are built from.
4
+ *
5
+ * ## What it solves
6
+ *
7
+ * A point of the triangle with barycentric `l` sits at clip position `sum(l_i * P_i)` and therefore
8
+ * at screen position `sum(l_i * P_i.xy) / sum(l_i * P_i.w)`. Asking for the `l` whose screen
9
+ * position is this pixel gives two linear equations, and `sum(l) == 1` gives the third:
10
+ *
11
+ * ```
12
+ * sum_i l_i * (x_i - pixel.x * w_i) = 0
13
+ * sum_i l_i * (y_i - pixel.y * w_i) = 0
14
+ * sum_i l_i = 1
15
+ * ```
16
+ *
17
+ * This function forms the two pixel-relative coordinate vectors that system is written in;
18
+ * {@link chunk_barycentric_solve} solves it.
19
+ *
20
+ * ## Why it is written this way
21
+ *
22
+ * **It never divides by w.** A vertex on the eye plane has `w == 0` and one behind it has `w < 0`;
23
+ * projecting either to NDC first yields an infinity or a sign-flipped coordinate hundreds of
24
+ * thousands of pixels outside the viewport, and every later term then has to cancel that magnitude
25
+ * back down. Here `w` only ever multiplies, so a triangle straddling the eye plane is an ordinary
26
+ * case rather than a near-singular one.
27
+ *
28
+ * **It has no anchor, and that is the point.** The previous formulation measured every pixel from
29
+ * `pixel - ndc0` and scaled by a determinant taken about vertex 1, so vertex 0 was the origin of
30
+ * the whole reconstruction and the three corners were not interchangeable. In exact arithmetic that
31
+ * is irrelevant. In f32, on a triangle whose corners project far outside the viewport, it is not:
32
+ * the rounding depended on which corner was first, so two coplanar triangles meeting along an edge
33
+ * reconstructed measurably different UVs on either side of it — and the difference moved with the
34
+ * TAA jitter, which turned it into a temporally unstable seam along the shared edge. Invisible in a
35
+ * still frame, plainly visible in a multi-frame difference. `src/shade/playground/ground_seam`
36
+ * measures it, and measured this rewrite: the seam goes from a 2.1x step in per-pixel temporal
37
+ * spread to none, and a two-triangle quad now behaves like the same quad subdivided 8x8.
38
+ *
39
+ * **The derivatives are evaluations, not a differentiation.** `ddx` is defined as
40
+ * `lambda(pixel + (1,0)) - lambda(pixel)`, a whole-pixel forward difference, which is what mip
41
+ * selection wants; it is computed by solving the same system one pixel over. Stepping the pixel by
42
+ * one in x subtracts `w` from `u`, so the second and third solves share every input with the first.
43
+ *
44
+ * @type {CodeChunk}
45
+ */
1
46
  export const chunk_barycentric_full: CodeChunk;
2
47
  import { CodeChunk } from "../../../compiler/CodeChunk.js";
3
48
  //# sourceMappingURL=chunk_barycentric_full.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_barycentric_full.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.js"],"names":[],"mappings":"AAWA,+CAiDE;0BA3DwB,gCAAgC"}
1
+ {"version":3,"file":"chunk_barycentric_full.d.ts","sourceRoot":"","sources":["../../../../../../../../src/shade/renderer/shader/chunk/geometry/triangle/chunk_barycentric_full.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,qCAFU,SAAS,CAuCjB;0BA5FwB,gCAAgC"}