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