@forgeax/engine-shader 0.1.28 → 0.1.29

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 (73) hide show
  1. package/NOTICE +35 -0
  2. package/README.md +39 -0
  3. package/dist/ShaderRegistry.d.ts +8 -0
  4. package/dist/ShaderRegistry.d.ts.map +1 -1
  5. package/dist/index.d.ts +6 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.mjs +312 -71
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/material/artifact-types.d.ts +12 -2
  10. package/dist/material/artifact-types.d.ts.map +1 -1
  11. package/dist/material-schemas.d.ts +5 -0
  12. package/dist/material-schemas.d.ts.map +1 -1
  13. package/package.json +5 -4
  14. package/src/ShaderRegistry.ts +10 -0
  15. package/src/__tests__/auto-exposure-graph.unit.test.ts +59 -0
  16. package/src/__tests__/bloom-fxaa-tonemap.unit.test.ts +30 -15
  17. package/src/__tests__/builtin-texture-sampling-contract.test.ts +1 -1
  18. package/src/__tests__/default-standard-pbr-alpha.unit.test.ts +2 -1
  19. package/src/__tests__/default-standard-pbr-transmission.unit.test.ts +167 -6
  20. package/src/__tests__/direct-light-layout.unit.test.ts +1 -1
  21. package/src/__tests__/lighting-punctual.unit.test.ts +29 -1
  22. package/src/__tests__/ltc-provenance.unit.test.ts +13 -2
  23. package/src/__tests__/material-builtins.unit.test.ts +1 -0
  24. package/src/__tests__/material-contract.unit.test.ts +42 -9
  25. package/src/__tests__/material-derived-builtins.integration.test.ts +18 -2
  26. package/src/__tests__/probe-lighting-composition.unit.test.ts +1 -1
  27. package/src/__tests__/reflection-probe-sampling.unit.test.ts +23 -2
  28. package/src/__tests__/scene-temporal.unit.test.ts +10 -0
  29. package/src/__tests__/shader.unit.test.ts +1 -0
  30. package/src/__tests__/sprite-variants.unit.test.ts +1 -0
  31. package/src/__tests__/ssr-artifact.unit.test.ts +141 -0
  32. package/src/__tests__/ssr-bgl.integration.test.ts +185 -0
  33. package/src/__tests__/standard-output-domain.unit.test.ts +36 -0
  34. package/src/__tests__/standard-pbr-artifact-receipt.unit.test.ts +93 -0
  35. package/src/__tests__/standard-surface-pass-evaluation.integration.test.ts +16 -4
  36. package/src/__tests__/surface-v1.unit.test.ts +6 -0
  37. package/src/__tests__/taa-resolve.unit.test.ts +20 -9
  38. package/src/__tests__/transmission-thickness-scale.unit.test.ts +6 -1
  39. package/src/__tests__/transparent-pbr.unit.test.ts +1 -1
  40. package/src/__tests__/vertex-color-variant.unit.test.ts +4 -1
  41. package/src/atmosphere-background.wgsl +3 -3
  42. package/src/auto-exposure-meter.wgsl +179 -0
  43. package/src/color-lut.wgsl +17 -0
  44. package/src/common.wgsl +7 -5
  45. package/src/default-standard-pbr-skin.wgsl +142 -40
  46. package/src/default-standard-pbr.wgsl +198 -82
  47. package/src/default_standard_surface.wgsl +56 -19
  48. package/src/fxaa.wgsl +9 -5
  49. package/src/ibl-sampling.wgsl +30 -6
  50. package/src/index.ts +189 -0
  51. package/src/lighting-punctual.wgsl +5 -6
  52. package/src/material/artifact-types.ts +109 -63
  53. package/src/material-schemas.ts +84 -8
  54. package/src/output-encoding.wgsl +10 -0
  55. package/src/pbr-temporal.wgsl +9 -1
  56. package/src/scene-temporal.wgsl +2 -0
  57. package/src/shadow-pcf.wgsl +6 -8
  58. package/src/shadow-surface.wgsl +16 -0
  59. package/src/shadow_caster.wgsl +99 -61
  60. package/src/sprite-lit.wgsl +4 -4
  61. package/src/sprite.wgsl +3 -3
  62. package/src/ssr-compose.wgsl +129 -0
  63. package/src/ssr-hiz-reduce.wgsl +53 -0
  64. package/src/ssr-hiz.wgsl +66 -0
  65. package/src/ssr-temporal.wgsl +305 -0
  66. package/src/ssr-trace.wgsl +784 -0
  67. package/src/standard-cluster.wgsl +6 -4
  68. package/src/standard-surface.wgsl +696 -0
  69. package/src/surface_v1.wgsl +6 -0
  70. package/src/taa-resolve.wgsl +222 -28
  71. package/src/tbn.wgsl +1 -1
  72. package/src/tonemap.wgsl +37 -18
  73. package/src/unlit.wgsl +3 -3
@@ -1,5 +1,5 @@
1
1
  #pragma material_slot surface
2
- #import forgeax_material::slot::surface::{evaluate_surface}
2
+ #import forgeax_material::slot::surface::{evaluate_surface, evaluate_standard_surface}
3
3
  #import forgeax_material::surface_v1::{SurfaceInput, SurfaceData}
4
4
  #import forgeax_view::common::{View, Mesh, InstanceData, view, meshes, instances, shadowMap, shadowSampler, sampleMaterialTexture}
5
5
  #import forgeax_scene_temporal::{sceneViewZ}
@@ -8,7 +8,7 @@
8
8
  #endif
9
9
  #import forgeax_pbr::temporal::{projectPbrSceneTemporal}
10
10
  #import forgeax_pbr::brdf::{f_schlick, v_smith, d_ggx}
11
- #import forgeax_pbr::ibl_sampling::{sampleIblDiffuse, sampleIblSpecular, sampleReflectionProbeSpecular}
11
+ #import forgeax_pbr::ibl_sampling::{decodeSpecularEnvironmentScale, sampleIblDiffuse, sampleIblSpecular, sampleReflectionProbeSpecular}
12
12
  #import forgeax_pbr::lighting_probe::{evaluateProbeDiffuse}
13
13
  #import forgeax_pbr::tbn::{decodeTangentSpaceNormalRg, scaleTangentSpaceNormal, applyTBN}
14
14
  #ifdef CLEARCOAT_AVAILABLE
@@ -36,6 +36,7 @@
36
36
  #pragma variant_axis EXTENDED_LIGHTING_AVAILABLE
37
37
  #pragma variant_axis TRANSMISSION_AVAILABLE
38
38
  #pragma variant_axis DIRECTIONAL_PCSS_AVAILABLE
39
+ #pragma variant_axis GPU_DRIVEN_SCENE_INDEX_AVAILABLE
39
40
 
40
41
  #ifdef PROBE_BLEND_AVAILABLE
41
42
  fn composeProbeDiffuse(
@@ -106,21 +107,35 @@ fn composeProbeDiffuse(
106
107
  // from the root ParamSchema during material composition. Keeping the ABI out
107
108
  // of this template prevents a second handwritten interface from drifting from
108
109
  // the runtime UBO writer.
110
+ #ifdef BASE_COLOR_TEXTURE_AVAILABLE
109
111
  @group(1) @binding(1) var baseColorTexture_sampler : sampler;
110
112
  @group(1) @binding(2) var baseColorTexture : texture_2d<f32>;
113
+ #endif
114
+ #ifdef METALLIC_ROUGHNESS_TEXTURE_AVAILABLE
111
115
  @group(1) @binding(3) var metallicRoughnessTexture_sampler : sampler;
112
116
  @group(1) @binding(4) var metallicRoughnessTexture : texture_2d<f32>;
117
+ #endif
118
+ #ifdef NORMAL_TEXTURE_AVAILABLE
113
119
  @group(1) @binding(5) var normalTexture_sampler : sampler;
114
120
  @group(1) @binding(6) var normalTexture : texture_2d<f32>;
121
+ #endif
122
+ #ifdef EMISSIVE_TEXTURE_AVAILABLE
115
123
  @group(1) @binding(9) var emissiveTexture_sampler : sampler;
116
124
  @group(1) @binding(10) var emissiveTexture : texture_2d<f32>;
125
+ #endif
126
+ #ifdef OCCLUSION_TEXTURE_AVAILABLE
117
127
  @group(1) @binding(11) var occlusionTexture_sampler : sampler;
118
128
  @group(1) @binding(12) var occlusionTexture : texture_2d<f32>;
129
+ #endif
119
130
  #ifdef TRANSMISSION_AVAILABLE
131
+ #ifdef TRANSMISSION_TEXTURE_AVAILABLE
120
132
  @group(1) @binding(13) var transmissionSampler : sampler;
121
133
  @group(1) @binding(14) var transmissionTexture : texture_2d<f32>;
134
+ #endif
135
+ #ifdef THICKNESS_TEXTURE_AVAILABLE
122
136
  @group(1) @binding(15) var thicknessSampler : sampler;
123
137
  @group(1) @binding(16) var thicknessTexture : texture_2d<f32>;
138
+ #endif
124
139
  @group(1) @binding(24) var transmissionBackdropSampler : sampler;
125
140
  @group(1) @binding(25) var transmissionBackdropTexture : texture_2d<f32>;
126
141
  #endif
@@ -167,11 +182,21 @@ fn composeProbeDiffuse(
167
182
 
168
183
  // Preserve filtering reflection for resources passed to the shared sampler.
169
184
  fn materialTextureFilteringWitness() {
185
+ #ifdef BASE_COLOR_TEXTURE_AVAILABLE
170
186
  let base = baseColorTexture;
187
+ #endif
188
+ #ifdef METALLIC_ROUGHNESS_TEXTURE_AVAILABLE
171
189
  let metallicRoughness = metallicRoughnessTexture;
190
+ #endif
191
+ #ifdef NORMAL_TEXTURE_AVAILABLE
172
192
  let normal = normalTexture;
193
+ #endif
194
+ #ifdef EMISSIVE_TEXTURE_AVAILABLE
173
195
  let emissive = emissiveTexture;
196
+ #endif
197
+ #ifdef OCCLUSION_TEXTURE_AVAILABLE
174
198
  let occlusion = occlusionTexture;
199
+ #endif
175
200
  #ifdef CLEARCOAT_TEXTURE_AVAILABLE
176
201
  let clearcoat = clearcoatTexture;
177
202
  #endif
@@ -182,14 +207,28 @@ fn materialTextureFilteringWitness() {
182
207
  let clearcoatNormal = clearcoatNormalTexture;
183
208
  #endif
184
209
  #ifdef TRANSMISSION_AVAILABLE
210
+ #ifdef TRANSMISSION_TEXTURE_AVAILABLE
185
211
  let transmission = transmissionTexture;
212
+ #endif
213
+ #ifdef THICKNESS_TEXTURE_AVAILABLE
186
214
  let thickness = thicknessTexture;
187
215
  #endif
216
+ #endif
217
+ #ifdef BASE_COLOR_TEXTURE_AVAILABLE
188
218
  let baseWitness = textureSample(base, baseColorTexture_sampler, vec2<f32>(0.0));
219
+ #endif
220
+ #ifdef METALLIC_ROUGHNESS_TEXTURE_AVAILABLE
189
221
  let metallicRoughnessWitness = textureSample(metallicRoughness, metallicRoughnessTexture_sampler, vec2<f32>(0.0));
222
+ #endif
223
+ #ifdef NORMAL_TEXTURE_AVAILABLE
190
224
  let normalWitness = textureSample(normal, normalTexture_sampler, vec2<f32>(0.0));
225
+ #endif
226
+ #ifdef EMISSIVE_TEXTURE_AVAILABLE
191
227
  let emissiveWitness = textureSample(emissive, emissiveTexture_sampler, vec2<f32>(0.0));
228
+ #endif
229
+ #ifdef OCCLUSION_TEXTURE_AVAILABLE
192
230
  let occlusionWitness = textureSample(occlusion, occlusionTexture_sampler, vec2<f32>(0.0));
231
+ #endif
193
232
  #ifdef CLEARCOAT_TEXTURE_AVAILABLE
194
233
  let clearcoatWitness = textureSample(clearcoat, clearcoatSampler, vec2<f32>(0.0));
195
234
  #endif
@@ -221,9 +260,13 @@ fn materialTextureFilteringWitness() {
221
260
  let specularColorWitness = textureSample(specularColorTexture, specularColorTextureSampler, vec2<f32>(0.0));
222
261
  #endif
223
262
  #ifdef TRANSMISSION_AVAILABLE
263
+ #ifdef TRANSMISSION_TEXTURE_AVAILABLE
224
264
  let transmissionWitness = textureSample(transmission, transmissionSampler, vec2<f32>(0.0));
265
+ #endif
266
+ #ifdef THICKNESS_TEXTURE_AVAILABLE
225
267
  let thicknessWitness = textureSample(thickness, thicknessSampler, vec2<f32>(0.0));
226
268
  #endif
269
+ #endif
227
270
  }
228
271
 
229
272
  struct SkylightUniforms {
@@ -252,6 +295,11 @@ struct SkylightUniforms {
252
295
  @group(3) @binding(1) var<storage, read> probeBlendRecords : array<vec4<f32>>;
253
296
  #endif
254
297
 
298
+ #ifdef GPU_DRIVEN_SCENE_INDEX_AVAILABLE
299
+ @group(1) @binding(46) var<storage, read> sceneMaterials : array<MaterialParameters>;
300
+ @group(3) @binding(2) var<storage, read> visibleItems : array<vec2<u32>>;
301
+ #endif
302
+
255
303
  #if STORAGE_BUFFER_AVAILABLE == true
256
304
  @group(2) @binding(1) var<storage, read> palette : array<mat4x4<f32>>;
257
305
  @group(2) @binding(2) var<storage, read> previousPalette : array<mat4x4<f32>>;
@@ -281,7 +329,7 @@ struct VsIn {
281
329
  #endif
282
330
  };
283
331
  struct VsOut {
284
- @builtin(position) clip : vec4<f32>,
332
+ @builtin(position) @invariant clip : vec4<f32>,
285
333
  #ifdef TRANSMISSION_AVAILABLE
286
334
  @location(4) @interpolate(flat) transmissionBasis0 : vec4<f32>,
287
335
  #else
@@ -310,10 +358,14 @@ struct VsOut {
310
358
  #ifdef TRANSMISSION_AVAILABLE
311
359
  @location(7) viewZ : f32,
312
360
  @location(13) @interpolate(flat) transmissionBasis1 : vec4<f32>,
361
+ #else
362
+ #if GPU_DRIVEN_SCENE_INDEX_AVAILABLE == true
363
+ @location(15) @interpolate(flat) materialIndex : u32,
364
+ #endif
313
365
  #endif
314
366
  };
315
367
 
316
- fn vs_main_impl(in : VsIn, meshIndex : u32, instanceIndex : u32) -> VsOut {
368
+ fn vs_main_impl(in : VsIn, meshIndex : u32, instanceIndex : u32, materialIndex : u32) -> VsOut {
317
369
  // 4-bone weighted skinning (plan-strategy D-3 / D-3a).
318
370
  // The host pre-computes each joint matrix as worldFromJoint * inverseBindMatrix
319
371
  // (CPU-side pre-multiplication, per D-4) and writes them into the palette
@@ -389,6 +441,11 @@ fn vs_main_impl(in : VsIn, meshIndex : u32, instanceIndex : u32) -> VsOut {
389
441
  // the fragment stage.
390
442
  out.transmissionBasis0 = vec4<f32>(skinMatrix[0].xyz, skinMatrix[1].x);
391
443
  out.transmissionBasis1 = vec4<f32>(skinMatrix[1].y, skinMatrix[1].z, skinMatrix[2].x, skinMatrix[2].y);
444
+ #endif
445
+ #if GPU_DRIVEN_SCENE_INDEX_AVAILABLE == true
446
+ #if TRANSMISSION_AVAILABLE == false
447
+ out.materialIndex = materialIndex;
448
+ #endif
392
449
  #endif
393
450
  let clipPos = out.clip;
394
451
  out.ndc = vec4(clipPos.xy / clipPos.w, clipPos.z / clipPos.w, skinMatrix[2].z);
@@ -413,14 +470,25 @@ fn standardViewZ(in : VsOut) -> f32 {
413
470
 
414
471
  @vertex
415
472
  fn vs_main(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
416
- return vs_main_impl(in, 0u, idx);
473
+ return vs_main_impl(in, 0u, idx, 0xffffffffu);
417
474
  }
418
475
 
476
+ #ifdef GPU_DRIVEN_SCENE_INDEX_AVAILABLE
419
477
  @vertex
420
478
  fn vs_scene_index(in : VsIn, @builtin(instance_index) idx : u32) -> VsOut {
421
- return vs_main_impl(in, idx, 0u);
479
+ let visible = visibleItems[idx];
480
+ return vs_main_impl(in, visible.x, 0u, visible.y);
481
+ }
482
+ #endif
483
+
484
+ #ifdef GPU_DRIVEN_SCENE_INDEX_AVAILABLE
485
+ fn selectedMaterial(index : u32) -> MaterialParameters {
486
+ return sceneMaterials[index];
422
487
  }
423
488
 
489
+
490
+ #endif
491
+
424
492
  fn transformedMaterialUv(transform : vec4<f32>, metadata : vec4<f32>, in : VsOut) -> vec2<f32> {
425
493
  var source = in.uv;
426
494
  if (metadata.x >= 1.0) { source = in.uv1; }
@@ -481,17 +549,20 @@ fn evaluateStandardSurface(in : VsOut, frontFacing : bool) -> SurfaceData {
481
549
  #else
482
550
  let positionOS = in.positionOSAndViewZ.xyz;
483
551
  #endif
484
- return evaluate_surface(SurfaceInput(
485
- positionOS,
486
- in.worldPos,
487
- in.worldNormal,
488
- in.worldTangent,
489
- viewDirectionWS,
490
- in.uv,
491
- in.uv1,
492
- materialVertexColor(in),
493
- frontFacing,
494
- ));
552
+ let input = SurfaceInput(
553
+ positionOS, in.worldPos, in.worldNormal, in.worldTangent, viewDirectionWS,
554
+ in.uv, in.uv1, in.uv2, in.uv3, in.uv4, in.uv5,
555
+ in.uv6And7.xy, in.uv6And7.zw, materialVertexColor(in), frontFacing,
556
+ );
557
+ #if GPU_DRIVEN_SCENE_INDEX_AVAILABLE == true
558
+ #if TRANSMISSION_AVAILABLE == false
559
+ return evaluate_standard_surface(input, selectedMaterial(in.materialIndex));
560
+ #else
561
+ return evaluate_surface(input);
562
+ #endif
563
+ #else
564
+ return evaluate_surface(input);
565
+ #endif
495
566
  }
496
567
 
497
568
  fn finiteScalar(value : f32, fallback : f32) -> f32 {
@@ -516,6 +587,11 @@ fn alphaTestSurface(surface : SurfaceData) {
516
587
  @fragment
517
588
  fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0) vec4<f32> {
518
589
  let _variantIdentity = standardSkinVariantIdentity();
590
+ #if GPU_DRIVEN_SCENE_INDEX_AVAILABLE == true
591
+ #if TRANSMISSION_AVAILABLE == false
592
+ let material = selectedMaterial(in.materialIndex);
593
+ #endif
594
+ #endif
519
595
  let surface = evaluateStandardSurface(in, frontFacing);
520
596
  alphaTestSurface(surface);
521
597
  let alpha = surface.opacity;
@@ -528,6 +604,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
528
604
  let v = normalize(view.cameraPos - in.worldPos);
529
605
  var specularColor = material.specularColor;
530
606
  #ifdef SPECULAR_COLOR_TEXTURE_AVAILABLE
607
+ if (standardUsesSpecularColorTexture()) {
531
608
  specularColor = specularColor * sampleMaterialTexture(
532
609
  specularColorTexture,
533
610
  specularColorTextureSampler,
@@ -538,9 +615,11 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
538
615
  ),
539
616
  material.specularColorTextureCoordinatesMetadata.zw,
540
617
  ).rgb;
618
+ }
541
619
  #endif
542
620
  var specularWeight = clamp(finiteScalar(material.specular, 1.0), 0.0, 1.0);
543
621
  #ifdef SPECULAR_TEXTURE_AVAILABLE
622
+ if (standardUsesSpecularTexture()) {
544
623
  let specularWeightUv = transformedMaterialUv(
545
624
  material.specularTextureCoordinatesTransform,
546
625
  material.specularTextureCoordinatesMetadata,
@@ -552,6 +631,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
552
631
  specularWeightUv,
553
632
  material.specularTextureCoordinatesMetadata.zw,
554
633
  ).a;
634
+ }
555
635
  #endif
556
636
  let safeIor = max(finiteScalar(material.ior, 1.5), 1.0);
557
637
  let dielectricF0 = pow((safeIor - 1.0) / (safeIor + 1.0), 2.0);
@@ -562,6 +642,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
562
642
  var anisotropyRotation = finiteScalar(material.anisotropyRotation, 0.0);
563
643
  var anisotropyDirection = vec2<f32>(1.0, 0.0);
564
644
  #ifdef ANISOTROPY_TEXTURE_AVAILABLE
645
+ if (standardUsesAnisotropyTexture()) {
565
646
  let anisotropyUv = transformedMaterialUv(
566
647
  material.anisotropyTextureCoordinatesTransform,
567
648
  material.anisotropyTextureCoordinatesMetadata,
@@ -578,6 +659,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
578
659
  anisotropyDirection = normalize(encodedAnisotropyDirection);
579
660
  }
580
661
  anisotropyStrength = anisotropyStrength * anisotropySample.b;
662
+ }
581
663
  #endif
582
664
  physicalNormal = evaluateAnisotropicNormal(
583
665
  n,
@@ -591,6 +673,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
591
673
  var iridescenceStrength = finiteScalar(material.iridescence, 0.0);
592
674
  var iridescenceThicknessFactor = 1.0;
593
675
  #ifdef IRIDESCENCE_TEXTURE_AVAILABLE
676
+ if (standardUsesIridescenceTexture()) {
594
677
  let iridescenceUv = transformedMaterialUv(
595
678
  material.iridescenceTextureCoordinatesTransform,
596
679
  material.iridescenceTextureCoordinatesMetadata,
@@ -603,8 +686,10 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
603
686
  material.iridescenceTextureCoordinatesMetadata.zw,
604
687
  );
605
688
  iridescenceStrength = iridescenceStrength * iridescenceSample.r;
689
+ }
606
690
  #endif
607
691
  #ifdef IRIDESCENCE_THICKNESS_TEXTURE_AVAILABLE
692
+ if (standardUsesIridescenceThicknessTexture()) {
608
693
  let iridescenceThicknessUv = transformedMaterialUv(
609
694
  material.iridescenceThicknessTextureCoordinatesTransform,
610
695
  material.iridescenceThicknessTextureCoordinatesMetadata,
@@ -617,6 +702,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
617
702
  material.iridescenceThicknessTextureCoordinatesMetadata.zw,
618
703
  );
619
704
  iridescenceThicknessFactor = clamp(iridescenceThicknessSample.g, 0.0, 1.0);
705
+ }
620
706
  #endif
621
707
  let filmThickness = mix(
622
708
  finiteScalar(material.iridescenceThicknessMinimum, 100.0),
@@ -632,28 +718,30 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
632
718
  #endif
633
719
  var diffuseAlbedo = albedo;
634
720
  #ifdef TRANSMISSION_AVAILABLE
635
- let transmissionUv = transformedMaterialUv(
636
- material.transmissionTextureCoordinatesTransform,
637
- material.transmissionTextureCoordinatesMetadata,
638
- in,
639
- );
640
- let thicknessUv = transformedMaterialUv(
641
- material.thicknessTextureCoordinatesTransform,
642
- material.thicknessTextureCoordinatesMetadata,
643
- in,
644
- );
645
- let transmissionSample = sampleMaterialTexture(
721
+ var transmissionSample = 1.0;
722
+ #ifdef TRANSMISSION_TEXTURE_AVAILABLE
723
+ if (standardUsesTransmissionTexture()) {
724
+ let transmissionUv = transformedMaterialUv(material.transmissionTextureCoordinatesTransform, material.transmissionTextureCoordinatesMetadata, in);
725
+ transmissionSample = sampleMaterialTexture(
646
726
  transmissionTexture,
647
727
  transmissionSampler,
648
728
  transmissionUv,
649
729
  material.transmissionTextureCoordinatesMetadata.zw,
650
730
  ).r;
651
- let thicknessSample = sampleMaterialTexture(
731
+ }
732
+ #endif
733
+ var thicknessSample = 1.0;
734
+ #ifdef THICKNESS_TEXTURE_AVAILABLE
735
+ if (standardUsesThicknessTexture()) {
736
+ let thicknessUv = transformedMaterialUv(material.thicknessTextureCoordinatesTransform, material.thicknessTextureCoordinatesMetadata, in);
737
+ thicknessSample = sampleMaterialTexture(
652
738
  thicknessTexture,
653
739
  thicknessSampler,
654
740
  thicknessUv,
655
741
  material.thicknessTextureCoordinatesMetadata.zw,
656
742
  ).g;
743
+ }
744
+ #endif
657
745
  let transmissionFactor = clamp(
658
746
  finiteScalar(material.transmission, 0.0) * finiteScalar(transmissionSample, 1.0),
659
747
  0.0,
@@ -705,6 +793,12 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
705
793
  let ao = surface.occlusion;
706
794
  let skyColor = vec3<f32>(skylight.colorR, skylight.colorG, skylight.colorB);
707
795
  let skyFactor = skyColor * skylight.intensity;
796
+ // ReflectionProbe sentinel metadata is decoded by the shared IBL owner so
797
+ // the blended and regular paths retain the same physical scaling.
798
+ let specularEnvironmentScale = decodeSpecularEnvironmentScale(
799
+ skyColor,
800
+ skylight.intensity,
801
+ );
708
802
  var ambient = (kD * irradiance * diffuseAlbedo + specularIbl) *
709
803
  (vec3<f32>(1.0) - coatF);
710
804
  #ifdef PROBE_BLEND_AVAILABLE
@@ -723,19 +817,14 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
723
817
  diffuseAlbedo,
724
818
  metallic,
725
819
  );
726
- ambient = (probeDiffuse + specularIbl * skyFactor) *
820
+ ambient = (probeDiffuse + specularIbl * specularEnvironmentScale) *
727
821
  (vec3<f32>(1.0) - coatF);
728
822
  #endif
729
823
  #ifdef PROBE_BLEND_AVAILABLE
730
824
  ambient = ambient * ao;
731
825
  #else
732
- if (skylight.intensity < 0.0) {
733
- let environmentScale = max(-skylight.intensity - 1.0, 0.0) * ao;
734
- ambient = ambient * environmentScale;
735
- } else {
736
- let environmentScale = skyColor * skylight.intensity * ao;
737
- ambient = ambient * environmentScale;
738
- }
826
+ let environmentScale = specularEnvironmentScale * ao;
827
+ ambient = ambient * environmentScale;
739
828
  #endif
740
829
  var color = ambient;
741
830
  #ifdef TRANSMISSION_AVAILABLE
@@ -833,27 +922,31 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
833
922
  #ifdef CLUSTER_FORWARD_AVAILABLE
834
923
  color = color + evaluateStandardClusterLights(
835
924
  in.ndc.xyz, standardViewZ(in), in.worldPos, physicalNormal, v,
836
- diffuseAlbedo, metallic, a, f0, false,
925
+ diffuseAlbedo, metallic, a, f0, false, true,
837
926
  );
838
927
  #endif // CLUSTER_FORWARD_AVAILABLE
839
928
  #ifdef SHEEN_AVAILABLE
840
929
  var sheenColor = material.sheenColor;
841
930
  var sheenRoughnessFactor = 1.0;
842
931
  #ifdef SHEEN_COLOR_TEXTURE_AVAILABLE
932
+ if (standardUsesSheenColorTexture()) {
843
933
  sheenColor = sheenColor * sampleMaterialTexture(
844
934
  sheenColorTexture,
845
935
  sheenColorSampler,
846
936
  transformedMaterialUv(material.sheenColorTextureCoordinatesTransform, material.sheenColorTextureCoordinatesMetadata, in),
847
937
  material.sheenColorTextureCoordinatesMetadata.zw,
848
938
  ).rgb;
939
+ }
849
940
  #endif
850
941
  #ifdef SHEEN_ROUGHNESS_TEXTURE_AVAILABLE
942
+ if (standardUsesSheenRoughnessTexture()) {
851
943
  sheenRoughnessFactor = sampleMaterialTexture(
852
944
  sheenRoughnessTexture,
853
945
  sheenRoughnessSampler,
854
946
  transformedMaterialUv(material.sheenRoughnessTextureCoordinatesTransform, material.sheenRoughnessTextureCoordinatesMetadata, in),
855
947
  material.sheenRoughnessTextureCoordinatesMetadata.zw,
856
948
  ).a;
949
+ }
857
950
  #endif
858
951
  let sheenRoughness = clamp(
859
952
  material.sheenRoughness * sheenRoughnessFactor,
@@ -865,6 +958,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
865
958
  #ifdef CLEARCOAT_AVAILABLE
866
959
  var clearcoatFactor = clamp(material.clearcoat, 0.0, 1.0);
867
960
  #ifdef CLEARCOAT_TEXTURE_AVAILABLE
961
+ if (standardUsesClearcoatTexture()) {
868
962
  let clearcoatUv = transformedMaterialUv(material.clearcoatTextureCoordinatesTransform, material.clearcoatTextureCoordinatesMetadata, in);
869
963
  clearcoatFactor = clamp(
870
964
  material.clearcoat * sampleMaterialTexture(
@@ -876,9 +970,11 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
876
970
  0.0,
877
971
  1.0,
878
972
  );
973
+ }
879
974
  #endif
880
975
  var clearcoatRoughnessValue = clamp(max(material.clearcoatRoughness, 0.04), 0.04, 1.0);
881
976
  #ifdef CLEARCOAT_ROUGHNESS_TEXTURE_AVAILABLE
977
+ if (standardUsesClearcoatRoughnessTexture()) {
882
978
  let clearcoatRoughnessUv = transformedMaterialUv(material.clearcoatRoughnessTextureCoordinatesTransform, material.clearcoatRoughnessTextureCoordinatesMetadata, in);
883
979
  clearcoatRoughnessValue = clamp(
884
980
  max(material.clearcoatRoughness, 0.04) * sampleMaterialTexture(
@@ -890,9 +986,11 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
890
986
  0.04,
891
987
  1.0,
892
988
  );
989
+ }
893
990
  #endif
894
991
  var clearcoatNormalValue = in.worldNormal;
895
992
  #ifdef CLEARCOAT_NORMAL_TEXTURE_AVAILABLE
993
+ if (standardUsesClearcoatNormalTexture()) {
896
994
  let clearcoatNormalUv = transformedMaterialUv(material.clearcoatNormalTextureCoordinatesTransform, material.clearcoatNormalTextureCoordinatesMetadata, in);
897
995
  clearcoatNormalValue = applyTBN(
898
996
  in.worldNormal,
@@ -907,6 +1005,7 @@ fn fs_main(in : VsOut, @builtin(front_facing) frontFacing : bool) -> @location(0
907
1005
  material.clearcoatNormalScale,
908
1006
  ),
909
1007
  );
1008
+ }
910
1009
  #endif
911
1010
  var clearcoatIbl = vec3<f32>(0.0);
912
1011
  if (skylight.intensity < 0.0) {
@@ -988,7 +1087,7 @@ fn fs_gbuffer(in : VsOut, @builtin(front_facing) frontFacing : bool) -> GBufferO
988
1087
  }
989
1088
 
990
1089
  struct TemporalVsOut {
991
- @builtin(position) clip : vec4<f32>,
1090
+ @builtin(position) @invariant clip : vec4<f32>,
992
1091
  @location(0) uv : vec2<f32>,
993
1092
  @location(1) uv1 : vec2<f32>,
994
1093
  @location(2) uv2 : vec2<f32>,
@@ -1018,7 +1117,7 @@ fn vs_temporal(in : VsIn, @builtin(instance_index) idx : u32) -> TemporalVsOut {
1018
1117
  let previousWorld = previousSkin * vec4<f32>(in.pos, 1.0);
1019
1118
  var out : TemporalVsOut;
1020
1119
  out.currentClip = view.temporalCurrentViewProj * currentWorld;
1021
- out.clip = out.currentClip;
1120
+ out.clip = view.worldViewProj * currentWorld;
1022
1121
  out.previousClip = view.temporalPreviousViewProj * previousWorld;
1023
1122
  out.uv = in.uv;
1024
1123
  out.uv1 = in.uv1;
@@ -1053,10 +1152,13 @@ fn fs_temporal(in : TemporalVsOut) -> @location(0) vec4<f32> {
1053
1152
  return projectPbrSceneTemporal(
1054
1153
  material.baseColor.a * temporalVertexAlpha(in),
1055
1154
  material.alphaCutoff,
1155
+ #ifdef BASE_COLOR_TEXTURE_AVAILABLE
1156
+ standardUsesBaseColorTexture(),
1056
1157
  baseColorTexture,
1057
1158
  baseColorTexture_sampler,
1058
1159
  material.baseColorTextureCoordinatesTransform,
1059
1160
  material.baseColorTextureCoordinatesMetadata,
1161
+ #endif
1060
1162
  in.currentClip,
1061
1163
  in.previousClip,
1062
1164
  view.temporalProjection,