@luma.gl/shadertools 9.2.6 → 9.3.0-alpha.11

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 (182) hide show
  1. package/dist/dist.dev.js +5388 -6438
  2. package/dist/dist.min.js +2264 -322
  3. package/dist/index.cjs +3601 -566
  4. package/dist/index.cjs.map +4 -4
  5. package/dist/index.d.ts +12 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +5 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/lib/glsl-utils/shader-utils.js +4 -4
  10. package/dist/lib/glsl-utils/shader-utils.js.map +1 -1
  11. package/dist/lib/preprocessor/preprocessor.d.ts.map +1 -1
  12. package/dist/lib/preprocessor/preprocessor.js +35 -8
  13. package/dist/lib/preprocessor/preprocessor.js.map +1 -1
  14. package/dist/lib/shader-assembler.d.ts +10 -0
  15. package/dist/lib/shader-assembler.d.ts.map +1 -1
  16. package/dist/lib/shader-assembler.js +20 -3
  17. package/dist/lib/shader-assembler.js.map +1 -1
  18. package/dist/lib/shader-assembly/assemble-shaders.d.ts +23 -2
  19. package/dist/lib/shader-assembly/assemble-shaders.d.ts.map +1 -1
  20. package/dist/lib/shader-assembly/assemble-shaders.js +265 -12
  21. package/dist/lib/shader-assembly/assemble-shaders.js.map +1 -1
  22. package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts +37 -0
  23. package/dist/lib/shader-assembly/wgsl-binding-debug.d.ts.map +1 -0
  24. package/dist/lib/shader-assembly/wgsl-binding-debug.js +144 -0
  25. package/dist/lib/shader-assembly/wgsl-binding-debug.js.map +1 -0
  26. package/dist/lib/shader-assembly/wgsl-binding-scan.d.ts +19 -0
  27. package/dist/lib/shader-assembly/wgsl-binding-scan.d.ts.map +1 -0
  28. package/dist/lib/shader-assembly/wgsl-binding-scan.js +151 -0
  29. package/dist/lib/shader-assembly/wgsl-binding-scan.js.map +1 -0
  30. package/dist/lib/shader-generator/glsl/generate-glsl.js +7 -4
  31. package/dist/lib/shader-generator/glsl/generate-glsl.js.map +1 -1
  32. package/dist/lib/shader-generator/wgsl/generate-wgsl.d.ts.map +1 -1
  33. package/dist/lib/shader-generator/wgsl/generate-wgsl.js +3 -0
  34. package/dist/lib/shader-generator/wgsl/generate-wgsl.js.map +1 -1
  35. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts +91 -0
  36. package/dist/lib/shader-module/shader-module-uniform-layout.d.ts.map +1 -0
  37. package/dist/lib/shader-module/shader-module-uniform-layout.js +253 -0
  38. package/dist/lib/shader-module/shader-module-uniform-layout.js.map +1 -0
  39. package/dist/lib/shader-module/shader-module.d.ts +12 -6
  40. package/dist/lib/shader-module/shader-module.d.ts.map +1 -1
  41. package/dist/lib/shader-module/shader-module.js.map +1 -1
  42. package/dist/lib/utils/assert.d.ts.map +1 -1
  43. package/dist/lib/utils/assert.js +3 -1
  44. package/dist/lib/utils/assert.js.map +1 -1
  45. package/dist/lib/utils/uniform-types.d.ts +11 -7
  46. package/dist/lib/utils/uniform-types.d.ts.map +1 -1
  47. package/dist/modules/engine/picking/picking.d.ts +5 -2
  48. package/dist/modules/engine/picking/picking.d.ts.map +1 -1
  49. package/dist/modules/engine/picking/picking.js +5 -2
  50. package/dist/modules/engine/picking/picking.js.map +1 -1
  51. package/dist/modules/engine/project/project.d.ts +1 -1
  52. package/dist/modules/engine/project/project.js +1 -1
  53. package/dist/modules/engine/skin/skin.d.ts +30 -0
  54. package/dist/modules/engine/skin/skin.d.ts.map +1 -0
  55. package/dist/modules/engine/skin/skin.js +86 -0
  56. package/dist/modules/engine/skin/skin.js.map +1 -0
  57. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts +1 -0
  58. package/dist/modules/lighting/gouraud-material/gouraud-material.d.ts.map +1 -1
  59. package/dist/modules/lighting/gouraud-material/gouraud-material.js +3 -0
  60. package/dist/modules/lighting/gouraud-material/gouraud-material.js.map +1 -1
  61. package/dist/modules/lighting/ibl/ibl.d.ts +26 -0
  62. package/dist/modules/lighting/ibl/ibl.d.ts.map +1 -0
  63. package/dist/modules/lighting/ibl/ibl.js +33 -0
  64. package/dist/modules/lighting/ibl/ibl.js.map +1 -0
  65. package/dist/modules/lighting/lambert-material/lambert-material.d.ts +10 -0
  66. package/dist/modules/lighting/lambert-material/lambert-material.d.ts.map +1 -0
  67. package/dist/modules/lighting/lambert-material/lambert-material.js +33 -0
  68. package/dist/modules/lighting/lambert-material/lambert-material.js.map +1 -0
  69. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts +3 -0
  70. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.d.ts.map +1 -0
  71. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js +60 -0
  72. package/dist/modules/lighting/lambert-material/lambert-shaders-glsl.js.map +1 -0
  73. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts +2 -0
  74. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.d.ts.map +1 -0
  75. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js +73 -0
  76. package/dist/modules/lighting/lambert-material/lambert-shaders-wgsl.js.map +1 -0
  77. package/dist/modules/lighting/lights/lighting-glsl.d.ts +1 -1
  78. package/dist/modules/lighting/lights/lighting-glsl.d.ts.map +1 -1
  79. package/dist/modules/lighting/lights/lighting-glsl.js +44 -38
  80. package/dist/modules/lighting/lights/lighting-glsl.js.map +1 -1
  81. package/dist/modules/lighting/lights/lighting-wgsl.d.ts +1 -1
  82. package/dist/modules/lighting/lights/lighting-wgsl.d.ts.map +1 -1
  83. package/dist/modules/lighting/lights/lighting-wgsl.js +46 -18
  84. package/dist/modules/lighting/lights/lighting-wgsl.js.map +1 -1
  85. package/dist/modules/lighting/lights/lighting.d.ts +104 -62
  86. package/dist/modules/lighting/lights/lighting.d.ts.map +1 -1
  87. package/dist/modules/lighting/lights/lighting.js +107 -68
  88. package/dist/modules/lighting/lights/lighting.js.map +1 -1
  89. package/dist/modules/lighting/no-material/dirlight.d.ts +8 -3
  90. package/dist/modules/lighting/no-material/dirlight.d.ts.map +1 -1
  91. package/dist/modules/lighting/no-material/dirlight.js +5 -3
  92. package/dist/modules/lighting/no-material/dirlight.js.map +1 -1
  93. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts +2 -2
  94. package/dist/modules/lighting/pbr-material/pbr-material-glsl.d.ts.map +1 -1
  95. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js +694 -38
  96. package/dist/modules/lighting/pbr-material/pbr-material-glsl.js.map +1 -1
  97. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts +2 -2
  98. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.d.ts.map +1 -1
  99. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js +956 -109
  100. package/dist/modules/lighting/pbr-material/pbr-material-wgsl.js.map +1 -1
  101. package/dist/modules/lighting/pbr-material/pbr-material.d.ts +242 -43
  102. package/dist/modules/lighting/pbr-material/pbr-material.d.ts.map +1 -1
  103. package/dist/modules/lighting/pbr-material/pbr-material.js +178 -2
  104. package/dist/modules/lighting/pbr-material/pbr-material.js.map +1 -1
  105. package/dist/modules/lighting/pbr-material/pbr-projection.d.ts.map +1 -1
  106. package/dist/modules/lighting/pbr-material/pbr-projection.js +14 -2
  107. package/dist/modules/lighting/pbr-material/pbr-projection.js.map +1 -1
  108. package/dist/modules/lighting/pbr-material/pbr-scene.d.ts +40 -0
  109. package/dist/modules/lighting/pbr-material/pbr-scene.d.ts.map +1 -0
  110. package/dist/modules/lighting/pbr-material/pbr-scene.js +67 -0
  111. package/dist/modules/lighting/pbr-material/pbr-scene.js.map +1 -0
  112. package/dist/modules/lighting/phong-material/phong-material.d.ts +1 -0
  113. package/dist/modules/lighting/phong-material/phong-material.d.ts.map +1 -1
  114. package/dist/modules/lighting/phong-material/phong-material.js +4 -0
  115. package/dist/modules/lighting/phong-material/phong-material.js.map +1 -1
  116. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts +2 -2
  117. package/dist/modules/lighting/phong-material/phong-shaders-glsl.d.ts.map +1 -1
  118. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js +17 -6
  119. package/dist/modules/lighting/phong-material/phong-shaders-glsl.js.map +1 -1
  120. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts +1 -40
  121. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.d.ts.map +1 -1
  122. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js +71 -76
  123. package/dist/modules/lighting/phong-material/phong-shaders-wgsl.js.map +1 -1
  124. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts +1 -1
  125. package/dist/modules/math/fp64/fp64-arithmetic-glsl.d.ts.map +1 -1
  126. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js +42 -11
  127. package/dist/modules/math/fp64/fp64-arithmetic-glsl.js.map +1 -1
  128. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts +2 -0
  129. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.d.ts.map +1 -0
  130. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js +212 -0
  131. package/dist/modules/math/fp64/fp64-arithmetic-wgsl.js.map +1 -0
  132. package/dist/modules/math/fp64/fp64.d.ts +1 -0
  133. package/dist/modules/math/fp64/fp64.d.ts.map +1 -1
  134. package/dist/modules/math/fp64/fp64.js +8 -2
  135. package/dist/modules/math/fp64/fp64.js.map +1 -1
  136. package/dist/modules/math/random/random.d.ts +1 -1
  137. package/dist/modules/math/random/random.d.ts.map +1 -1
  138. package/dist/modules/math/random/random.js +2 -3
  139. package/dist/modules/math/random/random.js.map +1 -1
  140. package/package.json +4 -5
  141. package/src/index.ts +37 -6
  142. package/src/lib/glsl-utils/shader-utils.ts +4 -4
  143. package/src/lib/preprocessor/preprocessor.ts +44 -8
  144. package/src/lib/shader-assembler.ts +25 -3
  145. package/src/lib/shader-assembly/assemble-shaders.ts +506 -13
  146. package/src/lib/shader-assembly/wgsl-binding-debug.ts +227 -0
  147. package/src/lib/shader-assembly/wgsl-binding-scan.ts +228 -0
  148. package/src/lib/shader-generator/glsl/generate-glsl.ts +11 -5
  149. package/src/lib/shader-generator/wgsl/generate-wgsl.ts +6 -0
  150. package/src/lib/shader-module/shader-module-uniform-layout.ts +420 -0
  151. package/src/lib/shader-module/shader-module.ts +17 -7
  152. package/src/lib/utils/assert.ts +3 -1
  153. package/src/lib/utils/uniform-types.ts +24 -9
  154. package/src/modules/engine/picking/picking.ts +5 -2
  155. package/src/modules/engine/project/project.ts +1 -1
  156. package/src/modules/engine/skin/skin.ts +114 -0
  157. package/src/modules/lighting/gouraud-material/gouraud-material.ts +4 -0
  158. package/src/modules/lighting/ibl/ibl.ts +44 -0
  159. package/src/modules/lighting/lambert-material/lambert-material.ts +42 -0
  160. package/src/modules/lighting/lambert-material/lambert-shaders-glsl.ts +61 -0
  161. package/src/modules/lighting/lambert-material/lambert-shaders-wgsl.ts +73 -0
  162. package/src/modules/lighting/lights/lighting-glsl.ts +44 -38
  163. package/src/modules/lighting/lights/lighting-wgsl.ts +46 -18
  164. package/src/modules/lighting/lights/lighting.ts +198 -99
  165. package/src/modules/lighting/no-material/dirlight.ts +5 -3
  166. package/src/modules/lighting/pbr-material/pbr-material-glsl.ts +694 -38
  167. package/src/modules/lighting/pbr-material/pbr-material-wgsl.ts +956 -109
  168. package/src/modules/lighting/pbr-material/pbr-material.ts +294 -7
  169. package/src/modules/lighting/pbr-material/pbr-projection.ts +15 -2
  170. package/src/modules/lighting/pbr-material/pbr-scene.ts +91 -0
  171. package/src/modules/lighting/phong-material/phong-material.ts +5 -0
  172. package/src/modules/lighting/phong-material/phong-shaders-glsl.ts +17 -6
  173. package/src/modules/lighting/phong-material/phong-shaders-wgsl.ts +71 -77
  174. package/src/modules/math/fp64/fp64-arithmetic-glsl.ts +42 -11
  175. package/src/modules/math/fp64/fp64-arithmetic-wgsl.ts +212 -0
  176. package/src/modules/math/fp64/fp64.ts +9 -3
  177. package/src/modules/math/random/random.ts +2 -3
  178. package/dist/lib/wgsl/get-shader-layout-wgsl.d.ts +0 -8
  179. package/dist/lib/wgsl/get-shader-layout-wgsl.d.ts.map +0 -1
  180. package/dist/lib/wgsl/get-shader-layout-wgsl.js +0 -95
  181. package/dist/lib/wgsl/get-shader-layout-wgsl.js.map +0 -1
  182. package/src/lib/wgsl/get-shader-layout-wgsl.ts +0 -105
@@ -37,6 +37,42 @@ uniform pbrMaterialUniforms {
37
37
 
38
38
  bool alphaCutoffEnabled;
39
39
  float alphaCutoff; // #ifdef ALPHA_CUTOFF
40
+
41
+ vec3 specularColorFactor;
42
+ float specularIntensityFactor;
43
+ bool specularColorMapEnabled;
44
+ bool specularIntensityMapEnabled;
45
+
46
+ float ior;
47
+
48
+ float transmissionFactor;
49
+ bool transmissionMapEnabled;
50
+
51
+ float thicknessFactor;
52
+ float attenuationDistance;
53
+ vec3 attenuationColor;
54
+
55
+ float clearcoatFactor;
56
+ float clearcoatRoughnessFactor;
57
+ bool clearcoatMapEnabled;
58
+ bool clearcoatRoughnessMapEnabled;
59
+
60
+ vec3 sheenColorFactor;
61
+ float sheenRoughnessFactor;
62
+ bool sheenColorMapEnabled;
63
+ bool sheenRoughnessMapEnabled;
64
+
65
+ float iridescenceFactor;
66
+ float iridescenceIor;
67
+ vec2 iridescenceThicknessRange;
68
+ bool iridescenceMapEnabled;
69
+
70
+ float anisotropyStrength;
71
+ float anisotropyRotation;
72
+ vec2 anisotropyDirection;
73
+ bool anisotropyMapEnabled;
74
+
75
+ float emissiveStrength;
40
76
 
41
77
  // IBL
42
78
  bool IBLenabled;
@@ -65,6 +101,42 @@ uniform sampler2D u_MetallicRoughnessSampler;
65
101
  #ifdef HAS_OCCLUSIONMAP
66
102
  uniform sampler2D u_OcclusionSampler;
67
103
  #endif
104
+ #ifdef HAS_SPECULARCOLORMAP
105
+ uniform sampler2D u_SpecularColorSampler;
106
+ #endif
107
+ #ifdef HAS_SPECULARINTENSITYMAP
108
+ uniform sampler2D u_SpecularIntensitySampler;
109
+ #endif
110
+ #ifdef HAS_TRANSMISSIONMAP
111
+ uniform sampler2D u_TransmissionSampler;
112
+ #endif
113
+ #ifdef HAS_THICKNESSMAP
114
+ uniform sampler2D u_ThicknessSampler;
115
+ #endif
116
+ #ifdef HAS_CLEARCOATMAP
117
+ uniform sampler2D u_ClearcoatSampler;
118
+ #endif
119
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
120
+ uniform sampler2D u_ClearcoatRoughnessSampler;
121
+ #endif
122
+ #ifdef HAS_CLEARCOATNORMALMAP
123
+ uniform sampler2D u_ClearcoatNormalSampler;
124
+ #endif
125
+ #ifdef HAS_SHEENCOLORMAP
126
+ uniform sampler2D u_SheenColorSampler;
127
+ #endif
128
+ #ifdef HAS_SHEENROUGHNESSMAP
129
+ uniform sampler2D u_SheenRoughnessSampler;
130
+ #endif
131
+ #ifdef HAS_IRIDESCENCEMAP
132
+ uniform sampler2D u_IridescenceSampler;
133
+ #endif
134
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
135
+ uniform sampler2D u_IridescenceThicknessSampler;
136
+ #endif
137
+ #ifdef HAS_ANISOTROPYMAP
138
+ uniform sampler2D u_AnisotropySampler;
139
+ #endif
68
140
  #ifdef USE_IBL
69
141
  uniform samplerCube u_DiffuseEnvSampler;
70
142
  uniform samplerCube u_SpecularEnvSampler;
@@ -76,58 +148,106 @@ uniform sampler2D u_brdfLUT;
76
148
  export const source = /* wgsl */ `\
77
149
  struct PBRFragmentInputs {
78
150
  pbr_vPosition: vec3f,
79
- pbr_vUV: vec2f,
80
- pbr_vTBN: mat3f,
151
+ pbr_vUV0: vec2f,
152
+ pbr_vUV1: vec2f,
153
+ pbr_vTBN: mat3x3f,
81
154
  pbr_vNormal: vec3f
82
155
  };
83
156
 
84
- var fragmentInputs: PBRFragmentInputs;
157
+ var<private> fragmentInputs: PBRFragmentInputs;
85
158
 
86
- fn pbr_setPositionNormalTangentUV(position: vec4f, normal: vec4f, tangent: vec4f, uv: vec2f)
159
+ fn pbr_setPositionNormalTangentUV(
160
+ position: vec4f,
161
+ normal: vec4f,
162
+ tangent: vec4f,
163
+ uv0: vec2f,
164
+ uv1: vec2f
165
+ )
87
166
  {
88
167
  var pos: vec4f = pbrProjection.modelMatrix * position;
89
- pbr_vPosition = vec3(pos.xyz) / pos.w;
168
+ fragmentInputs.pbr_vPosition = pos.xyz / pos.w;
169
+ fragmentInputs.pbr_vNormal = vec3f(0.0, 0.0, 1.0);
170
+ fragmentInputs.pbr_vTBN = mat3x3f(
171
+ vec3f(1.0, 0.0, 0.0),
172
+ vec3f(0.0, 1.0, 0.0),
173
+ vec3f(0.0, 0.0, 1.0)
174
+ );
175
+ fragmentInputs.pbr_vUV0 = vec2f(0.0, 0.0);
176
+ fragmentInputs.pbr_vUV1 = uv1;
90
177
 
91
178
  #ifdef HAS_NORMALS
179
+ let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);
180
+ fragmentInputs.pbr_vNormal = normalW;
92
181
  #ifdef HAS_TANGENTS
93
- let normalW: vec3f = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));
94
- let tangentW: vec3f = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));
182
+ let tangentW: vec3f = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);
95
183
  let bitangentW: vec3f = cross(normalW, tangentW) * tangent.w;
96
- fragmentInputs,pbr_vTBN = mat3(tangentW, bitangentW, normalW);
97
- #else // HAS_TANGENTS != 1
98
- fragmentInputs.pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));
184
+ fragmentInputs.pbr_vTBN = mat3x3f(tangentW, bitangentW, normalW);
99
185
  #endif
100
186
  #endif
101
187
 
102
188
  #ifdef HAS_UV
103
- pbr_vUV = uv;
104
- #else
105
- pbr_vUV = vec2(0.,0.);
189
+ fragmentInputs.pbr_vUV0 = uv0;
106
190
  #endif
107
191
  }
108
192
 
109
193
  struct pbrMaterialUniforms {
110
194
  // Material is unlit
111
- unlit: uint32,
195
+ unlit: u32,
112
196
 
113
197
  // Base color map
114
- baseColorMapEnabled: uint32,
198
+ baseColorMapEnabled: u32,
115
199
  baseColorFactor: vec4f,
116
200
 
117
- normalMapEnabled : uint32,
201
+ normalMapEnabled : u32,
118
202
  normalScale: f32, // #ifdef HAS_NORMALMAP
119
203
 
120
- emissiveMapEnabled: uint32,
204
+ emissiveMapEnabled: u32,
121
205
  emissiveFactor: vec3f, // #ifdef HAS_EMISSIVEMAP
122
206
 
123
207
  metallicRoughnessValues: vec2f,
124
- metallicRoughnessMapEnabled: uint32,
208
+ metallicRoughnessMapEnabled: u32,
125
209
 
126
210
  occlusionMapEnabled: i32,
127
211
  occlusionStrength: f32, // #ifdef HAS_OCCLUSIONMAP
128
212
 
129
213
  alphaCutoffEnabled: i32,
130
214
  alphaCutoff: f32, // #ifdef ALPHA_CUTOFF
215
+
216
+ specularColorFactor: vec3f,
217
+ specularIntensityFactor: f32,
218
+ specularColorMapEnabled: i32,
219
+ specularIntensityMapEnabled: i32,
220
+
221
+ ior: f32,
222
+
223
+ transmissionFactor: f32,
224
+ transmissionMapEnabled: i32,
225
+
226
+ thicknessFactor: f32,
227
+ attenuationDistance: f32,
228
+ attenuationColor: vec3f,
229
+
230
+ clearcoatFactor: f32,
231
+ clearcoatRoughnessFactor: f32,
232
+ clearcoatMapEnabled: i32,
233
+ clearcoatRoughnessMapEnabled: i32,
234
+
235
+ sheenColorFactor: vec3f,
236
+ sheenRoughnessFactor: f32,
237
+ sheenColorMapEnabled: i32,
238
+ sheenRoughnessMapEnabled: i32,
239
+
240
+ iridescenceFactor: f32,
241
+ iridescenceIor: f32,
242
+ iridescenceThicknessRange: vec2f,
243
+ iridescenceMapEnabled: i32,
244
+
245
+ anisotropyStrength: f32,
246
+ anisotropyRotation: f32,
247
+ anisotropyDirection: vec2f,
248
+ anisotropyMapEnabled: i32,
249
+
250
+ emissiveStrength: f32,
131
251
 
132
252
  // IBL
133
253
  IBLenabled: i32,
@@ -136,34 +256,116 @@ struct pbrMaterialUniforms {
136
256
  // debugging flags used for shader output of intermediate PBR variables
137
257
  // #ifdef PBR_DEBUG
138
258
  scaleDiffBaseMR: vec4f,
139
- scaleFGDSpec: vec4f
259
+ scaleFGDSpec: vec4f,
140
260
  // #endif
141
- }
142
-
143
- @binding(2) @group(0) var<uniform> material : pbrMaterialUniforms;
261
+
262
+ baseColorUVSet: i32,
263
+ baseColorUVTransform: mat3x3f,
264
+ metallicRoughnessUVSet: i32,
265
+ metallicRoughnessUVTransform: mat3x3f,
266
+ normalUVSet: i32,
267
+ normalUVTransform: mat3x3f,
268
+ occlusionUVSet: i32,
269
+ occlusionUVTransform: mat3x3f,
270
+ emissiveUVSet: i32,
271
+ emissiveUVTransform: mat3x3f,
272
+ specularColorUVSet: i32,
273
+ specularColorUVTransform: mat3x3f,
274
+ specularIntensityUVSet: i32,
275
+ specularIntensityUVTransform: mat3x3f,
276
+ transmissionUVSet: i32,
277
+ transmissionUVTransform: mat3x3f,
278
+ thicknessUVSet: i32,
279
+ thicknessUVTransform: mat3x3f,
280
+ clearcoatUVSet: i32,
281
+ clearcoatUVTransform: mat3x3f,
282
+ clearcoatRoughnessUVSet: i32,
283
+ clearcoatRoughnessUVTransform: mat3x3f,
284
+ clearcoatNormalUVSet: i32,
285
+ clearcoatNormalUVTransform: mat3x3f,
286
+ sheenColorUVSet: i32,
287
+ sheenColorUVTransform: mat3x3f,
288
+ sheenRoughnessUVSet: i32,
289
+ sheenRoughnessUVTransform: mat3x3f,
290
+ iridescenceUVSet: i32,
291
+ iridescenceUVTransform: mat3x3f,
292
+ iridescenceThicknessUVSet: i32,
293
+ iridescenceThicknessUVTransform: mat3x3f,
294
+ anisotropyUVSet: i32,
295
+ anisotropyUVTransform: mat3x3f,
296
+ }
297
+
298
+ @group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;
144
299
 
145
300
  // Samplers
146
301
  #ifdef HAS_BASECOLORMAP
147
- uniform sampler2D pbr_baseColorSampler;
302
+ @group(3) @binding(auto) var pbr_baseColorSampler: texture_2d<f32>;
303
+ @group(3) @binding(auto) var pbr_baseColorSamplerSampler: sampler;
148
304
  #endif
149
305
  #ifdef HAS_NORMALMAP
150
- uniform sampler2D pbr_normalSampler;
306
+ @group(3) @binding(auto) var pbr_normalSampler: texture_2d<f32>;
307
+ @group(3) @binding(auto) var pbr_normalSamplerSampler: sampler;
151
308
  #endif
152
309
  #ifdef HAS_EMISSIVEMAP
153
- uniform sampler2D pbr_emissiveSampler;
310
+ @group(3) @binding(auto) var pbr_emissiveSampler: texture_2d<f32>;
311
+ @group(3) @binding(auto) var pbr_emissiveSamplerSampler: sampler;
154
312
  #endif
155
313
  #ifdef HAS_METALROUGHNESSMAP
156
- uniform sampler2D pbr_metallicRoughnessSampler;
314
+ @group(3) @binding(auto) var pbr_metallicRoughnessSampler: texture_2d<f32>;
315
+ @group(3) @binding(auto) var pbr_metallicRoughnessSamplerSampler: sampler;
157
316
  #endif
158
317
  #ifdef HAS_OCCLUSIONMAP
159
- uniform sampler2D pbr_occlusionSampler;
318
+ @group(3) @binding(auto) var pbr_occlusionSampler: texture_2d<f32>;
319
+ @group(3) @binding(auto) var pbr_occlusionSamplerSampler: sampler;
160
320
  #endif
161
- #ifdef USE_IBL
162
- uniform samplerCube pbr_diffuseEnvSampler;
163
- uniform samplerCube pbr_specularEnvSampler;
164
- uniform sampler2D pbr_brdfLUT;
321
+ #ifdef HAS_SPECULARCOLORMAP
322
+ @group(3) @binding(auto) var pbr_specularColorSampler: texture_2d<f32>;
323
+ @group(3) @binding(auto) var pbr_specularColorSamplerSampler: sampler;
324
+ #endif
325
+ #ifdef HAS_SPECULARINTENSITYMAP
326
+ @group(3) @binding(auto) var pbr_specularIntensitySampler: texture_2d<f32>;
327
+ @group(3) @binding(auto) var pbr_specularIntensitySamplerSampler: sampler;
328
+ #endif
329
+ #ifdef HAS_TRANSMISSIONMAP
330
+ @group(3) @binding(auto) var pbr_transmissionSampler: texture_2d<f32>;
331
+ @group(3) @binding(auto) var pbr_transmissionSamplerSampler: sampler;
332
+ #endif
333
+ #ifdef HAS_THICKNESSMAP
334
+ @group(3) @binding(auto) var pbr_thicknessSampler: texture_2d<f32>;
335
+ @group(3) @binding(auto) var pbr_thicknessSamplerSampler: sampler;
336
+ #endif
337
+ #ifdef HAS_CLEARCOATMAP
338
+ @group(3) @binding(auto) var pbr_clearcoatSampler: texture_2d<f32>;
339
+ @group(3) @binding(auto) var pbr_clearcoatSamplerSampler: sampler;
340
+ #endif
341
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
342
+ @group(3) @binding(auto) var pbr_clearcoatRoughnessSampler: texture_2d<f32>;
343
+ @group(3) @binding(auto) var pbr_clearcoatRoughnessSamplerSampler: sampler;
344
+ #endif
345
+ #ifdef HAS_CLEARCOATNORMALMAP
346
+ @group(3) @binding(auto) var pbr_clearcoatNormalSampler: texture_2d<f32>;
347
+ @group(3) @binding(auto) var pbr_clearcoatNormalSamplerSampler: sampler;
348
+ #endif
349
+ #ifdef HAS_SHEENCOLORMAP
350
+ @group(3) @binding(auto) var pbr_sheenColorSampler: texture_2d<f32>;
351
+ @group(3) @binding(auto) var pbr_sheenColorSamplerSampler: sampler;
352
+ #endif
353
+ #ifdef HAS_SHEENROUGHNESSMAP
354
+ @group(3) @binding(auto) var pbr_sheenRoughnessSampler: texture_2d<f32>;
355
+ @group(3) @binding(auto) var pbr_sheenRoughnessSamplerSampler: sampler;
356
+ #endif
357
+ #ifdef HAS_IRIDESCENCEMAP
358
+ @group(3) @binding(auto) var pbr_iridescenceSampler: texture_2d<f32>;
359
+ @group(3) @binding(auto) var pbr_iridescenceSamplerSampler: sampler;
360
+ #endif
361
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
362
+ @group(3) @binding(auto) var pbr_iridescenceThicknessSampler: texture_2d<f32>;
363
+ @group(3) @binding(auto) var pbr_iridescenceThicknessSamplerSampler: sampler;
364
+ #endif
365
+ #ifdef HAS_ANISOTROPYMAP
366
+ @group(3) @binding(auto) var pbr_anisotropySampler: texture_2d<f32>;
367
+ @group(3) @binding(auto) var pbr_anisotropySamplerSampler: sampler;
165
368
  #endif
166
-
167
369
  // Encapsulate the various inputs used by the various functions in the shading equation
168
370
  // We store values in this struct to simplify the integration of alternative implementations
169
371
  // of the shading terms, outlined in the Readme.MD Appendix.
@@ -189,80 +391,142 @@ const c_MinRoughness = 0.04;
189
391
 
190
392
  fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
191
393
  {
394
+ var linOut: vec3f = srgbIn.xyz;
192
395
  #ifdef MANUAL_SRGB
396
+ let bLess: vec3f = step(vec3f(0.04045), srgbIn.xyz);
397
+ linOut = mix(
398
+ srgbIn.xyz / vec3f(12.92),
399
+ pow((srgbIn.xyz + vec3f(0.055)) / vec3f(1.055), vec3f(2.4)),
400
+ bLess
401
+ );
193
402
  #ifdef SRGB_FAST_APPROXIMATION
194
- var linOut: vec3f = pow(srgbIn.xyz,vec3(2.2));
195
- #else // SRGB_FAST_APPROXIMATION
196
- var bLess: vec3f = step(vec3(0.04045),srgbIn.xyz);
197
- var linOut: vec3f = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
198
- #endif //SRGB_FAST_APPROXIMATION
199
- return vec4f(linOut,srgbIn.w);;
200
- #else //MANUAL_SRGB
201
- return srgbIn;
202
- #endif //MANUAL_SRGB
403
+ linOut = pow(srgbIn.xyz, vec3f(2.2));
404
+ #endif
405
+ #endif
406
+ return vec4f(linOut, srgbIn.w);
203
407
  }
204
408
 
205
- // Find the normal for this fragment, pulling either from a predefined normal map
206
- // or from the interpolated mesh normal and tangent attributes.
207
- fn getNormal() -> vec3f
409
+ fn getMaterialUV(uvSet: i32, uvTransform: mat3x3f) -> vec2f
410
+ {
411
+ var baseUV = fragmentInputs.pbr_vUV0;
412
+ if (uvSet == 1) {
413
+ baseUV = fragmentInputs.pbr_vUV1;
414
+ }
415
+ return (uvTransform * vec3f(baseUV, 1.0)).xy;
416
+ }
417
+
418
+ // Build the tangent basis from interpolated attributes or screen-space derivatives.
419
+ fn getTBN(uv: vec2f) -> mat3x3f
208
420
  {
209
- // Retrieve the tangent space matrix
210
- #ifndef HAS_TANGENTS
211
- var pos_dx: vec3f = dFdx(pbr_vPosition);
212
- var pos_dy: vec3f = dFdy(pbr_vPosition);
213
- var tex_dx: vec3f = dFdx(vec3(pbr_vUV, 0.0));
214
- var tex_dy: vec3f = dFdy(vec3(pbr_vUV, 0.0));
215
- var t: vec3f = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);
421
+ let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);
422
+ let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);
423
+ let tex_dx: vec3f = dpdx(vec3f(uv, 0.0));
424
+ let tex_dy: vec3f = dpdy(vec3f(uv, 0.0));
425
+ 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);
216
426
 
217
- #ifdef HAS_NORMALS
218
- var ng: vec3f = normalize(pbr_vNormal);
219
- #else
220
427
  var ng: vec3f = cross(pos_dx, pos_dy);
428
+ #ifdef HAS_NORMALS
429
+ ng = normalize(fragmentInputs.pbr_vNormal);
221
430
  #endif
222
-
223
431
  t = normalize(t - ng * dot(ng, t));
224
432
  var b: vec3f = normalize(cross(ng, t));
225
- var tbn: mat3f = mat3f(t, b, ng);
226
- #else // HAS_TANGENTS
227
- var tbn: mat3f = pbr_vTBN;
433
+ var tbn: mat3x3f = mat3x3f(t, b, ng);
434
+ #ifdef HAS_TANGENTS
435
+ tbn = fragmentInputs.pbr_vTBN;
228
436
  #endif
229
437
 
230
- #ifdef HAS_NORMALMAP
231
- vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
232
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
233
- #else
438
+ return tbn;
439
+ }
440
+
441
+ // Find the normal for this fragment, pulling either from a predefined normal map
442
+ // or from the interpolated mesh normal and tangent attributes.
443
+ fn getMappedNormal(
444
+ normalSampler: texture_2d<f32>,
445
+ normalSamplerBinding: sampler,
446
+ tbn: mat3x3f,
447
+ normalScale: f32,
448
+ uv: vec2f
449
+ ) -> vec3f
450
+ {
451
+ let n = textureSample(normalSampler, normalSamplerBinding, uv).rgb;
452
+ return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));
453
+ }
454
+
455
+ fn getNormal(tbn: mat3x3f, uv: vec2f) -> vec3f
456
+ {
234
457
  // The tbn matrix is linearly interpolated, so we need to re-normalize
235
- vec3 n = normalize(tbn[2].xyz);
458
+ var n: vec3f = normalize(tbn[2].xyz);
459
+ #ifdef HAS_NORMALMAP
460
+ n = getMappedNormal(
461
+ pbr_normalSampler,
462
+ pbr_normalSamplerSampler,
463
+ tbn,
464
+ pbrMaterial.normalScale,
465
+ uv
466
+ );
236
467
  #endif
237
468
 
238
469
  return n;
239
470
  }
240
471
 
472
+ fn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f, uv: vec2f) -> vec3f
473
+ {
474
+ #ifdef HAS_CLEARCOATNORMALMAP
475
+ return getMappedNormal(
476
+ pbr_clearcoatNormalSampler,
477
+ pbr_clearcoatNormalSamplerSampler,
478
+ tbn,
479
+ 1.0,
480
+ uv
481
+ );
482
+ #else
483
+ return baseNormal;
484
+ #endif
485
+ }
486
+
241
487
  // Calculation of the lighting contribution from an optional Image Based Light source.
242
488
  // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
243
489
  // See our README.md on Environment Maps [3] for additional discussion.
244
490
  #ifdef USE_IBL
245
- fn getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection) -> vec3f
491
+ fn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f
246
492
  {
247
- float mipCount = 9.0; // resolution of 512x512
248
- float lod = (pbrInfo.perceptualRoughness * mipCount);
493
+ let mipCount: f32 = 9.0; // resolution of 512x512
494
+ let lod: f32 = pbrInfo.perceptualRoughness * mipCount;
249
495
  // retrieve a scale and bias to F0. See [1], Figure 3
250
- vec3 brdf = SRGBtoLINEAR(texture(pbr_brdfLUT,
251
- vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb;
252
- vec3 diffuseLight = SRGBtoLINEAR(texture(pbr_diffuseEnvSampler, n)).rgb;
253
-
496
+ let brdf = SRGBtoLINEAR(
497
+ textureSampleLevel(
498
+ pbr_brdfLUT,
499
+ pbr_brdfLUTSampler,
500
+ vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness),
501
+ 0.0
502
+ )
503
+ ).rgb;
504
+ let diffuseLight =
505
+ SRGBtoLINEAR(
506
+ textureSampleLevel(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, n, 0.0)
507
+ ).rgb;
508
+ var specularLight = SRGBtoLINEAR(
509
+ textureSampleLevel(
510
+ pbr_specularEnvSampler,
511
+ pbr_specularEnvSamplerSampler,
512
+ reflection,
513
+ 0.0
514
+ )
515
+ ).rgb;
254
516
  #ifdef USE_TEX_LOD
255
- vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection, lod)).rgb;
256
- #else
257
- vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection)).rgb;
517
+ specularLight = SRGBtoLINEAR(
518
+ textureSampleLevel(
519
+ pbr_specularEnvSampler,
520
+ pbr_specularEnvSamplerSampler,
521
+ reflection,
522
+ lod
523
+ )
524
+ ).rgb;
258
525
  #endif
259
526
 
260
- vec3 diffuse = diffuseLight * pbrInfo.diffuseColor;
261
- vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y);
262
-
263
- // For presentation, this allows us to disable IBL terms
264
- diffuse *= pbrMaterial.scaleIBLAmbient.x;
265
- specular *= pbrMaterial.scaleIBLAmbient.y;
527
+ let diffuse = diffuseLight * pbrInfo.diffuseColor * pbrMaterial.scaleIBLAmbient.x;
528
+ let specular =
529
+ specularLight * (pbrInfo.specularColor * brdf.x + brdf.y) * pbrMaterial.scaleIBLAmbient.y;
266
530
 
267
531
  return diffuse + specular;
268
532
  }
@@ -272,7 +536,7 @@ fn getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection) -> vec3f
272
536
  // Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog
273
537
  // See also [1], Equation 1
274
538
  fn diffuse(pbrInfo: PBRInfo) -> vec3<f32> {
275
- return pbrInfo.diffuseColor / PI;
539
+ return pbrInfo.diffuseColor / M_PI;
276
540
  }
277
541
 
278
542
  // The following equation models the Fresnel reflectance term of the spec equation (aka F())
@@ -306,7 +570,173 @@ fn geometricOcclusion(pbrInfo: PBRInfo) -> f32 {
306
570
  fn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {
307
571
  let roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;
308
572
  let f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;
309
- return roughnessSq / (PI * f * f);
573
+ return roughnessSq / (M_PI * f * f);
574
+ }
575
+
576
+ fn maxComponent(value: vec3f) -> f32 {
577
+ return max(max(value.r, value.g), value.b);
578
+ }
579
+
580
+ fn getDielectricF0(ior: f32) -> f32 {
581
+ let clampedIor = max(ior, 1.0);
582
+ let ratio = (clampedIor - 1.0) / (clampedIor + 1.0);
583
+ return ratio * ratio;
584
+ }
585
+
586
+ fn normalizeDirection(direction: vec2f) -> vec2f {
587
+ let directionLength = length(direction);
588
+ if (directionLength > 0.0001) {
589
+ return direction / directionLength;
590
+ }
591
+
592
+ return vec2f(1.0, 0.0);
593
+ }
594
+
595
+ fn rotateDirection(direction: vec2f, rotation: f32) -> vec2f {
596
+ let s = sin(rotation);
597
+ let c = cos(rotation);
598
+ return vec2f(direction.x * c - direction.y * s, direction.x * s + direction.y * c);
599
+ }
600
+
601
+ fn getIridescenceTint(iridescence: f32, thickness: f32, NdotV: f32) -> vec3f {
602
+ if (iridescence <= 0.0) {
603
+ return vec3f(1.0);
604
+ }
605
+
606
+ let phase = 0.015 * thickness * pbrMaterial.iridescenceIor + (1.0 - NdotV) * 6.0;
607
+ let thinFilmTint =
608
+ 0.5 +
609
+ 0.5 *
610
+ cos(vec3f(phase, phase + 2.0943951, phase + 4.1887902));
611
+ return mix(vec3f(1.0), thinFilmTint, iridescence);
612
+ }
613
+
614
+ fn getVolumeAttenuation(thickness: f32) -> vec3f {
615
+ if (thickness <= 0.0) {
616
+ return vec3f(1.0);
617
+ }
618
+
619
+ let attenuationCoefficient =
620
+ -log(max(pbrMaterial.attenuationColor, vec3f(0.0001))) /
621
+ max(pbrMaterial.attenuationDistance, 0.0001);
622
+ return exp(-attenuationCoefficient * thickness);
623
+ }
624
+
625
+ fn createClearcoatPBRInfo(
626
+ basePBRInfo: PBRInfo,
627
+ clearcoatNormal: vec3f,
628
+ clearcoatRoughness: f32
629
+ ) -> PBRInfo {
630
+ let perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
631
+ let alphaRoughness = perceptualRoughness * perceptualRoughness;
632
+ let NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);
633
+
634
+ return PBRInfo(
635
+ basePBRInfo.NdotL,
636
+ NdotV,
637
+ basePBRInfo.NdotH,
638
+ basePBRInfo.LdotH,
639
+ basePBRInfo.VdotH,
640
+ perceptualRoughness,
641
+ 0.0,
642
+ vec3f(0.04),
643
+ vec3f(1.0),
644
+ alphaRoughness,
645
+ vec3f(0.0),
646
+ vec3f(0.04),
647
+ clearcoatNormal,
648
+ basePBRInfo.v
649
+ );
650
+ }
651
+
652
+ fn calculateClearcoatContribution(
653
+ pbrInfo: PBRInfo,
654
+ lightColor: vec3f,
655
+ clearcoatNormal: vec3f,
656
+ clearcoatFactor: f32,
657
+ clearcoatRoughness: f32
658
+ ) -> vec3f {
659
+ if (clearcoatFactor <= 0.0) {
660
+ return vec3f(0.0);
661
+ }
662
+
663
+ let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
664
+ return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;
665
+ }
666
+
667
+ #ifdef USE_IBL
668
+ fn calculateClearcoatIBLContribution(
669
+ pbrInfo: PBRInfo,
670
+ clearcoatNormal: vec3f,
671
+ reflection: vec3f,
672
+ clearcoatFactor: f32,
673
+ clearcoatRoughness: f32
674
+ ) -> vec3f {
675
+ if (clearcoatFactor <= 0.0) {
676
+ return vec3f(0.0);
677
+ }
678
+
679
+ let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
680
+ return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;
681
+ }
682
+ #endif
683
+
684
+ fn calculateSheenContribution(
685
+ pbrInfo: PBRInfo,
686
+ lightColor: vec3f,
687
+ sheenColor: vec3f,
688
+ sheenRoughness: f32
689
+ ) -> vec3f {
690
+ if (maxComponent(sheenColor) <= 0.0) {
691
+ return vec3f(0.0);
692
+ }
693
+
694
+ let sheenFresnel = pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
695
+ let sheenVisibility = mix(1.0, pbrInfo.NdotL * pbrInfo.NdotV, sheenRoughness);
696
+ return pbrInfo.NdotL *
697
+ lightColor *
698
+ sheenColor *
699
+ (0.25 + 0.75 * sheenFresnel) *
700
+ sheenVisibility *
701
+ (1.0 - pbrInfo.metalness);
702
+ }
703
+
704
+ fn calculateAnisotropyBoost(
705
+ pbrInfo: PBRInfo,
706
+ anisotropyTangent: vec3f,
707
+ anisotropyStrength: f32
708
+ ) -> f32 {
709
+ if (anisotropyStrength <= 0.0) {
710
+ return 1.0;
711
+ }
712
+
713
+ let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));
714
+ let bitangentViewAlignment = abs(dot(pbrInfo.v, anisotropyBitangent));
715
+ return mix(1.0, 0.65 + 0.7 * bitangentViewAlignment, anisotropyStrength);
716
+ }
717
+
718
+ fn calculateMaterialLightColor(
719
+ pbrInfo: PBRInfo,
720
+ lightColor: vec3f,
721
+ clearcoatNormal: vec3f,
722
+ clearcoatFactor: f32,
723
+ clearcoatRoughness: f32,
724
+ sheenColor: vec3f,
725
+ sheenRoughness: f32,
726
+ anisotropyTangent: vec3f,
727
+ anisotropyStrength: f32
728
+ ) -> vec3f {
729
+ let anisotropyBoost = calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
730
+ var color = calculateFinalColor(pbrInfo, lightColor) * anisotropyBoost;
731
+ color += calculateClearcoatContribution(
732
+ pbrInfo,
733
+ lightColor,
734
+ clearcoatNormal,
735
+ clearcoatFactor,
736
+ clearcoatRoughness
737
+ );
738
+ color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);
739
+ return color;
310
740
  }
311
741
 
312
742
  fn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {
@@ -329,7 +759,12 @@ fn PBRInfo_setDirectionalLight(pbrInfo: ptr<function, PBRInfo>, lightDirection:
329
759
  }
330
760
 
331
761
  fn PBRInfo_setPointLight(pbrInfo: ptr<function, PBRInfo>, pointLight: PointLight) {
332
- let light_direction = normalize(pointLight.position - pbr_vPosition);
762
+ let light_direction = normalize(pointLight.position - fragmentInputs.pbr_vPosition);
763
+ PBRInfo_setDirectionalLight(pbrInfo, light_direction);
764
+ }
765
+
766
+ fn PBRInfo_setSpotLight(pbrInfo: ptr<function, PBRInfo>, spotLight: SpotLight) {
767
+ let light_direction = normalize(spotLight.position - fragmentInputs.pbr_vPosition);
333
768
  PBRInfo_setDirectionalLight(pbrInfo, light_direction);
334
769
  }
335
770
 
@@ -347,12 +782,63 @@ fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
347
782
  }
348
783
 
349
784
  fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
785
+ let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);
786
+ let metallicRoughnessUV = getMaterialUV(
787
+ pbrMaterial.metallicRoughnessUVSet,
788
+ pbrMaterial.metallicRoughnessUVTransform
789
+ );
790
+ let normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);
791
+ let occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);
792
+ let emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);
793
+ let specularColorUV = getMaterialUV(
794
+ pbrMaterial.specularColorUVSet,
795
+ pbrMaterial.specularColorUVTransform
796
+ );
797
+ let specularIntensityUV = getMaterialUV(
798
+ pbrMaterial.specularIntensityUVSet,
799
+ pbrMaterial.specularIntensityUVTransform
800
+ );
801
+ let transmissionUV = getMaterialUV(
802
+ pbrMaterial.transmissionUVSet,
803
+ pbrMaterial.transmissionUVTransform
804
+ );
805
+ let thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);
806
+ let clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);
807
+ let clearcoatRoughnessUV = getMaterialUV(
808
+ pbrMaterial.clearcoatRoughnessUVSet,
809
+ pbrMaterial.clearcoatRoughnessUVTransform
810
+ );
811
+ let clearcoatNormalUV = getMaterialUV(
812
+ pbrMaterial.clearcoatNormalUVSet,
813
+ pbrMaterial.clearcoatNormalUVTransform
814
+ );
815
+ let sheenColorUV = getMaterialUV(
816
+ pbrMaterial.sheenColorUVSet,
817
+ pbrMaterial.sheenColorUVTransform
818
+ );
819
+ let sheenRoughnessUV = getMaterialUV(
820
+ pbrMaterial.sheenRoughnessUVSet,
821
+ pbrMaterial.sheenRoughnessUVTransform
822
+ );
823
+ let iridescenceUV = getMaterialUV(
824
+ pbrMaterial.iridescenceUVSet,
825
+ pbrMaterial.iridescenceUVTransform
826
+ );
827
+ let iridescenceThicknessUV = getMaterialUV(
828
+ pbrMaterial.iridescenceThicknessUVSet,
829
+ pbrMaterial.iridescenceThicknessUVTransform
830
+ );
831
+ let anisotropyUV = getMaterialUV(
832
+ pbrMaterial.anisotropyUVSet,
833
+ pbrMaterial.anisotropyUVTransform
834
+ );
835
+
350
836
  // The albedo may be defined from a base texture or a flat color
351
- var baseColor: vec4<f32>;
837
+ var baseColor: vec4<f32> = pbrMaterial.baseColorFactor;
352
838
  #ifdef HAS_BASECOLORMAP
353
- baseColor = SRGBtoLINEAR(textureSample(pbr_baseColorSampler, pbr_baseColorSampler, pbr_vUV)) * pbrMaterial.baseColorFactor;
354
- #else
355
- baseColor = pbrMaterial.baseColorFactor;
839
+ baseColor = SRGBtoLINEAR(
840
+ textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, baseColorUV)
841
+ ) * pbrMaterial.baseColorFactor;
356
842
  #endif
357
843
 
358
844
  #ifdef ALPHA_CUTOFF
@@ -362,8 +848,9 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
362
848
  #endif
363
849
 
364
850
  var color = vec3<f32>(0.0, 0.0, 0.0);
851
+ var transmission = 0.0;
365
852
 
366
- if (pbrMaterial.unlit) {
853
+ if (pbrMaterial.unlit != 0u) {
367
854
  color = baseColor.rgb;
368
855
  } else {
369
856
  // Metallic and Roughness material properties are packed together
@@ -374,20 +861,317 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
374
861
  #ifdef HAS_METALROUGHNESSMAP
375
862
  // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
376
863
  // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
377
- let mrSample = textureSample(pbr_metallicRoughnessSampler, pbr_metallicRoughnessSampler, pbr_vUV);
864
+ let mrSample = textureSample(
865
+ pbr_metallicRoughnessSampler,
866
+ pbr_metallicRoughnessSamplerSampler,
867
+ metallicRoughnessUV
868
+ );
378
869
  perceptualRoughness = mrSample.g * perceptualRoughness;
379
870
  metallic = mrSample.b * metallic;
380
871
  #endif
381
872
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
382
873
  metallic = clamp(metallic, 0.0, 1.0);
874
+ let tbn = getTBN(normalUV);
875
+ let n = getNormal(tbn, normalUV); // normal at surface point
876
+ let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
877
+ let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
878
+ var useExtendedPBR = false;
879
+ #ifdef USE_MATERIAL_EXTENSIONS
880
+ useExtendedPBR =
881
+ pbrMaterial.specularColorMapEnabled != 0 ||
882
+ pbrMaterial.specularIntensityMapEnabled != 0 ||
883
+ abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||
884
+ maxComponent(abs(pbrMaterial.specularColorFactor - vec3f(1.0))) > 0.0001 ||
885
+ abs(pbrMaterial.ior - 1.5) > 0.0001 ||
886
+ pbrMaterial.transmissionMapEnabled != 0 ||
887
+ pbrMaterial.transmissionFactor > 0.0001 ||
888
+ pbrMaterial.clearcoatMapEnabled != 0 ||
889
+ pbrMaterial.clearcoatRoughnessMapEnabled != 0 ||
890
+ pbrMaterial.clearcoatFactor > 0.0001 ||
891
+ pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||
892
+ pbrMaterial.sheenColorMapEnabled != 0 ||
893
+ pbrMaterial.sheenRoughnessMapEnabled != 0 ||
894
+ maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||
895
+ pbrMaterial.sheenRoughnessFactor > 0.0001 ||
896
+ pbrMaterial.iridescenceMapEnabled != 0 ||
897
+ pbrMaterial.iridescenceFactor > 0.0001 ||
898
+ abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||
899
+ abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||
900
+ abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||
901
+ pbrMaterial.anisotropyMapEnabled != 0 ||
902
+ pbrMaterial.anisotropyStrength > 0.0001 ||
903
+ abs(pbrMaterial.anisotropyRotation) > 0.0001 ||
904
+ length(pbrMaterial.anisotropyDirection - vec2f(1.0, 0.0)) > 0.0001;
905
+ #endif
906
+
907
+ if (!useExtendedPBR) {
908
+ let alphaRoughness = perceptualRoughness * perceptualRoughness;
909
+
910
+ let f0 = vec3<f32>(0.04);
911
+ var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
912
+ diffuseColor *= 1.0 - metallic;
913
+ let specularColor = mix(f0, baseColor.rgb, metallic);
914
+
915
+ let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
916
+ let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
917
+ let specularEnvironmentR0 = specularColor;
918
+ let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
919
+ let reflection = -normalize(reflect(v, n));
920
+
921
+ var pbrInfo = PBRInfo(
922
+ 0.0, // NdotL
923
+ NdotV,
924
+ 0.0, // NdotH
925
+ 0.0, // LdotH
926
+ 0.0, // VdotH
927
+ perceptualRoughness,
928
+ metallic,
929
+ specularEnvironmentR0,
930
+ specularEnvironmentR90,
931
+ alphaRoughness,
932
+ diffuseColor,
933
+ specularColor,
934
+ n,
935
+ v
936
+ );
937
+
938
+ #ifdef USE_LIGHTS
939
+ PBRInfo_setAmbientLight(&pbrInfo);
940
+ color += calculateFinalColor(pbrInfo, lighting.ambientColor);
941
+
942
+ for (var i = 0; i < lighting.directionalLightCount; i++) {
943
+ if (i < lighting.directionalLightCount) {
944
+ PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
945
+ color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
946
+ }
947
+ }
948
+
949
+ for (var i = 0; i < lighting.pointLightCount; i++) {
950
+ if (i < lighting.pointLightCount) {
951
+ PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));
952
+ let attenuation = getPointLightAttenuation(
953
+ lighting_getPointLight(i),
954
+ distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
955
+ );
956
+ color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
957
+ }
958
+ }
959
+
960
+ for (var i = 0; i < lighting.spotLightCount; i++) {
961
+ if (i < lighting.spotLightCount) {
962
+ PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));
963
+ let attenuation = getSpotLightAttenuation(
964
+ lighting_getSpotLight(i),
965
+ fragmentInputs.pbr_vPosition
966
+ );
967
+ color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color / attenuation);
968
+ }
969
+ }
970
+ #endif
971
+
972
+ #ifdef USE_IBL
973
+ if (pbrMaterial.IBLenabled != 0) {
974
+ color += getIBLContribution(pbrInfo, n, reflection);
975
+ }
976
+ #endif
977
+
978
+ #ifdef HAS_OCCLUSIONMAP
979
+ if (pbrMaterial.occlusionMapEnabled != 0) {
980
+ let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
981
+ color = mix(color, color * ao, pbrMaterial.occlusionStrength);
982
+ }
983
+ #endif
984
+
985
+ var emissive = pbrMaterial.emissiveFactor;
986
+ #ifdef HAS_EMISSIVEMAP
987
+ if (pbrMaterial.emissiveMapEnabled != 0u) {
988
+ emissive *= SRGBtoLINEAR(
989
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)
990
+ ).rgb;
991
+ }
992
+ #endif
993
+ color += emissive * pbrMaterial.emissiveStrength;
994
+
995
+ #ifdef PBR_DEBUG
996
+ color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
997
+ color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);
998
+ color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
999
+ #endif
1000
+
1001
+ return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), baseColor.a);
1002
+ }
1003
+
1004
+ var specularIntensity = pbrMaterial.specularIntensityFactor;
1005
+ #ifdef HAS_SPECULARINTENSITYMAP
1006
+ if (pbrMaterial.specularIntensityMapEnabled != 0) {
1007
+ specularIntensity *= textureSample(
1008
+ pbr_specularIntensitySampler,
1009
+ pbr_specularIntensitySamplerSampler,
1010
+ specularIntensityUV
1011
+ ).a;
1012
+ }
1013
+ #endif
1014
+
1015
+ var specularFactor = pbrMaterial.specularColorFactor;
1016
+ #ifdef HAS_SPECULARCOLORMAP
1017
+ if (pbrMaterial.specularColorMapEnabled != 0) {
1018
+ specularFactor *= SRGBtoLINEAR(
1019
+ textureSample(
1020
+ pbr_specularColorSampler,
1021
+ pbr_specularColorSamplerSampler,
1022
+ specularColorUV
1023
+ )
1024
+ ).rgb;
1025
+ }
1026
+ #endif
1027
+
1028
+ transmission = pbrMaterial.transmissionFactor;
1029
+ #ifdef HAS_TRANSMISSIONMAP
1030
+ if (pbrMaterial.transmissionMapEnabled != 0) {
1031
+ transmission *= textureSample(
1032
+ pbr_transmissionSampler,
1033
+ pbr_transmissionSamplerSampler,
1034
+ transmissionUV
1035
+ ).r;
1036
+ }
1037
+ #endif
1038
+ transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);
1039
+ var thickness = max(pbrMaterial.thicknessFactor, 0.0);
1040
+ #ifdef HAS_THICKNESSMAP
1041
+ thickness *= textureSample(
1042
+ pbr_thicknessSampler,
1043
+ pbr_thicknessSamplerSampler,
1044
+ thicknessUV
1045
+ ).g;
1046
+ #endif
1047
+
1048
+ var clearcoatFactor = pbrMaterial.clearcoatFactor;
1049
+ var clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;
1050
+ #ifdef HAS_CLEARCOATMAP
1051
+ if (pbrMaterial.clearcoatMapEnabled != 0) {
1052
+ clearcoatFactor *= textureSample(
1053
+ pbr_clearcoatSampler,
1054
+ pbr_clearcoatSamplerSampler,
1055
+ clearcoatUV
1056
+ ).r;
1057
+ }
1058
+ #endif
1059
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
1060
+ if (pbrMaterial.clearcoatRoughnessMapEnabled != 0) {
1061
+ clearcoatRoughness *= textureSample(
1062
+ pbr_clearcoatRoughnessSampler,
1063
+ pbr_clearcoatRoughnessSamplerSampler,
1064
+ clearcoatRoughnessUV
1065
+ ).g;
1066
+ }
1067
+ #endif
1068
+ clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
1069
+ clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
1070
+ let clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);
1071
+
1072
+ var sheenColor = pbrMaterial.sheenColorFactor;
1073
+ var sheenRoughness = pbrMaterial.sheenRoughnessFactor;
1074
+ #ifdef HAS_SHEENCOLORMAP
1075
+ if (pbrMaterial.sheenColorMapEnabled != 0) {
1076
+ sheenColor *= SRGBtoLINEAR(
1077
+ textureSample(
1078
+ pbr_sheenColorSampler,
1079
+ pbr_sheenColorSamplerSampler,
1080
+ sheenColorUV
1081
+ )
1082
+ ).rgb;
1083
+ }
1084
+ #endif
1085
+ #ifdef HAS_SHEENROUGHNESSMAP
1086
+ if (pbrMaterial.sheenRoughnessMapEnabled != 0) {
1087
+ sheenRoughness *= textureSample(
1088
+ pbr_sheenRoughnessSampler,
1089
+ pbr_sheenRoughnessSamplerSampler,
1090
+ sheenRoughnessUV
1091
+ ).a;
1092
+ }
1093
+ #endif
1094
+ sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);
1095
+
1096
+ var iridescence = pbrMaterial.iridescenceFactor;
1097
+ #ifdef HAS_IRIDESCENCEMAP
1098
+ if (pbrMaterial.iridescenceMapEnabled != 0) {
1099
+ iridescence *= textureSample(
1100
+ pbr_iridescenceSampler,
1101
+ pbr_iridescenceSamplerSampler,
1102
+ iridescenceUV
1103
+ ).r;
1104
+ }
1105
+ #endif
1106
+ iridescence = clamp(iridescence, 0.0, 1.0);
1107
+ var iridescenceThickness = mix(
1108
+ pbrMaterial.iridescenceThicknessRange.x,
1109
+ pbrMaterial.iridescenceThicknessRange.y,
1110
+ 0.5
1111
+ );
1112
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
1113
+ iridescenceThickness = mix(
1114
+ pbrMaterial.iridescenceThicknessRange.x,
1115
+ pbrMaterial.iridescenceThicknessRange.y,
1116
+ textureSample(
1117
+ pbr_iridescenceThicknessSampler,
1118
+ pbr_iridescenceThicknessSamplerSampler,
1119
+ iridescenceThicknessUV
1120
+ ).g
1121
+ );
1122
+ #endif
1123
+
1124
+ var anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);
1125
+ var anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);
1126
+ #ifdef HAS_ANISOTROPYMAP
1127
+ if (pbrMaterial.anisotropyMapEnabled != 0) {
1128
+ let anisotropySample = textureSample(
1129
+ pbr_anisotropySampler,
1130
+ pbr_anisotropySamplerSampler,
1131
+ anisotropyUV
1132
+ ).rgb;
1133
+ anisotropyStrength *= anisotropySample.b;
1134
+ let mappedDirection = anisotropySample.rg * 2.0 - 1.0;
1135
+ if (length(mappedDirection) > 0.0001) {
1136
+ anisotropyDirection = normalize(mappedDirection);
1137
+ }
1138
+ }
1139
+ #endif
1140
+ anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);
1141
+ var anisotropyTangent =
1142
+ normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);
1143
+ if (length(anisotropyTangent) < 0.0001) {
1144
+ anisotropyTangent = normalize(tbn[0]);
1145
+ }
1146
+ let anisotropyViewAlignment = abs(dot(v, anisotropyTangent));
1147
+ perceptualRoughness = mix(
1148
+ perceptualRoughness,
1149
+ clamp(perceptualRoughness * (1.0 - 0.6 * anisotropyViewAlignment), c_MinRoughness, 1.0),
1150
+ anisotropyStrength
1151
+ );
1152
+
383
1153
  // Roughness is authored as perceptual roughness; as is convention,
384
1154
  // convert to material roughness by squaring the perceptual roughness [2].
385
1155
  let alphaRoughness = perceptualRoughness * perceptualRoughness;
386
1156
 
387
- let f0 = vec3<f32>(0.04);
388
- var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
389
- diffuseColor *= 1.0 - metallic;
390
- let specularColor = mix(f0, baseColor.rgb, metallic);
1157
+ let dielectricF0 = getDielectricF0(pbrMaterial.ior);
1158
+ var dielectricSpecularF0 = min(
1159
+ vec3f(dielectricF0) * specularFactor * specularIntensity,
1160
+ vec3f(1.0)
1161
+ );
1162
+ let iridescenceTint = getIridescenceTint(iridescence, iridescenceThickness, NdotV);
1163
+ dielectricSpecularF0 = mix(
1164
+ dielectricSpecularF0,
1165
+ dielectricSpecularF0 * iridescenceTint,
1166
+ iridescence
1167
+ );
1168
+ var diffuseColor = baseColor.rgb * (vec3f(1.0) - dielectricSpecularF0);
1169
+ diffuseColor *= (1.0 - metallic) * (1.0 - transmission);
1170
+ var specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);
1171
+
1172
+ let baseLayerEnergy = 1.0 - clearcoatFactor * 0.25;
1173
+ diffuseColor *= baseLayerEnergy;
1174
+ specularColor *= baseLayerEnergy;
391
1175
 
392
1176
  // Compute reflectance.
393
1177
  let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
@@ -399,11 +1183,6 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
399
1183
  let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
400
1184
  let specularEnvironmentR0 = specularColor;
401
1185
  let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
402
-
403
- let n = getNormal(); // normal at surface point
404
- let v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
405
-
406
- let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
407
1186
  let reflection = -normalize(reflect(v, n));
408
1187
 
409
1188
  var pbrInfo = PBRInfo(
@@ -426,13 +1205,33 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
426
1205
  #ifdef USE_LIGHTS
427
1206
  // Apply ambient light
428
1207
  PBRInfo_setAmbientLight(&pbrInfo);
429
- color += calculateFinalColor(pbrInfo, lighting.ambientColor);
1208
+ color += calculateMaterialLightColor(
1209
+ pbrInfo,
1210
+ lighting.ambientColor,
1211
+ clearcoatNormal,
1212
+ clearcoatFactor,
1213
+ clearcoatRoughness,
1214
+ sheenColor,
1215
+ sheenRoughness,
1216
+ anisotropyTangent,
1217
+ anisotropyStrength
1218
+ );
430
1219
 
431
1220
  // Apply directional light
432
1221
  for (var i = 0; i < lighting.directionalLightCount; i++) {
433
1222
  if (i < lighting.directionalLightCount) {
434
1223
  PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
435
- color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
1224
+ color += calculateMaterialLightColor(
1225
+ pbrInfo,
1226
+ lighting_getDirectionalLight(i).color,
1227
+ clearcoatNormal,
1228
+ clearcoatFactor,
1229
+ clearcoatRoughness,
1230
+ sheenColor,
1231
+ sheenRoughness,
1232
+ anisotropyTangent,
1233
+ anisotropyStrength
1234
+ );
436
1235
  }
437
1236
  }
438
1237
 
@@ -440,33 +1239,80 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
440
1239
  for (var i = 0; i < lighting.pointLightCount; i++) {
441
1240
  if (i < lighting.pointLightCount) {
442
1241
  PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));
443
- let attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
444
- color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
1242
+ let attenuation = getPointLightAttenuation(
1243
+ lighting_getPointLight(i),
1244
+ distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
1245
+ );
1246
+ color += calculateMaterialLightColor(
1247
+ pbrInfo,
1248
+ lighting_getPointLight(i).color / attenuation,
1249
+ clearcoatNormal,
1250
+ clearcoatFactor,
1251
+ clearcoatRoughness,
1252
+ sheenColor,
1253
+ sheenRoughness,
1254
+ anisotropyTangent,
1255
+ anisotropyStrength
1256
+ );
1257
+ }
1258
+ }
1259
+
1260
+ for (var i = 0; i < lighting.spotLightCount; i++) {
1261
+ if (i < lighting.spotLightCount) {
1262
+ PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));
1263
+ let attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), fragmentInputs.pbr_vPosition);
1264
+ color += calculateMaterialLightColor(
1265
+ pbrInfo,
1266
+ lighting_getSpotLight(i).color / attenuation,
1267
+ clearcoatNormal,
1268
+ clearcoatFactor,
1269
+ clearcoatRoughness,
1270
+ sheenColor,
1271
+ sheenRoughness,
1272
+ anisotropyTangent,
1273
+ anisotropyStrength
1274
+ );
445
1275
  }
446
1276
  }
447
1277
  #endif
448
1278
 
449
1279
  // Calculate lighting contribution from image based lighting source (IBL)
450
1280
  #ifdef USE_IBL
451
- if (pbrMaterial.IBLenabled) {
452
- color += getIBLContribution(pbrInfo, n, reflection);
1281
+ if (pbrMaterial.IBLenabled != 0) {
1282
+ color += getIBLContribution(pbrInfo, n, reflection) *
1283
+ calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
1284
+ color += calculateClearcoatIBLContribution(
1285
+ pbrInfo,
1286
+ clearcoatNormal,
1287
+ -normalize(reflect(v, clearcoatNormal)),
1288
+ clearcoatFactor,
1289
+ clearcoatRoughness
1290
+ );
1291
+ color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;
453
1292
  }
454
1293
  #endif
455
1294
 
456
1295
  // Apply optional PBR terms for additional (optional) shading
457
1296
  #ifdef HAS_OCCLUSIONMAP
458
- if (pbrMaterial.occlusionMapEnabled) {
459
- let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSampler, pbr_vUV).r;
1297
+ if (pbrMaterial.occlusionMapEnabled != 0) {
1298
+ let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;
460
1299
  color = mix(color, color * ao, pbrMaterial.occlusionStrength);
461
1300
  }
462
1301
  #endif
463
1302
 
1303
+ var emissive = pbrMaterial.emissiveFactor;
464
1304
  #ifdef HAS_EMISSIVEMAP
465
- if (pbrMaterial.emissiveMapEnabled) {
466
- let emissive = SRGBtoLINEAR(textureSample(pbr_emissiveSampler, pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
467
- color += emissive;
1305
+ if (pbrMaterial.emissiveMapEnabled != 0u) {
1306
+ emissive *= SRGBtoLINEAR(
1307
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)
1308
+ ).rgb;
468
1309
  }
469
1310
  #endif
1311
+ color += emissive * pbrMaterial.emissiveStrength;
1312
+
1313
+ if (transmission > 0.0) {
1314
+ color = mix(color, color * getVolumeAttenuation(thickness), transmission);
1315
+ }
470
1316
 
471
1317
  // This section uses mix to override final color for reference app visualization
472
1318
  // of various parameters in the lighting equation.
@@ -485,6 +1331,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
485
1331
  #endif
486
1332
  }
487
1333
 
488
- return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), baseColor.a);
1334
+ let alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);
1335
+ return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), alpha);
489
1336
  }
490
1337
  `;