@zephyr3d/scene 0.9.22 → 0.9.24

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 (234) hide show
  1. package/dist/animation/joint_dynamics/collision.js +1 -7
  2. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  3. package/dist/animation/joint_dynamics/constraints.js +2 -17
  4. package/dist/animation/joint_dynamics/constraints.js.map +1 -1
  5. package/dist/animation/joint_dynamics/controller.js +2 -20
  6. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  7. package/dist/animation/joint_dynamics/joint_dynamics_system.js +1 -3
  8. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  9. package/dist/animation/joint_dynamics/solver.js +14 -60
  10. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  11. package/dist/animation/joint_dynamics/types.js +3 -3
  12. package/dist/animation/joint_dynamics/types.js.map +1 -1
  13. package/dist/app/app.js +23 -0
  14. package/dist/app/app.js.map +1 -1
  15. package/dist/app/scriptregistry.js +16 -53
  16. package/dist/app/scriptregistry.js.map +1 -1
  17. package/dist/asset/assetmanager.js +2 -0
  18. package/dist/asset/assetmanager.js.map +1 -1
  19. package/dist/asset/model.js +22 -0
  20. package/dist/asset/model.js.map +1 -1
  21. package/dist/blitter/bilateralblur.js +3 -1
  22. package/dist/blitter/bilateralblur.js.map +1 -1
  23. package/dist/blitter/blitter.js +3 -3
  24. package/dist/blitter/blitter.js.map +1 -1
  25. package/dist/camera/camera.js +398 -45
  26. package/dist/camera/camera.js.map +1 -1
  27. package/dist/camera/perspectivecamera.js +69 -2
  28. package/dist/camera/perspectivecamera.js.map +1 -1
  29. package/dist/index.d.ts +9113 -8740
  30. package/dist/index.js +10 -2
  31. package/dist/index.js.map +1 -1
  32. package/dist/material/blinn.js +1 -1
  33. package/dist/material/blinn.js.map +1 -1
  34. package/dist/material/lambert.js +3 -3
  35. package/dist/material/lambert.js.map +1 -1
  36. package/dist/material/material.js +8 -5
  37. package/dist/material/material.js.map +1 -1
  38. package/dist/material/meshmaterial.js +17 -10
  39. package/dist/material/meshmaterial.js.map +1 -1
  40. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  41. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  42. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  43. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  44. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +21 -6
  45. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  46. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +1 -1
  47. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  48. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +1 -1
  49. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  50. package/dist/material/mixins/lit.js +33 -11
  51. package/dist/material/mixins/lit.js.map +1 -1
  52. package/dist/material/mixins/pbr/brdf.js +44 -12
  53. package/dist/material/mixins/pbr/brdf.js.map +1 -1
  54. package/dist/material/mixins/pbr/common.js +149 -14
  55. package/dist/material/mixins/pbr/common.js.map +1 -1
  56. package/dist/material/mtoon.js +7 -4
  57. package/dist/material/mtoon.js.map +1 -1
  58. package/dist/material/pbrblueprint.js +5 -1
  59. package/dist/material/pbrblueprint.js.map +1 -1
  60. package/dist/material/pbrmr.js +1 -1
  61. package/dist/material/pbrmr.js.map +1 -1
  62. package/dist/material/pbrsg.js +1 -1
  63. package/dist/material/pbrsg.js.map +1 -1
  64. package/dist/material/shader/helper.js +512 -334
  65. package/dist/material/shader/helper.js.map +1 -1
  66. package/dist/material/skin.js +2 -2
  67. package/dist/material/skin.js.map +1 -1
  68. package/dist/material/terrain-cm.js +5 -5
  69. package/dist/material/terrain-cm.js.map +1 -1
  70. package/dist/material/water.js +6 -4
  71. package/dist/material/water.js.map +1 -1
  72. package/dist/posteffect/bloom.js +54 -4
  73. package/dist/posteffect/bloom.js.map +1 -1
  74. package/dist/posteffect/compositor.js +41 -0
  75. package/dist/posteffect/compositor.js.map +1 -1
  76. package/dist/posteffect/posteffect.js +35 -0
  77. package/dist/posteffect/posteffect.js.map +1 -1
  78. package/dist/posteffect/sao.js +7 -6
  79. package/dist/posteffect/sao.js.map +1 -1
  80. package/dist/posteffect/skinsss.js +3 -3
  81. package/dist/posteffect/skinsss.js.map +1 -1
  82. package/dist/posteffect/ssgi.js +988 -436
  83. package/dist/posteffect/ssgi.js.map +1 -1
  84. package/dist/posteffect/ssr.js +83 -45
  85. package/dist/posteffect/ssr.js.map +1 -1
  86. package/dist/posteffect/sss.js +18 -15
  87. package/dist/posteffect/sss.js.map +1 -1
  88. package/dist/posteffect/taa.js +5 -4
  89. package/dist/posteffect/taa.js.map +1 -1
  90. package/dist/posteffect/tonemap.js +15 -3
  91. package/dist/posteffect/tonemap.js.map +1 -1
  92. package/dist/render/abuffer_oit.js +2 -2
  93. package/dist/render/abuffer_oit.js.map +1 -1
  94. package/dist/render/cluster_light.js +22 -16
  95. package/dist/render/cluster_light.js.map +1 -1
  96. package/dist/render/drawable_mixin.js +8 -5
  97. package/dist/render/drawable_mixin.js.map +1 -1
  98. package/dist/render/dualdepthpeeling_oit.js +10 -5
  99. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  100. package/dist/render/envlight.js +298 -5
  101. package/dist/render/envlight.js.map +1 -1
  102. package/dist/render/gpu_picking.js +7 -5
  103. package/dist/render/gpu_picking.js.map +1 -1
  104. package/dist/render/hzb.js +28 -19
  105. package/dist/render/hzb.js.map +1 -1
  106. package/dist/render/lightpass.js +18 -4
  107. package/dist/render/lightpass.js.map +1 -1
  108. package/dist/render/render_queue.js +37 -4
  109. package/dist/render/render_queue.js.map +1 -1
  110. package/dist/render/renderer.js +8 -3
  111. package/dist/render/renderer.js.map +1 -1
  112. package/dist/render/rendergraph/blackboard.js +20 -48
  113. package/dist/render/rendergraph/blackboard.js.map +1 -1
  114. package/dist/render/rendergraph/device_pool_allocator.js +18 -58
  115. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -1
  116. package/dist/render/rendergraph/executor.js +89 -115
  117. package/dist/render/rendergraph/executor.js.map +1 -1
  118. package/dist/render/rendergraph/forward_plus_builder.js +1003 -715
  119. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  120. package/dist/render/rendergraph/frame_graph_context.js +1 -1
  121. package/dist/render/rendergraph/frame_graph_context.js.map +1 -1
  122. package/dist/render/rendergraph/frame_resource_requirements.js +14 -0
  123. package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -0
  124. package/dist/render/rendergraph/history_resource_manager.js +74 -140
  125. package/dist/render/rendergraph/history_resource_manager.js.map +1 -1
  126. package/dist/render/rendergraph/history_resources.js +7 -5
  127. package/dist/render/rendergraph/history_resources.js.map +1 -1
  128. package/dist/render/rendergraph/render_context.js +19 -0
  129. package/dist/render/rendergraph/render_context.js.map +1 -0
  130. package/dist/render/rendergraph/render_pipeline.js +315 -0
  131. package/dist/render/rendergraph/render_pipeline.js.map +1 -0
  132. package/dist/render/rendergraph/rendergraph.js +158 -141
  133. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  134. package/dist/render/rendergraph/scene_render_context.js +267 -0
  135. package/dist/render/rendergraph/scene_render_context.js.map +1 -0
  136. package/dist/render/rendergraph/texture_affinity_cache.js +19 -0
  137. package/dist/render/rendergraph/texture_affinity_cache.js.map +1 -0
  138. package/dist/render/rendergraph/types.js +19 -31
  139. package/dist/render/rendergraph/types.js.map +1 -1
  140. package/dist/render/renderpass.js +3 -3
  141. package/dist/render/renderpass.js.map +1 -1
  142. package/dist/render/shadow_mask_pass.js +7 -6
  143. package/dist/render/shadow_mask_pass.js.map +1 -1
  144. package/dist/render/sky.js +257 -95
  145. package/dist/render/sky.js.map +1 -1
  146. package/dist/render/weightedblended_oit.js +4 -3
  147. package/dist/render/weightedblended_oit.js.map +1 -1
  148. package/dist/scene/basesprite.js +2 -0
  149. package/dist/scene/basesprite.js.map +1 -1
  150. package/dist/scene/batchgroup.js +10 -0
  151. package/dist/scene/batchgroup.js.map +1 -1
  152. package/dist/scene/environment.js +61 -2
  153. package/dist/scene/environment.js.map +1 -1
  154. package/dist/scene/light.js +178 -10
  155. package/dist/scene/light.js.map +1 -1
  156. package/dist/scene/meshdrawable.js +89 -2
  157. package/dist/scene/meshdrawable.js.map +1 -1
  158. package/dist/scene/msdftext.js +2 -0
  159. package/dist/scene/msdftext.js.map +1 -1
  160. package/dist/scene/msdftextsprite.js +2 -0
  161. package/dist/scene/msdftextsprite.js.map +1 -1
  162. package/dist/scene/particlesys.js +2 -0
  163. package/dist/scene/particlesys.js.map +1 -1
  164. package/dist/scene/scene.js +34 -1
  165. package/dist/scene/scene.js.map +1 -1
  166. package/dist/scene/terrain-cm/grass.js +2 -1
  167. package/dist/scene/terrain-cm/grass.js.map +1 -1
  168. package/dist/scene/terrain-cm/terrain-cm.js +2 -0
  169. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  170. package/dist/scene/water.js +2 -0
  171. package/dist/scene/water.js.map +1 -1
  172. package/dist/shaders/atmosphere.js +5 -4
  173. package/dist/shaders/atmosphere.js.map +1 -1
  174. package/dist/shaders/fog.js +10 -3
  175. package/dist/shaders/fog.js.map +1 -1
  176. package/dist/shaders/shadow.js +149 -40
  177. package/dist/shaders/shadow.js.map +1 -1
  178. package/dist/shaders/ssgi_reprojection.js +118 -0
  179. package/dist/shaders/ssgi_reprojection.js.map +1 -0
  180. package/dist/shaders/ssr.js +322 -154
  181. package/dist/shaders/ssr.js.map +1 -1
  182. package/dist/shadow/esm.js +10 -7
  183. package/dist/shadow/esm.js.map +1 -1
  184. package/dist/shadow/pcf_opt.js +12 -12
  185. package/dist/shadow/pcf_opt.js.map +1 -1
  186. package/dist/shadow/pcf_pd.js +12 -12
  187. package/dist/shadow/pcf_pd.js.map +1 -1
  188. package/dist/shadow/pcss.js +16 -11
  189. package/dist/shadow/pcss.js.map +1 -1
  190. package/dist/shadow/shadow_impl.js +29 -3
  191. package/dist/shadow/shadow_impl.js.map +1 -1
  192. package/dist/shadow/shadowmapper.js +5 -2
  193. package/dist/shadow/shadowmapper.js.map +1 -1
  194. package/dist/shadow/ssm.js +13 -13
  195. package/dist/shadow/ssm.js.map +1 -1
  196. package/dist/shadow/vsm.js +7 -7
  197. package/dist/shadow/vsm.js.map +1 -1
  198. package/dist/utility/physical.js +74 -0
  199. package/dist/utility/physical.js.map +1 -0
  200. package/dist/utility/rendermipmap.js +2 -2
  201. package/dist/utility/rendermipmap.js.map +1 -1
  202. package/dist/utility/serialization/manager.js +3 -1
  203. package/dist/utility/serialization/manager.js.map +1 -1
  204. package/dist/utility/serialization/scene/animation.js +3 -1
  205. package/dist/utility/serialization/scene/animation.js.map +1 -1
  206. package/dist/utility/serialization/scene/batch.js +3 -1
  207. package/dist/utility/serialization/scene/batch.js.map +1 -1
  208. package/dist/utility/serialization/scene/camera.js +598 -2
  209. package/dist/utility/serialization/scene/camera.js.map +1 -1
  210. package/dist/utility/serialization/scene/light.js +180 -9
  211. package/dist/utility/serialization/scene/light.js.map +1 -1
  212. package/dist/utility/serialization/scene/material.js +43 -3
  213. package/dist/utility/serialization/scene/material.js.map +1 -1
  214. package/dist/utility/serialization/scene/mesh.js +3 -1
  215. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  216. package/dist/utility/serialization/scene/node.js +3 -1
  217. package/dist/utility/serialization/scene/node.js.map +1 -1
  218. package/dist/utility/serialization/scene/particle.js +3 -1
  219. package/dist/utility/serialization/scene/particle.js.map +1 -1
  220. package/dist/utility/serialization/scene/primitive.js +2 -0
  221. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  222. package/dist/utility/serialization/scene/scene.js +70 -0
  223. package/dist/utility/serialization/scene/scene.js.map +1 -1
  224. package/dist/utility/serialization/scene/sprite.js +3 -1
  225. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  226. package/dist/utility/serialization/scene/terrain.js +3 -1
  227. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  228. package/dist/utility/serialization/scene/text.js +3 -0
  229. package/dist/utility/serialization/scene/text.js.map +1 -1
  230. package/dist/utility/serialization/scene/water.js +3 -1
  231. package/dist/utility/serialization/scene/water.js.map +1 -1
  232. package/dist/values.js +59 -65
  233. package/dist/values.js.map +1 -1
  234. package/package.json +3 -3
@@ -1,8 +1,9 @@
1
- import { Vector3, Vector4, Vector2 } from '@zephyr3d/base';
2
- import { RENDER_PASS_TYPE_DEPTH, RENDER_PASS_TYPE_SHADOWMAP, RENDER_PASS_TYPE_OBJECT_COLOR, RENDER_PASS_TYPE_LIGHT, MaterialVaryingFlags, MAX_CLUSTERED_LIGHTS, MORPH_WEIGHTS_VECTOR_COUNT, MORPH_TARGET_POSITION, MORPH_TARGET_NORMAL, MORPH_TARGET_TANGENT, MORPH_ATTRIBUTE_VECTOR_COUNT } from '../../values.js';
1
+ import { Vector3, Vector4, Vector2, REVERSE_Z, DEPTH_FARTHEST, DEPTH_REDUCE_CLOSER, DEPTH_REDUCE_FARTHER } from '@zephyr3d/base';
2
+ import { RENDER_PASS_TYPE_DEPTH, RENDER_PASS_TYPE_SHADOWMAP, RENDER_PASS_TYPE_OBJECT_COLOR, RENDER_PASS_TYPE_LIGHT, MaterialVaryingFlags, MORPH_WEIGHTS_VECTOR_COUNT, MORPH_TARGET_POSITION, MORPH_TARGET_NORMAL, MORPH_TARGET_TANGENT, MORPH_ATTRIBUTE_VECTOR_COUNT } from '../../values.js';
3
3
  import { ProgramBuilder } from '@zephyr3d/device';
4
4
  import { decodeNormalizedFloatFromRGBA, linearToGamma } from '../../shaders/misc.js';
5
5
  import { getSamplerOptions, fetchSampler } from '../../utility/misc.js';
6
+ import { PHYSICAL_BAKE_EXPOSURE } from '../../utility/physical.js';
6
7
  import { getDevice } from '../../app/api.js';
7
8
  import { getDefaultAtmosphereParams, getAtmosphereParamsStruct } from '../../shaders/atmosphere.js';
8
9
  import { getDefaultHeightFogParams, getHeightFogParamsStruct, calculateFog } from '../../shaders/fog.js';
@@ -33,9 +34,9 @@ const UNIFORM_NAME_BONE_TEXTURE_SIZE = 'Z_UniformBoneTexSize';
33
34
  const UNIFORM_NAME_BONE_INV_BIND_MATRIX = 'Z_UniformBoneInvBindMatrix';
34
35
  const UNIFORM_NAME_MORPH_DATA = 'Z_UniformMorphData';
35
36
  const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
36
- /**
37
- * Helper shader functions for the builtin material system
38
- * @public
37
+ /**
38
+ * Helper shader functions for the builtin material system
39
+ * @public
39
40
  */ class ShaderHelper {
40
41
  static BILLBOARD_SPHERICAL = 1;
41
42
  static BILLBOARD_SYLINDRAL = 2;
@@ -128,25 +129,25 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
128
129
  }
129
130
  return bindGroupLayout;
130
131
  }
131
- /**
132
- * Prepares the fragment shader which is going to be used in our material system
133
- *
134
- * @remarks
135
- * This function will setup all nessesary uniforms acoording to the drawing context
136
- *
137
- * @param pb - The program builder
138
- * @param ctx - The drawing context
132
+ /**
133
+ * Prepares the fragment shader which is going to be used in our material system
134
+ *
135
+ * @remarks
136
+ * This function will setup all nessesary uniforms acoording to the drawing context
137
+ *
138
+ * @param pb - The program builder
139
+ * @param ctx - The drawing context
139
140
  */ static prepareFragmentShader(pb, ctx) {
140
141
  this.setupGlobalUniforms(pb, ctx);
141
142
  }
142
- /**
143
- * Prepares the vertex shader which is going to be used in our material system
144
- *
145
- * @remarks
146
- * This function will setup all nessesary uniforms according to the drawing context
147
- *
148
- * @param pb - The program builder
149
- * @param ctx - The drawing context
143
+ /**
144
+ * Prepares the vertex shader which is going to be used in our material system
145
+ *
146
+ * @remarks
147
+ * This function will setup all nessesary uniforms according to the drawing context
148
+ *
149
+ * @param pb - The program builder
150
+ * @param ctx - The drawing context
150
151
  */ static prepareVertexShader(pb, ctx) {
151
152
  this.setupGlobalUniforms(pb, ctx);
152
153
  this.prepareVertexShaderCommon(pb, ctx);
@@ -173,6 +174,7 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
173
174
  pb.float('shadowDebugCascades'),
174
175
  pb.float('frameDeltaTime'),
175
176
  pb.float('elapsedTime'),
177
+ pb.float('preExposure'),
176
178
  pb.int('framestamp')
177
179
  ]);
178
180
  if (ctx.renderPass.type === RENDER_PASS_TYPE_SHADOWMAP) {
@@ -237,7 +239,7 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
237
239
  scope.camera = cameraStruct().uniform(0);
238
240
  scope.light = lightStruct().uniform(0);
239
241
  if (useClusteredLighting) {
240
- scope[UNIFORM_NAME_LIGHT_BUFFER] = pb.vec4[(MAX_CLUSTERED_LIGHTS + 1) * 4]().uniformBuffer(0);
242
+ scope[UNIFORM_NAME_LIGHT_BUFFER] = pb.vec4[(this.getMaxClusterLights() + 1) * 4]().uniformBuffer(0);
241
243
  // Non-WebGL1 devices fetch the light index texture with textureLoad
242
244
  scope[UNIFORM_NAME_LIGHT_INDEX_TEXTURE] = (pb.getDevice().type === 'webgl' ? pb.tex2D() : pb.utex2D().noSampler()).uniform(0);
243
245
  // Screen-space shadow mask array (rgba8unorm, 4 shadow lights per layer).
@@ -271,12 +273,12 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
271
273
  scope[UNIFORM_NAME_SHADOW_MAP] = tex.uniform(0);
272
274
  }
273
275
  if (ctx.drawEnvLight) {
274
- ctx.env.light.envLight.initShaderBindings(pb);
276
+ ctx.env.light.envLight.initShaderBindings(pb, ctx);
275
277
  }
276
278
  if (ctx.linearDepthTexture) {
277
279
  // Depth values must never be filtered across geometry edges; nearest
278
280
  // matches the default sampler for unfilterable float formats.
279
- scope[UNIFORM_NAME_LINEAR_DEPTH_MAP] = pb.tex2D().uniform(0).withSampler(getSamplerOptions('clamp_nearest_nomip'));
281
+ scope[UNIFORM_NAME_LINEAR_DEPTH_MAP] = pb.tex2D().sampleType('unfilterable-float').uniform(0).withSampler(getSamplerOptions('clamp_nearest_nomip'));
280
282
  scope[UNIFORM_NAME_LINEAR_DEPTH_MAP_SIZE] = pb.vec2().uniform(0);
281
283
  }
282
284
  if (ctx.sceneColorTexture) {
@@ -286,35 +288,35 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
286
288
  }
287
289
  if (ctx.HiZTexture) {
288
290
  // Matches the fetchSampler('clamp_nearest') previously passed at runtime
289
- scope[UNIFORM_NAME_HIZ_DEPTH_MAP] = pb.tex2D().uniform(0).withSampler(getSamplerOptions('clamp_nearest'));
291
+ scope[UNIFORM_NAME_HIZ_DEPTH_MAP] = pb.tex2D().sampleType('unfilterable-float').uniform(0).withSampler(getSamplerOptions('clamp_nearest'));
290
292
  scope[UNIFORM_NAME_HIZ_DEPTH_MAP_INFO] = pb.vec4().uniform(0);
291
293
  }
292
294
  }
293
295
  }
294
- /**
295
- * This function checks if the shader needs to process skeletal animation.
296
- *
297
- * @param scope - Current shader scope
298
- *
299
- * @returns true if the shader needs to process skeletal animation, otherwise false.
296
+ /**
297
+ * This function checks if the shader needs to process skeletal animation.
298
+ *
299
+ * @param scope - Current shader scope
300
+ *
301
+ * @returns true if the shader needs to process skeletal animation, otherwise false.
300
302
  */ static hasSkinning(scope) {
301
303
  return !!scope[UNIFORM_NAME_BONE_MATRICES];
302
304
  }
303
- /**
304
- * This function checks if the shader needs to process morph target animation.
305
- *
306
- * @param scope - Current shader scope
307
- *
308
- * @returns true if the shader needs to process morph target animation, otherwise false.
305
+ /**
306
+ * This function checks if the shader needs to process morph target animation.
307
+ *
308
+ * @param scope - Current shader scope
309
+ *
310
+ * @returns true if the shader needs to process morph target animation, otherwise false.
309
311
  */ static hasMorphing(scope) {
310
312
  return !!scope[UNIFORM_NAME_MORPH_DATA];
311
313
  }
312
- /**
313
- * Calculate skinning matrix for current vertex
314
- *
315
- * @param scope - Current shader scope
316
- *
317
- * @returns Skinning matrix for current vertex, or null if there is not skeletal animation
314
+ /**
315
+ * Calculate skinning matrix for current vertex
316
+ *
317
+ * @param scope - Current shader scope
318
+ *
319
+ * @returns Skinning matrix for current vertex, or null if there is not skeletal animation
318
320
  */ static calculateSkinMatrix(scope) {
319
321
  if (!this.hasSkinning(scope)) {
320
322
  return null;
@@ -469,12 +471,12 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
469
471
  scope.$l[that.SKIN_PREV_MATRIX_NAME] = scope[funcNameGetSkinningMatrix](scope[that.SKIN_BONE_OFFSET].y);
470
472
  }
471
473
  }
472
- /**
473
- * Calculates the vertex position of type vec3 in object space
474
- *
475
- * @param scope - Current shader scope
476
- * @param skinMatrix - The skinning matrix if there is skeletal animation, otherwise null
477
- * @returns The calculated vertex position in object space, or null if pos is null
474
+ /**
475
+ * Calculates the vertex position of type vec3 in object space
476
+ *
477
+ * @param scope - Current shader scope
478
+ * @param skinMatrix - The skinning matrix if there is skeletal animation, otherwise null
479
+ * @returns The calculated vertex position in object space, or null if pos is null
478
480
  */ static resolveVertexPosition(scope) {
479
481
  const pb = scope.$builder;
480
482
  if (pb.shaderKind !== 'vertex') {
@@ -516,12 +518,12 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
516
518
  });
517
519
  return scope[that.SKIN_MATRIX_NAME] && scope[that.SKIN_PREV_MATRIX_NAME] ? scope.Z_resolveVertexPosition(scope[that.SKIN_MATRIX_NAME], scope[that.SKIN_PREV_MATRIX_NAME]) : scope[that.SKIN_MATRIX_NAME] ? scope.Z_resolveVertexPosition(scope[that.SKIN_MATRIX_NAME]) : scope.Z_resolveVertexPosition();
518
520
  }
519
- /**
520
- * Resolve motion vector
521
- *
522
- * @param scope - Current shader scope
523
- * @param worldPos - Current object position in world space
524
- * @param prevWorldPos - Previous object position in world space
521
+ /**
522
+ * Resolve motion vector
523
+ *
524
+ * @param scope - Current shader scope
525
+ * @param worldPos - Current object position in world space
526
+ * @param prevWorldPos - Previous object position in world space
525
527
  */ static resolveMotionVector(scope, worldPos, prevWorldPos) {
526
528
  const that = this;
527
529
  const pb = scope.$builder;
@@ -532,13 +534,13 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
532
534
  scope.$outputs.zMotionVectorPosPrev = pb.mul(prevUnjitteredVPMatrix, pb.vec4(prevWorldPos.xyz, 1));
533
535
  }
534
536
  }
535
- /**
536
- * Calculates the normal vector of type vec3 in object space
537
- *
538
- * @param scope - Current shader scope
539
- * @param normal - Vertex normal input, must be type of vec3, null if no vertex normal input
540
- * @param skinMatrix - The skinning matrix if there is skeletal animation, otherwise null
541
- * @returns The calculated normal vector in object space, or null if normal is null
537
+ /**
538
+ * Calculates the normal vector of type vec3 in object space
539
+ *
540
+ * @param scope - Current shader scope
541
+ * @param normal - Vertex normal input, must be type of vec3, null if no vertex normal input
542
+ * @param skinMatrix - The skinning matrix if there is skeletal animation, otherwise null
543
+ * @returns The calculated normal vector in object space, or null if normal is null
542
544
  */ static resolveVertexNormal(scope, normal) {
543
545
  const pb = scope.$builder;
544
546
  if (pb.shaderKind !== 'vertex') {
@@ -563,13 +565,13 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
563
565
  return normal;
564
566
  }
565
567
  }
566
- /**
567
- * Calculates the tangent vector of type vec3 in object space
568
- *
569
- * @param scope - Current shader scope
570
- * @param tangent - Vertex tangent input, must be type of vec4, null if no vertex tangent input
571
- * @param skinMatrix - The skinning matrix if there is skeletal animation, otherwise null
572
- * @returns The calculated tangent vector of type vec4 in object space, or null if tangent is null
568
+ /**
569
+ * Calculates the tangent vector of type vec3 in object space
570
+ *
571
+ * @param scope - Current shader scope
572
+ * @param tangent - Vertex tangent input, must be type of vec4, null if no vertex tangent input
573
+ * @param skinMatrix - The skinning matrix if there is skeletal animation, otherwise null
574
+ * @returns The calculated tangent vector of type vec4 in object space, or null if tangent is null
573
575
  */ static resolveVertexTangent(scope, tangent) {
574
576
  const pb = scope.$builder;
575
577
  if (pb.shaderKind !== 'vertex') {
@@ -594,18 +596,18 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
594
596
  return tangent;
595
597
  }
596
598
  }
597
- /**
598
- * Gets the uniform variable of type mat4 which holds the world matrix of current object to be drawn
599
- * @param scope - Current shader scope
600
- * @returns The world matrix of current object to be drawn
599
+ /**
600
+ * Gets the uniform variable of type mat4 which holds the world matrix of current object to be drawn
601
+ * @param scope - Current shader scope
602
+ * @returns The world matrix of current object to be drawn
601
603
  */ static getWorldMatrix(scope) {
602
604
  const pb = scope.$builder;
603
605
  return scope[UNIFORM_NAME_WORLD_MATRIX] ?? pb.mat4(this.getInstancedUniform(scope, 0), this.getInstancedUniform(scope, 1), this.getInstancedUniform(scope, 2), this.getInstancedUniform(scope, 3));
604
606
  }
605
- /**
606
- * Gets the uniform variable of type mat4 which holds the world matrix at previous frame of current object to be drawn
607
- * @param scope - Current shader scope
608
- * @returns The world matrix at previous frame of current object to be drawn
607
+ /**
608
+ * Gets the uniform variable of type mat4 which holds the world matrix at previous frame of current object to be drawn
609
+ * @param scope - Current shader scope
610
+ * @returns The world matrix at previous frame of current object to be drawn
609
611
  */ static getPrevWorldMatrix(scope) {
610
612
  const pb = scope.$builder;
611
613
  const that = this;
@@ -636,28 +638,28 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
636
638
  return scope.Z_getPrevWorldMatrix(framestamp);
637
639
  }
638
640
  }
639
- /**
640
- * Gets the instance uniform value of type vec4 by uniform index
641
- * @param scope - Current shader scope
642
- * @returns instance uniform value
641
+ /**
642
+ * Gets the instance uniform value of type vec4 by uniform index
643
+ * @param scope - Current shader scope
644
+ * @returns instance uniform value
643
645
  */ static getInstancedUniform(scope, uniformIndex) {
644
646
  const pb = scope.$builder;
645
647
  return scope[UNIFORM_NAME_INSTANCE_DATA].at(pb.add(pb.mul(scope[UNIFORM_NAME_INSTANCE_DATA_STRIDE], pb.uint(scope.$builtins.instanceIndex)), scope[UNIFORM_NAME_INSTANCE_DATA_OFFSET], pb.uint(uniformIndex)));
646
648
  }
647
- /**
648
- * Gets the uniform variable of type mat4 which holds the normal matrix of current object to be drawn
649
- *
650
- * @param scope - Current shader scope
651
- * @returns The normal matrix of current object to be drawn
649
+ /**
650
+ * Gets the uniform variable of type mat4 which holds the normal matrix of current object to be drawn
651
+ *
652
+ * @param scope - Current shader scope
653
+ * @returns The normal matrix of current object to be drawn
652
654
  */ static getNormalMatrix(scope) {
653
655
  return this.getWorldMatrix(scope);
654
656
  }
655
- /**
656
- * Vertex shader drawable stuff
657
- *
658
- * @param scope - Current shader scope
659
- * @param skinning - true if skinning is used, otherwise false.
660
- * @param instanced - true if instancing is used, otherwise false.
657
+ /**
658
+ * Vertex shader drawable stuff
659
+ *
660
+ * @param scope - Current shader scope
661
+ * @param skinning - true if skinning is used, otherwise false.
662
+ * @param instanced - true if instancing is used, otherwise false.
661
663
  */ static vertexShaderDrawableStuff(scope, skinning, morphing, instanced) {
662
664
  const pb = scope.$builder;
663
665
  if (instanced) {
@@ -703,6 +705,7 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
703
705
  shadowDebugCascades: camera.shadowDebugCascades ? 1 : 0,
704
706
  frameDeltaTime: ctx.device.frameInfo.elapsedFrame * 0.001,
705
707
  elapsedTime: ctx.device.frameInfo.elapsedOverall * 0.001,
708
+ preExposure: this.getPreExposure(ctx),
706
709
  framestamp: ctx.device.frameInfo.frameCounter
707
710
  };
708
711
  if (ctx.motionVectors && ctx.renderPass.type === RENDER_PASS_TYPE_DEPTH) {
@@ -746,12 +749,72 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
746
749
  bindGroup.setTexture(UNIFORM_NAME_AERIALPERSPECTIVE_LUT, aerialPerspectiveLUT);
747
750
  bindGroup.setTexture(UNIFORM_NAME_SKYDISTANTLIGHT_LUT, skyDistantLightLUT);
748
751
  }
752
+ /**
753
+ * @internal
754
+ *
755
+ * Camera pre-exposure factor for scene-linear lighting quantities.
756
+ *
757
+ * @remarks
758
+ * Physical lighting authors light intensities in photometric units (lux, candela, cd/m²), whose
759
+ * magnitudes (~1e5 for daylight) neither fit an rgba16f render target nor leave usable headroom
760
+ * for specular highlights. Following Filament, the camera exposure is folded into every light
761
+ * quantity on the CPU so the HDR target stays near 1.0 and downstream passes need no unit
762
+ * awareness. Legacy returns 1 so its uploads stay byte-identical.
763
+ */ static getPreExposure(ctx) {
764
+ return ctx.scene.lightingMode === 'physical' ? ctx.camera.exposure : 1;
765
+ }
766
+ /**
767
+ * @internal
768
+ *
769
+ * Light color/intensity vector with the camera pre-exposure folded into the intensity component.
770
+ *
771
+ * @remarks
772
+ * Only the intensity (`w`) is scaled; the color stays untouched, matching Filament's
773
+ * `FScene::prepareDynamicLights`. The light's own cached vector is never mutated because it is
774
+ * shared across every camera rendering the scene.
775
+ */ static getPreExposedColorIntensity(light, ctx, out) {
776
+ const src = light.diffuseAndIntensity;
777
+ const result = out ?? new Vector4();
778
+ result.setXYZW(src.x, src.y, src.z, src.w * this.getPreExposure(ctx));
779
+ return result;
780
+ }
781
+ /**
782
+ * @internal
783
+ *
784
+ * Environment lighting scale uploaded as `light.envLightStrength`.
785
+ *
786
+ * @remarks
787
+ * Legacy uses the unitless {@link EnvLightWrapper.strength}.
788
+ *
789
+ * Physical returns the ratio that converts the cached sky bake from its fixed storage exposure
790
+ * (`SkyRenderer.PHYSICAL_BAKE_EXPOSURE`) to the live camera exposure. Every environment source is
791
+ * normalized into that one space before it reaches the IBL -- the scattering atmosphere emits
792
+ * photometric luminance, authored 0..1 skyboxes/panoramas are lifted by
793
+ * {@link EnvLightWrapper.intensity} -- so no pass consuming `envLightStrength` has to know the
794
+ * sky type.
795
+ *
796
+ * The bake cannot simply hold raw cd/m²: the environment cubemap is `rg11b10uf`/`rgba16f` and a
797
+ * daylight sun overflows it to Inf, which `prefilterCubemap` then spreads across the whole IBL.
798
+ *
799
+ * {@link EnvLightWrapper.strength} multiplies the result in both modes. It is the only per-frame
800
+ * dimmer for environment lighting: the photometric `intensity` reaches the image solely through
801
+ * the cached bake, and a `scatter` sky does not even consult it (its brightness comes from the
802
+ * sun), so without this factor there would be no way to turn the IBL down without re-baking.
803
+ */ static getEnvLightLuminance(ctx) {
804
+ const env = ctx.env;
805
+ if (!env) {
806
+ return 0;
807
+ }
808
+ const strength = env.light.strength ?? 0;
809
+ return ctx.scene.lightingMode === 'physical' ? this.getPreExposure(ctx) / PHYSICAL_BAKE_EXPOSURE * strength : strength;
810
+ }
749
811
  /** @internal */ static setLightUniforms(bindGroup, ctx, clusterParams, countParams, lightBuffer, lightIndexTexture) {
812
+ const envLightStrength = this.getEnvLightLuminance(ctx);
750
813
  bindGroup.setValue('light', {
751
814
  sunDir: ctx.sunLight ? ctx.sunLight.directionAndCutoff.xyz().scaleBy(-1) : this.defaultSunDir,
752
815
  clusterParams: clusterParams,
753
816
  countParams: countParams,
754
- envLightStrength: ctx.env.light.strength ?? 0,
817
+ envLightStrength,
755
818
  envLightSpecularStrength: ctx.env.light.specularStrength ?? 1,
756
819
  lightIndexTexSize: new Int32Array([
757
820
  lightIndexTexture.width,
@@ -772,7 +835,7 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
772
835
  }
773
836
  bindGroup.setTexture(UNIFORM_NAME_BAKED_SKY_MAP, ctx.scene.env.sky.getBakedSkyTexture(ctx));
774
837
  if (ctx.drawEnvLight) {
775
- ctx.env.light.envLight.updateBindGroup(bindGroup);
838
+ ctx.env.light.envLight.updateBindGroup(bindGroup, ctx);
776
839
  }
777
840
  }
778
841
  /** @internal */ static setLightUniformsShadow(bindGroup, ctx, light) {
@@ -781,7 +844,7 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
781
844
  this._lightUniformShadow.shadowCascades = shadowMapParams.numShadowCascades;
782
845
  this._lightUniformShadow.positionAndRange.set(light.positionAndRange);
783
846
  this._lightUniformShadow.directionAndCutoff.set(light.directionAndCutoff);
784
- this._lightUniformShadow.diffuseAndIntensity.set(light.diffuseAndIntensity);
847
+ this.getPreExposedColorIntensity(light, ctx, this._lightUniformShadow.diffuseAndIntensity);
785
848
  this._lightUniformShadow.extraParams.set(light.extraParams);
786
849
  this._lightUniformShadow.cascadeDistances.set(shadowMapParams.cascadeDistances);
787
850
  this._lightUniformShadow.depthBiasValues.set(shadowMapParams.depthBiasValues[0]);
@@ -790,153 +853,183 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
790
853
  shadowMapParams.impl.getParams(this._lightUniformShadow.implParams);
791
854
  this._lightUniformShadow.shadowMatrices.set(shadowMapParams.shadowMatrices);
792
855
  this._lightUniformShadow.shadowStrength = light.shadow.shadowStrength;
793
- this._lightUniformShadow.envLightStrength = ctx.env?.light.strength ?? 0;
856
+ this._lightUniformShadow.envLightStrength = this.getEnvLightLuminance(ctx);
794
857
  this._lightUniformShadow.envLightSpecularStrength = ctx.env?.light.specularStrength ?? 1;
795
858
  bindGroup.setValue('light', this._lightUniformShadow);
796
859
  bindGroup.setTexture(UNIFORM_NAME_SHADOW_MAP, shadowMapParams.shadowMap, shadowMapParams.shadowMapSampler);
797
860
  bindGroup.setTexture(UNIFORM_NAME_BAKED_SKY_MAP, ctx.scene.env.sky.getBakedSkyTexture(ctx));
798
861
  if (ctx.drawEnvLight) {
799
- ctx.env.light.envLight.updateBindGroup(bindGroup);
862
+ ctx.env.light.envLight.updateBindGroup(bindGroup, ctx);
800
863
  }
801
864
  }
802
- /**
803
- * Gets the uniform variable of type float which holds the strength of the environment light
804
- *
805
- * @remarks
806
- * This function can only be used in the fragment shader
807
- *
808
- * @param scope - Current shader scope
809
- * @returns The uniform variable of which presents the strength of the environment light
865
+ /**
866
+ * Gets the uniform variable of type float which holds the strength of the environment light
867
+ *
868
+ * @remarks
869
+ * This function can only be used in the fragment shader
870
+ *
871
+ * @param scope - Current shader scope
872
+ * @returns The uniform variable of which presents the strength of the environment light
810
873
  */ static getEnvLightStrength(scope) {
811
874
  return scope.light.envLightStrength;
812
875
  }
813
- /**
814
- * Gets the uniform variable of type float which holds the specular strength of the environment light
815
- *
816
- * @remarks
817
- * This function can only be used in the fragment shader
818
- *
819
- * @param scope - Current shader scope
820
- * @returns The uniform variable which presents the specular strength of the environment light
876
+ /**
877
+ * Gets the uniform variable of type float which holds the specular strength of the environment light
878
+ *
879
+ * @remarks
880
+ * This function can only be used in the fragment shader
881
+ *
882
+ * @param scope - Current shader scope
883
+ * @returns The uniform variable which presents the specular strength of the environment light
821
884
  */ static getEnvLightSpecularStrength(scope) {
822
885
  return scope.light.envLightSpecularStrength ?? scope.$builder.float(1);
823
886
  }
824
- /**
825
- * Gets current scene color texture
826
- * @param scope - Current shader scope
827
- * @returns current scene color texture
887
+ /**
888
+ * Gets current scene color texture
889
+ * @param scope - Current shader scope
890
+ * @returns current scene color texture
828
891
  */ static getSceneColorTexture(scope) {
829
892
  return scope[UNIFORM_NAME_SCENE_COLOR_MAP];
830
893
  }
831
- /**
832
- * Gets the size of current scene color texture
833
- * @param scope - Current shader scope
834
- * @returns The size of current scene color texture
894
+ /**
895
+ * Gets the size of current scene color texture
896
+ * @param scope - Current shader scope
897
+ * @returns The size of current scene color texture
835
898
  */ static getSceneColorTextureSize(scope) {
836
899
  return scope[UNIFORM_NAME_SCENE_COLOR_MAP_SIZE];
837
900
  }
838
- /**
839
- * Gets current linear depth texture
840
- * @param scope - Current shader scope
841
- * @returns current linear depth texture
901
+ /**
902
+ * Gets current linear depth texture
903
+ * @param scope - Current shader scope
904
+ * @returns current linear depth texture
842
905
  */ static getLinearDepthTexture(scope) {
843
906
  return scope[UNIFORM_NAME_LINEAR_DEPTH_MAP];
844
907
  }
845
- /**
846
- * Gets the size of current linear depth texture
847
- * @param scope - Current shader scope
848
- * @returns The size of current linear depth texture
908
+ /**
909
+ * Gets the size of current linear depth texture
910
+ * @param scope - Current shader scope
911
+ * @returns The size of current linear depth texture
849
912
  */ static getLinearDepthTextureSize(scope) {
850
913
  return scope[UNIFORM_NAME_LINEAR_DEPTH_MAP_SIZE];
851
914
  }
852
- /**
853
- * Gets current HiZ depth texture
854
- * @param scope - Current shader scope
855
- * @returns current HiZ depth texture
915
+ /**
916
+ * Gets current HiZ depth texture
917
+ * @param scope - Current shader scope
918
+ * @returns current HiZ depth texture
856
919
  */ static getHiZDepthTexture(scope) {
857
920
  return scope[UNIFORM_NAME_HIZ_DEPTH_MAP];
858
921
  }
859
- /**
860
- * Gets the size of current HiZ depth texture
861
- * @param scope - Current shader scope
862
- * @returns The size of current HiZ depth texture
922
+ /**
923
+ * Gets the size of current HiZ depth texture
924
+ * @param scope - Current shader scope
925
+ * @returns The size of current HiZ depth texture
863
926
  */ static getHiZDepthTextureSize(scope) {
864
927
  return scope[UNIFORM_NAME_HIZ_DEPTH_MAP_INFO].xy;
865
928
  }
866
- /**
867
- * Gets the mipmap levels count of current HiZ depth texture
868
- * @param scope - Current shader scope
869
- * @returns The mipmap levels count of current HiZ depth texture
929
+ /**
930
+ * Gets the mipmap levels count of current HiZ depth texture
931
+ * @param scope - Current shader scope
932
+ * @returns The mipmap levels count of current HiZ depth texture
870
933
  */ static getHiZDepthTextureMipLevelCount(scope) {
871
934
  return scope[UNIFORM_NAME_HIZ_DEPTH_MAP_INFO].z;
872
935
  }
873
- /**
874
- * Gets current baked skybox texture
875
- * @param scope - Current shader scope
876
- * @returns current baked skybox texture
936
+ /**
937
+ * Gets current baked skybox texture
938
+ * @param scope - Current shader scope
939
+ * @returns current baked skybox texture
877
940
  */ static getBakedSkyTexture(scope) {
878
941
  return scope[UNIFORM_NAME_BAKED_SKY_MAP];
879
942
  }
880
- /**
881
- * Gets the elapsed time in seconds
882
- * @param scope - Current shader scope
883
- * @returns The elapsed time in seconds
943
+ /**
944
+ * Samples the baked sky cubemap in the same pre-exposed space as the scene color buffer.
945
+ *
946
+ * @remarks
947
+ * The bake is cached and therefore exposure-independent, stored at the fixed
948
+ * `PHYSICAL_BAKE_EXPOSURE`. Anything that blends it against already-pre-exposed lit color (water
949
+ * reflection, blueprint sky lookups) must first convert it to the live exposure.
950
+ * `envLightStrength` carries exactly that ratio in physical mode, and the legacy environment
951
+ * strength (its established meaning) otherwise.
952
+ *
953
+ * @param scope - Current shader scope
954
+ * @param direction - Sampling direction
955
+ * @returns Pre-exposed sky radiance
956
+ */ static sampleBakedSkyPreExposed(scope, direction) {
957
+ const pb = scope.$builder;
958
+ return pb.mul(pb.textureSampleLevel(this.getBakedSkyTexture(scope), direction, 0).rgb, this.getEnvLightStrength(scope));
959
+ }
960
+ /**
961
+ * Gets the camera pre-exposure factor.
962
+ *
963
+ * @remarks
964
+ * The multiplier every photometric quantity is scaled by before it reaches the HDR target. 1 in
965
+ * legacy. Use it for material-authored emitters (emissive), which are not covered by the CPU-side
966
+ * light pre-exposure.
967
+ *
968
+ * @param scope - Current shader scope
969
+ * @returns The pre-exposure factor
970
+ */ static getPreExposureUniform(scope) {
971
+ return scope.camera.preExposure;
972
+ }
973
+ /**
974
+ * Gets the elapsed time in seconds
975
+ * @param scope - Current shader scope
976
+ * @returns The elapsed time in seconds
884
977
  */ static getElapsedTime(scope) {
885
978
  return scope.camera.elapsedTime;
886
979
  }
887
- /**
888
- * Gets the elapsed time since last frame in seconds
889
- * @param scope - Current shader scope
890
- * @returns The elapsed time since last frame in seconds
980
+ /**
981
+ * Gets the elapsed time since last frame in seconds
982
+ * @param scope - Current shader scope
983
+ * @returns The elapsed time since last frame in seconds
891
984
  */ static getElapsedTimeFrame(scope) {
892
985
  return scope.camera.frameDeltaTime;
893
986
  }
894
- /**
895
- * Gets the uniform variable of type vec3 which holds the camera position
896
- * @param scope - Current shader scope
897
- * @returns The camera position
987
+ /**
988
+ * Gets the uniform variable of type vec3 which holds the camera position
989
+ * @param scope - Current shader scope
990
+ * @returns The camera position
898
991
  */ static getCameraPosition(scope) {
899
992
  return scope.camera.position.xyz;
900
993
  }
901
- /**
902
- * Gets the uniform variable of type float which holds the roughness factor
903
- * @param scope - Current shader scope
904
- * @returns The roughness factor
994
+ /**
995
+ * Gets the uniform variable of type float which holds the roughness factor
996
+ * @param scope - Current shader scope
997
+ * @returns The roughness factor
905
998
  */ static getCameraRoughnessFactor(scope) {
906
999
  return scope.camera.roughnessFactor;
907
1000
  }
908
- /**
909
- * Gets framebuffer size for rendering
910
- * @param scope - Current shader scope
911
- * @returns The roughness factor
1001
+ /**
1002
+ * Gets framebuffer size for rendering
1003
+ * @param scope - Current shader scope
1004
+ * @returns The roughness factor
912
1005
  */ static getRenderSize(scope) {
913
1006
  return scope.camera.renderSize;
914
1007
  }
915
- /**
916
- * Gets the uniform variable of type uint which holds the framestamp
917
- * @param scope - Current shader scope
918
- * @returns The framestamp
1008
+ /**
1009
+ * Gets the uniform variable of type uint which holds the framestamp
1010
+ * @param scope - Current shader scope
1011
+ * @returns The framestamp
919
1012
  */ static getFramestamp(scope) {
920
1013
  return scope.camera.framestamp;
921
1014
  }
922
- /**
923
- * Gets the clip plane flag
924
- * @param scope - Current shader scope
925
- * @returns A float value of 1 indices the clip plane presents, otherwise 0
1015
+ /**
1016
+ * Gets the clip plane flag
1017
+ * @param scope - Current shader scope
1018
+ * @returns A float value of 1 indices the clip plane presents, otherwise 0
926
1019
  */ static getCameraClipPlaneFlag(scope) {
927
1020
  return scope.camera.position.w;
928
1021
  }
929
- /**
930
- * Gets the clip plane
931
- * @param scope - Current shader scope
932
- * @returns A vec4 presents the clip plane
1022
+ /**
1023
+ * Gets the clip plane
1024
+ * @param scope - Current shader scope
1025
+ * @returns A vec4 presents the clip plane
933
1026
  */ static getCameraClipPlane(scope) {
934
1027
  return scope.camera.clipPlane;
935
1028
  }
936
- /**
937
- * Gets the uniform variable of type vec4 which holds the camera parameters
938
- * @param scope - Current shader scope
939
- * @returns The camera parameters
1029
+ /**
1030
+ * Gets the uniform variable of type vec4 which holds the camera parameters
1031
+ * @param scope - Current shader scope
1032
+ * @returns The camera parameters
940
1033
  */ static getCameraParams(scope) {
941
1034
  return scope.camera.params;
942
1035
  }
@@ -946,36 +1039,36 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
946
1039
  /** @internal */ static getCountParams(scope) {
947
1040
  return scope.light.countParams;
948
1041
  }
949
- /**
950
- * Number of shadow-casting lights at the head of the clustered light buffer.
951
- * Only defined on the screen-space shadow mask path (ctx.screenSpaceShadowMask);
952
- * a clustered light whose buffer index is `<= N` samples the shadow mask.
953
- * @internal
1042
+ /**
1043
+ * Number of shadow-casting lights at the head of the clustered light buffer.
1044
+ * Only defined on the screen-space shadow mask path (ctx.screenSpaceShadowMask);
1045
+ * a clustered light whose buffer index is `<= N` samples the shadow mask.
1046
+ * @internal
954
1047
  */ static getNumShadowLights(scope) {
955
1048
  return scope.light.numShadowLights;
956
1049
  }
957
- /**
958
- * Cluster shadow-mask mode for the current queue: 1 = sample the opaque shadow
959
- * mask for shadow lights; 0 = skip shadow lights (they are lit inline by the
960
- * additive passes, used for the transparent queue). Only defined on the
961
- * screen-space shadow mask path.
962
- * @internal
1050
+ /**
1051
+ * Cluster shadow-mask mode for the current queue: 1 = sample the opaque shadow
1052
+ * mask for shadow lights; 0 = skip shadow lights (they are lit inline by the
1053
+ * additive passes, used for the transparent queue). Only defined on the
1054
+ * screen-space shadow mask path.
1055
+ * @internal
963
1056
  */ static getShadowMaskMode(scope) {
964
1057
  return scope[UNIFORM_NAME_SHADOW_MASK_MODE];
965
1058
  }
966
- /**
967
- * Bind the per-queue cluster shadow-mask mode. Call in the clustered light pass
968
- * only when the screen-space shadow mask path is active.
969
- * @internal
1059
+ /**
1060
+ * Bind the per-queue cluster shadow-mask mode. Call in the clustered light pass
1061
+ * only when the screen-space shadow mask path is active.
1062
+ * @internal
970
1063
  */ static setShadowMaskMode(bindGroup, sampleMask) {
971
1064
  bindGroup.setValue(UNIFORM_NAME_SHADOW_MASK_MODE, sampleMask ? 1 : 0);
972
1065
  }
973
- /**
974
- * Lazily-created 1x1x1 rgba8unorm array texture used as the shadow-mask binding
975
- * fallback when the screen-space shadow mask path is enabled but no mask was
976
- * produced this frame (no shadow-casting lights). It is never sampled in that
977
- * case, but the declared uniform still requires a valid binding.
978
- * @internal
1066
+ /**
1067
+ * Lazily-created 1x1x1 rgba8unorm array texture used as the shadow-mask binding
1068
+ * fallback when the screen-space shadow mask path is enabled but no mask was
1069
+ * produced this frame (no shadow-casting lights). It is never sampled in that
1070
+ * case, but the declared uniform still requires a valid binding.
1071
+ * @internal
979
1072
  */ static getDummyShadowMask(device) {
980
1073
  let tex = this._dummyShadowMask;
981
1074
  if (!tex || tex.disposed) {
@@ -990,22 +1083,22 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
990
1083
  /** @internal */ static getClusteredLightIndexTexture(scope) {
991
1084
  return scope[UNIFORM_NAME_LIGHT_INDEX_TEXTURE];
992
1085
  }
993
- /**
994
- * Clustered shadow factor for a light, in `[0,1]` (1 = fully lit).
995
- *
996
- * - Lights whose clustered buffer index is greater than `numShadowLights` are not
997
- * shadow-casters and return 1.0.
998
- * - Shadow-casting lights on the opaque queue (shadow mask mode 1) return the
999
- * screen-space mask value. Layer/channel are derived from the zero-based light
1000
- * ordinal `s = index-1`: `layer = s >> 2`, `channel = s & 3`, matching the
1001
- * ShadowMaskPass packing.
1002
- * - Shadow-casting lights on a transparent queue (mode 0) return 0: their clustered
1003
- * contribution is suppressed because they are lit inline by the additive passes,
1004
- * where shadows are sampled at the true (transparent) surface depth rather than
1005
- * from the opaque-depth mask.
1006
- *
1007
- * Only valid on the screen-space shadow mask path (ctx.screenSpaceShadowMask).
1008
- * @internal
1086
+ /**
1087
+ * Clustered shadow factor for a light, in `[0,1]` (1 = fully lit).
1088
+ *
1089
+ * - Lights whose clustered buffer index is greater than `numShadowLights` are not
1090
+ * shadow-casters and return 1.0.
1091
+ * - Shadow-casting lights on the opaque queue (shadow mask mode 1) return the
1092
+ * screen-space mask value. Layer/channel are derived from the zero-based light
1093
+ * ordinal `s = index-1`: `layer = s >> 2`, `channel = s & 3`, matching the
1094
+ * ShadowMaskPass packing.
1095
+ * - Shadow-casting lights on a transparent queue (mode 0) return 0: their clustered
1096
+ * contribution is suppressed because they are lit inline by the additive passes,
1097
+ * where shadows are sampled at the true (transparent) surface depth rather than
1098
+ * from the opaque-depth mask.
1099
+ *
1100
+ * Only valid on the screen-space shadow mask path (ctx.screenSpaceShadowMask).
1101
+ * @internal
1009
1102
  */ static sampleShadowMask(scope, lightIndex) {
1010
1103
  const pb = scope.$builder;
1011
1104
  const that = this;
@@ -1032,87 +1125,87 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
1032
1125
  });
1033
1126
  return pb.getGlobalScope()[funcName](lightIndex);
1034
1127
  }
1035
- /**
1036
- * Gets the uniform variable that contains atmosphere parameters
1037
- * @param scope - Current shader scope
1038
- * @returns The atmosphere parameters
1128
+ /**
1129
+ * Gets the uniform variable that contains atmosphere parameters
1130
+ * @param scope - Current shader scope
1131
+ * @returns The atmosphere parameters
1039
1132
  */ static getAtmosphereParams(scope) {
1040
1133
  return scope.fog.atmosphereParams;
1041
1134
  }
1042
- /**
1043
- * Gets the aerial perspective LUT
1044
- * @param scope - Current shader scope
1045
- * @returns The aerial perspective LUT texture
1135
+ /**
1136
+ * Gets the aerial perspective LUT
1137
+ * @param scope - Current shader scope
1138
+ * @returns The aerial perspective LUT texture
1046
1139
  */ static getAerialPerspectiveLUT(scope) {
1047
1140
  return scope[UNIFORM_NAME_AERIALPERSPECTIVE_LUT];
1048
1141
  }
1049
- /**
1050
- * Gets the uniform variable of type mat4 which holds the view projection matrix of current camera
1051
- * @param scope - Current shader scope
1052
- * @returns The view projection matrix of current camera
1142
+ /**
1143
+ * Gets the uniform variable of type mat4 which holds the view projection matrix of current camera
1144
+ * @param scope - Current shader scope
1145
+ * @returns The view projection matrix of current camera
1053
1146
  */ static getViewProjectionMatrix(scope) {
1054
1147
  return scope.camera.viewProjectionMatrix;
1055
1148
  }
1056
- /**
1057
- * Gets the uniform variable of type mat4 which holds the inversed view projection matrix of current camera
1058
- * @param scope - Current shader scope
1059
- * @returns The inversed view projection matrix of current camera
1149
+ /**
1150
+ * Gets the uniform variable of type mat4 which holds the inversed view projection matrix of current camera
1151
+ * @param scope - Current shader scope
1152
+ * @returns The inversed view projection matrix of current camera
1060
1153
  */ static getInvViewProjectionMatrix(scope) {
1061
1154
  return scope.camera.invViewProjectionMatrix;
1062
1155
  }
1063
- /**
1064
- * Gets the uniform variable of type mat4 which holds the projection matrix of current camera
1065
- * @param scope - Current shader scope
1066
- * @returns The projection matrix of current camera
1156
+ /**
1157
+ * Gets the uniform variable of type mat4 which holds the projection matrix of current camera
1158
+ * @param scope - Current shader scope
1159
+ * @returns The projection matrix of current camera
1067
1160
  */ static getProjectionMatrix(scope) {
1068
1161
  return scope.camera.projectionMatrix;
1069
1162
  }
1070
- /**
1071
- * Gets the uniform variable of type mat4 which holds the inversed projection matrix of current camera
1072
- * @param scope - Current shader scope
1073
- * @returns The inversed projection matrix of current camera
1163
+ /**
1164
+ * Gets the uniform variable of type mat4 which holds the inversed projection matrix of current camera
1165
+ * @param scope - Current shader scope
1166
+ * @returns The inversed projection matrix of current camera
1074
1167
  */ static getInvProjectionMatrix(scope) {
1075
1168
  return scope.camera.invProjectionMatrix;
1076
1169
  }
1077
- /**
1078
- * Gets the uniform variable of type mat4 which holds the unjittered view projection matrix of current camera
1079
- * @param scope - Current shader scope
1080
- * @returns The unjittered view projection matrix of current camera
1170
+ /**
1171
+ * Gets the uniform variable of type mat4 which holds the unjittered view projection matrix of current camera
1172
+ * @param scope - Current shader scope
1173
+ * @returns The unjittered view projection matrix of current camera
1081
1174
  */ static getUnjitteredViewProjectionMatrix(scope) {
1082
1175
  return scope.camera.unjitteredVPMatrix;
1083
1176
  }
1084
- /**
1085
- * Gets the uniform variable of type vec2 which holds the jitter value of the projection matrix of current camera
1086
- * @param scope - Current shader scope
1087
- * @returns The jitter value of projection matrix of current camera
1177
+ /**
1178
+ * Gets the uniform variable of type vec2 which holds the jitter value of the projection matrix of current camera
1179
+ * @param scope - Current shader scope
1180
+ * @returns The jitter value of projection matrix of current camera
1088
1181
  */ static getProjectionMatrixJitterValue(scope) {
1089
1182
  return scope.camera.jitterValue;
1090
1183
  }
1091
- /**
1092
- * Gets the uniform variable of type mat4 which holds the jittered inversed view-projection matrix
1093
- * @param scope - Current shader scope
1094
- * @returns The jittered inversed view-projection matrix
1184
+ /**
1185
+ * Gets the uniform variable of type mat4 which holds the jittered inversed view-projection matrix
1186
+ * @param scope - Current shader scope
1187
+ * @returns The jittered inversed view-projection matrix
1095
1188
  */ static getJitteredInvVPMatrix(scope) {
1096
1189
  return scope.camera.jitteredInvVPMatrix;
1097
1190
  }
1098
- /**
1099
- * Gets the uniform variable of type mat4 which holds the unjittered view projection at previous frame matrix of current camera
1100
- * @param scope - Current shader scope
1101
- * @returns The unjittered view projection matrix at previous frame of current camera
1191
+ /**
1192
+ * Gets the uniform variable of type mat4 which holds the unjittered view projection at previous frame matrix of current camera
1193
+ * @param scope - Current shader scope
1194
+ * @returns The unjittered view projection matrix at previous frame of current camera
1102
1195
  */ static getPrevUnjitteredViewProjectionMatrix(scope) {
1103
1196
  return scope.camera.prevUnjitteredVPMatrix;
1104
1197
  }
1105
- /**
1106
- * Gets the uniform variable of type mat4 which holds the view matrix of current camera (world space to camera space)
1107
- * @param scope - Current shader scope
1108
- * @returns The view matrix of current camera
1198
+ /**
1199
+ * Gets the uniform variable of type mat4 which holds the view matrix of current camera (world space to camera space)
1200
+ * @param scope - Current shader scope
1201
+ * @returns The view matrix of current camera
1109
1202
  */ static getViewMatrix(scope) {
1110
1203
  return scope.camera.viewMatrix;
1111
1204
  }
1112
- /**
1113
- * Gets the uniform variable of type mat4 which holds the inv-view matrix of current camera (camera space to world space)
1114
- * @param scope - Current shader scope
1115
- * @returns The inv-view matrix of current camera
1205
+ /**
1206
+ * Gets the uniform variable of type mat4 which holds the inv-view matrix of current camera (camera space to world space)
1207
+ * @param scope - Current shader scope
1208
+ * @returns The inv-view matrix of current camera
1116
1209
  */ static getInvViewMatrix(scope) {
1117
1210
  return scope.camera.worldMatrix;
1118
1211
  }
@@ -1166,20 +1259,20 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
1166
1259
  /** @internal */ static getLightExtra(scope, lightIndex) {
1167
1260
  return scope[UNIFORM_NAME_LIGHT_BUFFER].at(scope.$builder.add(scope.$builder.mul(lightIndex, 4), 3));
1168
1261
  }
1169
- /**
1170
- * Sets the clip space position in vertex shader
1171
- *
1172
- * @remarks
1173
- * Use this function instead of using
1174
- * <pre>
1175
- * // Do not use this
1176
- * this.$builtins.position = some_value;
1177
- * // Use this
1178
- * ShaderFramework.setClipSpacePosition(some_value);
1179
- * </pre>,
1180
- *
1181
- * @param scope - Current shader scope
1182
- * @param pos - The clip space position to be set
1262
+ /**
1263
+ * Sets the clip space position in vertex shader
1264
+ *
1265
+ * @remarks
1266
+ * Use this function instead of using
1267
+ * <pre>
1268
+ * // Do not use this
1269
+ * this.$builtins.position = some_value;
1270
+ * // Use this
1271
+ * ShaderFramework.setClipSpacePosition(some_value);
1272
+ * </pre>,
1273
+ *
1274
+ * @param scope - Current shader scope
1275
+ * @param pos - The clip space position to be set
1183
1276
  */ static setClipSpacePosition(scope, pos) {
1184
1277
  const pb = scope.$builder;
1185
1278
  const cameraParams = this.getCameraParams(scope);
@@ -1189,20 +1282,20 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
1189
1282
  scope.$builtins.position = pos;
1190
1283
  }
1191
1284
  }
1192
- /**
1193
- * Get shadow map uniform value
1194
- *
1195
- * @param scope - Shader scope
1196
- * @returns The shadow map texture uniform
1285
+ /**
1286
+ * Get shadow map uniform value
1287
+ *
1288
+ * @param scope - Shader scope
1289
+ * @returns The shadow map texture uniform
1197
1290
  */ static getShadowMap(scope) {
1198
1291
  return scope[UNIFORM_NAME_SHADOW_MAP];
1199
1292
  }
1200
- /**
1201
- * Calculates shadow of current fragment
1202
- *
1203
- * @param scope - Shader scope
1204
- * @param NoL - NdotL vector
1205
- * @returns Shadow of current fragment, 1 means no shadow and 0 means full shadowed.
1293
+ /**
1294
+ * Calculates shadow of current fragment
1295
+ *
1296
+ * @param scope - Shader scope
1297
+ * @param NoL - NdotL vector
1298
+ * @returns Shadow of current fragment, 1 means no shadow and 0 means full shadowed.
1206
1299
  */ static calculateShadow(scope, worldPos, NoL, ctx) {
1207
1300
  const pb = scope.$builder;
1208
1301
  const that = this;
@@ -1278,49 +1371,131 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
1278
1371
  scope[funcName](worldPos, color);
1279
1372
  }
1280
1373
  }
1281
- /**
1282
- * Calculates the non-linear depth from linear depth
1283
- *
1284
- * @param scope - Current shader scope
1285
- * @param depth - The linear depth
1286
- * @param nearFar - A vector that contains the near clip plane in x component and the far clip plane in y component
1287
- * @returns The calculated non-linear depth
1374
+ /**
1375
+ * Calculates the non-linear depth from linear depth
1376
+ *
1377
+ * @param scope - Current shader scope
1378
+ * @param depth - The linear depth
1379
+ * @param nearFar - A vector that contains the near clip plane in x component and the far clip plane in y component
1380
+ * @returns The calculated non-linear depth
1288
1381
  */ static linearDepthToNonLinear(scope, depth, nearFar) {
1289
1382
  const pb = scope.$builder;
1290
1383
  nearFar = nearFar ?? this.getCameraParams(scope);
1384
+ if (REVERSE_Z) {
1385
+ return pb.div(pb.sub(pb.div(pb.mul(nearFar.x, nearFar.y), depth), nearFar.x), pb.sub(nearFar.y, nearFar.x));
1386
+ }
1291
1387
  return pb.div(pb.sub(nearFar.y, pb.div(pb.mul(nearFar.x, nearFar.y), depth)), pb.sub(nearFar.y, nearFar.x));
1292
1388
  }
1293
- /**
1294
- * Calculates the linear depth from non-linear depth
1295
- *
1296
- * @param scope - Current shader scope
1297
- * @param depth - The non-linear depth
1298
- * @param nearFar - A vector that contains the near clip plane in x component and the far clip plane in y component
1299
- * @returns The calculated linear depth
1389
+ /**
1390
+ * Calculates the linear depth from non-linear depth
1391
+ *
1392
+ * @param scope - Current shader scope
1393
+ * @param depth - The non-linear depth
1394
+ * @param nearFar - A vector that contains the near clip plane in x component and the far clip plane in y component
1395
+ * @returns The calculated linear depth
1300
1396
  */ static nonLinearDepthToLinear(scope, depth, nearFar) {
1301
1397
  const pb = scope.$builder;
1302
1398
  nearFar = nearFar ?? this.getCameraParams(scope);
1399
+ if (REVERSE_Z) {
1400
+ return pb.div(pb.mul(nearFar.x, nearFar.y), pb.mix(nearFar.x, nearFar.y, depth));
1401
+ }
1303
1402
  return pb.div(pb.mul(nearFar.x, nearFar.y), pb.mix(nearFar.y, nearFar.x, depth));
1304
1403
  }
1305
- /**
1306
- * Calculates the normalized linear depth from non-linear depth
1307
- *
1308
- * @param scope - Current shader scope
1309
- * @param depth - The non-linear depth
1310
- * @param nearFar - A vector that contains the near clip plane in x component and the far clip plane in y component
1311
- * @returns The calculated normalized linear depth
1404
+ /**
1405
+ * Calculates the normalized linear depth from non-linear depth
1406
+ *
1407
+ * @param scope - Current shader scope
1408
+ * @param depth - The non-linear depth
1409
+ * @param nearFar - A vector that contains the near clip plane in x component and the far clip plane in y component
1410
+ * @returns The calculated normalized linear depth
1312
1411
  */ static nonLinearDepthToLinearNormalized(scope, depth, nearFar) {
1313
1412
  const pb = scope.$builder;
1314
1413
  nearFar = nearFar ?? this.getCameraParams(scope);
1414
+ if (REVERSE_Z) {
1415
+ return pb.div(nearFar.x, pb.mix(nearFar.x, nearFar.y, depth));
1416
+ }
1315
1417
  return pb.div(nearFar.x, pb.mix(nearFar.y, nearFar.x, depth));
1316
1418
  }
1317
- /**
1318
- * Sample linear depth from linear depth texture
1319
- * @param scope - Current shader scope
1320
- * @param tex - The linear depth texture
1321
- * @param uv - The uv coordinates
1322
- * @param level - The mipmap level to sample
1323
- * @returns Linear depth value
1419
+ /**
1420
+ * Converts normalized linear depth back to device non-linear depth.
1421
+ *
1422
+ * @remarks
1423
+ * The normalized linear depth convention (range [near/far, 1] with 1 at
1424
+ * the far plane, as produced by {@link ShaderHelper.nonLinearDepthToLinearNormalized})
1425
+ * is independent of the engine depth convention; only the mapping to
1426
+ * device depth flips under reverse-Z.
1427
+ *
1428
+ * @param scope - Current shader scope
1429
+ * @param depth - The normalized linear depth
1430
+ * @param nearFar - A vector that contains the near clip plane in x component and the far clip plane in y component
1431
+ * @returns The device non-linear depth
1432
+ */ static linearNormalizedToNonLinearDepth(scope, depth, nearFar) {
1433
+ const pb = scope.$builder;
1434
+ nearFar = nearFar ?? this.getCameraParams(scope);
1435
+ if (REVERSE_Z) {
1436
+ return pb.div(pb.sub(pb.div(nearFar.x, depth), nearFar.x), pb.sub(nearFar.y, nearFar.x));
1437
+ }
1438
+ return pb.div(pb.sub(pb.div(nearFar.x, depth), nearFar.y), pb.sub(nearFar.x, nearFar.y));
1439
+ }
1440
+ /**
1441
+ * Maps a device depth value to the canonical clip-space z coordinate
1442
+ * (GL [-1,1] under standard-Z, zero-to-one under reverse-Z), suitable for
1443
+ * unprojection with the engine's inverse projection matrices.
1444
+ *
1445
+ * @param scope - Current shader scope
1446
+ * @param depth - The device depth value
1447
+ * @returns The canonical clip-space z
1448
+ */ static deviceDepthToClipZ(scope, depth) {
1449
+ const pb = scope.$builder;
1450
+ return REVERSE_Z ? depth : pb.sub(pb.mul(depth, 2), 1);
1451
+ }
1452
+ /**
1453
+ * Clip-space z that places a vertex exactly on the far plane (sky domes,
1454
+ * background geometry).
1455
+ *
1456
+ * @param scope - Current shader scope
1457
+ * @param w - The clip-space w coordinate of the vertex
1458
+ * @returns The clip-space z value for the far plane
1459
+ */ static farthestClipZ(scope, w) {
1460
+ return REVERSE_Z ? 0 : w;
1461
+ }
1462
+ /**
1463
+ * Tests whether a device depth value equals the cleared (farthest) depth,
1464
+ * i.e. no geometry was rendered at this position.
1465
+ *
1466
+ * @param scope - Current shader scope
1467
+ * @param depth - The device depth value
1468
+ * @returns Boolean expression, true for background pixels
1469
+ */ static isFarthestDepth(scope, depth) {
1470
+ return scope.$builder.equal(depth, DEPTH_FARTHEST);
1471
+ }
1472
+ /**
1473
+ * Selects the closer of two device depth values.
1474
+ *
1475
+ * @param scope - Current shader scope
1476
+ * @param a - First device depth value
1477
+ * @param b - Second device depth value
1478
+ * @returns The value closer to the camera
1479
+ */ static closerDepth(scope, a, b) {
1480
+ return scope.$builder[DEPTH_REDUCE_CLOSER](a, b);
1481
+ }
1482
+ /**
1483
+ * Selects the farther of two device depth values.
1484
+ *
1485
+ * @param scope - Current shader scope
1486
+ * @param a - First device depth value
1487
+ * @param b - Second device depth value
1488
+ * @returns The value farther from the camera
1489
+ */ static fartherDepth(scope, a, b) {
1490
+ return scope.$builder[DEPTH_REDUCE_FARTHER](a, b);
1491
+ }
1492
+ /**
1493
+ * Sample linear depth from linear depth texture
1494
+ * @param scope - Current shader scope
1495
+ * @param tex - The linear depth texture
1496
+ * @param uv - The uv coordinates
1497
+ * @param level - The mipmap level to sample
1498
+ * @returns Linear depth value
1324
1499
  */ static sampleLinearDepth(scope, tex, uv, level) {
1325
1500
  const pb = scope.$builder;
1326
1501
  const depth = pb.textureSampleLevel(tex, uv, level);
@@ -1335,30 +1510,30 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
1335
1510
  pb.mat4('mat')
1336
1511
  ], function() {
1337
1512
  this.$l.linearDepth = that.sampleLinearDepth(this, depthTex, this.uv, 0);
1338
- this.$l.nonLinearDepth = pb.div(pb.sub(pb.div(this.cameraNearFar.x, this.linearDepth), this.cameraNearFar.y), pb.sub(this.cameraNearFar.x, this.cameraNearFar.y));
1339
- this.$l.clipSpacePos = pb.vec4(pb.sub(pb.mul(this.uv, 2), pb.vec2(1)), pb.sub(pb.mul(pb.clamp(this.nonLinearDepth, 0, 1), 2), 1), 1);
1513
+ this.$l.nonLinearDepth = that.linearNormalizedToNonLinearDepth(this, this.linearDepth, this.cameraNearFar);
1514
+ this.$l.clipSpacePos = pb.vec4(pb.sub(pb.mul(this.uv, 2), pb.vec2(1)), that.deviceDepthToClipZ(this, pb.clamp(this.nonLinearDepth, 0, 1)), 1);
1340
1515
  this.$l.wPos = pb.mul(this.mat, this.clipSpacePos);
1341
1516
  this.$return(pb.vec4(pb.div(this.wPos.xyz, this.wPos.w), this.linearDepth));
1342
1517
  });
1343
1518
  return scope.zSamplePositionFromDepth(uv, cameraNearFar, mat);
1344
1519
  }
1345
- /**
1346
- * Sample linear depth from linear depth texture with backface
1347
- * @param scope - Current shader scope
1348
- * @param tex - The linear depth texture
1349
- * @param uv - The uv coordinates
1350
- * @param level - The mipmap level to sample
1351
- * @returns Linear depth value
1520
+ /**
1521
+ * Sample linear depth from linear depth texture with backface
1522
+ * @param scope - Current shader scope
1523
+ * @param tex - The linear depth texture
1524
+ * @param uv - The uv coordinates
1525
+ * @param level - The mipmap level to sample
1526
+ * @returns Linear depth value
1352
1527
  */ static sampleLinearDepthWithBackface(scope, tex, uv, level) {
1353
1528
  const pb = scope.$builder;
1354
1529
  return pb.textureSampleLevel(tex, uv, level).rg;
1355
1530
  }
1356
- /**
1357
- * Transform color to sRGB color space if nessesary
1358
- *
1359
- * @param scope - Current shader scope
1360
- * @param outputColor - The color to be transformed
1361
- * @returns The transformed color
1531
+ /**
1532
+ * Transform color to sRGB color space if nessesary
1533
+ *
1534
+ * @param scope - Current shader scope
1535
+ * @param outputColor - The color to be transformed
1536
+ * @returns The transformed color
1362
1537
  */ static encodeColorOutput(scope, outputColor) {
1363
1538
  const pb = scope.$builder;
1364
1539
  const that = this;
@@ -1375,6 +1550,9 @@ const UNIFORM_NAME_MORPH_INFO = 'Z_UniformMorphInfo';
1375
1550
  });
1376
1551
  return pb.getGlobalScope()[funcName](outputColor);
1377
1552
  }
1553
+ /** @internal */ static getMaxClusterLights() {
1554
+ return getDevice().type === 'webgl' ? 64 : 255;
1555
+ }
1378
1556
  }
1379
1557
 
1380
1558
  export { ShaderHelper };