@luma.gl/shaders 10.0.0-alpha.6 → 10.0.0-alpha.8

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 (109) hide show
  1. package/dist/dist.dev.js +236 -141
  2. package/dist/dist.min.js +130 -125
  3. package/dist/glsl.cjs.map +1 -1
  4. package/dist/index.cjs.map +2 -2
  5. package/dist/index.d.ts +1 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/lib/glsl-shader-assembler.cjs +1 -1
  9. package/dist/lib/glsl-shader-assembler.js +1 -1
  10. package/dist/lib/glsl-shader-assembler.js.map +1 -1
  11. package/dist/lib/preprocessor/preprocessor.cjs +21 -0
  12. package/dist/lib/preprocessor/preprocessor.js +21 -0
  13. package/dist/lib/preprocessor/preprocessor.js.map +1 -1
  14. package/dist/lib/shader-assembly/assemble-glsl-shaders.cjs +12 -20
  15. package/dist/lib/shader-assembly/assemble-glsl-shaders.d.ts +3 -2
  16. package/dist/lib/shader-assembly/assemble-glsl-shaders.d.ts.map +1 -1
  17. package/dist/lib/shader-assembly/assemble-glsl-shaders.js +13 -21
  18. package/dist/lib/shader-assembly/assemble-glsl-shaders.js.map +1 -1
  19. package/dist/lib/shader-assembly/assemble-wgsl-shaders.cjs +7 -7
  20. package/dist/lib/shader-assembly/assemble-wgsl-shaders.js +8 -8
  21. package/dist/lib/shader-assembly/assemble-wgsl-shaders.js.map +1 -1
  22. package/dist/lib/shader-assembly/shader-assembly-types.d.ts +11 -7
  23. package/dist/lib/shader-assembly/shader-assembly-types.d.ts.map +1 -1
  24. package/dist/lib/shader-assembly/shader-hooks.cjs +23 -4
  25. package/dist/lib/shader-assembly/shader-hooks.d.ts +1 -1
  26. package/dist/lib/shader-assembly/shader-hooks.d.ts.map +1 -1
  27. package/dist/lib/shader-assembly/shader-hooks.js +27 -4
  28. package/dist/lib/shader-assembly/shader-hooks.js.map +1 -1
  29. package/dist/lib/shader-assembly/shader-injections.d.ts +2 -0
  30. package/dist/lib/shader-assembly/shader-injections.d.ts.map +1 -1
  31. package/dist/lib/shader-assembly/shader-injections.js.map +1 -1
  32. package/dist/lib/shader-assembly/shader-plugin-varyings.cjs +39 -22
  33. package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts +5 -5
  34. package/dist/lib/shader-assembly/shader-plugin-varyings.d.ts.map +1 -1
  35. package/dist/lib/shader-assembly/shader-plugin-varyings.js +45 -19
  36. package/dist/lib/shader-assembly/shader-plugin-varyings.js.map +1 -1
  37. package/dist/lib/shader-generator/glsl/generate-glsl.d.ts +1 -1
  38. package/dist/lib/shader-generator/glsl/generate-glsl.d.ts.map +1 -1
  39. package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts +1 -1
  40. package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts.map +1 -1
  41. package/dist/lib/shader-plugin.cjs +94 -34
  42. package/dist/lib/shader-plugin.d.ts +55 -37
  43. package/dist/lib/shader-plugin.d.ts.map +1 -1
  44. package/dist/lib/shader-plugin.js +103 -35
  45. package/dist/lib/shader-plugin.js.map +1 -1
  46. package/dist/lib/wgsl-shader-assembler.cjs +1 -1
  47. package/dist/lib/wgsl-shader-assembler.js +1 -1
  48. package/dist/lib/wgsl-shader-assembler.js.map +1 -1
  49. package/dist/modules/engine/clip/clip.cjs +20 -30
  50. package/dist/modules/engine/clip/clip.d.ts.map +1 -1
  51. package/dist/modules/engine/clip/clip.js +21 -31
  52. package/dist/modules/engine/clip/clip.js.map +1 -1
  53. package/dist/modules/engine/filter/filter.cjs +10 -18
  54. package/dist/modules/engine/filter/filter.d.ts.map +1 -1
  55. package/dist/modules/engine/filter/filter.js +10 -18
  56. package/dist/modules/engine/filter/filter.js.map +1 -1
  57. package/dist/modules/lighting/lights/lighting.d.ts +1 -1
  58. package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
  59. package/dist/modules/lighting/pbr-material/pbr-material-glsl.cjs +2 -2
  60. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +1 -1
  61. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
  62. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +2 -2
  63. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.cjs +2 -2
  64. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +1 -1
  65. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
  66. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +2 -2
  67. package/dist/modules/lighting/pbr-material/pbr-material.d.ts +2 -2
  68. package/dist/modules/math/fp64/fp64.cjs +1 -1
  69. package/dist/modules/math/fp64/fp64.d.ts +1 -1
  70. package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
  71. package/dist/modules/math/fp64/fp64.js +1 -1
  72. package/dist/modules/math/fp64/fp64.js.map +1 -1
  73. package/dist/types/texture-formats.d.ts +1 -1
  74. package/dist/types/texture-formats.d.ts.map +1 -1
  75. package/dist/types.cjs +27 -16
  76. package/dist/types.d.ts +7 -7
  77. package/dist/types.d.ts.map +1 -1
  78. package/dist/types.js +2 -7
  79. package/dist/types.js.map +1 -1
  80. package/dist/wgsl.cjs +20 -4
  81. package/dist/wgsl.cjs.map +1 -1
  82. package/dist/wgsl.d.ts +1 -1
  83. package/dist/wgsl.d.ts.map +1 -1
  84. package/dist/wgsl.js +1 -1
  85. package/dist/wgsl.js.map +1 -1
  86. package/package.json +3 -3
  87. package/src/index.ts +5 -4
  88. package/src/lib/glsl-shader-assembler.ts +1 -1
  89. package/src/lib/preprocessor/preprocessor.ts +25 -0
  90. package/src/lib/shader-assembly/assemble-glsl-shaders.ts +19 -23
  91. package/src/lib/shader-assembly/assemble-wgsl-shaders.ts +9 -9
  92. package/src/lib/shader-assembly/shader-assembly-types.ts +11 -7
  93. package/src/lib/shader-assembly/shader-hooks.ts +33 -4
  94. package/src/lib/shader-assembly/shader-injections.ts +2 -0
  95. package/src/lib/shader-assembly/shader-plugin-varyings.ts +58 -27
  96. package/src/lib/shader-generator/glsl/generate-glsl.ts +1 -1
  97. package/src/lib/shader-generator/wgsl/generate-wgsl.ts +1 -1
  98. package/src/lib/shader-module/shader-module-dependencies.ts +1 -1
  99. package/src/lib/shader-plugin.ts +154 -77
  100. package/src/lib/wgsl-shader-assembler.ts +1 -1
  101. package/src/modules/engine/clip/clip.ts +21 -31
  102. package/src/modules/engine/filter/filter.ts +10 -18
  103. package/src/modules/lighting/lights/lighting.ts +1 -1
  104. package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +2 -2
  105. package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +2 -2
  106. package/src/modules/math/fp64/fp64.ts +1 -1
  107. package/src/types/texture-formats.ts +2 -0
  108. package/src/types.ts +75 -7
  109. package/src/wgsl.ts +12 -1
@@ -1245,7 +1245,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
1245
1245
 
1246
1246
  for(int i = 0; i < lighting.directionalLightCount; i++) {
1247
1247
  if (i < lighting.directionalLightCount) {
1248
- PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
1248
+ PBRInfo_setDirectionalLight(pbrInfo, -lighting_getDirectionalLight(i).direction);
1249
1249
  color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
1250
1250
  }
1251
1251
  }
@@ -1533,7 +1533,7 @@ vec4 pbr_filterColorWithSpotShadows(vec4 vertexColor, vec4 spotVisibility)
1533
1533
  // Apply directional light
1534
1534
  for(int i = 0; i < lighting.directionalLightCount; i++) {
1535
1535
  if (i < lighting.directionalLightCount) {
1536
- PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
1536
+ PBRInfo_setDirectionalLight(pbrInfo, -lighting_getDirectionalLight(i).direction);
1537
1537
  color += calculateMaterialLightColor(
1538
1538
  pbrInfo,
1539
1539
  lighting_getDirectionalLight(i).color,
@@ -1481,7 +1481,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
1481
1481
 
1482
1482
  for (var i = 0; i < lighting.directionalLightCount; i++) {
1483
1483
  if (i < lighting.directionalLightCount) {
1484
- PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
1484
+ PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
1485
1485
  color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
1486
1486
  }
1487
1487
  }
@@ -1841,7 +1841,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
1841
1841
  // Apply directional light
1842
1842
  for (var i = 0; i < lighting.directionalLightCount; i++) {
1843
1843
  if (i < lighting.directionalLightCount) {
1844
- PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
1844
+ PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
1845
1845
  color += calculateMaterialLightColor(
1846
1846
  pbrInfo,
1847
1847
  lighting_getDirectionalLight(i).color,
@@ -1,3 +1,3 @@
1
1
  export declare const pbrMaterialUniforms = "uniform Projection {\n // Projection\n vec3 u_Camera;\n};\n\nuniform pbrMaterialUniforms {\n // Material is unlit\n bool unlit;\n\n // Base color map\n bool baseColorMapEnabled;\n vec4 baseColorFactor;\n\n bool normalMapEnabled; \n float normalScale; // #ifdef HAS_NORMALMAP\n\n bool emissiveMapEnabled;\n bool lightmapMapEnabled;\n vec3 emissiveFactor; // #ifdef HAS_EMISSIVEMAP\n\n vec2 metallicRoughnessValues;\n bool metallicRoughnessMapEnabled;\n\n bool occlusionMapEnabled;\n float occlusionStrength; // #ifdef HAS_OCCLUSIONMAP\n \n bool alphaCutoffEnabled;\n float alphaCutoff; // #ifdef ALPHA_CUTOFF\n\n vec3 specularColorFactor;\n float specularIntensityFactor;\n bool specularColorMapEnabled;\n bool specularIntensityMapEnabled;\n\n float ior;\n\n float transmissionFactor;\n bool transmissionMapEnabled;\n\n float thicknessFactor;\n float attenuationDistance;\n vec3 attenuationColor;\n\n float clearcoatFactor;\n float clearcoatRoughnessFactor;\n bool clearcoatMapEnabled;\n bool clearcoatRoughnessMapEnabled;\n\n vec3 sheenColorFactor;\n float sheenRoughnessFactor;\n bool sheenColorMapEnabled;\n bool sheenRoughnessMapEnabled;\n\n float iridescenceFactor;\n float iridescenceIor;\n vec2 iridescenceThicknessRange;\n bool iridescenceMapEnabled;\n\n float anisotropyStrength;\n float anisotropyRotation;\n vec2 anisotropyDirection;\n bool anisotropyMapEnabled;\n\n float emissiveStrength;\n float lightmapIntensity;\n float dispersion;\n \n // IBL\n bool IBLenabled;\n vec2 scaleIBLAmbient; // #ifdef USE_IBL\n \n // debugging flags used for shader output of intermediate PBR variables\n // #ifdef PBR_DEBUG\n vec4 scaleDiffBaseMR;\n vec4 scaleFGDSpec;\n // #endif\n};\n\n// Samplers\n#ifdef HAS_BASECOLORMAP\nuniform sampler2D u_BaseColorSampler;\n#endif\n#ifdef HAS_NORMALMAP\nuniform sampler2D u_NormalSampler;\n#endif\n#ifdef HAS_EMISSIVEMAP\nuniform sampler2D u_EmissiveSampler;\n#endif\n#ifdef HAS_LIGHTMAP\nuniform sampler2D u_LightmapSampler;\n#endif\n#ifdef HAS_METALROUGHNESSMAP\nuniform sampler2D u_MetallicRoughnessSampler;\n#endif\n#ifdef HAS_OCCLUSIONMAP\nuniform sampler2D u_OcclusionSampler;\n#endif\n#ifdef HAS_SPECULARCOLORMAP\nuniform sampler2D u_SpecularColorSampler;\n#endif\n#ifdef HAS_SPECULARINTENSITYMAP\nuniform sampler2D u_SpecularIntensitySampler;\n#endif\n#ifdef HAS_TRANSMISSIONMAP\nuniform sampler2D u_TransmissionSampler;\n#endif\n#ifdef HAS_THICKNESSMAP\nuniform sampler2D u_ThicknessSampler;\n#endif\n#ifdef HAS_CLEARCOATMAP\nuniform sampler2D u_ClearcoatSampler;\n#endif\n#ifdef HAS_CLEARCOATROUGHNESSMAP\nuniform sampler2D u_ClearcoatRoughnessSampler;\n#endif\n#ifdef HAS_CLEARCOATNORMALMAP\nuniform sampler2D u_ClearcoatNormalSampler;\n#endif\n#ifdef HAS_SHEENCOLORMAP\nuniform sampler2D u_SheenColorSampler;\n#endif\n#ifdef HAS_SHEENROUGHNESSMAP\nuniform sampler2D u_SheenRoughnessSampler;\n#endif\n#ifdef HAS_IRIDESCENCEMAP\nuniform sampler2D u_IridescenceSampler;\n#endif\n#ifdef HAS_IRIDESCENCETHICKNESSMAP\nuniform sampler2D u_IridescenceThicknessSampler;\n#endif\n#ifdef HAS_ANISOTROPYMAP\nuniform sampler2D u_AnisotropySampler;\n#endif\n#ifdef USE_IBL\nuniform samplerCube u_DiffuseEnvSampler;\nuniform samplerCube u_SpecularEnvSampler;\nuniform sampler2D u_brdfLUT;\n#endif\n\n";
2
- export declare const source = "#ifdef DOUBLE_SIDED\nvar<private> pbr_frontFacing: bool = true;\n#endif\nstruct PBRFragmentInputs {\n pbr_vPosition: vec3f,\n pbr_vUV0: vec2f,\n pbr_vUV1: vec2f,\n pbr_vTBN: mat3x3f,\n pbr_vNormal: vec3f\n};\n\nvar<private> fragmentInputs: PBRFragmentInputs;\n\nfn pbr_setPositionNormalTangentUV(\n position: vec4f,\n normal: vec4f,\n tangent: vec4f,\n uv0: vec2f,\n uv1: vec2f\n)\n{\n var pos: vec4f = pbrProjection.modelMatrix * position;\n fragmentInputs.pbr_vPosition = pos.xyz / pos.w;\n fragmentInputs.pbr_vNormal = vec3f(0.0, 0.0, 1.0);\n fragmentInputs.pbr_vTBN = mat3x3f(\n vec3f(1.0, 0.0, 0.0),\n vec3f(0.0, 1.0, 0.0),\n vec3f(0.0, 0.0, 1.0)\n );\n fragmentInputs.pbr_vUV0 = vec2f(0.0, 0.0);\n fragmentInputs.pbr_vUV1 = uv1;\n\n#ifdef HAS_NORMALS\n let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);\n fragmentInputs.pbr_vNormal = normalW;\n#ifdef HAS_TANGENTS\n let tangentW: vec3f = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);\n let bitangentW: vec3f = cross(normalW, tangentW) * tangent.w;\n fragmentInputs.pbr_vTBN = mat3x3f(tangentW, bitangentW, normalW);\n#endif\n#endif\n\n#ifdef HAS_UV\n fragmentInputs.pbr_vUV0 = uv0;\n#endif\n}\n\nstruct pbrMaterialUniforms {\n // Material is unlit\n unlit: u32,\n\n // Base color map\n baseColorMapEnabled: u32,\n baseColorFactor: vec4f,\n\n normalMapEnabled : u32,\n normalScale: f32, // #ifdef HAS_NORMALMAP\n\n emissiveMapEnabled: u32,\n emissiveFactor: vec3f, // #ifdef HAS_EMISSIVEMAP\n\n metallicRoughnessValues: vec2f,\n metallicRoughnessMapEnabled: u32,\n\n occlusionMapEnabled: i32,\n occlusionStrength: f32, // #ifdef HAS_OCCLUSIONMAP\n \n alphaCutoffEnabled: i32,\n alphaCutoff: f32, // #ifdef ALPHA_CUTOFF\n\n specularColorFactor: vec3f,\n specularIntensityFactor: f32,\n specularColorMapEnabled: i32,\n specularIntensityMapEnabled: i32,\n\n ior: f32,\n\n transmissionFactor: f32,\n transmissionMapEnabled: i32,\n\n thicknessFactor: f32,\n attenuationDistance: f32,\n attenuationColor: vec3f,\n\n clearcoatFactor: f32,\n clearcoatRoughnessFactor: f32,\n clearcoatMapEnabled: i32,\n clearcoatRoughnessMapEnabled: i32,\n\n sheenColorFactor: vec3f,\n sheenRoughnessFactor: f32,\n sheenColorMapEnabled: i32,\n sheenRoughnessMapEnabled: i32,\n\n iridescenceFactor: f32,\n iridescenceIor: f32,\n iridescenceThicknessRange: vec2f,\n iridescenceMapEnabled: i32,\n\n anisotropyStrength: f32,\n anisotropyRotation: f32,\n anisotropyDirection: vec2f,\n anisotropyMapEnabled: i32,\n\n emissiveStrength: f32,\n dispersion: f32,\n \n // IBL\n IBLenabled: i32,\n scaleIBLAmbient: vec2f, // #ifdef USE_IBL\n \n // debugging flags used for shader output of intermediate PBR variables\n // #ifdef PBR_DEBUG\n scaleDiffBaseMR: vec4f,\n scaleFGDSpec: vec4f,\n // #endif\n\n baseColorUVSet: i32,\n baseColorUVTransform: mat3x3f,\n metallicRoughnessUVSet: i32,\n metallicRoughnessUVTransform: mat3x3f,\n normalUVSet: i32,\n normalUVTransform: mat3x3f,\n occlusionUVSet: i32,\n occlusionUVTransform: mat3x3f,\n emissiveUVSet: i32,\n emissiveUVTransform: mat3x3f,\n specularColorUVSet: i32,\n specularColorUVTransform: mat3x3f,\n specularIntensityUVSet: i32,\n specularIntensityUVTransform: mat3x3f,\n transmissionUVSet: i32,\n transmissionUVTransform: mat3x3f,\n thicknessUVSet: i32,\n thicknessUVTransform: mat3x3f,\n clearcoatUVSet: i32,\n clearcoatUVTransform: mat3x3f,\n clearcoatRoughnessUVSet: i32,\n clearcoatRoughnessUVTransform: mat3x3f,\n clearcoatNormalUVSet: i32,\n clearcoatNormalUVTransform: mat3x3f,\n sheenColorUVSet: i32,\n sheenColorUVTransform: mat3x3f,\n sheenRoughnessUVSet: i32,\n sheenRoughnessUVTransform: mat3x3f,\n iridescenceUVSet: i32,\n iridescenceUVTransform: mat3x3f,\n iridescenceThicknessUVSet: i32,\n iridescenceThicknessUVTransform: mat3x3f,\n anisotropyUVSet: i32,\n anisotropyUVTransform: mat3x3f,\n\n bumpFactor: f32,\n bumpMapEnabled: i32,\n diffuseTransmissionFactor: f32,\n diffuseTransmissionMapEnabled: i32,\n diffuseTransmissionColorFactor: vec3f,\n diffuseTransmissionColorMapEnabled: i32,\n multiscatterColorFactor: vec3f,\n multiscatterColorMapEnabled: i32,\n scatterAnisotropy: f32,\n\n bumpUVSet: i32,\n bumpUVTransform: mat3x3f,\n diffuseTransmissionUVSet: i32,\n diffuseTransmissionUVTransform: mat3x3f,\n diffuseTransmissionColorUVSet: i32,\n diffuseTransmissionColorUVTransform: mat3x3f,\n multiscatterColorUVSet: i32,\n multiscatterColorUVTransform: mat3x3f,\n lightmapMapEnabled: u32,\n lightmapIntensity: f32,\n lightmapUVSet: i32,\n lightmapUVTransform: mat3x3f,\n scatterStrengthFactor: f32,\n}\n\n@group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;\n\n// Samplers\n#ifdef HAS_BASECOLORMAP\n@group(3) @binding(auto) var pbr_baseColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_baseColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_NORMALMAP\n@group(3) @binding(auto) var pbr_normalSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_normalSamplerSampler: sampler;\n#endif\n#ifdef HAS_EMISSIVEMAP\n@group(3) @binding(auto) var pbr_emissiveSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_emissiveSamplerSampler: sampler;\n#endif\n#ifdef HAS_LIGHTMAP\n@group(3) @binding(auto) var pbr_lightmapSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_lightmapSamplerSampler: sampler;\n#endif\n#ifdef HAS_METALROUGHNESSMAP\n@group(3) @binding(auto) var pbr_metallicRoughnessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_metallicRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_OCCLUSIONMAP\n@group(3) @binding(auto) var pbr_occlusionSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_occlusionSamplerSampler: sampler;\n#endif\n#ifdef HAS_SPECULARCOLORMAP\n@group(3) @binding(auto) var pbr_specularColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_specularColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_SPECULARINTENSITYMAP\n@group(3) @binding(auto) var pbr_specularIntensitySampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_specularIntensitySamplerSampler: sampler;\n#endif\n#ifdef HAS_TRANSMISSIONMAP\n@group(3) @binding(auto) var pbr_transmissionSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_transmissionSamplerSampler: sampler;\n#endif\n#ifdef HAS_THICKNESSMAP\n@group(3) @binding(auto) var pbr_thicknessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_thicknessSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATMAP\n@group(3) @binding(auto) var pbr_clearcoatSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_clearcoatSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATROUGHNESSMAP\n@group(3) @binding(auto) var pbr_clearcoatRoughnessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_clearcoatRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATNORMALMAP\n@group(3) @binding(auto) var pbr_clearcoatNormalSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_clearcoatNormalSamplerSampler: sampler;\n#endif\n#ifdef HAS_SHEENCOLORMAP\n@group(3) @binding(auto) var pbr_sheenColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_sheenColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_SHEENROUGHNESSMAP\n@group(3) @binding(auto) var pbr_sheenRoughnessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_sheenRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_IRIDESCENCEMAP\n@group(3) @binding(auto) var pbr_iridescenceSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_iridescenceSamplerSampler: sampler;\n#endif\n#ifdef HAS_IRIDESCENCETHICKNESSMAP\n@group(3) @binding(auto) var pbr_iridescenceThicknessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_iridescenceThicknessSamplerSampler: sampler;\n#endif\n#ifdef HAS_ANISOTROPYMAP\n@group(3) @binding(auto) var pbr_anisotropySampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_anisotropySamplerSampler: sampler;\n#endif\n#ifdef HAS_BUMPMAP\n@group(3) @binding(auto) var pbr_bumpSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_bumpSamplerSampler: sampler;\n#endif\n#ifdef HAS_DIFFUSETRANSMISSIONMAP\n@group(3) @binding(auto) var pbr_diffuseTransmissionSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_diffuseTransmissionSamplerSampler: sampler;\n#endif\n#ifdef HAS_DIFFUSETRANSMISSIONCOLORMAP\n@group(3) @binding(auto) var pbr_diffuseTransmissionColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_diffuseTransmissionColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_MULTISCATTERCOLORMAP\n@group(3) @binding(auto) var pbr_multiscatterColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_multiscatterColorSamplerSampler: sampler;\n#endif\n// Encapsulate the various inputs used by the various functions in the shading equation\n// We store values in this struct to simplify the integration of alternative implementations\n// of the shading terms, outlined in the Readme.MD Appendix.\nstruct PBRInfo {\n NdotL: f32, // cos angle between normal and light direction\n NdotV: f32, // cos angle between normal and view direction\n NdotH: f32, // cos angle between normal and half vector\n LdotH: f32, // cos angle between light direction and half vector\n VdotH: f32, // cos angle between view direction and half vector\n perceptualRoughness: f32, // roughness value, as authored by the model creator (input to shader)\n metalness: f32, // metallic value at the surface\n reflectance0: vec3f, // full reflectance color (normal incidence angle)\n reflectance90: vec3f, // reflectance color at grazing angle\n alphaRoughness: f32, // roughness mapped to a more linear change in the roughness (proposed by [2])\n diffuseColor: vec3f, // color contribution from diffuse lighting\n specularColor: vec3f, // color contribution from specular lighting\n n: vec3f, // normal at surface point\n v: vec3f, // vector from surface point to camera\n l: vec3f, // direction from the surface toward the current light\n h: vec3f // half vector between the current light and camera\n};\n\nconst M_PI = 3.141592653589793;\nconst c_MinRoughness = 0.04;\n\n// Widen sub-pixel specular lobes using the screen-space normal footprint.\n// This is geometric specular antialiasing: the normal variance is converted\n// into an additional squared perceptual roughness before evaluating BRDFs.\nfn widenSpecularRoughness(perceptualRoughness: f32, normal: vec3f) -> f32 {\n let normalDerivativeX = dpdx(normal);\n let normalDerivativeY = dpdy(normal);\n let normalVariance =\n dot(normalDerivativeX, normalDerivativeX) +\n dot(normalDerivativeY, normalDerivativeY);\n let kernelRoughnessSquared = min(2.0 * normalVariance, 1.0);\n return clamp(\n sqrt(perceptualRoughness * perceptualRoughness + kernelRoughnessSquared),\n c_MinRoughness,\n 1.0\n );\n}\n\nfn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f\n{\n var linOut: vec3f = srgbIn.xyz;\n#ifdef MANUAL_SRGB\n let bLess: vec3f = step(vec3f(0.04045), srgbIn.xyz);\n linOut = mix(\n srgbIn.xyz / vec3f(12.92),\n pow((srgbIn.xyz + vec3f(0.055)) / vec3f(1.055), vec3f(2.4)),\n bLess\n );\n#ifdef SRGB_FAST_APPROXIMATION\n linOut = pow(srgbIn.xyz, vec3f(2.2));\n#endif\n#endif\n return vec4f(linOut, srgbIn.w);\n}\n\nfn getMaterialUV(uvSet: i32, uvTransform: mat3x3f) -> vec2f\n{\n var baseUV = fragmentInputs.pbr_vUV0;\n if (uvSet == 1) {\n baseUV = fragmentInputs.pbr_vUV1;\n }\n return (uvTransform * vec3f(baseUV, 1.0)).xy;\n}\n\n// Build the tangent basis from interpolated attributes or screen-space derivatives.\nfn getTBN(uv: vec2f) -> mat3x3f\n{\n let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);\n let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);\n let tex_dx: vec3f = dpdx(vec3f(uv, 0.0));\n let tex_dy: vec3f = dpdy(vec3f(uv, 0.0));\n var t: vec3f = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y);\n\n var ng: vec3f = cross(pos_dy, pos_dx);\n#ifdef HAS_NORMALS\n ng = normalize(fragmentInputs.pbr_vNormal);\n#endif\n t = normalize(t - ng * dot(ng, t));\n var b: vec3f = normalize(cross(ng, t));\n var tbn: mat3x3f = mat3x3f(t, b, ng);\n#ifdef HAS_TANGENTS\n tbn = fragmentInputs.pbr_vTBN;\n#endif\n\n#ifdef DOUBLE_SIDED\n#ifdef HAS_NORMALS\n // Derivative normals already face the viewer; only flip an authored basis.\n if (!pbr_frontFacing) { tbn = mat3x3f(-tbn[0], -tbn[1], -tbn[2]); }\n#endif\n#endif\n return tbn;\n}\n\n// Find the normal for this fragment, pulling either from a predefined normal map\n// or from the interpolated mesh normal and tangent attributes.\nfn getMappedNormal(\n normalSampler: texture_2d<f32>,\n normalSamplerBinding: sampler,\n tbn: mat3x3f,\n normalScale: f32,\n uv: vec2f\n) -> vec3f\n{\n let n = textureSample(normalSampler, normalSamplerBinding, uv).rgb;\n return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));\n}\n\nfn getNormal(tbn: mat3x3f, uv: vec2f) -> vec3f\n{\n // The tbn matrix is linearly interpolated, so we need to re-normalize\n var n: vec3f = normalize(tbn[2].xyz);\n#ifdef HAS_NORMALMAP\n n = getMappedNormal(\n pbr_normalSampler,\n pbr_normalSamplerSampler,\n tbn,\n pbrMaterial.normalScale,\n uv\n );\n#endif\n\n#ifdef HAS_BUMPMAP\n let bumpUV = getMaterialUV(pbrMaterial.bumpUVSet, pbrMaterial.bumpUVTransform);\n let bumpTexelSize = 1.0 / vec2f(textureDimensions(pbr_bumpSampler, 0));\n let bumpHeight = textureSample(pbr_bumpSampler, pbr_bumpSamplerSampler, bumpUV).r;\n let bumpGradient = vec2f(\n textureSample(\n pbr_bumpSampler,\n pbr_bumpSamplerSampler,\n bumpUV + vec2f(bumpTexelSize.x, 0.0)\n ).r - bumpHeight,\n textureSample(\n pbr_bumpSampler,\n pbr_bumpSamplerSampler,\n bumpUV + vec2f(0.0, bumpTexelSize.y)\n ).r - bumpHeight\n );\n n = normalize(n - pbrMaterial.bumpFactor *\n (tbn[0] * bumpGradient.x + tbn[1] * bumpGradient.y));\n#endif\n\n return n;\n}\n\nfn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f, uv: vec2f) -> vec3f\n{\n#ifdef HAS_CLEARCOATNORMALMAP\n return getMappedNormal(\n pbr_clearcoatNormalSampler,\n pbr_clearcoatNormalSamplerSampler,\n tbn,\n 1.0,\n uv\n );\n#else\n return baseNormal;\n#endif\n}\n\n// Calculation of the lighting contribution from an optional Image Based Light source.\n// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].\n// See our README.md on Environment Maps [3] for additional discussion.\n#ifdef USE_IBL\nfn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f\n{\n#ifdef USE_SCENE_ENVIRONMENT\n let maximumMipLevel = max(pbrScene.environmentMipCount - 1.0, 0.0);\n let rotationSine = sin(pbrScene.environmentRotation);\n let rotationCosine = cos(pbrScene.environmentRotation);\n let environmentRotation = mat2x2f(\n vec2f(rotationCosine, rotationSine),\n vec2f(-rotationSine, rotationCosine)\n );\n let rotatedNormal = environmentRotation * n.xz;\n let rotatedReflection = environmentRotation * reflection.xz;\n let environmentNormal = vec3f(rotatedNormal.x, n.y, rotatedNormal.y);\n let environmentReflection = vec3f(rotatedReflection.x, reflection.y, rotatedReflection.y);\n#else\n let maximumMipLevel = 9.0;\n let environmentNormal = n;\n let environmentReflection = reflection;\n#endif\n let lod = pbrInfo.perceptualRoughness * maximumMipLevel;\n // retrieve a scale and bias to F0. See [1], Figure 3\n let brdfSample = textureSampleLevel(\n pbr_brdfLUT,\n pbr_brdfLUTSampler,\n vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness),\n 0.0\n );\n let diffuseSample = textureSampleLevel(\n pbr_diffuseEnvSampler,\n pbr_diffuseEnvSamplerSampler,\n environmentNormal,\n 0.0\n );\n var specularSample = textureSampleLevel(\n pbr_specularEnvSampler,\n pbr_specularEnvSamplerSampler,\n environmentReflection,\n 0.0\n );\n#ifdef USE_TEX_LOD\n specularSample = textureSampleLevel(\n pbr_specularEnvSampler,\n pbr_specularEnvSamplerSampler,\n environmentReflection,\n lod\n );\n#endif\n\n#ifdef USE_SCENE_ENVIRONMENT\n let brdf = brdfSample.rgb;\n let diffuseLight = diffuseSample.rgb;\n let specularLight = specularSample.rgb;\n#else\n let brdf = SRGBtoLINEAR(brdfSample).rgb;\n let diffuseLight = SRGBtoLINEAR(diffuseSample).rgb;\n let specularLight = SRGBtoLINEAR(specularSample).rgb;\n#endif\n\n let diffuse = diffuseLight * pbrInfo.diffuseColor * pbrMaterial.scaleIBLAmbient.x;\n let specular =\n specularLight * (pbrInfo.specularColor * brdf.x + brdf.y) * pbrMaterial.scaleIBLAmbient.y;\n\n#ifdef USE_SCENE_ENVIRONMENT\n return (diffuse + specular) * max(pbrScene.environmentIntensity, 0.0);\n#else\n return diffuse + specular;\n#endif\n}\n#endif\n\n// Basic Lambertian diffuse\n// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog\n// See also [1], Equation 1\nfn diffuse(pbrInfo: PBRInfo) -> vec3<f32> {\n return pbrInfo.diffuseColor / M_PI;\n}\n\n// The following equation models the Fresnel reflectance term of the spec equation (aka F())\n// Implementation of fresnel from [4], Equation 15\nfn specularReflection(pbrInfo: PBRInfo) -> vec3<f32> {\n return pbrInfo.reflectance0 +\n (pbrInfo.reflectance90 - pbrInfo.reflectance0) *\n pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);\n}\n\n// This calculates the specular geometric attenuation (aka G()),\n// where rougher material will reflect less light back to the viewer.\n// This implementation is based on [1] Equation 4, and we adopt their modifications to\n// alphaRoughness as input as originally proposed in [2].\nfn geometricOcclusion(pbrInfo: PBRInfo) -> f32 {\n let NdotL: f32 = pbrInfo.NdotL;\n let NdotV: f32 = pbrInfo.NdotV;\n let r: f32 = pbrInfo.alphaRoughness;\n\n let attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));\n let attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));\n return attenuationL * attenuationV;\n}\n\n// The following equation(s) model the distribution of microfacet normals across\n// the area being drawn (aka D())\n// Implementation from \"Average Irregularity Representation of a Roughened Surface\n// for Ray Reflection\" by T. S. Trowbridge, and K. P. Reitz\n// Follows the distribution function recommended in the SIGGRAPH 2013 course notes\n// from EPIC Games [1], Equation 3.\nfn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {\n let roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;\n let f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;\n return roughnessSq / (M_PI * f * f);\n}\n\nfn maxComponent(value: vec3f) -> f32 {\n return max(max(value.r, value.g), value.b);\n}\n\nfn getDielectricF0(ior: f32) -> f32 {\n let clampedIor = max(ior, 1.0);\n let ratio = (clampedIor - 1.0) / (clampedIor + 1.0);\n return ratio * ratio;\n}\n\nfn normalizeDirection(direction: vec2f) -> vec2f {\n let directionLength = length(direction);\n if (directionLength > 0.0001) {\n return direction / directionLength;\n }\n\n return vec2f(1.0, 0.0);\n}\n\nfn rotateDirection(direction: vec2f, rotation: f32) -> vec2f {\n let s = sin(rotation);\n let c = cos(rotation);\n return vec2f(direction.x * c - direction.y * s, direction.x * s + direction.y * c);\n}\n\nfn encodeLinearSRGB(linearColor: vec3f) -> vec3f {\n let positiveColor = max(linearColor, vec3f(0.0));\n return select(\n positiveColor * 12.92,\n 1.055 * pow(positiveColor, vec3f(1.0 / 2.4)) - 0.055,\n positiveColor > vec3f(0.0031308)\n );\n}\n\nfn toneMapKhronosPBRNeutral(inputColor: vec3f) -> vec3f {\n let startCompression = 0.76;\n let darkestChannel = min(inputColor.r, min(inputColor.g, inputColor.b));\n let offset = select(\n 0.04,\n darkestChannel - 6.25 * darkestChannel * darkestChannel,\n darkestChannel < 0.08\n );\n var color = inputColor - vec3f(offset);\n let peak = maxComponent(color);\n if (peak < startCompression) {\n return color;\n }\n\n let compressionRange = 1.0 - startCompression;\n let compressedPeak = 1.0 - compressionRange * compressionRange /\n (peak + compressionRange - startCompression);\n color *= compressedPeak / max(peak, 0.0001);\n let desaturation = 1.0 - 1.0 / (0.15 * (peak - compressedPeak) + 1.0);\n return mix(color, vec3f(compressedPeak), desaturation);\n}\n\nfn applySceneColorManagement(sceneColor: vec3f) -> vec3f {\n#ifdef USE_SCENE_COLOR_MANAGEMENT\n var color = max(sceneColor, vec3f(0.0)) * max(pbrScene.exposure, 0.0);\n if (pbrScene.toneMapMode == 1) {\n color /= vec3f(1.0) + color;\n } else if (pbrScene.toneMapMode == 2) {\n color = toneMapKhronosPBRNeutral(color);\n } else if (pbrScene.toneMapMode == 3) {\n color = clamp(\n (color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14),\n vec3f(0.0),\n vec3f(1.0)\n );\n }\n if (pbrScene.outputEncoding == 0) {\n return color;\n }\n return encodeLinearSRGB(color);\n#else\n return pow(max(sceneColor, vec3f(0.0)), vec3f(1.0 / 2.2));\n#endif\n}\n\nfn dielectricSchlick(reflectance: f32, cosine: f32) -> f32 {\n return reflectance + (1.0 - reflectance) * pow(clamp(1.0 - cosine, 0.0, 1.0), 5.0);\n}\n\nfn evaluateIridescenceSensitivity(opticalPathDifference: f32, phaseShift: vec3f) -> vec3f {\n let phase = 2.0 * M_PI * opticalPathDifference * 1.0e-9;\n let sensitivity = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13);\n let position = vec3f(1.6810e6, 1.7953e6, 2.2084e6);\n let variance = vec3f(4.3278e9, 9.3046e9, 6.6121e9);\n var xyz = sensitivity * sqrt(2.0 * M_PI * variance) *\n cos(position * phase + phaseShift) * exp(-phase * phase * variance);\n xyz.x += 9.7470e-14 * sqrt(2.0 * M_PI * 4.5282e9) *\n cos(2.2399e6 * phase + phaseShift.x) * exp(-4.5282e9 * phase * phase);\n xyz /= 1.0685e-7;\n return mat3x3f(\n vec3f(3.2404542, -0.9692660, 0.0556434),\n vec3f(-1.5371385, 1.8760108, -0.2040259),\n vec3f(-0.4985314, 0.0415560, 1.0572252)\n ) * xyz;\n}\n\nfn getIridescenceTint(\n iridescence: f32,\n thickness: f32,\n NdotV: f32,\n baseReflectance: vec3f\n) -> vec3f {\n if (iridescence <= 0.0 || thickness <= 0.0) {\n return baseReflectance;\n }\n\n let filmIor = max(pbrMaterial.iridescenceIor, 1.0);\n let sineSquared = (1.0 - NdotV * NdotV) / (filmIor * filmIor);\n let cosineSquared = 1.0 - sineSquared;\n if (cosineSquared <= 0.0) {\n return mix(baseReflectance, vec3f(1.0), iridescence);\n }\n let filmCosine = sqrt(cosineSquared);\n let firstInterfaceReflectance = dielectricSchlick(getDielectricF0(filmIor), NdotV);\n let transmittedEnergy = 1.0 - firstInterfaceReflectance;\n let squareRootReflectance = sqrt(clamp(baseReflectance, vec3f(0.0), vec3f(0.9999)));\n let baseIor = (vec3f(1.0) + squareRootReflectance) /\n (vec3f(1.0) - squareRootReflectance);\n var secondInterfaceF0 = (baseIor - vec3f(filmIor)) / (baseIor + vec3f(filmIor));\n secondInterfaceF0 *= secondInterfaceF0;\n let secondInterfaceReflectance = secondInterfaceF0 +\n (vec3f(1.0) - secondInterfaceF0) * pow(1.0 - filmCosine, 5.0);\n let phaseShift = vec3f(M_PI) + select(\n vec3f(0.0),\n vec3f(M_PI),\n baseIor < vec3f(filmIor)\n );\n let opticalPathDifference = 2.0 * filmIor * thickness * filmCosine;\n let combinedReflectance = clamp(\n firstInterfaceReflectance * secondInterfaceReflectance,\n vec3f(0.00001),\n vec3f(0.9999)\n );\n let recurringAmplitude = sqrt(combinedReflectance);\n let interfaceResponse = transmittedEnergy * transmittedEnergy * secondInterfaceReflectance /\n (vec3f(1.0) - combinedReflectance);\n var reflectedSpectrum = vec3f(firstInterfaceReflectance) + interfaceResponse;\n var harmonicAmplitude = interfaceResponse - vec3f(transmittedEnergy);\n for (var harmonic = 1; harmonic <= 2; harmonic++) {\n harmonicAmplitude *= recurringAmplitude;\n reflectedSpectrum += harmonicAmplitude * 2.0 * evaluateIridescenceSensitivity(\n f32(harmonic) * opticalPathDifference,\n f32(harmonic) * phaseShift\n );\n }\n return mix(baseReflectance, clamp(reflectedSpectrum, vec3f(0.0), vec3f(1.0)), iridescence);\n}\n\nfn getVolumeAttenuation(thickness: f32) -> vec3f {\n if (thickness <= 0.0) {\n return vec3f(1.0);\n }\n\n let attenuationCoefficient =\n -log(max(pbrMaterial.attenuationColor, vec3f(0.0001))) /\n max(pbrMaterial.attenuationDistance, 0.0001);\n return exp(-attenuationCoefficient * thickness);\n}\n\n// KHR_materials_volume_scatter is an active draft. This evaluates a local,\n// thickness-aware single-scattering approximation rather than random walk.\nfn getDiffuseTransmissionAttenuation(\n pbrInfo: PBRInfo,\n multiscatterColor: vec3f,\n thickness: f32\n) -> vec3f {\n let volumeAttenuation = getVolumeAttenuation(thickness);\n let scatteringStrength = maxComponent(multiscatterColor);\n if (thickness <= 0.0 || scatteringStrength <= 0.0001) {\n return volumeAttenuation;\n }\n\n let anisotropy = clamp(pbrMaterial.scatterAnisotropy, -0.95, 0.95);\n let scatteringCosine = clamp(dot(-pbrInfo.v, pbrInfo.l), -1.0, 1.0);\n let phaseDenominator = max(\n 1.0 + anisotropy * anisotropy - 2.0 * anisotropy * scatteringCosine,\n 0.0001\n );\n let phaseWeight = clamp(\n (1.0 - anisotropy * anisotropy) / pow(phaseDenominator, 1.5),\n 0.0,\n 4.0\n );\n let scatteringDepth = thickness / max(pbrMaterial.attenuationDistance, 0.0001);\n let scatteringProbability = 1.0 - exp(-scatteringDepth);\n let scatteringColor = clamp(multiscatterColor, vec3f(0.0), vec3f(1.0));\n return mix(\n volumeAttenuation,\n volumeAttenuation * mix(vec3f(1.0), scatteringColor * phaseWeight, scatteringColor),\n scatteringProbability\n );\n}\n\nfn calculateDiffuseTransmissionLight(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n diffuseTransmissionColor: vec3f,\n diffuseTransmission: f32,\n multiscatterColor: vec3f,\n thickness: f32\n) -> vec3f {\n let oppositeHemisphere = max(dot(-pbrInfo.n, pbrInfo.l), 0.0);\n if (oppositeHemisphere <= 0.0 || diffuseTransmission <= 0.0) {\n return vec3f(0.0);\n }\n\n let nonReflectedEnergy = vec3f(1.0) - clamp(pbrInfo.reflectance0, vec3f(0.0), vec3f(1.0));\n let attenuatedColor = getDiffuseTransmissionAttenuation(\n pbrInfo,\n multiscatterColor,\n thickness\n );\n return lightColor * diffuseTransmissionColor * nonReflectedEnergy *\n attenuatedColor * (diffuseTransmission * oppositeHemisphere / M_PI);\n}\n\n#ifdef USE_IBL\nfn calculateDiffuseTransmissionIBL(\n pbrInfo: PBRInfo,\n diffuseTransmissionColor: vec3f,\n diffuseTransmission: f32,\n multiscatterColor: vec3f,\n thickness: f32\n) -> vec3f {\n if (diffuseTransmission <= 0.0) {\n return vec3f(0.0);\n }\n\n#ifdef USE_SCENE_ENVIRONMENT\n let rotationSine = sin(pbrScene.environmentRotation);\n let rotationCosine = cos(pbrScene.environmentRotation);\n let environmentRotation = mat2x2f(\n vec2f(rotationCosine, rotationSine),\n vec2f(-rotationSine, rotationCosine)\n );\n let rotatedNormal = environmentRotation * -pbrInfo.n.xz;\n let oppositeNormal = vec3f(rotatedNormal.x, -pbrInfo.n.y, rotatedNormal.y);\n let environmentColor = textureSampleLevel(\n pbr_diffuseEnvSampler,\n pbr_diffuseEnvSamplerSampler,\n oppositeNormal,\n 0.0\n ).rgb * max(pbrScene.environmentIntensity, 0.0);\n#else\n let environmentColor = SRGBtoLINEAR(\n textureSampleLevel(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, -pbrInfo.n, 0.0)\n ).rgb;\n#endif\n let nonReflectedEnergy = vec3f(1.0) - clamp(pbrInfo.reflectance0, vec3f(0.0), vec3f(1.0));\n return environmentColor * diffuseTransmissionColor * nonReflectedEnergy *\n getDiffuseTransmissionAttenuation(pbrInfo, multiscatterColor, thickness) *\n diffuseTransmission * pbrMaterial.scaleIBLAmbient.x;\n}\n#endif\n\n#ifdef USE_TRANSMISSION_FRAMEBUFFER\nfn sampleTransmittedSceneColor(\n position: vec3f,\n normal: vec3f,\n viewDirection: vec3f,\n thickness: f32,\n perceptualRoughness: f32,\n indexOfRefraction: f32\n) -> vec3f {\n let refractionDirection = refract(\n -viewDirection,\n normal,\n 1.0 / max(indexOfRefraction, 1.0)\n );\n let refractedPosition = position + refractionDirection * thickness;\n let clipPosition = pbrScene.projectionMatrix *\n pbrScene.viewMatrix * vec4f(refractedPosition, 1.0);\n var textureCoordinate = clipPosition.xy / max(clipPosition.w, 0.0001) * 0.5 + 0.5;\n textureCoordinate.y = 1.0 - textureCoordinate.y;\n textureCoordinate = clamp(textureCoordinate, vec2f(0.001), vec2f(0.999));\n\n let blurRadius = perceptualRoughness * perceptualRoughness * 8.0 /\n max(pbrScene.framebufferSize, vec2f(1.0));\n var sceneColor = textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate,\n 0.0\n ).rgb * 0.4;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate + vec2f(blurRadius.x, 0.0),\n 0.0\n ).rgb * 0.15;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate - vec2f(blurRadius.x, 0.0),\n 0.0\n ).rgb * 0.15;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate + vec2f(0.0, blurRadius.y),\n 0.0\n ).rgb * 0.15;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate - vec2f(0.0, blurRadius.y),\n 0.0\n ).rgb * 0.15;\n return max(sceneColor, vec3f(0.0));\n}\n\nfn getTransmittedSceneColor(\n position: vec3f,\n normal: vec3f,\n viewDirection: vec3f,\n thickness: f32,\n perceptualRoughness: f32\n) -> vec3f {\n if (pbrMaterial.dispersion <= 0.0) {\n return sampleTransmittedSceneColor(\n position,\n normal,\n viewDirection,\n thickness,\n perceptualRoughness,\n pbrMaterial.ior\n );\n }\n\n let halfSpread = (max(pbrMaterial.ior, 1.0) - 1.0) * 0.025 * pbrMaterial.dispersion;\n let indicesOfRefraction = max(\n vec3f(pbrMaterial.ior - halfSpread, pbrMaterial.ior, pbrMaterial.ior + halfSpread),\n vec3f(1.0)\n );\n return vec3f(\n sampleTransmittedSceneColor(\n position, normal, viewDirection, thickness, perceptualRoughness, indicesOfRefraction.r\n ).r,\n sampleTransmittedSceneColor(\n position, normal, viewDirection, thickness, perceptualRoughness, indicesOfRefraction.g\n ).g,\n sampleTransmittedSceneColor(\n position, normal, viewDirection, thickness, perceptualRoughness, indicesOfRefraction.b\n ).b\n );\n}\n#endif\n\nfn createClearcoatPBRInfo(\n basePBRInfo: PBRInfo,\n clearcoatNormal: vec3f,\n clearcoatRoughness: f32\n) -> PBRInfo {\n let perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n let NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);\n\n return PBRInfo(\n basePBRInfo.NdotL,\n NdotV,\n basePBRInfo.NdotH,\n basePBRInfo.LdotH,\n basePBRInfo.VdotH,\n perceptualRoughness,\n 0.0,\n vec3f(0.04),\n vec3f(1.0),\n alphaRoughness,\n vec3f(0.0),\n vec3f(0.04),\n clearcoatNormal,\n basePBRInfo.v,\n basePBRInfo.l,\n basePBRInfo.h\n );\n}\n\nfn calculateClearcoatContribution(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n clearcoatNormal: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32\n) -> vec3f {\n if (clearcoatFactor <= 0.0) {\n return vec3f(0.0);\n }\n\n let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;\n}\n\n#ifdef USE_IBL\nfn calculateClearcoatIBLContribution(\n pbrInfo: PBRInfo,\n clearcoatNormal: vec3f,\n reflection: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32\n) -> vec3f {\n if (clearcoatFactor <= 0.0) {\n return vec3f(0.0);\n }\n\n let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;\n}\n#endif\n\nfn calculateSheenContribution(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n sheenColor: vec3f,\n sheenRoughness: f32\n) -> vec3f {\n if (maxComponent(sheenColor) <= 0.0) {\n return vec3f(0.0);\n }\n\n let alpha = max(sheenRoughness * sheenRoughness, 0.0001);\n let inverseAlpha = 1.0 / alpha;\n let sineSquared = max(1.0 - pbrInfo.NdotH * pbrInfo.NdotH, 0.0);\n let distribution = (2.0 + inverseAlpha) * pow(sineSquared, inverseAlpha * 0.5) /\n (2.0 * M_PI);\n let visibility = 1.0 / max(\n 4.0 * (pbrInfo.NdotL + pbrInfo.NdotV - pbrInfo.NdotL * pbrInfo.NdotV),\n 0.0001\n );\n return pbrInfo.NdotL * lightColor * sheenColor * distribution * visibility *\n (1.0 - pbrInfo.metalness);\n}\n\nfn calculateAnisotropicLightColor(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> vec3f {\n if (anisotropyStrength <= 0.0) {\n return calculateFinalColor(pbrInfo, lightColor);\n }\n\n let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));\n let tangentRoughness = mix(\n pbrInfo.alphaRoughness,\n 1.0,\n anisotropyStrength * anisotropyStrength\n );\n let bitangentRoughness = clamp(pbrInfo.alphaRoughness, 0.001, 1.0);\n let roughnessProduct = tangentRoughness * bitangentRoughness;\n let distributionVector = vec3f(\n bitangentRoughness * dot(anisotropyTangent, pbrInfo.h),\n tangentRoughness * dot(anisotropyBitangent, pbrInfo.h),\n roughnessProduct * pbrInfo.NdotH\n );\n let distributionFactor = roughnessProduct /\n max(dot(distributionVector, distributionVector), 0.000001);\n let distribution = roughnessProduct * distributionFactor * distributionFactor / M_PI;\n let viewMask = pbrInfo.NdotL * length(vec3f(\n tangentRoughness * dot(anisotropyTangent, pbrInfo.v),\n bitangentRoughness * dot(anisotropyBitangent, pbrInfo.v),\n pbrInfo.NdotV\n ));\n let lightMask = pbrInfo.NdotV * length(vec3f(\n tangentRoughness * dot(anisotropyTangent, pbrInfo.l),\n bitangentRoughness * dot(anisotropyBitangent, pbrInfo.l),\n pbrInfo.NdotL\n ));\n let visibility = clamp(0.5 / max(viewMask + lightMask, 0.000001), 0.0, 1.0);\n let fresnel = specularReflection(pbrInfo);\n let diffuseContribution = (vec3f(1.0) - fresnel) * diffuse(pbrInfo);\n return pbrInfo.NdotL * lightColor *\n (diffuseContribution + fresnel * distribution * visibility);\n}\n\nfn getAnisotropicReflection(\n pbrInfo: PBRInfo,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> vec3f {\n if (anisotropyStrength <= 0.0) {\n return -normalize(reflect(pbrInfo.v, pbrInfo.n));\n }\n let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));\n var anisotropicNormal = normalize(cross(anisotropyBitangent, pbrInfo.v));\n anisotropicNormal = normalize(cross(anisotropicNormal, anisotropyBitangent));\n let bend = anisotropyStrength * (1.0 - pbrInfo.perceptualRoughness);\n return -normalize(reflect(pbrInfo.v, normalize(mix(pbrInfo.n, anisotropicNormal, bend))));\n}\n\nfn calculateMaterialLightColor(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n clearcoatNormal: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32,\n sheenColor: vec3f,\n sheenRoughness: f32,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> vec3f {\n var color = calculateAnisotropicLightColor(\n pbrInfo,\n lightColor,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateClearcoatContribution(\n pbrInfo,\n lightColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness\n );\n color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);\n return color;\n}\n\nfn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {\n (*pbrInfo).NdotL = 1.0;\n (*pbrInfo).NdotH = 0.0;\n (*pbrInfo).LdotH = 0.0;\n (*pbrInfo).VdotH = 1.0;\n (*pbrInfo).l = (*pbrInfo).n;\n (*pbrInfo).h = (*pbrInfo).n;\n}\n\nfn PBRInfo_setDirectionalLight(pbrInfo: ptr<function, PBRInfo>, lightDirection: vec3<f32>) {\n let n = (*pbrInfo).n;\n let v = (*pbrInfo).v;\n let l = normalize(lightDirection); // Vector from surface point to light\n let h = normalize(l + v); // Half vector between both l and v\n\n (*pbrInfo).NdotL = clamp(dot(n, l), 0.001, 1.0);\n (*pbrInfo).NdotH = clamp(dot(n, h), 0.0, 1.0);\n (*pbrInfo).LdotH = clamp(dot(l, h), 0.0, 1.0);\n (*pbrInfo).VdotH = clamp(dot(v, h), 0.0, 1.0);\n (*pbrInfo).l = l;\n (*pbrInfo).h = h;\n}\n\nfn PBRInfo_setPointLight(pbrInfo: ptr<function, PBRInfo>, pointLight: PointLight) {\n let light_direction = normalize(pointLight.position - fragmentInputs.pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nfn PBRInfo_setSpotLight(pbrInfo: ptr<function, PBRInfo>, spotLight: SpotLight) {\n let light_direction = normalize(spotLight.position - fragmentInputs.pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nfn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {\n // Calculate the shading terms for the microfacet specular shading model\n let F = specularReflection(pbrInfo);\n let G = geometricOcclusion(pbrInfo);\n let D = microfacetDistribution(pbrInfo);\n\n // Calculation of analytical lighting contribution\n let diffuseContrib = (1.0 - F) * diffuse(pbrInfo);\n let specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);\n // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)\n return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);\n}\n\n// Visibility for the first four spotlights; environment and other lights are unaffected.\nfn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f) -> vec4<f32> {\n let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);\n let metallicRoughnessUV = getMaterialUV(\n pbrMaterial.metallicRoughnessUVSet,\n pbrMaterial.metallicRoughnessUVTransform\n );\n let normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);\n let occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);\n let emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);\n let lightmapUV = getMaterialUV(pbrMaterial.lightmapUVSet, pbrMaterial.lightmapUVTransform);\n let specularColorUV = getMaterialUV(\n pbrMaterial.specularColorUVSet,\n pbrMaterial.specularColorUVTransform\n );\n let specularIntensityUV = getMaterialUV(\n pbrMaterial.specularIntensityUVSet,\n pbrMaterial.specularIntensityUVTransform\n );\n let transmissionUV = getMaterialUV(\n pbrMaterial.transmissionUVSet,\n pbrMaterial.transmissionUVTransform\n );\n let thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);\n let clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);\n let clearcoatRoughnessUV = getMaterialUV(\n pbrMaterial.clearcoatRoughnessUVSet,\n pbrMaterial.clearcoatRoughnessUVTransform\n );\n let clearcoatNormalUV = getMaterialUV(\n pbrMaterial.clearcoatNormalUVSet,\n pbrMaterial.clearcoatNormalUVTransform\n );\n let sheenColorUV = getMaterialUV(\n pbrMaterial.sheenColorUVSet,\n pbrMaterial.sheenColorUVTransform\n );\n let sheenRoughnessUV = getMaterialUV(\n pbrMaterial.sheenRoughnessUVSet,\n pbrMaterial.sheenRoughnessUVTransform\n );\n let iridescenceUV = getMaterialUV(\n pbrMaterial.iridescenceUVSet,\n pbrMaterial.iridescenceUVTransform\n );\n let iridescenceThicknessUV = getMaterialUV(\n pbrMaterial.iridescenceThicknessUVSet,\n pbrMaterial.iridescenceThicknessUVTransform\n );\n let anisotropyUV = getMaterialUV(\n pbrMaterial.anisotropyUVSet,\n pbrMaterial.anisotropyUVTransform\n );\n let diffuseTransmissionUV = getMaterialUV(\n pbrMaterial.diffuseTransmissionUVSet,\n pbrMaterial.diffuseTransmissionUVTransform\n );\n let diffuseTransmissionColorUV = getMaterialUV(\n pbrMaterial.diffuseTransmissionColorUVSet,\n pbrMaterial.diffuseTransmissionColorUVTransform\n );\n let multiscatterColorUV = getMaterialUV(\n pbrMaterial.multiscatterColorUVSet,\n pbrMaterial.multiscatterColorUVTransform\n );\n\n // The albedo may be defined from a base texture or a flat color\n var baseColor: vec4<f32> = pbrMaterial.baseColorFactor * vertexColor;\n #ifdef HAS_BASECOLORMAP\n baseColor = SRGBtoLINEAR(\n textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, baseColorUV)\n ) * pbrMaterial.baseColorFactor * vertexColor;\n #endif\n\n #ifdef ALPHA_CUTOFF\n if (baseColor.a < pbrMaterial.alphaCutoff) {\n discard;\n }\n #endif\n\n var color = vec3<f32>(0.0, 0.0, 0.0);\n var transmission = 0.0;\n\n var lightmapIrradiance = vec3<f32>(0.0);\n #ifdef HAS_LIGHTMAP\n if (pbrMaterial.lightmapMapEnabled != 0u) {\n lightmapIrradiance = textureSample(pbr_lightmapSampler, pbr_lightmapSamplerSampler, lightmapUV).rgb * pbrMaterial.lightmapIntensity;\n }\n #endif\n\n if (pbrMaterial.unlit != 0u) {\n color = baseColor.rgb;\n #ifdef HAS_LIGHTMAP\n if (pbrMaterial.lightmapMapEnabled != 0u) {\n color *= lightmapIrradiance / M_PI;\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n }\n #endif\n } else {\n // Metallic and Roughness material properties are packed together\n // In glTF, these factors can be specified by fixed scalar values\n // or from a metallic-roughness map\n var perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;\n var metallic = pbrMaterial.metallicRoughnessValues.x;\n #ifdef HAS_METALROUGHNESSMAP\n // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.\n // This layout intentionally reserves the 'r' channel for (optional) occlusion map data\n let mrSample = textureSample(\n pbr_metallicRoughnessSampler,\n pbr_metallicRoughnessSamplerSampler,\n metallicRoughnessUV\n );\n perceptualRoughness = mrSample.g * perceptualRoughness;\n metallic = mrSample.b * metallic;\n #endif\n perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);\n metallic = clamp(metallic, 0.0, 1.0);\n let tbn = getTBN(normalUV);\n let n = getNormal(tbn, normalUV); // normal at surface point\n perceptualRoughness = widenSpecularRoughness(perceptualRoughness, n);\n let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera\n let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);\n var useExtendedPBR = false;\n #ifdef USE_MATERIAL_EXTENSIONS\n useExtendedPBR =\n pbrMaterial.specularColorMapEnabled != 0 ||\n pbrMaterial.specularIntensityMapEnabled != 0 ||\n abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||\n maxComponent(abs(pbrMaterial.specularColorFactor - vec3f(1.0))) > 0.0001 ||\n abs(pbrMaterial.ior - 1.5) > 0.0001 ||\n pbrMaterial.dispersion > 0.0001 ||\n pbrMaterial.transmissionMapEnabled != 0 ||\n pbrMaterial.transmissionFactor > 0.0001 ||\n pbrMaterial.diffuseTransmissionMapEnabled != 0 ||\n pbrMaterial.diffuseTransmissionColorMapEnabled != 0 ||\n pbrMaterial.diffuseTransmissionFactor > 0.0001 ||\n pbrMaterial.multiscatterColorMapEnabled != 0 ||\n maxComponent(pbrMaterial.multiscatterColorFactor) > 0.0001 ||\n pbrMaterial.clearcoatMapEnabled != 0 ||\n pbrMaterial.clearcoatRoughnessMapEnabled != 0 ||\n pbrMaterial.clearcoatFactor > 0.0001 ||\n pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||\n pbrMaterial.sheenColorMapEnabled != 0 ||\n pbrMaterial.sheenRoughnessMapEnabled != 0 ||\n maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||\n pbrMaterial.sheenRoughnessFactor > 0.0001 ||\n pbrMaterial.iridescenceMapEnabled != 0 ||\n pbrMaterial.iridescenceFactor > 0.0001 ||\n abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||\n pbrMaterial.anisotropyMapEnabled != 0 ||\n pbrMaterial.anisotropyStrength > 0.0001 ||\n abs(pbrMaterial.anisotropyRotation) > 0.0001 ||\n length(pbrMaterial.anisotropyDirection - vec2f(1.0, 0.0)) > 0.0001;\n #endif\n\n if (!useExtendedPBR) {\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n let f0 = vec3<f32>(0.04);\n var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);\n diffuseColor *= 1.0 - metallic;\n let specularColor = mix(f0, baseColor.rgb, metallic);\n\n let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n let specularEnvironmentR0 = specularColor;\n let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;\n let reflection = -normalize(reflect(v, n));\n\n var pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v,\n n,\n n\n );\n\n #ifdef USE_LIGHTS\n PBRInfo_setAmbientLight(&pbrInfo);\n color += calculateFinalColor(pbrInfo, lighting.ambientColor);\n\n for (var i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);\n color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);\n }\n }\n\n for (var i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));\n let attenuation = getPointLightAttenuation(\n lighting_getPointLight(i),\n distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)\n );\n color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);\n }\n }\n\n for (var i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));\n let attenuation = getSpotLightAttenuation(\n lighting_getSpotLight(i),\n fragmentInputs.pbr_vPosition\n );\n color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color * select(1.0, clamp(spotVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation);\n }\n }\n for (var areaIndex: i32 = 0; areaIndex < areaLighting_getLightCount(); areaIndex++) {\n#ifdef USE_AREA_LIGHT_LTC\n color += areaLTC_evaluate(areaIndex, fragmentInputs.pbr_vPosition, pbrInfo.n, pbrInfo.v, pbrInfo.perceptualRoughness, pbrInfo.diffuseColor, pbrInfo.reflectance0, pbrInfo.reflectance90);\n#else\n for (var sampleIndex: i32 = 0; sampleIndex < areaLighting.sampleCount; sampleIndex++) {\n let sampleLight = areaLighting_getSample(areaIndex, sampleIndex, fragmentInputs.pbr_vPosition);\n if (dot(sampleLight.color, sampleLight.color) > 0.0) {\n PBRInfo_setPointLight(&pbrInfo, sampleLight);\n color += calculateFinalColor(pbrInfo, sampleLight.color);\n }\n }\n#endif\n }\n #endif\n\n #ifdef USE_IBL\n if (pbrMaterial.IBLenabled != 0) {\n color += getIBLContribution(pbrInfo, n, reflection);\n }\n #endif\n\n // The pinned KHR_lightmap draft explicitly defines c_diff = (1 - metallic) * baseColor.\n color += baseColor.rgb * (1.0 - metallic) * lightmapIrradiance / M_PI;\n\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n\n var emissive = pbrMaterial.emissiveFactor;\n #ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled != 0u) {\n emissive *= SRGBtoLINEAR(\n textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)\n ).rgb;\n }\n #endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n #ifdef PBR_DEBUG\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n #endif\n\n return vec4<f32>(applySceneColorManagement(color), baseColor.a);\n }\n\n var specularIntensity = pbrMaterial.specularIntensityFactor;\n #ifdef HAS_SPECULARINTENSITYMAP\n if (pbrMaterial.specularIntensityMapEnabled != 0) {\n specularIntensity *= textureSample(\n pbr_specularIntensitySampler,\n pbr_specularIntensitySamplerSampler,\n specularIntensityUV\n ).a;\n }\n #endif\n\n var specularFactor = pbrMaterial.specularColorFactor;\n #ifdef HAS_SPECULARCOLORMAP\n if (pbrMaterial.specularColorMapEnabled != 0) {\n specularFactor *= SRGBtoLINEAR(\n textureSample(\n pbr_specularColorSampler,\n pbr_specularColorSamplerSampler,\n specularColorUV\n )\n ).rgb;\n }\n #endif\n\n transmission = pbrMaterial.transmissionFactor;\n #ifdef HAS_TRANSMISSIONMAP\n if (pbrMaterial.transmissionMapEnabled != 0) {\n transmission *= textureSample(\n pbr_transmissionSampler,\n pbr_transmissionSamplerSampler,\n transmissionUV\n ).r;\n }\n #endif\n transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);\n var thickness = max(pbrMaterial.thicknessFactor, 0.0);\n #ifdef HAS_THICKNESSMAP\n thickness *= textureSample(\n pbr_thicknessSampler,\n pbr_thicknessSamplerSampler,\n thicknessUV\n ).g;\n #endif\n\n var diffuseTransmission = clamp(pbrMaterial.diffuseTransmissionFactor, 0.0, 1.0);\n #ifdef HAS_DIFFUSETRANSMISSIONMAP\n if (pbrMaterial.diffuseTransmissionMapEnabled != 0) {\n diffuseTransmission *= textureSample(\n pbr_diffuseTransmissionSampler,\n pbr_diffuseTransmissionSamplerSampler,\n diffuseTransmissionUV\n ).a;\n }\n #endif\n diffuseTransmission *= (1.0 - metallic) * (1.0 - transmission);\n var diffuseTransmissionColor = pbrMaterial.diffuseTransmissionColorFactor;\n #ifdef HAS_DIFFUSETRANSMISSIONCOLORMAP\n if (pbrMaterial.diffuseTransmissionColorMapEnabled != 0) {\n diffuseTransmissionColor *= SRGBtoLINEAR(\n textureSample(\n pbr_diffuseTransmissionColorSampler,\n pbr_diffuseTransmissionColorSamplerSampler,\n diffuseTransmissionColorUV\n )\n ).rgb;\n }\n #endif\n var multiscatterColor = pbrMaterial.multiscatterColorFactor;\n #ifdef HAS_MULTISCATTERCOLORMAP\n if (pbrMaterial.multiscatterColorMapEnabled != 0) {\n multiscatterColor *= SRGBtoLINEAR(\n textureSample(\n pbr_multiscatterColorSampler,\n pbr_multiscatterColorSamplerSampler,\n multiscatterColorUV\n )\n ).rgb;\n }\n #endif\n\n let originalTransmission = transmission;\n var scatterReflection = 0.0;\n#ifdef HAS_MATERIAL_SCATTER\n if (thickness <= 0.0) {\n var strength = clamp(pbrMaterial.scatterStrengthFactor, 0.0, 1.0);\n#ifdef HAS_DIFFUSETRANSMISSIONMAP\n if (pbrMaterial.diffuseTransmissionMapEnabled != 0) {\n strength *= textureSample(\n pbr_diffuseTransmissionSampler,\n pbr_diffuseTransmissionSamplerSampler,\n diffuseTransmissionUV\n ).a;\n }\n#endif\n let anisotropy = pbrMaterial.scatterAnisotropy;\n scatterReflection = originalTransmission * strength * (1.0 - anisotropy) * 0.5;\n diffuseTransmission = originalTransmission * strength * (1.0 + anisotropy) * 0.5;\n diffuseTransmissionColor = multiscatterColor;\n transmission *= 1.0 - strength;\n }\n#endif\n\n var clearcoatFactor = pbrMaterial.clearcoatFactor;\n var clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;\n #ifdef HAS_CLEARCOATMAP\n if (pbrMaterial.clearcoatMapEnabled != 0) {\n clearcoatFactor *= textureSample(\n pbr_clearcoatSampler,\n pbr_clearcoatSamplerSampler,\n clearcoatUV\n ).r;\n }\n #endif\n #ifdef HAS_CLEARCOATROUGHNESSMAP\n if (pbrMaterial.clearcoatRoughnessMapEnabled != 0) {\n clearcoatRoughness *= textureSample(\n pbr_clearcoatRoughnessSampler,\n pbr_clearcoatRoughnessSamplerSampler,\n clearcoatRoughnessUV\n ).g;\n }\n #endif\n clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);\n clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n let clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);\n clearcoatRoughness = widenSpecularRoughness(clearcoatRoughness, clearcoatNormal);\n\n var sheenColor = pbrMaterial.sheenColorFactor;\n var sheenRoughness = pbrMaterial.sheenRoughnessFactor;\n #ifdef HAS_SHEENCOLORMAP\n if (pbrMaterial.sheenColorMapEnabled != 0) {\n sheenColor *= SRGBtoLINEAR(\n textureSample(\n pbr_sheenColorSampler,\n pbr_sheenColorSamplerSampler,\n sheenColorUV\n )\n ).rgb;\n }\n #endif\n #ifdef HAS_SHEENROUGHNESSMAP\n if (pbrMaterial.sheenRoughnessMapEnabled != 0) {\n sheenRoughness *= textureSample(\n pbr_sheenRoughnessSampler,\n pbr_sheenRoughnessSamplerSampler,\n sheenRoughnessUV\n ).a;\n }\n #endif\n sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);\n\n var iridescence = pbrMaterial.iridescenceFactor;\n #ifdef HAS_IRIDESCENCEMAP\n if (pbrMaterial.iridescenceMapEnabled != 0) {\n iridescence *= textureSample(\n pbr_iridescenceSampler,\n pbr_iridescenceSamplerSampler,\n iridescenceUV\n ).r;\n }\n #endif\n iridescence = clamp(iridescence, 0.0, 1.0);\n var iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n 0.5\n );\n #ifdef HAS_IRIDESCENCETHICKNESSMAP\n iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n textureSample(\n pbr_iridescenceThicknessSampler,\n pbr_iridescenceThicknessSamplerSampler,\n iridescenceThicknessUV\n ).g\n );\n #endif\n\n var anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);\n var anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);\n #ifdef HAS_ANISOTROPYMAP\n if (pbrMaterial.anisotropyMapEnabled != 0) {\n let anisotropySample = textureSample(\n pbr_anisotropySampler,\n pbr_anisotropySamplerSampler,\n anisotropyUV\n ).rgb;\n anisotropyStrength *= anisotropySample.b;\n let mappedDirection = anisotropySample.rg * 2.0 - 1.0;\n if (length(mappedDirection) > 0.0001) {\n anisotropyDirection = normalize(mappedDirection);\n }\n }\n #endif\n anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);\n var anisotropyTangent =\n normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);\n if (length(anisotropyTangent) < 0.0001) {\n anisotropyTangent = normalize(tbn[0]);\n }\n // Roughness is authored as perceptual roughness; as is convention,\n // convert to material roughness by squaring the perceptual roughness [2].\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n let dielectricF0 = getDielectricF0(pbrMaterial.ior);\n var dielectricSpecularF0 = min(\n vec3f(dielectricF0) * specularFactor * specularIntensity,\n vec3f(1.0)\n );\n dielectricSpecularF0 = getIridescenceTint(\n iridescence,\n iridescenceThickness,\n NdotV,\n dielectricSpecularF0\n );\n var diffuseColor = baseColor.rgb * (vec3f(1.0) - dielectricSpecularF0);\n diffuseColor *= (1.0 - metallic) * (1.0 - transmission) * (1.0 - diffuseTransmission);\n#ifdef HAS_MATERIAL_SCATTER\n diffuseColor = (baseColor.rgb * (1.0 - metallic) * (1.0 - originalTransmission) +\n multiscatterColor * scatterReflection) * (vec3f(1.0) - dielectricSpecularF0);\n#endif\n var specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);\n\n let clearcoatViewFresnel = dielectricSchlick(\n 0.04,\n clamp(abs(dot(clearcoatNormal, v)), 0.0, 1.0)\n );\n let sheenDirectionalAlbedo = maxComponent(sheenColor) *\n (0.157 + 0.343 * (1.0 - NdotV)) * (1.0 - sheenRoughness * 0.5);\n let baseLayerEnergy = (1.0 - clearcoatFactor * clearcoatViewFresnel) *\n (1.0 - clamp(sheenDirectionalAlbedo, 0.0, 1.0));\n diffuseColor *= baseLayerEnergy;\n specularColor *= baseLayerEnergy;\n\n // Compute reflectance.\n let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n\n // For typical incident reflectance range (between 4% to 100%) set the grazing\n // reflectance to 100% for typical fresnel effect.\n // For very low reflectance range on highly diffuse objects (below 4%),\n // incrementally reduce grazing reflectance to 0%.\n let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n let specularEnvironmentR0 = specularColor;\n let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;\n let reflection = -normalize(reflect(v, n));\n\n var pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v,\n n,\n n\n );\n\n #ifdef USE_LIGHTS\n // Apply ambient light\n PBRInfo_setAmbientLight(&pbrInfo);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting.ambientColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n\n // Apply directional light\n for (var i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getDirectionalLight(i).color,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateDiffuseTransmissionLight(\n pbrInfo,\n lighting_getDirectionalLight(i).color,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n }\n }\n\n // Apply point light\n for (var i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));\n let attenuation = getPointLightAttenuation(\n lighting_getPointLight(i),\n distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)\n );\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getPointLight(i).color / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateDiffuseTransmissionLight(\n pbrInfo,\n lighting_getPointLight(i).color / attenuation,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n }\n }\n\n for (var i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));\n let attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), fragmentInputs.pbr_vPosition);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getSpotLight(i).color * select(1.0, clamp(spotVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateDiffuseTransmissionLight(\n pbrInfo,\n lighting_getSpotLight(i).color * select(1.0, clamp(spotVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n }\n }\n for (var areaIndex: i32 = 0; areaIndex < areaLighting_getLightCount(); areaIndex++) {\n#ifdef USE_AREA_LIGHT_LTC\n // Unsupported fits retain numerical integration rather than silently dropping material lobes.\n if (anisotropyStrength <= 0.0001 && dot(sheenColor, sheenColor) <= 0.000001 && diffuseTransmission <= 0.0001) {\n color += areaLTC_evaluate(areaIndex, fragmentInputs.pbr_vPosition, pbrInfo.n, pbrInfo.v, pbrInfo.perceptualRoughness, pbrInfo.diffuseColor, pbrInfo.reflectance0, pbrInfo.reflectance90);\n color += clearcoatFactor * areaLTC_specular(areaLighting_getLight(areaIndex), fragmentInputs.pbr_vPosition, clearcoatNormal, pbrInfo.v, clearcoatRoughness, vec3f(0.04), vec3f(1.0));\n } else {\n for (var sampleIndex: i32 = 0; sampleIndex < areaLighting.sampleCount; sampleIndex++) {\n let sampleLight = areaLighting_getSample(areaIndex, sampleIndex, fragmentInputs.pbr_vPosition);\n if (dot(sampleLight.color, sampleLight.color) > 0.0) {\n PBRInfo_setPointLight(&pbrInfo, sampleLight);\n color += calculateMaterialLightColor(pbrInfo, sampleLight.color, clearcoatNormal,\n clearcoatFactor, clearcoatRoughness, sheenColor, sheenRoughness, anisotropyTangent, anisotropyStrength);\n color += calculateDiffuseTransmissionLight(pbrInfo, sampleLight.color,\n diffuseTransmissionColor, diffuseTransmission, multiscatterColor, thickness);\n }\n }\n\n }\n#else\n for (var sampleIndex: i32 = 0; sampleIndex < areaLighting.sampleCount; sampleIndex++) {\n let sampleLight = areaLighting_getSample(areaIndex, sampleIndex, fragmentInputs.pbr_vPosition);\n if (dot(sampleLight.color, sampleLight.color) > 0.0) {\n PBRInfo_setPointLight(&pbrInfo, sampleLight);\n color += calculateMaterialLightColor(pbrInfo, sampleLight.color, clearcoatNormal,\n clearcoatFactor, clearcoatRoughness, sheenColor, sheenRoughness, anisotropyTangent, anisotropyStrength);\n color += calculateDiffuseTransmissionLight(pbrInfo, sampleLight.color,\n diffuseTransmissionColor, diffuseTransmission, multiscatterColor, thickness);\n }\n }\n\n#endif\n }\n #endif\n\n // Calculate lighting contribution from image based lighting source (IBL)\n #ifdef USE_IBL\n if (pbrMaterial.IBLenabled != 0) {\n color += getIBLContribution(\n pbrInfo,\n n,\n getAnisotropicReflection(pbrInfo, anisotropyTangent, anisotropyStrength)\n );\n color += calculateClearcoatIBLContribution(\n pbrInfo,\n clearcoatNormal,\n -normalize(reflect(v, clearcoatNormal)),\n clearcoatFactor,\n clearcoatRoughness\n );\n color += calculateDiffuseTransmissionIBL(\n pbrInfo,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;\n }\n #endif\n\n#ifdef HAS_MATERIAL_SCATTER\n color += (baseColor.rgb * (1.0 - metallic) * (1.0 - originalTransmission) +\n multiscatterColor * scatterReflection) * baseLayerEnergy * lightmapIrradiance / M_PI;\n#else\n color += baseColor.rgb * (1.0 - metallic) * (1.0 - transmission) *\n (1.0 - diffuseTransmission) * baseLayerEnergy * lightmapIrradiance / M_PI;\n#endif\n\n // Apply optional PBR terms for additional (optional) shading\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n\n var emissive = pbrMaterial.emissiveFactor;\n #ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled != 0u) {\n emissive *= SRGBtoLINEAR(\n textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)\n ).rgb;\n }\n #endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n if (transmission > 0.0) {\n #ifdef USE_TRANSMISSION_FRAMEBUFFER\n let dielectricFresnel = getDielectricF0(pbrMaterial.ior);\n let transmissionFresnel = dielectricFresnel +\n (1.0 - dielectricFresnel) * pow(1.0 - NdotV, 5.0);\n let transmittedColor = getTransmittedSceneColor(\n fragmentInputs.pbr_vPosition,\n n,\n v,\n thickness,\n perceptualRoughness\n );\n color += transmittedColor * getVolumeAttenuation(thickness) *\n transmission * (1.0 - transmissionFresnel);\n #else\n color = mix(color, color * getVolumeAttenuation(thickness), transmission);\n #endif\n }\n\n // This section uses mix to override final color for reference app visualization\n // of various parameters in the lighting equation.\n #ifdef PBR_DEBUG\n // TODO: Figure out how to debug multiple lights\n\n // color = mix(color, F, pbr_scaleFGDSpec.x);\n // color = mix(color, vec3(G), pbr_scaleFGDSpec.y);\n // color = mix(color, vec3(D), pbr_scaleFGDSpec.z);\n // color = mix(color, specContrib, pbr_scaleFGDSpec.w);\n\n // color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n #endif\n }\n\n #ifdef USE_TRANSMISSION_FRAMEBUFFER\n let alpha = clamp(baseColor.a, 0.0, 1.0);\n #else\n let alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);\n #endif\n return vec4<f32>(applySceneColorManagement(color), alpha);\n}\n\nfn pbr_filterColor(vertexColor: vec4<f32>) -> vec4<f32> {\n return pbr_filterColorWithSpotShadows(vertexColor, vec4f(1.0));\n}\n";
2
+ export declare const source = "#ifdef DOUBLE_SIDED\nvar<private> pbr_frontFacing: bool = true;\n#endif\nstruct PBRFragmentInputs {\n pbr_vPosition: vec3f,\n pbr_vUV0: vec2f,\n pbr_vUV1: vec2f,\n pbr_vTBN: mat3x3f,\n pbr_vNormal: vec3f\n};\n\nvar<private> fragmentInputs: PBRFragmentInputs;\n\nfn pbr_setPositionNormalTangentUV(\n position: vec4f,\n normal: vec4f,\n tangent: vec4f,\n uv0: vec2f,\n uv1: vec2f\n)\n{\n var pos: vec4f = pbrProjection.modelMatrix * position;\n fragmentInputs.pbr_vPosition = pos.xyz / pos.w;\n fragmentInputs.pbr_vNormal = vec3f(0.0, 0.0, 1.0);\n fragmentInputs.pbr_vTBN = mat3x3f(\n vec3f(1.0, 0.0, 0.0),\n vec3f(0.0, 1.0, 0.0),\n vec3f(0.0, 0.0, 1.0)\n );\n fragmentInputs.pbr_vUV0 = vec2f(0.0, 0.0);\n fragmentInputs.pbr_vUV1 = uv1;\n\n#ifdef HAS_NORMALS\n let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);\n fragmentInputs.pbr_vNormal = normalW;\n#ifdef HAS_TANGENTS\n let tangentW: vec3f = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);\n let bitangentW: vec3f = cross(normalW, tangentW) * tangent.w;\n fragmentInputs.pbr_vTBN = mat3x3f(tangentW, bitangentW, normalW);\n#endif\n#endif\n\n#ifdef HAS_UV\n fragmentInputs.pbr_vUV0 = uv0;\n#endif\n}\n\nstruct pbrMaterialUniforms {\n // Material is unlit\n unlit: u32,\n\n // Base color map\n baseColorMapEnabled: u32,\n baseColorFactor: vec4f,\n\n normalMapEnabled : u32,\n normalScale: f32, // #ifdef HAS_NORMALMAP\n\n emissiveMapEnabled: u32,\n emissiveFactor: vec3f, // #ifdef HAS_EMISSIVEMAP\n\n metallicRoughnessValues: vec2f,\n metallicRoughnessMapEnabled: u32,\n\n occlusionMapEnabled: i32,\n occlusionStrength: f32, // #ifdef HAS_OCCLUSIONMAP\n \n alphaCutoffEnabled: i32,\n alphaCutoff: f32, // #ifdef ALPHA_CUTOFF\n\n specularColorFactor: vec3f,\n specularIntensityFactor: f32,\n specularColorMapEnabled: i32,\n specularIntensityMapEnabled: i32,\n\n ior: f32,\n\n transmissionFactor: f32,\n transmissionMapEnabled: i32,\n\n thicknessFactor: f32,\n attenuationDistance: f32,\n attenuationColor: vec3f,\n\n clearcoatFactor: f32,\n clearcoatRoughnessFactor: f32,\n clearcoatMapEnabled: i32,\n clearcoatRoughnessMapEnabled: i32,\n\n sheenColorFactor: vec3f,\n sheenRoughnessFactor: f32,\n sheenColorMapEnabled: i32,\n sheenRoughnessMapEnabled: i32,\n\n iridescenceFactor: f32,\n iridescenceIor: f32,\n iridescenceThicknessRange: vec2f,\n iridescenceMapEnabled: i32,\n\n anisotropyStrength: f32,\n anisotropyRotation: f32,\n anisotropyDirection: vec2f,\n anisotropyMapEnabled: i32,\n\n emissiveStrength: f32,\n dispersion: f32,\n \n // IBL\n IBLenabled: i32,\n scaleIBLAmbient: vec2f, // #ifdef USE_IBL\n \n // debugging flags used for shader output of intermediate PBR variables\n // #ifdef PBR_DEBUG\n scaleDiffBaseMR: vec4f,\n scaleFGDSpec: vec4f,\n // #endif\n\n baseColorUVSet: i32,\n baseColorUVTransform: mat3x3f,\n metallicRoughnessUVSet: i32,\n metallicRoughnessUVTransform: mat3x3f,\n normalUVSet: i32,\n normalUVTransform: mat3x3f,\n occlusionUVSet: i32,\n occlusionUVTransform: mat3x3f,\n emissiveUVSet: i32,\n emissiveUVTransform: mat3x3f,\n specularColorUVSet: i32,\n specularColorUVTransform: mat3x3f,\n specularIntensityUVSet: i32,\n specularIntensityUVTransform: mat3x3f,\n transmissionUVSet: i32,\n transmissionUVTransform: mat3x3f,\n thicknessUVSet: i32,\n thicknessUVTransform: mat3x3f,\n clearcoatUVSet: i32,\n clearcoatUVTransform: mat3x3f,\n clearcoatRoughnessUVSet: i32,\n clearcoatRoughnessUVTransform: mat3x3f,\n clearcoatNormalUVSet: i32,\n clearcoatNormalUVTransform: mat3x3f,\n sheenColorUVSet: i32,\n sheenColorUVTransform: mat3x3f,\n sheenRoughnessUVSet: i32,\n sheenRoughnessUVTransform: mat3x3f,\n iridescenceUVSet: i32,\n iridescenceUVTransform: mat3x3f,\n iridescenceThicknessUVSet: i32,\n iridescenceThicknessUVTransform: mat3x3f,\n anisotropyUVSet: i32,\n anisotropyUVTransform: mat3x3f,\n\n bumpFactor: f32,\n bumpMapEnabled: i32,\n diffuseTransmissionFactor: f32,\n diffuseTransmissionMapEnabled: i32,\n diffuseTransmissionColorFactor: vec3f,\n diffuseTransmissionColorMapEnabled: i32,\n multiscatterColorFactor: vec3f,\n multiscatterColorMapEnabled: i32,\n scatterAnisotropy: f32,\n\n bumpUVSet: i32,\n bumpUVTransform: mat3x3f,\n diffuseTransmissionUVSet: i32,\n diffuseTransmissionUVTransform: mat3x3f,\n diffuseTransmissionColorUVSet: i32,\n diffuseTransmissionColorUVTransform: mat3x3f,\n multiscatterColorUVSet: i32,\n multiscatterColorUVTransform: mat3x3f,\n lightmapMapEnabled: u32,\n lightmapIntensity: f32,\n lightmapUVSet: i32,\n lightmapUVTransform: mat3x3f,\n scatterStrengthFactor: f32,\n}\n\n@group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;\n\n// Samplers\n#ifdef HAS_BASECOLORMAP\n@group(3) @binding(auto) var pbr_baseColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_baseColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_NORMALMAP\n@group(3) @binding(auto) var pbr_normalSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_normalSamplerSampler: sampler;\n#endif\n#ifdef HAS_EMISSIVEMAP\n@group(3) @binding(auto) var pbr_emissiveSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_emissiveSamplerSampler: sampler;\n#endif\n#ifdef HAS_LIGHTMAP\n@group(3) @binding(auto) var pbr_lightmapSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_lightmapSamplerSampler: sampler;\n#endif\n#ifdef HAS_METALROUGHNESSMAP\n@group(3) @binding(auto) var pbr_metallicRoughnessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_metallicRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_OCCLUSIONMAP\n@group(3) @binding(auto) var pbr_occlusionSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_occlusionSamplerSampler: sampler;\n#endif\n#ifdef HAS_SPECULARCOLORMAP\n@group(3) @binding(auto) var pbr_specularColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_specularColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_SPECULARINTENSITYMAP\n@group(3) @binding(auto) var pbr_specularIntensitySampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_specularIntensitySamplerSampler: sampler;\n#endif\n#ifdef HAS_TRANSMISSIONMAP\n@group(3) @binding(auto) var pbr_transmissionSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_transmissionSamplerSampler: sampler;\n#endif\n#ifdef HAS_THICKNESSMAP\n@group(3) @binding(auto) var pbr_thicknessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_thicknessSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATMAP\n@group(3) @binding(auto) var pbr_clearcoatSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_clearcoatSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATROUGHNESSMAP\n@group(3) @binding(auto) var pbr_clearcoatRoughnessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_clearcoatRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATNORMALMAP\n@group(3) @binding(auto) var pbr_clearcoatNormalSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_clearcoatNormalSamplerSampler: sampler;\n#endif\n#ifdef HAS_SHEENCOLORMAP\n@group(3) @binding(auto) var pbr_sheenColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_sheenColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_SHEENROUGHNESSMAP\n@group(3) @binding(auto) var pbr_sheenRoughnessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_sheenRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_IRIDESCENCEMAP\n@group(3) @binding(auto) var pbr_iridescenceSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_iridescenceSamplerSampler: sampler;\n#endif\n#ifdef HAS_IRIDESCENCETHICKNESSMAP\n@group(3) @binding(auto) var pbr_iridescenceThicknessSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_iridescenceThicknessSamplerSampler: sampler;\n#endif\n#ifdef HAS_ANISOTROPYMAP\n@group(3) @binding(auto) var pbr_anisotropySampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_anisotropySamplerSampler: sampler;\n#endif\n#ifdef HAS_BUMPMAP\n@group(3) @binding(auto) var pbr_bumpSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_bumpSamplerSampler: sampler;\n#endif\n#ifdef HAS_DIFFUSETRANSMISSIONMAP\n@group(3) @binding(auto) var pbr_diffuseTransmissionSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_diffuseTransmissionSamplerSampler: sampler;\n#endif\n#ifdef HAS_DIFFUSETRANSMISSIONCOLORMAP\n@group(3) @binding(auto) var pbr_diffuseTransmissionColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_diffuseTransmissionColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_MULTISCATTERCOLORMAP\n@group(3) @binding(auto) var pbr_multiscatterColorSampler: texture_2d<f32>;\n@group(3) @binding(auto) var pbr_multiscatterColorSamplerSampler: sampler;\n#endif\n// Encapsulate the various inputs used by the various functions in the shading equation\n// We store values in this struct to simplify the integration of alternative implementations\n// of the shading terms, outlined in the Readme.MD Appendix.\nstruct PBRInfo {\n NdotL: f32, // cos angle between normal and light direction\n NdotV: f32, // cos angle between normal and view direction\n NdotH: f32, // cos angle between normal and half vector\n LdotH: f32, // cos angle between light direction and half vector\n VdotH: f32, // cos angle between view direction and half vector\n perceptualRoughness: f32, // roughness value, as authored by the model creator (input to shader)\n metalness: f32, // metallic value at the surface\n reflectance0: vec3f, // full reflectance color (normal incidence angle)\n reflectance90: vec3f, // reflectance color at grazing angle\n alphaRoughness: f32, // roughness mapped to a more linear change in the roughness (proposed by [2])\n diffuseColor: vec3f, // color contribution from diffuse lighting\n specularColor: vec3f, // color contribution from specular lighting\n n: vec3f, // normal at surface point\n v: vec3f, // vector from surface point to camera\n l: vec3f, // direction from the surface toward the current light\n h: vec3f // half vector between the current light and camera\n};\n\nconst M_PI = 3.141592653589793;\nconst c_MinRoughness = 0.04;\n\n// Widen sub-pixel specular lobes using the screen-space normal footprint.\n// This is geometric specular antialiasing: the normal variance is converted\n// into an additional squared perceptual roughness before evaluating BRDFs.\nfn widenSpecularRoughness(perceptualRoughness: f32, normal: vec3f) -> f32 {\n let normalDerivativeX = dpdx(normal);\n let normalDerivativeY = dpdy(normal);\n let normalVariance =\n dot(normalDerivativeX, normalDerivativeX) +\n dot(normalDerivativeY, normalDerivativeY);\n let kernelRoughnessSquared = min(2.0 * normalVariance, 1.0);\n return clamp(\n sqrt(perceptualRoughness * perceptualRoughness + kernelRoughnessSquared),\n c_MinRoughness,\n 1.0\n );\n}\n\nfn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f\n{\n var linOut: vec3f = srgbIn.xyz;\n#ifdef MANUAL_SRGB\n let bLess: vec3f = step(vec3f(0.04045), srgbIn.xyz);\n linOut = mix(\n srgbIn.xyz / vec3f(12.92),\n pow((srgbIn.xyz + vec3f(0.055)) / vec3f(1.055), vec3f(2.4)),\n bLess\n );\n#ifdef SRGB_FAST_APPROXIMATION\n linOut = pow(srgbIn.xyz, vec3f(2.2));\n#endif\n#endif\n return vec4f(linOut, srgbIn.w);\n}\n\nfn getMaterialUV(uvSet: i32, uvTransform: mat3x3f) -> vec2f\n{\n var baseUV = fragmentInputs.pbr_vUV0;\n if (uvSet == 1) {\n baseUV = fragmentInputs.pbr_vUV1;\n }\n return (uvTransform * vec3f(baseUV, 1.0)).xy;\n}\n\n// Build the tangent basis from interpolated attributes or screen-space derivatives.\nfn getTBN(uv: vec2f) -> mat3x3f\n{\n let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);\n let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);\n let tex_dx: vec3f = dpdx(vec3f(uv, 0.0));\n let tex_dy: vec3f = dpdy(vec3f(uv, 0.0));\n var t: vec3f = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y);\n\n var ng: vec3f = cross(pos_dy, pos_dx);\n#ifdef HAS_NORMALS\n ng = normalize(fragmentInputs.pbr_vNormal);\n#endif\n t = normalize(t - ng * dot(ng, t));\n var b: vec3f = normalize(cross(ng, t));\n var tbn: mat3x3f = mat3x3f(t, b, ng);\n#ifdef HAS_TANGENTS\n tbn = fragmentInputs.pbr_vTBN;\n#endif\n\n#ifdef DOUBLE_SIDED\n#ifdef HAS_NORMALS\n // Derivative normals already face the viewer; only flip an authored basis.\n if (!pbr_frontFacing) { tbn = mat3x3f(-tbn[0], -tbn[1], -tbn[2]); }\n#endif\n#endif\n return tbn;\n}\n\n// Find the normal for this fragment, pulling either from a predefined normal map\n// or from the interpolated mesh normal and tangent attributes.\nfn getMappedNormal(\n normalSampler: texture_2d<f32>,\n normalSamplerBinding: sampler,\n tbn: mat3x3f,\n normalScale: f32,\n uv: vec2f\n) -> vec3f\n{\n let n = textureSample(normalSampler, normalSamplerBinding, uv).rgb;\n return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));\n}\n\nfn getNormal(tbn: mat3x3f, uv: vec2f) -> vec3f\n{\n // The tbn matrix is linearly interpolated, so we need to re-normalize\n var n: vec3f = normalize(tbn[2].xyz);\n#ifdef HAS_NORMALMAP\n n = getMappedNormal(\n pbr_normalSampler,\n pbr_normalSamplerSampler,\n tbn,\n pbrMaterial.normalScale,\n uv\n );\n#endif\n\n#ifdef HAS_BUMPMAP\n let bumpUV = getMaterialUV(pbrMaterial.bumpUVSet, pbrMaterial.bumpUVTransform);\n let bumpTexelSize = 1.0 / vec2f(textureDimensions(pbr_bumpSampler, 0));\n let bumpHeight = textureSample(pbr_bumpSampler, pbr_bumpSamplerSampler, bumpUV).r;\n let bumpGradient = vec2f(\n textureSample(\n pbr_bumpSampler,\n pbr_bumpSamplerSampler,\n bumpUV + vec2f(bumpTexelSize.x, 0.0)\n ).r - bumpHeight,\n textureSample(\n pbr_bumpSampler,\n pbr_bumpSamplerSampler,\n bumpUV + vec2f(0.0, bumpTexelSize.y)\n ).r - bumpHeight\n );\n n = normalize(n - pbrMaterial.bumpFactor *\n (tbn[0] * bumpGradient.x + tbn[1] * bumpGradient.y));\n#endif\n\n return n;\n}\n\nfn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f, uv: vec2f) -> vec3f\n{\n#ifdef HAS_CLEARCOATNORMALMAP\n return getMappedNormal(\n pbr_clearcoatNormalSampler,\n pbr_clearcoatNormalSamplerSampler,\n tbn,\n 1.0,\n uv\n );\n#else\n return baseNormal;\n#endif\n}\n\n// Calculation of the lighting contribution from an optional Image Based Light source.\n// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].\n// See our README.md on Environment Maps [3] for additional discussion.\n#ifdef USE_IBL\nfn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f\n{\n#ifdef USE_SCENE_ENVIRONMENT\n let maximumMipLevel = max(pbrScene.environmentMipCount - 1.0, 0.0);\n let rotationSine = sin(pbrScene.environmentRotation);\n let rotationCosine = cos(pbrScene.environmentRotation);\n let environmentRotation = mat2x2f(\n vec2f(rotationCosine, rotationSine),\n vec2f(-rotationSine, rotationCosine)\n );\n let rotatedNormal = environmentRotation * n.xz;\n let rotatedReflection = environmentRotation * reflection.xz;\n let environmentNormal = vec3f(rotatedNormal.x, n.y, rotatedNormal.y);\n let environmentReflection = vec3f(rotatedReflection.x, reflection.y, rotatedReflection.y);\n#else\n let maximumMipLevel = 9.0;\n let environmentNormal = n;\n let environmentReflection = reflection;\n#endif\n let lod = pbrInfo.perceptualRoughness * maximumMipLevel;\n // retrieve a scale and bias to F0. See [1], Figure 3\n let brdfSample = textureSampleLevel(\n pbr_brdfLUT,\n pbr_brdfLUTSampler,\n vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness),\n 0.0\n );\n let diffuseSample = textureSampleLevel(\n pbr_diffuseEnvSampler,\n pbr_diffuseEnvSamplerSampler,\n environmentNormal,\n 0.0\n );\n var specularSample = textureSampleLevel(\n pbr_specularEnvSampler,\n pbr_specularEnvSamplerSampler,\n environmentReflection,\n 0.0\n );\n#ifdef USE_TEX_LOD\n specularSample = textureSampleLevel(\n pbr_specularEnvSampler,\n pbr_specularEnvSamplerSampler,\n environmentReflection,\n lod\n );\n#endif\n\n#ifdef USE_SCENE_ENVIRONMENT\n let brdf = brdfSample.rgb;\n let diffuseLight = diffuseSample.rgb;\n let specularLight = specularSample.rgb;\n#else\n let brdf = SRGBtoLINEAR(brdfSample).rgb;\n let diffuseLight = SRGBtoLINEAR(diffuseSample).rgb;\n let specularLight = SRGBtoLINEAR(specularSample).rgb;\n#endif\n\n let diffuse = diffuseLight * pbrInfo.diffuseColor * pbrMaterial.scaleIBLAmbient.x;\n let specular =\n specularLight * (pbrInfo.specularColor * brdf.x + brdf.y) * pbrMaterial.scaleIBLAmbient.y;\n\n#ifdef USE_SCENE_ENVIRONMENT\n return (diffuse + specular) * max(pbrScene.environmentIntensity, 0.0);\n#else\n return diffuse + specular;\n#endif\n}\n#endif\n\n// Basic Lambertian diffuse\n// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog\n// See also [1], Equation 1\nfn diffuse(pbrInfo: PBRInfo) -> vec3<f32> {\n return pbrInfo.diffuseColor / M_PI;\n}\n\n// The following equation models the Fresnel reflectance term of the spec equation (aka F())\n// Implementation of fresnel from [4], Equation 15\nfn specularReflection(pbrInfo: PBRInfo) -> vec3<f32> {\n return pbrInfo.reflectance0 +\n (pbrInfo.reflectance90 - pbrInfo.reflectance0) *\n pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);\n}\n\n// This calculates the specular geometric attenuation (aka G()),\n// where rougher material will reflect less light back to the viewer.\n// This implementation is based on [1] Equation 4, and we adopt their modifications to\n// alphaRoughness as input as originally proposed in [2].\nfn geometricOcclusion(pbrInfo: PBRInfo) -> f32 {\n let NdotL: f32 = pbrInfo.NdotL;\n let NdotV: f32 = pbrInfo.NdotV;\n let r: f32 = pbrInfo.alphaRoughness;\n\n let attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));\n let attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));\n return attenuationL * attenuationV;\n}\n\n// The following equation(s) model the distribution of microfacet normals across\n// the area being drawn (aka D())\n// Implementation from \"Average Irregularity Representation of a Roughened Surface\n// for Ray Reflection\" by T. S. Trowbridge, and K. P. Reitz\n// Follows the distribution function recommended in the SIGGRAPH 2013 course notes\n// from EPIC Games [1], Equation 3.\nfn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {\n let roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;\n let f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;\n return roughnessSq / (M_PI * f * f);\n}\n\nfn maxComponent(value: vec3f) -> f32 {\n return max(max(value.r, value.g), value.b);\n}\n\nfn getDielectricF0(ior: f32) -> f32 {\n let clampedIor = max(ior, 1.0);\n let ratio = (clampedIor - 1.0) / (clampedIor + 1.0);\n return ratio * ratio;\n}\n\nfn normalizeDirection(direction: vec2f) -> vec2f {\n let directionLength = length(direction);\n if (directionLength > 0.0001) {\n return direction / directionLength;\n }\n\n return vec2f(1.0, 0.0);\n}\n\nfn rotateDirection(direction: vec2f, rotation: f32) -> vec2f {\n let s = sin(rotation);\n let c = cos(rotation);\n return vec2f(direction.x * c - direction.y * s, direction.x * s + direction.y * c);\n}\n\nfn encodeLinearSRGB(linearColor: vec3f) -> vec3f {\n let positiveColor = max(linearColor, vec3f(0.0));\n return select(\n positiveColor * 12.92,\n 1.055 * pow(positiveColor, vec3f(1.0 / 2.4)) - 0.055,\n positiveColor > vec3f(0.0031308)\n );\n}\n\nfn toneMapKhronosPBRNeutral(inputColor: vec3f) -> vec3f {\n let startCompression = 0.76;\n let darkestChannel = min(inputColor.r, min(inputColor.g, inputColor.b));\n let offset = select(\n 0.04,\n darkestChannel - 6.25 * darkestChannel * darkestChannel,\n darkestChannel < 0.08\n );\n var color = inputColor - vec3f(offset);\n let peak = maxComponent(color);\n if (peak < startCompression) {\n return color;\n }\n\n let compressionRange = 1.0 - startCompression;\n let compressedPeak = 1.0 - compressionRange * compressionRange /\n (peak + compressionRange - startCompression);\n color *= compressedPeak / max(peak, 0.0001);\n let desaturation = 1.0 - 1.0 / (0.15 * (peak - compressedPeak) + 1.0);\n return mix(color, vec3f(compressedPeak), desaturation);\n}\n\nfn applySceneColorManagement(sceneColor: vec3f) -> vec3f {\n#ifdef USE_SCENE_COLOR_MANAGEMENT\n var color = max(sceneColor, vec3f(0.0)) * max(pbrScene.exposure, 0.0);\n if (pbrScene.toneMapMode == 1) {\n color /= vec3f(1.0) + color;\n } else if (pbrScene.toneMapMode == 2) {\n color = toneMapKhronosPBRNeutral(color);\n } else if (pbrScene.toneMapMode == 3) {\n color = clamp(\n (color * (2.51 * color + 0.03)) / (color * (2.43 * color + 0.59) + 0.14),\n vec3f(0.0),\n vec3f(1.0)\n );\n }\n if (pbrScene.outputEncoding == 0) {\n return color;\n }\n return encodeLinearSRGB(color);\n#else\n return pow(max(sceneColor, vec3f(0.0)), vec3f(1.0 / 2.2));\n#endif\n}\n\nfn dielectricSchlick(reflectance: f32, cosine: f32) -> f32 {\n return reflectance + (1.0 - reflectance) * pow(clamp(1.0 - cosine, 0.0, 1.0), 5.0);\n}\n\nfn evaluateIridescenceSensitivity(opticalPathDifference: f32, phaseShift: vec3f) -> vec3f {\n let phase = 2.0 * M_PI * opticalPathDifference * 1.0e-9;\n let sensitivity = vec3f(5.4856e-13, 4.4201e-13, 5.2481e-13);\n let position = vec3f(1.6810e6, 1.7953e6, 2.2084e6);\n let variance = vec3f(4.3278e9, 9.3046e9, 6.6121e9);\n var xyz = sensitivity * sqrt(2.0 * M_PI * variance) *\n cos(position * phase + phaseShift) * exp(-phase * phase * variance);\n xyz.x += 9.7470e-14 * sqrt(2.0 * M_PI * 4.5282e9) *\n cos(2.2399e6 * phase + phaseShift.x) * exp(-4.5282e9 * phase * phase);\n xyz /= 1.0685e-7;\n return mat3x3f(\n vec3f(3.2404542, -0.9692660, 0.0556434),\n vec3f(-1.5371385, 1.8760108, -0.2040259),\n vec3f(-0.4985314, 0.0415560, 1.0572252)\n ) * xyz;\n}\n\nfn getIridescenceTint(\n iridescence: f32,\n thickness: f32,\n NdotV: f32,\n baseReflectance: vec3f\n) -> vec3f {\n if (iridescence <= 0.0 || thickness <= 0.0) {\n return baseReflectance;\n }\n\n let filmIor = max(pbrMaterial.iridescenceIor, 1.0);\n let sineSquared = (1.0 - NdotV * NdotV) / (filmIor * filmIor);\n let cosineSquared = 1.0 - sineSquared;\n if (cosineSquared <= 0.0) {\n return mix(baseReflectance, vec3f(1.0), iridescence);\n }\n let filmCosine = sqrt(cosineSquared);\n let firstInterfaceReflectance = dielectricSchlick(getDielectricF0(filmIor), NdotV);\n let transmittedEnergy = 1.0 - firstInterfaceReflectance;\n let squareRootReflectance = sqrt(clamp(baseReflectance, vec3f(0.0), vec3f(0.9999)));\n let baseIor = (vec3f(1.0) + squareRootReflectance) /\n (vec3f(1.0) - squareRootReflectance);\n var secondInterfaceF0 = (baseIor - vec3f(filmIor)) / (baseIor + vec3f(filmIor));\n secondInterfaceF0 *= secondInterfaceF0;\n let secondInterfaceReflectance = secondInterfaceF0 +\n (vec3f(1.0) - secondInterfaceF0) * pow(1.0 - filmCosine, 5.0);\n let phaseShift = vec3f(M_PI) + select(\n vec3f(0.0),\n vec3f(M_PI),\n baseIor < vec3f(filmIor)\n );\n let opticalPathDifference = 2.0 * filmIor * thickness * filmCosine;\n let combinedReflectance = clamp(\n firstInterfaceReflectance * secondInterfaceReflectance,\n vec3f(0.00001),\n vec3f(0.9999)\n );\n let recurringAmplitude = sqrt(combinedReflectance);\n let interfaceResponse = transmittedEnergy * transmittedEnergy * secondInterfaceReflectance /\n (vec3f(1.0) - combinedReflectance);\n var reflectedSpectrum = vec3f(firstInterfaceReflectance) + interfaceResponse;\n var harmonicAmplitude = interfaceResponse - vec3f(transmittedEnergy);\n for (var harmonic = 1; harmonic <= 2; harmonic++) {\n harmonicAmplitude *= recurringAmplitude;\n reflectedSpectrum += harmonicAmplitude * 2.0 * evaluateIridescenceSensitivity(\n f32(harmonic) * opticalPathDifference,\n f32(harmonic) * phaseShift\n );\n }\n return mix(baseReflectance, clamp(reflectedSpectrum, vec3f(0.0), vec3f(1.0)), iridescence);\n}\n\nfn getVolumeAttenuation(thickness: f32) -> vec3f {\n if (thickness <= 0.0) {\n return vec3f(1.0);\n }\n\n let attenuationCoefficient =\n -log(max(pbrMaterial.attenuationColor, vec3f(0.0001))) /\n max(pbrMaterial.attenuationDistance, 0.0001);\n return exp(-attenuationCoefficient * thickness);\n}\n\n// KHR_materials_volume_scatter is an active draft. This evaluates a local,\n// thickness-aware single-scattering approximation rather than random walk.\nfn getDiffuseTransmissionAttenuation(\n pbrInfo: PBRInfo,\n multiscatterColor: vec3f,\n thickness: f32\n) -> vec3f {\n let volumeAttenuation = getVolumeAttenuation(thickness);\n let scatteringStrength = maxComponent(multiscatterColor);\n if (thickness <= 0.0 || scatteringStrength <= 0.0001) {\n return volumeAttenuation;\n }\n\n let anisotropy = clamp(pbrMaterial.scatterAnisotropy, -0.95, 0.95);\n let scatteringCosine = clamp(dot(-pbrInfo.v, pbrInfo.l), -1.0, 1.0);\n let phaseDenominator = max(\n 1.0 + anisotropy * anisotropy - 2.0 * anisotropy * scatteringCosine,\n 0.0001\n );\n let phaseWeight = clamp(\n (1.0 - anisotropy * anisotropy) / pow(phaseDenominator, 1.5),\n 0.0,\n 4.0\n );\n let scatteringDepth = thickness / max(pbrMaterial.attenuationDistance, 0.0001);\n let scatteringProbability = 1.0 - exp(-scatteringDepth);\n let scatteringColor = clamp(multiscatterColor, vec3f(0.0), vec3f(1.0));\n return mix(\n volumeAttenuation,\n volumeAttenuation * mix(vec3f(1.0), scatteringColor * phaseWeight, scatteringColor),\n scatteringProbability\n );\n}\n\nfn calculateDiffuseTransmissionLight(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n diffuseTransmissionColor: vec3f,\n diffuseTransmission: f32,\n multiscatterColor: vec3f,\n thickness: f32\n) -> vec3f {\n let oppositeHemisphere = max(dot(-pbrInfo.n, pbrInfo.l), 0.0);\n if (oppositeHemisphere <= 0.0 || diffuseTransmission <= 0.0) {\n return vec3f(0.0);\n }\n\n let nonReflectedEnergy = vec3f(1.0) - clamp(pbrInfo.reflectance0, vec3f(0.0), vec3f(1.0));\n let attenuatedColor = getDiffuseTransmissionAttenuation(\n pbrInfo,\n multiscatterColor,\n thickness\n );\n return lightColor * diffuseTransmissionColor * nonReflectedEnergy *\n attenuatedColor * (diffuseTransmission * oppositeHemisphere / M_PI);\n}\n\n#ifdef USE_IBL\nfn calculateDiffuseTransmissionIBL(\n pbrInfo: PBRInfo,\n diffuseTransmissionColor: vec3f,\n diffuseTransmission: f32,\n multiscatterColor: vec3f,\n thickness: f32\n) -> vec3f {\n if (diffuseTransmission <= 0.0) {\n return vec3f(0.0);\n }\n\n#ifdef USE_SCENE_ENVIRONMENT\n let rotationSine = sin(pbrScene.environmentRotation);\n let rotationCosine = cos(pbrScene.environmentRotation);\n let environmentRotation = mat2x2f(\n vec2f(rotationCosine, rotationSine),\n vec2f(-rotationSine, rotationCosine)\n );\n let rotatedNormal = environmentRotation * -pbrInfo.n.xz;\n let oppositeNormal = vec3f(rotatedNormal.x, -pbrInfo.n.y, rotatedNormal.y);\n let environmentColor = textureSampleLevel(\n pbr_diffuseEnvSampler,\n pbr_diffuseEnvSamplerSampler,\n oppositeNormal,\n 0.0\n ).rgb * max(pbrScene.environmentIntensity, 0.0);\n#else\n let environmentColor = SRGBtoLINEAR(\n textureSampleLevel(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, -pbrInfo.n, 0.0)\n ).rgb;\n#endif\n let nonReflectedEnergy = vec3f(1.0) - clamp(pbrInfo.reflectance0, vec3f(0.0), vec3f(1.0));\n return environmentColor * diffuseTransmissionColor * nonReflectedEnergy *\n getDiffuseTransmissionAttenuation(pbrInfo, multiscatterColor, thickness) *\n diffuseTransmission * pbrMaterial.scaleIBLAmbient.x;\n}\n#endif\n\n#ifdef USE_TRANSMISSION_FRAMEBUFFER\nfn sampleTransmittedSceneColor(\n position: vec3f,\n normal: vec3f,\n viewDirection: vec3f,\n thickness: f32,\n perceptualRoughness: f32,\n indexOfRefraction: f32\n) -> vec3f {\n let refractionDirection = refract(\n -viewDirection,\n normal,\n 1.0 / max(indexOfRefraction, 1.0)\n );\n let refractedPosition = position + refractionDirection * thickness;\n let clipPosition = pbrScene.projectionMatrix *\n pbrScene.viewMatrix * vec4f(refractedPosition, 1.0);\n var textureCoordinate = clipPosition.xy / max(clipPosition.w, 0.0001) * 0.5 + 0.5;\n textureCoordinate.y = 1.0 - textureCoordinate.y;\n textureCoordinate = clamp(textureCoordinate, vec2f(0.001), vec2f(0.999));\n\n let blurRadius = perceptualRoughness * perceptualRoughness * 8.0 /\n max(pbrScene.framebufferSize, vec2f(1.0));\n var sceneColor = textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate,\n 0.0\n ).rgb * 0.4;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate + vec2f(blurRadius.x, 0.0),\n 0.0\n ).rgb * 0.15;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate - vec2f(blurRadius.x, 0.0),\n 0.0\n ).rgb * 0.15;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate + vec2f(0.0, blurRadius.y),\n 0.0\n ).rgb * 0.15;\n sceneColor += textureSampleLevel(\n pbr_transmissionFramebufferSampler,\n pbr_transmissionFramebufferSamplerSampler,\n textureCoordinate - vec2f(0.0, blurRadius.y),\n 0.0\n ).rgb * 0.15;\n return max(sceneColor, vec3f(0.0));\n}\n\nfn getTransmittedSceneColor(\n position: vec3f,\n normal: vec3f,\n viewDirection: vec3f,\n thickness: f32,\n perceptualRoughness: f32\n) -> vec3f {\n if (pbrMaterial.dispersion <= 0.0) {\n return sampleTransmittedSceneColor(\n position,\n normal,\n viewDirection,\n thickness,\n perceptualRoughness,\n pbrMaterial.ior\n );\n }\n\n let halfSpread = (max(pbrMaterial.ior, 1.0) - 1.0) * 0.025 * pbrMaterial.dispersion;\n let indicesOfRefraction = max(\n vec3f(pbrMaterial.ior - halfSpread, pbrMaterial.ior, pbrMaterial.ior + halfSpread),\n vec3f(1.0)\n );\n return vec3f(\n sampleTransmittedSceneColor(\n position, normal, viewDirection, thickness, perceptualRoughness, indicesOfRefraction.r\n ).r,\n sampleTransmittedSceneColor(\n position, normal, viewDirection, thickness, perceptualRoughness, indicesOfRefraction.g\n ).g,\n sampleTransmittedSceneColor(\n position, normal, viewDirection, thickness, perceptualRoughness, indicesOfRefraction.b\n ).b\n );\n}\n#endif\n\nfn createClearcoatPBRInfo(\n basePBRInfo: PBRInfo,\n clearcoatNormal: vec3f,\n clearcoatRoughness: f32\n) -> PBRInfo {\n let perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n let NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);\n\n return PBRInfo(\n basePBRInfo.NdotL,\n NdotV,\n basePBRInfo.NdotH,\n basePBRInfo.LdotH,\n basePBRInfo.VdotH,\n perceptualRoughness,\n 0.0,\n vec3f(0.04),\n vec3f(1.0),\n alphaRoughness,\n vec3f(0.0),\n vec3f(0.04),\n clearcoatNormal,\n basePBRInfo.v,\n basePBRInfo.l,\n basePBRInfo.h\n );\n}\n\nfn calculateClearcoatContribution(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n clearcoatNormal: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32\n) -> vec3f {\n if (clearcoatFactor <= 0.0) {\n return vec3f(0.0);\n }\n\n let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;\n}\n\n#ifdef USE_IBL\nfn calculateClearcoatIBLContribution(\n pbrInfo: PBRInfo,\n clearcoatNormal: vec3f,\n reflection: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32\n) -> vec3f {\n if (clearcoatFactor <= 0.0) {\n return vec3f(0.0);\n }\n\n let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;\n}\n#endif\n\nfn calculateSheenContribution(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n sheenColor: vec3f,\n sheenRoughness: f32\n) -> vec3f {\n if (maxComponent(sheenColor) <= 0.0) {\n return vec3f(0.0);\n }\n\n let alpha = max(sheenRoughness * sheenRoughness, 0.0001);\n let inverseAlpha = 1.0 / alpha;\n let sineSquared = max(1.0 - pbrInfo.NdotH * pbrInfo.NdotH, 0.0);\n let distribution = (2.0 + inverseAlpha) * pow(sineSquared, inverseAlpha * 0.5) /\n (2.0 * M_PI);\n let visibility = 1.0 / max(\n 4.0 * (pbrInfo.NdotL + pbrInfo.NdotV - pbrInfo.NdotL * pbrInfo.NdotV),\n 0.0001\n );\n return pbrInfo.NdotL * lightColor * sheenColor * distribution * visibility *\n (1.0 - pbrInfo.metalness);\n}\n\nfn calculateAnisotropicLightColor(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> vec3f {\n if (anisotropyStrength <= 0.0) {\n return calculateFinalColor(pbrInfo, lightColor);\n }\n\n let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));\n let tangentRoughness = mix(\n pbrInfo.alphaRoughness,\n 1.0,\n anisotropyStrength * anisotropyStrength\n );\n let bitangentRoughness = clamp(pbrInfo.alphaRoughness, 0.001, 1.0);\n let roughnessProduct = tangentRoughness * bitangentRoughness;\n let distributionVector = vec3f(\n bitangentRoughness * dot(anisotropyTangent, pbrInfo.h),\n tangentRoughness * dot(anisotropyBitangent, pbrInfo.h),\n roughnessProduct * pbrInfo.NdotH\n );\n let distributionFactor = roughnessProduct /\n max(dot(distributionVector, distributionVector), 0.000001);\n let distribution = roughnessProduct * distributionFactor * distributionFactor / M_PI;\n let viewMask = pbrInfo.NdotL * length(vec3f(\n tangentRoughness * dot(anisotropyTangent, pbrInfo.v),\n bitangentRoughness * dot(anisotropyBitangent, pbrInfo.v),\n pbrInfo.NdotV\n ));\n let lightMask = pbrInfo.NdotV * length(vec3f(\n tangentRoughness * dot(anisotropyTangent, pbrInfo.l),\n bitangentRoughness * dot(anisotropyBitangent, pbrInfo.l),\n pbrInfo.NdotL\n ));\n let visibility = clamp(0.5 / max(viewMask + lightMask, 0.000001), 0.0, 1.0);\n let fresnel = specularReflection(pbrInfo);\n let diffuseContribution = (vec3f(1.0) - fresnel) * diffuse(pbrInfo);\n return pbrInfo.NdotL * lightColor *\n (diffuseContribution + fresnel * distribution * visibility);\n}\n\nfn getAnisotropicReflection(\n pbrInfo: PBRInfo,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> vec3f {\n if (anisotropyStrength <= 0.0) {\n return -normalize(reflect(pbrInfo.v, pbrInfo.n));\n }\n let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));\n var anisotropicNormal = normalize(cross(anisotropyBitangent, pbrInfo.v));\n anisotropicNormal = normalize(cross(anisotropicNormal, anisotropyBitangent));\n let bend = anisotropyStrength * (1.0 - pbrInfo.perceptualRoughness);\n return -normalize(reflect(pbrInfo.v, normalize(mix(pbrInfo.n, anisotropicNormal, bend))));\n}\n\nfn calculateMaterialLightColor(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n clearcoatNormal: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32,\n sheenColor: vec3f,\n sheenRoughness: f32,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> vec3f {\n var color = calculateAnisotropicLightColor(\n pbrInfo,\n lightColor,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateClearcoatContribution(\n pbrInfo,\n lightColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness\n );\n color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);\n return color;\n}\n\nfn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {\n (*pbrInfo).NdotL = 1.0;\n (*pbrInfo).NdotH = 0.0;\n (*pbrInfo).LdotH = 0.0;\n (*pbrInfo).VdotH = 1.0;\n (*pbrInfo).l = (*pbrInfo).n;\n (*pbrInfo).h = (*pbrInfo).n;\n}\n\nfn PBRInfo_setDirectionalLight(pbrInfo: ptr<function, PBRInfo>, lightDirection: vec3<f32>) {\n let n = (*pbrInfo).n;\n let v = (*pbrInfo).v;\n let l = normalize(lightDirection); // Vector from surface point to light\n let h = normalize(l + v); // Half vector between both l and v\n\n (*pbrInfo).NdotL = clamp(dot(n, l), 0.001, 1.0);\n (*pbrInfo).NdotH = clamp(dot(n, h), 0.0, 1.0);\n (*pbrInfo).LdotH = clamp(dot(l, h), 0.0, 1.0);\n (*pbrInfo).VdotH = clamp(dot(v, h), 0.0, 1.0);\n (*pbrInfo).l = l;\n (*pbrInfo).h = h;\n}\n\nfn PBRInfo_setPointLight(pbrInfo: ptr<function, PBRInfo>, pointLight: PointLight) {\n let light_direction = normalize(pointLight.position - fragmentInputs.pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nfn PBRInfo_setSpotLight(pbrInfo: ptr<function, PBRInfo>, spotLight: SpotLight) {\n let light_direction = normalize(spotLight.position - fragmentInputs.pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nfn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {\n // Calculate the shading terms for the microfacet specular shading model\n let F = specularReflection(pbrInfo);\n let G = geometricOcclusion(pbrInfo);\n let D = microfacetDistribution(pbrInfo);\n\n // Calculation of analytical lighting contribution\n let diffuseContrib = (1.0 - F) * diffuse(pbrInfo);\n let specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);\n // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)\n return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);\n}\n\n// Visibility for the first four spotlights; environment and other lights are unaffected.\nfn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f) -> vec4<f32> {\n let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);\n let metallicRoughnessUV = getMaterialUV(\n pbrMaterial.metallicRoughnessUVSet,\n pbrMaterial.metallicRoughnessUVTransform\n );\n let normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);\n let occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);\n let emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);\n let lightmapUV = getMaterialUV(pbrMaterial.lightmapUVSet, pbrMaterial.lightmapUVTransform);\n let specularColorUV = getMaterialUV(\n pbrMaterial.specularColorUVSet,\n pbrMaterial.specularColorUVTransform\n );\n let specularIntensityUV = getMaterialUV(\n pbrMaterial.specularIntensityUVSet,\n pbrMaterial.specularIntensityUVTransform\n );\n let transmissionUV = getMaterialUV(\n pbrMaterial.transmissionUVSet,\n pbrMaterial.transmissionUVTransform\n );\n let thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);\n let clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);\n let clearcoatRoughnessUV = getMaterialUV(\n pbrMaterial.clearcoatRoughnessUVSet,\n pbrMaterial.clearcoatRoughnessUVTransform\n );\n let clearcoatNormalUV = getMaterialUV(\n pbrMaterial.clearcoatNormalUVSet,\n pbrMaterial.clearcoatNormalUVTransform\n );\n let sheenColorUV = getMaterialUV(\n pbrMaterial.sheenColorUVSet,\n pbrMaterial.sheenColorUVTransform\n );\n let sheenRoughnessUV = getMaterialUV(\n pbrMaterial.sheenRoughnessUVSet,\n pbrMaterial.sheenRoughnessUVTransform\n );\n let iridescenceUV = getMaterialUV(\n pbrMaterial.iridescenceUVSet,\n pbrMaterial.iridescenceUVTransform\n );\n let iridescenceThicknessUV = getMaterialUV(\n pbrMaterial.iridescenceThicknessUVSet,\n pbrMaterial.iridescenceThicknessUVTransform\n );\n let anisotropyUV = getMaterialUV(\n pbrMaterial.anisotropyUVSet,\n pbrMaterial.anisotropyUVTransform\n );\n let diffuseTransmissionUV = getMaterialUV(\n pbrMaterial.diffuseTransmissionUVSet,\n pbrMaterial.diffuseTransmissionUVTransform\n );\n let diffuseTransmissionColorUV = getMaterialUV(\n pbrMaterial.diffuseTransmissionColorUVSet,\n pbrMaterial.diffuseTransmissionColorUVTransform\n );\n let multiscatterColorUV = getMaterialUV(\n pbrMaterial.multiscatterColorUVSet,\n pbrMaterial.multiscatterColorUVTransform\n );\n\n // The albedo may be defined from a base texture or a flat color\n var baseColor: vec4<f32> = pbrMaterial.baseColorFactor * vertexColor;\n #ifdef HAS_BASECOLORMAP\n baseColor = SRGBtoLINEAR(\n textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, baseColorUV)\n ) * pbrMaterial.baseColorFactor * vertexColor;\n #endif\n\n #ifdef ALPHA_CUTOFF\n if (baseColor.a < pbrMaterial.alphaCutoff) {\n discard;\n }\n #endif\n\n var color = vec3<f32>(0.0, 0.0, 0.0);\n var transmission = 0.0;\n\n var lightmapIrradiance = vec3<f32>(0.0);\n #ifdef HAS_LIGHTMAP\n if (pbrMaterial.lightmapMapEnabled != 0u) {\n lightmapIrradiance = textureSample(pbr_lightmapSampler, pbr_lightmapSamplerSampler, lightmapUV).rgb * pbrMaterial.lightmapIntensity;\n }\n #endif\n\n if (pbrMaterial.unlit != 0u) {\n color = baseColor.rgb;\n #ifdef HAS_LIGHTMAP\n if (pbrMaterial.lightmapMapEnabled != 0u) {\n color *= lightmapIrradiance / M_PI;\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n }\n #endif\n } else {\n // Metallic and Roughness material properties are packed together\n // In glTF, these factors can be specified by fixed scalar values\n // or from a metallic-roughness map\n var perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;\n var metallic = pbrMaterial.metallicRoughnessValues.x;\n #ifdef HAS_METALROUGHNESSMAP\n // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.\n // This layout intentionally reserves the 'r' channel for (optional) occlusion map data\n let mrSample = textureSample(\n pbr_metallicRoughnessSampler,\n pbr_metallicRoughnessSamplerSampler,\n metallicRoughnessUV\n );\n perceptualRoughness = mrSample.g * perceptualRoughness;\n metallic = mrSample.b * metallic;\n #endif\n perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);\n metallic = clamp(metallic, 0.0, 1.0);\n let tbn = getTBN(normalUV);\n let n = getNormal(tbn, normalUV); // normal at surface point\n perceptualRoughness = widenSpecularRoughness(perceptualRoughness, n);\n let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera\n let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);\n var useExtendedPBR = false;\n #ifdef USE_MATERIAL_EXTENSIONS\n useExtendedPBR =\n pbrMaterial.specularColorMapEnabled != 0 ||\n pbrMaterial.specularIntensityMapEnabled != 0 ||\n abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||\n maxComponent(abs(pbrMaterial.specularColorFactor - vec3f(1.0))) > 0.0001 ||\n abs(pbrMaterial.ior - 1.5) > 0.0001 ||\n pbrMaterial.dispersion > 0.0001 ||\n pbrMaterial.transmissionMapEnabled != 0 ||\n pbrMaterial.transmissionFactor > 0.0001 ||\n pbrMaterial.diffuseTransmissionMapEnabled != 0 ||\n pbrMaterial.diffuseTransmissionColorMapEnabled != 0 ||\n pbrMaterial.diffuseTransmissionFactor > 0.0001 ||\n pbrMaterial.multiscatterColorMapEnabled != 0 ||\n maxComponent(pbrMaterial.multiscatterColorFactor) > 0.0001 ||\n pbrMaterial.clearcoatMapEnabled != 0 ||\n pbrMaterial.clearcoatRoughnessMapEnabled != 0 ||\n pbrMaterial.clearcoatFactor > 0.0001 ||\n pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||\n pbrMaterial.sheenColorMapEnabled != 0 ||\n pbrMaterial.sheenRoughnessMapEnabled != 0 ||\n maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||\n pbrMaterial.sheenRoughnessFactor > 0.0001 ||\n pbrMaterial.iridescenceMapEnabled != 0 ||\n pbrMaterial.iridescenceFactor > 0.0001 ||\n abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||\n pbrMaterial.anisotropyMapEnabled != 0 ||\n pbrMaterial.anisotropyStrength > 0.0001 ||\n abs(pbrMaterial.anisotropyRotation) > 0.0001 ||\n length(pbrMaterial.anisotropyDirection - vec2f(1.0, 0.0)) > 0.0001;\n #endif\n\n if (!useExtendedPBR) {\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n let f0 = vec3<f32>(0.04);\n var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);\n diffuseColor *= 1.0 - metallic;\n let specularColor = mix(f0, baseColor.rgb, metallic);\n\n let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n let specularEnvironmentR0 = specularColor;\n let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;\n let reflection = -normalize(reflect(v, n));\n\n var pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v,\n n,\n n\n );\n\n #ifdef USE_LIGHTS\n PBRInfo_setAmbientLight(&pbrInfo);\n color += calculateFinalColor(pbrInfo, lighting.ambientColor);\n\n for (var i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);\n color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);\n }\n }\n\n for (var i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));\n let attenuation = getPointLightAttenuation(\n lighting_getPointLight(i),\n distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)\n );\n color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);\n }\n }\n\n for (var i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));\n let attenuation = getSpotLightAttenuation(\n lighting_getSpotLight(i),\n fragmentInputs.pbr_vPosition\n );\n color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color * select(1.0, clamp(spotVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation);\n }\n }\n for (var areaIndex: i32 = 0; areaIndex < areaLighting_getLightCount(); areaIndex++) {\n#ifdef USE_AREA_LIGHT_LTC\n color += areaLTC_evaluate(areaIndex, fragmentInputs.pbr_vPosition, pbrInfo.n, pbrInfo.v, pbrInfo.perceptualRoughness, pbrInfo.diffuseColor, pbrInfo.reflectance0, pbrInfo.reflectance90);\n#else\n for (var sampleIndex: i32 = 0; sampleIndex < areaLighting.sampleCount; sampleIndex++) {\n let sampleLight = areaLighting_getSample(areaIndex, sampleIndex, fragmentInputs.pbr_vPosition);\n if (dot(sampleLight.color, sampleLight.color) > 0.0) {\n PBRInfo_setPointLight(&pbrInfo, sampleLight);\n color += calculateFinalColor(pbrInfo, sampleLight.color);\n }\n }\n#endif\n }\n #endif\n\n #ifdef USE_IBL\n if (pbrMaterial.IBLenabled != 0) {\n color += getIBLContribution(pbrInfo, n, reflection);\n }\n #endif\n\n // The pinned KHR_lightmap draft explicitly defines c_diff = (1 - metallic) * baseColor.\n color += baseColor.rgb * (1.0 - metallic) * lightmapIrradiance / M_PI;\n\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n\n var emissive = pbrMaterial.emissiveFactor;\n #ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled != 0u) {\n emissive *= SRGBtoLINEAR(\n textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)\n ).rgb;\n }\n #endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n #ifdef PBR_DEBUG\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n #endif\n\n return vec4<f32>(applySceneColorManagement(color), baseColor.a);\n }\n\n var specularIntensity = pbrMaterial.specularIntensityFactor;\n #ifdef HAS_SPECULARINTENSITYMAP\n if (pbrMaterial.specularIntensityMapEnabled != 0) {\n specularIntensity *= textureSample(\n pbr_specularIntensitySampler,\n pbr_specularIntensitySamplerSampler,\n specularIntensityUV\n ).a;\n }\n #endif\n\n var specularFactor = pbrMaterial.specularColorFactor;\n #ifdef HAS_SPECULARCOLORMAP\n if (pbrMaterial.specularColorMapEnabled != 0) {\n specularFactor *= SRGBtoLINEAR(\n textureSample(\n pbr_specularColorSampler,\n pbr_specularColorSamplerSampler,\n specularColorUV\n )\n ).rgb;\n }\n #endif\n\n transmission = pbrMaterial.transmissionFactor;\n #ifdef HAS_TRANSMISSIONMAP\n if (pbrMaterial.transmissionMapEnabled != 0) {\n transmission *= textureSample(\n pbr_transmissionSampler,\n pbr_transmissionSamplerSampler,\n transmissionUV\n ).r;\n }\n #endif\n transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);\n var thickness = max(pbrMaterial.thicknessFactor, 0.0);\n #ifdef HAS_THICKNESSMAP\n thickness *= textureSample(\n pbr_thicknessSampler,\n pbr_thicknessSamplerSampler,\n thicknessUV\n ).g;\n #endif\n\n var diffuseTransmission = clamp(pbrMaterial.diffuseTransmissionFactor, 0.0, 1.0);\n #ifdef HAS_DIFFUSETRANSMISSIONMAP\n if (pbrMaterial.diffuseTransmissionMapEnabled != 0) {\n diffuseTransmission *= textureSample(\n pbr_diffuseTransmissionSampler,\n pbr_diffuseTransmissionSamplerSampler,\n diffuseTransmissionUV\n ).a;\n }\n #endif\n diffuseTransmission *= (1.0 - metallic) * (1.0 - transmission);\n var diffuseTransmissionColor = pbrMaterial.diffuseTransmissionColorFactor;\n #ifdef HAS_DIFFUSETRANSMISSIONCOLORMAP\n if (pbrMaterial.diffuseTransmissionColorMapEnabled != 0) {\n diffuseTransmissionColor *= SRGBtoLINEAR(\n textureSample(\n pbr_diffuseTransmissionColorSampler,\n pbr_diffuseTransmissionColorSamplerSampler,\n diffuseTransmissionColorUV\n )\n ).rgb;\n }\n #endif\n var multiscatterColor = pbrMaterial.multiscatterColorFactor;\n #ifdef HAS_MULTISCATTERCOLORMAP\n if (pbrMaterial.multiscatterColorMapEnabled != 0) {\n multiscatterColor *= SRGBtoLINEAR(\n textureSample(\n pbr_multiscatterColorSampler,\n pbr_multiscatterColorSamplerSampler,\n multiscatterColorUV\n )\n ).rgb;\n }\n #endif\n\n let originalTransmission = transmission;\n var scatterReflection = 0.0;\n#ifdef HAS_MATERIAL_SCATTER\n if (thickness <= 0.0) {\n var strength = clamp(pbrMaterial.scatterStrengthFactor, 0.0, 1.0);\n#ifdef HAS_DIFFUSETRANSMISSIONMAP\n if (pbrMaterial.diffuseTransmissionMapEnabled != 0) {\n strength *= textureSample(\n pbr_diffuseTransmissionSampler,\n pbr_diffuseTransmissionSamplerSampler,\n diffuseTransmissionUV\n ).a;\n }\n#endif\n let anisotropy = pbrMaterial.scatterAnisotropy;\n scatterReflection = originalTransmission * strength * (1.0 - anisotropy) * 0.5;\n diffuseTransmission = originalTransmission * strength * (1.0 + anisotropy) * 0.5;\n diffuseTransmissionColor = multiscatterColor;\n transmission *= 1.0 - strength;\n }\n#endif\n\n var clearcoatFactor = pbrMaterial.clearcoatFactor;\n var clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;\n #ifdef HAS_CLEARCOATMAP\n if (pbrMaterial.clearcoatMapEnabled != 0) {\n clearcoatFactor *= textureSample(\n pbr_clearcoatSampler,\n pbr_clearcoatSamplerSampler,\n clearcoatUV\n ).r;\n }\n #endif\n #ifdef HAS_CLEARCOATROUGHNESSMAP\n if (pbrMaterial.clearcoatRoughnessMapEnabled != 0) {\n clearcoatRoughness *= textureSample(\n pbr_clearcoatRoughnessSampler,\n pbr_clearcoatRoughnessSamplerSampler,\n clearcoatRoughnessUV\n ).g;\n }\n #endif\n clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);\n clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n let clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);\n clearcoatRoughness = widenSpecularRoughness(clearcoatRoughness, clearcoatNormal);\n\n var sheenColor = pbrMaterial.sheenColorFactor;\n var sheenRoughness = pbrMaterial.sheenRoughnessFactor;\n #ifdef HAS_SHEENCOLORMAP\n if (pbrMaterial.sheenColorMapEnabled != 0) {\n sheenColor *= SRGBtoLINEAR(\n textureSample(\n pbr_sheenColorSampler,\n pbr_sheenColorSamplerSampler,\n sheenColorUV\n )\n ).rgb;\n }\n #endif\n #ifdef HAS_SHEENROUGHNESSMAP\n if (pbrMaterial.sheenRoughnessMapEnabled != 0) {\n sheenRoughness *= textureSample(\n pbr_sheenRoughnessSampler,\n pbr_sheenRoughnessSamplerSampler,\n sheenRoughnessUV\n ).a;\n }\n #endif\n sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);\n\n var iridescence = pbrMaterial.iridescenceFactor;\n #ifdef HAS_IRIDESCENCEMAP\n if (pbrMaterial.iridescenceMapEnabled != 0) {\n iridescence *= textureSample(\n pbr_iridescenceSampler,\n pbr_iridescenceSamplerSampler,\n iridescenceUV\n ).r;\n }\n #endif\n iridescence = clamp(iridescence, 0.0, 1.0);\n var iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n 0.5\n );\n #ifdef HAS_IRIDESCENCETHICKNESSMAP\n iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n textureSample(\n pbr_iridescenceThicknessSampler,\n pbr_iridescenceThicknessSamplerSampler,\n iridescenceThicknessUV\n ).g\n );\n #endif\n\n var anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);\n var anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);\n #ifdef HAS_ANISOTROPYMAP\n if (pbrMaterial.anisotropyMapEnabled != 0) {\n let anisotropySample = textureSample(\n pbr_anisotropySampler,\n pbr_anisotropySamplerSampler,\n anisotropyUV\n ).rgb;\n anisotropyStrength *= anisotropySample.b;\n let mappedDirection = anisotropySample.rg * 2.0 - 1.0;\n if (length(mappedDirection) > 0.0001) {\n anisotropyDirection = normalize(mappedDirection);\n }\n }\n #endif\n anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);\n var anisotropyTangent =\n normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);\n if (length(anisotropyTangent) < 0.0001) {\n anisotropyTangent = normalize(tbn[0]);\n }\n // Roughness is authored as perceptual roughness; as is convention,\n // convert to material roughness by squaring the perceptual roughness [2].\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n let dielectricF0 = getDielectricF0(pbrMaterial.ior);\n var dielectricSpecularF0 = min(\n vec3f(dielectricF0) * specularFactor * specularIntensity,\n vec3f(1.0)\n );\n dielectricSpecularF0 = getIridescenceTint(\n iridescence,\n iridescenceThickness,\n NdotV,\n dielectricSpecularF0\n );\n var diffuseColor = baseColor.rgb * (vec3f(1.0) - dielectricSpecularF0);\n diffuseColor *= (1.0 - metallic) * (1.0 - transmission) * (1.0 - diffuseTransmission);\n#ifdef HAS_MATERIAL_SCATTER\n diffuseColor = (baseColor.rgb * (1.0 - metallic) * (1.0 - originalTransmission) +\n multiscatterColor * scatterReflection) * (vec3f(1.0) - dielectricSpecularF0);\n#endif\n var specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);\n\n let clearcoatViewFresnel = dielectricSchlick(\n 0.04,\n clamp(abs(dot(clearcoatNormal, v)), 0.0, 1.0)\n );\n let sheenDirectionalAlbedo = maxComponent(sheenColor) *\n (0.157 + 0.343 * (1.0 - NdotV)) * (1.0 - sheenRoughness * 0.5);\n let baseLayerEnergy = (1.0 - clearcoatFactor * clearcoatViewFresnel) *\n (1.0 - clamp(sheenDirectionalAlbedo, 0.0, 1.0));\n diffuseColor *= baseLayerEnergy;\n specularColor *= baseLayerEnergy;\n\n // Compute reflectance.\n let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n\n // For typical incident reflectance range (between 4% to 100%) set the grazing\n // reflectance to 100% for typical fresnel effect.\n // For very low reflectance range on highly diffuse objects (below 4%),\n // incrementally reduce grazing reflectance to 0%.\n let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n let specularEnvironmentR0 = specularColor;\n let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;\n let reflection = -normalize(reflect(v, n));\n\n var pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v,\n n,\n n\n );\n\n #ifdef USE_LIGHTS\n // Apply ambient light\n PBRInfo_setAmbientLight(&pbrInfo);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting.ambientColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n\n // Apply directional light\n for (var i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getDirectionalLight(i).color,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateDiffuseTransmissionLight(\n pbrInfo,\n lighting_getDirectionalLight(i).color,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n }\n }\n\n // Apply point light\n for (var i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));\n let attenuation = getPointLightAttenuation(\n lighting_getPointLight(i),\n distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)\n );\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getPointLight(i).color / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateDiffuseTransmissionLight(\n pbrInfo,\n lighting_getPointLight(i).color / attenuation,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n }\n }\n\n for (var i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));\n let attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), fragmentInputs.pbr_vPosition);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getSpotLight(i).color * select(1.0, clamp(spotVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n color += calculateDiffuseTransmissionLight(\n pbrInfo,\n lighting_getSpotLight(i).color * select(1.0, clamp(spotVisibility[min(i, 3)], 0.0, 1.0), i < 4) / attenuation,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n }\n }\n for (var areaIndex: i32 = 0; areaIndex < areaLighting_getLightCount(); areaIndex++) {\n#ifdef USE_AREA_LIGHT_LTC\n // Unsupported fits retain numerical integration rather than silently dropping material lobes.\n if (anisotropyStrength <= 0.0001 && dot(sheenColor, sheenColor) <= 0.000001 && diffuseTransmission <= 0.0001) {\n color += areaLTC_evaluate(areaIndex, fragmentInputs.pbr_vPosition, pbrInfo.n, pbrInfo.v, pbrInfo.perceptualRoughness, pbrInfo.diffuseColor, pbrInfo.reflectance0, pbrInfo.reflectance90);\n color += clearcoatFactor * areaLTC_specular(areaLighting_getLight(areaIndex), fragmentInputs.pbr_vPosition, clearcoatNormal, pbrInfo.v, clearcoatRoughness, vec3f(0.04), vec3f(1.0));\n } else {\n for (var sampleIndex: i32 = 0; sampleIndex < areaLighting.sampleCount; sampleIndex++) {\n let sampleLight = areaLighting_getSample(areaIndex, sampleIndex, fragmentInputs.pbr_vPosition);\n if (dot(sampleLight.color, sampleLight.color) > 0.0) {\n PBRInfo_setPointLight(&pbrInfo, sampleLight);\n color += calculateMaterialLightColor(pbrInfo, sampleLight.color, clearcoatNormal,\n clearcoatFactor, clearcoatRoughness, sheenColor, sheenRoughness, anisotropyTangent, anisotropyStrength);\n color += calculateDiffuseTransmissionLight(pbrInfo, sampleLight.color,\n diffuseTransmissionColor, diffuseTransmission, multiscatterColor, thickness);\n }\n }\n\n }\n#else\n for (var sampleIndex: i32 = 0; sampleIndex < areaLighting.sampleCount; sampleIndex++) {\n let sampleLight = areaLighting_getSample(areaIndex, sampleIndex, fragmentInputs.pbr_vPosition);\n if (dot(sampleLight.color, sampleLight.color) > 0.0) {\n PBRInfo_setPointLight(&pbrInfo, sampleLight);\n color += calculateMaterialLightColor(pbrInfo, sampleLight.color, clearcoatNormal,\n clearcoatFactor, clearcoatRoughness, sheenColor, sheenRoughness, anisotropyTangent, anisotropyStrength);\n color += calculateDiffuseTransmissionLight(pbrInfo, sampleLight.color,\n diffuseTransmissionColor, diffuseTransmission, multiscatterColor, thickness);\n }\n }\n\n#endif\n }\n #endif\n\n // Calculate lighting contribution from image based lighting source (IBL)\n #ifdef USE_IBL\n if (pbrMaterial.IBLenabled != 0) {\n color += getIBLContribution(\n pbrInfo,\n n,\n getAnisotropicReflection(pbrInfo, anisotropyTangent, anisotropyStrength)\n );\n color += calculateClearcoatIBLContribution(\n pbrInfo,\n clearcoatNormal,\n -normalize(reflect(v, clearcoatNormal)),\n clearcoatFactor,\n clearcoatRoughness\n );\n color += calculateDiffuseTransmissionIBL(\n pbrInfo,\n diffuseTransmissionColor,\n diffuseTransmission,\n multiscatterColor,\n thickness\n );\n color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;\n }\n #endif\n\n#ifdef HAS_MATERIAL_SCATTER\n color += (baseColor.rgb * (1.0 - metallic) * (1.0 - originalTransmission) +\n multiscatterColor * scatterReflection) * baseLayerEnergy * lightmapIrradiance / M_PI;\n#else\n color += baseColor.rgb * (1.0 - metallic) * (1.0 - transmission) *\n (1.0 - diffuseTransmission) * baseLayerEnergy * lightmapIrradiance / M_PI;\n#endif\n\n // Apply optional PBR terms for additional (optional) shading\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n\n var emissive = pbrMaterial.emissiveFactor;\n #ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled != 0u) {\n emissive *= SRGBtoLINEAR(\n textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)\n ).rgb;\n }\n #endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n if (transmission > 0.0) {\n #ifdef USE_TRANSMISSION_FRAMEBUFFER\n let dielectricFresnel = getDielectricF0(pbrMaterial.ior);\n let transmissionFresnel = dielectricFresnel +\n (1.0 - dielectricFresnel) * pow(1.0 - NdotV, 5.0);\n let transmittedColor = getTransmittedSceneColor(\n fragmentInputs.pbr_vPosition,\n n,\n v,\n thickness,\n perceptualRoughness\n );\n color += transmittedColor * getVolumeAttenuation(thickness) *\n transmission * (1.0 - transmissionFresnel);\n #else\n color = mix(color, color * getVolumeAttenuation(thickness), transmission);\n #endif\n }\n\n // This section uses mix to override final color for reference app visualization\n // of various parameters in the lighting equation.\n #ifdef PBR_DEBUG\n // TODO: Figure out how to debug multiple lights\n\n // color = mix(color, F, pbr_scaleFGDSpec.x);\n // color = mix(color, vec3(G), pbr_scaleFGDSpec.y);\n // color = mix(color, vec3(D), pbr_scaleFGDSpec.z);\n // color = mix(color, specContrib, pbr_scaleFGDSpec.w);\n\n // color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n #endif\n }\n\n #ifdef USE_TRANSMISSION_FRAMEBUFFER\n let alpha = clamp(baseColor.a, 0.0, 1.0);\n #else\n let alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);\n #endif\n return vec4<f32>(applySceneColorManagement(color), alpha);\n}\n\nfn pbr_filterColor(vertexColor: vec4<f32>) -> vec4<f32> {\n return pbr_filterColorWithSpotShadows(vertexColor, vec4f(1.0));\n}\n";
3
3
  //# sourceMappingURL=pbr-material-wgsl.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pbr-material-wgsl.d.ts","sourceRoot":"","sources":["../../../../src/modules/lighting/pbr-material/pbr-material-wgsl.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,mBAAmB,kuGA4I/B,CAAC;AAEF,eAAO,MAAM,MAAM,4zlEAg2DlB,CAAC"}
1
+ {"version":3,"file":"pbr-material-wgsl.d.ts","sourceRoot":"","sources":["../../../../src/modules/lighting/pbr-material/pbr-material-wgsl.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,mBAAmB,kuGA4I/B,CAAC;AAEF,eAAO,MAAM,MAAM,8zlEAg2DlB,CAAC"}
@@ -1464,7 +1464,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
1464
1464
 
1465
1465
  for (var i = 0; i < lighting.directionalLightCount; i++) {
1466
1466
  if (i < lighting.directionalLightCount) {
1467
- PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
1467
+ PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
1468
1468
  color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
1469
1469
  }
1470
1470
  }
@@ -1824,7 +1824,7 @@ fn pbr_filterColorWithSpotShadows(vertexColor: vec4<f32>, spotVisibility: vec4f)
1824
1824
  // Apply directional light
1825
1825
  for (var i = 0; i < lighting.directionalLightCount; i++) {
1826
1826
  if (i < lighting.directionalLightCount) {
1827
- PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
1827
+ PBRInfo_setDirectionalLight(&pbrInfo, -lighting_getDirectionalLight(i).direction);
1828
1828
  color += calculateMaterialLightColor(
1829
1829
  pbrInfo,
1830
1830
  lighting_getDirectionalLight(i).color,