@deck.gl/geo-layers 9.3.0-alpha.3 → 9.3.0-alpha.5

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.
package/dist/dist.dev.js CHANGED
@@ -14996,7 +14996,12 @@ var __exports__ = (() => {
14996
14996
  get isLoaded() {
14997
14997
  return Boolean(
14998
14998
  this.state?.tileset?.selectedTiles?.every(
14999
- (tile) => tile.isLoaded && tile.layers && tile.layers.every((layer) => layer.isLoaded)
14999
+ (tile) => (
15000
+ // Error / empty tiles resolve to `content === null`. Once Tile2DHeader marks those
15001
+ // requests as loaded, do not wait for generated sublayers because there is nothing to
15002
+ // render for that tile and `tile.layers` will remain null.
15003
+ tile.isLoaded && (!tile.content || !tile.layers || tile.layers.every((layer) => layer.isLoaded))
15004
+ )
15000
15005
  )
15001
15006
  );
15002
15007
  }
@@ -15166,7 +15171,7 @@ var __exports__ = (() => {
15166
15171
  var import_layers6 = __toESM(require_layers(), 1);
15167
15172
 
15168
15173
  // src/trips-layer/trips-layer-uniforms.ts
15169
- var uniformBlock = `uniform tripsUniforms {
15174
+ var uniformBlock = `layout(std140) uniform tripsUniforms {
15170
15175
  bool fadeTrail;
15171
15176
  float trailLength;
15172
15177
  float currentTime;
@@ -16084,6 +16089,35 @@ out float vTime;
16084
16089
  // ../../node_modules/@luma.gl/gltf/dist/parsers/parse-pbr-material.js
16085
16090
  var import_core20 = __toESM(require_core3(), 1);
16086
16091
 
16092
+ // ../../node_modules/@luma.gl/gltf/dist/webgl-to-webgpu/gltf-webgl-constants.js
16093
+ var GLEnum;
16094
+ (function(GLEnum2) {
16095
+ GLEnum2[GLEnum2["POINTS"] = 0] = "POINTS";
16096
+ GLEnum2[GLEnum2["LINES"] = 1] = "LINES";
16097
+ GLEnum2[GLEnum2["LINE_LOOP"] = 2] = "LINE_LOOP";
16098
+ GLEnum2[GLEnum2["LINE_STRIP"] = 3] = "LINE_STRIP";
16099
+ GLEnum2[GLEnum2["TRIANGLES"] = 4] = "TRIANGLES";
16100
+ GLEnum2[GLEnum2["TRIANGLE_STRIP"] = 5] = "TRIANGLE_STRIP";
16101
+ GLEnum2[GLEnum2["TRIANGLE_FAN"] = 6] = "TRIANGLE_FAN";
16102
+ GLEnum2[GLEnum2["ONE"] = 1] = "ONE";
16103
+ GLEnum2[GLEnum2["SRC_ALPHA"] = 770] = "SRC_ALPHA";
16104
+ GLEnum2[GLEnum2["ONE_MINUS_SRC_ALPHA"] = 771] = "ONE_MINUS_SRC_ALPHA";
16105
+ GLEnum2[GLEnum2["FUNC_ADD"] = 32774] = "FUNC_ADD";
16106
+ GLEnum2[GLEnum2["LINEAR"] = 9729] = "LINEAR";
16107
+ GLEnum2[GLEnum2["NEAREST"] = 9728] = "NEAREST";
16108
+ GLEnum2[GLEnum2["NEAREST_MIPMAP_NEAREST"] = 9984] = "NEAREST_MIPMAP_NEAREST";
16109
+ GLEnum2[GLEnum2["LINEAR_MIPMAP_NEAREST"] = 9985] = "LINEAR_MIPMAP_NEAREST";
16110
+ GLEnum2[GLEnum2["NEAREST_MIPMAP_LINEAR"] = 9986] = "NEAREST_MIPMAP_LINEAR";
16111
+ GLEnum2[GLEnum2["LINEAR_MIPMAP_LINEAR"] = 9987] = "LINEAR_MIPMAP_LINEAR";
16112
+ GLEnum2[GLEnum2["TEXTURE_MIN_FILTER"] = 10241] = "TEXTURE_MIN_FILTER";
16113
+ GLEnum2[GLEnum2["TEXTURE_WRAP_S"] = 10242] = "TEXTURE_WRAP_S";
16114
+ GLEnum2[GLEnum2["TEXTURE_WRAP_T"] = 10243] = "TEXTURE_WRAP_T";
16115
+ GLEnum2[GLEnum2["REPEAT"] = 10497] = "REPEAT";
16116
+ GLEnum2[GLEnum2["CLAMP_TO_EDGE"] = 33071] = "CLAMP_TO_EDGE";
16117
+ GLEnum2[GLEnum2["MIRRORED_REPEAT"] = 33648] = "MIRRORED_REPEAT";
16118
+ GLEnum2[GLEnum2["UNPACK_FLIP_Y_WEBGL"] = 37440] = "UNPACK_FLIP_Y_WEBGL";
16119
+ })(GLEnum || (GLEnum = {}));
16120
+
16087
16121
  // ../../node_modules/@luma.gl/gltf/dist/webgl-to-webgpu/convert-webgl-sampler.js
16088
16122
  function convertSampler(gltfSampler) {
16089
16123
  return {
@@ -16095,11 +16129,11 @@ out float vTime;
16095
16129
  }
16096
16130
  function convertSamplerWrapMode(mode) {
16097
16131
  switch (mode) {
16098
- case 33071:
16132
+ case GLEnum.CLAMP_TO_EDGE:
16099
16133
  return "clamp-to-edge";
16100
- case 10497:
16134
+ case GLEnum.REPEAT:
16101
16135
  return "repeat";
16102
- case 33648:
16136
+ case GLEnum.MIRRORED_REPEAT:
16103
16137
  return "mirror-repeat";
16104
16138
  default:
16105
16139
  return void 0;
@@ -16107,9 +16141,9 @@ out float vTime;
16107
16141
  }
16108
16142
  function convertSamplerMagFilter(mode) {
16109
16143
  switch (mode) {
16110
- case 9728:
16144
+ case GLEnum.NEAREST:
16111
16145
  return "nearest";
16112
- case 9729:
16146
+ case GLEnum.LINEAR:
16113
16147
  return "linear";
16114
16148
  default:
16115
16149
  return void 0;
@@ -16117,17 +16151,17 @@ out float vTime;
16117
16151
  }
16118
16152
  function convertSamplerMinFilter(mode) {
16119
16153
  switch (mode) {
16120
- case 9728:
16154
+ case GLEnum.NEAREST:
16121
16155
  return { minFilter: "nearest" };
16122
- case 9729:
16156
+ case GLEnum.LINEAR:
16123
16157
  return { minFilter: "linear" };
16124
- case 9984:
16158
+ case GLEnum.NEAREST_MIPMAP_NEAREST:
16125
16159
  return { minFilter: "nearest", mipmapFilter: "nearest" };
16126
- case 9985:
16160
+ case GLEnum.LINEAR_MIPMAP_NEAREST:
16127
16161
  return { minFilter: "linear", mipmapFilter: "nearest" };
16128
- case 9986:
16162
+ case GLEnum.NEAREST_MIPMAP_LINEAR:
16129
16163
  return { minFilter: "nearest", mipmapFilter: "linear" };
16130
- case 9987:
16164
+ case GLEnum.LINEAR_MIPMAP_LINEAR:
16131
16165
  return { minFilter: "linear", mipmapFilter: "linear" };
16132
16166
  default:
16133
16167
  return {};
@@ -16159,7 +16193,8 @@ out float vTime;
16159
16193
  if (imageBasedLightingEnvironment) {
16160
16194
  parsedMaterial.bindings.pbr_diffuseEnvSampler = imageBasedLightingEnvironment.diffuseEnvSampler.texture;
16161
16195
  parsedMaterial.bindings.pbr_specularEnvSampler = imageBasedLightingEnvironment.specularEnvSampler.texture;
16162
- parsedMaterial.bindings.pbr_BrdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
16196
+ parsedMaterial.bindings.pbr_brdfLUT = imageBasedLightingEnvironment.brdfLutTexture.texture;
16197
+ parsedMaterial.uniforms.IBLenabled = true;
16163
16198
  parsedMaterial.uniforms.scaleIBLAmbient = [1, 1];
16164
16199
  }
16165
16200
  if (options?.pbrDebug) {
@@ -16182,68 +16217,415 @@ out float vTime;
16182
16217
  if (options?.lights)
16183
16218
  parsedMaterial.defines["USE_LIGHTS"] = true;
16184
16219
  if (material) {
16185
- parseMaterial(device, material, parsedMaterial);
16220
+ if (options.validateAttributes !== false) {
16221
+ warnOnMissingExpectedAttributes(material, attributes);
16222
+ }
16223
+ parseMaterial(device, material, parsedMaterial, options.gltf);
16186
16224
  }
16187
16225
  return parsedMaterial;
16188
16226
  }
16189
- function parseMaterial(device, material, parsedMaterial) {
16190
- parsedMaterial.uniforms.unlit = Boolean(material.unlit);
16227
+ function warnOnMissingExpectedAttributes(material, attributes) {
16228
+ const uvDependentTextureSlots = getUvDependentTextureSlots(material);
16229
+ if (uvDependentTextureSlots.length > 0 && !attributes["TEXCOORD_0"]) {
16230
+ import_core20.log.warn(`glTF material uses ${uvDependentTextureSlots.join(", ")} but primitive is missing TEXCOORD_0; textured shading will sample the default UV coordinates`)();
16231
+ }
16232
+ const isUnlitMaterial = Boolean(material.unlit || material.extensions?.KHR_materials_unlit);
16233
+ if (isUnlitMaterial || attributes["NORMAL"]) {
16234
+ return;
16235
+ }
16236
+ const missingNormalReason = material.normalTexture ? "lit PBR shading with normalTexture" : "lit PBR shading";
16237
+ import_core20.log.warn(`glTF primitive is missing NORMAL while using ${missingNormalReason}; shading will fall back to geometric normals`)();
16238
+ }
16239
+ function getUvDependentTextureSlots(material) {
16240
+ const uvDependentTextureSlots = [];
16241
+ if (material.pbrMetallicRoughness?.baseColorTexture) {
16242
+ uvDependentTextureSlots.push("baseColorTexture");
16243
+ }
16244
+ if (material.pbrMetallicRoughness?.metallicRoughnessTexture) {
16245
+ uvDependentTextureSlots.push("metallicRoughnessTexture");
16246
+ }
16247
+ if (material.normalTexture) {
16248
+ uvDependentTextureSlots.push("normalTexture");
16249
+ }
16250
+ if (material.occlusionTexture) {
16251
+ uvDependentTextureSlots.push("occlusionTexture");
16252
+ }
16253
+ if (material.emissiveTexture) {
16254
+ uvDependentTextureSlots.push("emissiveTexture");
16255
+ }
16256
+ if (material.extensions?.KHR_materials_specular?.specularTexture) {
16257
+ uvDependentTextureSlots.push("KHR_materials_specular.specularTexture");
16258
+ }
16259
+ if (material.extensions?.KHR_materials_specular?.specularColorTexture) {
16260
+ uvDependentTextureSlots.push("KHR_materials_specular.specularColorTexture");
16261
+ }
16262
+ if (material.extensions?.KHR_materials_transmission?.transmissionTexture) {
16263
+ uvDependentTextureSlots.push("KHR_materials_transmission.transmissionTexture");
16264
+ }
16265
+ if (material.extensions?.KHR_materials_clearcoat?.clearcoatTexture) {
16266
+ uvDependentTextureSlots.push("KHR_materials_clearcoat.clearcoatTexture");
16267
+ }
16268
+ if (material.extensions?.KHR_materials_clearcoat?.clearcoatRoughnessTexture) {
16269
+ uvDependentTextureSlots.push("KHR_materials_clearcoat.clearcoatRoughnessTexture");
16270
+ }
16271
+ if (material.extensions?.KHR_materials_sheen?.sheenColorTexture) {
16272
+ uvDependentTextureSlots.push("KHR_materials_sheen.sheenColorTexture");
16273
+ }
16274
+ if (material.extensions?.KHR_materials_sheen?.sheenRoughnessTexture) {
16275
+ uvDependentTextureSlots.push("KHR_materials_sheen.sheenRoughnessTexture");
16276
+ }
16277
+ if (material.extensions?.KHR_materials_iridescence?.iridescenceTexture) {
16278
+ uvDependentTextureSlots.push("KHR_materials_iridescence.iridescenceTexture");
16279
+ }
16280
+ if (material.extensions?.KHR_materials_anisotropy?.anisotropyTexture) {
16281
+ uvDependentTextureSlots.push("KHR_materials_anisotropy.anisotropyTexture");
16282
+ }
16283
+ return uvDependentTextureSlots;
16284
+ }
16285
+ function parseMaterial(device, material, parsedMaterial, gltf) {
16286
+ parsedMaterial.uniforms.unlit = Boolean(material.unlit || material.extensions?.KHR_materials_unlit);
16191
16287
  if (material.pbrMetallicRoughness) {
16192
- parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial);
16288
+ parsePbrMetallicRoughness(device, material.pbrMetallicRoughness, parsedMaterial, gltf);
16193
16289
  }
16194
16290
  if (material.normalTexture) {
16195
- addTexture(device, material.normalTexture, "pbr_normalSampler", "HAS_NORMALMAP", parsedMaterial);
16291
+ addTexture(device, material.normalTexture, "pbr_normalSampler", parsedMaterial, {
16292
+ featureOptions: {
16293
+ define: "HAS_NORMALMAP",
16294
+ enabledUniformName: "normalMapEnabled"
16295
+ },
16296
+ gltf
16297
+ });
16196
16298
  const { scale: scale12 = 1 } = material.normalTexture;
16197
16299
  parsedMaterial.uniforms.normalScale = scale12;
16198
16300
  }
16199
16301
  if (material.occlusionTexture) {
16200
- addTexture(device, material.occlusionTexture, "pbr_occlusionSampler", "HAS_OCCLUSIONMAP", parsedMaterial);
16302
+ addTexture(device, material.occlusionTexture, "pbr_occlusionSampler", parsedMaterial, {
16303
+ featureOptions: {
16304
+ define: "HAS_OCCLUSIONMAP",
16305
+ enabledUniformName: "occlusionMapEnabled"
16306
+ },
16307
+ gltf
16308
+ });
16201
16309
  const { strength = 1 } = material.occlusionTexture;
16202
16310
  parsedMaterial.uniforms.occlusionStrength = strength;
16203
16311
  }
16312
+ parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
16204
16313
  if (material.emissiveTexture) {
16205
- addTexture(device, material.emissiveTexture, "pbr_emissiveSampler", "HAS_EMISSIVEMAP", parsedMaterial);
16206
- parsedMaterial.uniforms.emissiveFactor = material.emissiveFactor || [0, 0, 0];
16314
+ addTexture(device, material.emissiveTexture, "pbr_emissiveSampler", parsedMaterial, {
16315
+ featureOptions: {
16316
+ define: "HAS_EMISSIVEMAP",
16317
+ enabledUniformName: "emissiveMapEnabled"
16318
+ },
16319
+ gltf
16320
+ });
16207
16321
  }
16208
- switch (material.alphaMode || "MASK") {
16209
- case "MASK":
16322
+ parseMaterialExtensions(device, material.extensions, parsedMaterial, gltf);
16323
+ switch (material.alphaMode || "OPAQUE") {
16324
+ case "OPAQUE":
16325
+ break;
16326
+ case "MASK": {
16210
16327
  const { alphaCutoff = 0.5 } = material;
16211
16328
  parsedMaterial.defines["ALPHA_CUTOFF"] = true;
16329
+ parsedMaterial.uniforms.alphaCutoffEnabled = true;
16212
16330
  parsedMaterial.uniforms.alphaCutoff = alphaCutoff;
16213
16331
  break;
16332
+ }
16214
16333
  case "BLEND":
16215
16334
  import_core20.log.warn("glTF BLEND alphaMode might not work well because it requires mesh sorting")();
16216
- parsedMaterial.parameters.blend = true;
16217
- parsedMaterial.parameters.blendColorOperation = "add";
16218
- parsedMaterial.parameters.blendColorSrcFactor = "src-alpha";
16219
- parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
16220
- parsedMaterial.parameters.blendAlphaOperation = "add";
16221
- parsedMaterial.parameters.blendAlphaSrcFactor = "one";
16222
- parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
16223
- parsedMaterial.glParameters["blend"] = true;
16224
- parsedMaterial.glParameters["blendEquation"] = 32774;
16225
- parsedMaterial.glParameters["blendFunc"] = [
16226
- 770,
16227
- 771,
16228
- 1,
16229
- 771
16230
- ];
16335
+ applyAlphaBlendParameters(parsedMaterial);
16231
16336
  break;
16232
16337
  }
16233
16338
  }
16234
- function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial) {
16339
+ function applyAlphaBlendParameters(parsedMaterial) {
16340
+ parsedMaterial.parameters.blend = true;
16341
+ parsedMaterial.parameters.blendColorOperation = "add";
16342
+ parsedMaterial.parameters.blendColorSrcFactor = "src-alpha";
16343
+ parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
16344
+ parsedMaterial.parameters.blendAlphaOperation = "add";
16345
+ parsedMaterial.parameters.blendAlphaSrcFactor = "one";
16346
+ parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
16347
+ parsedMaterial.glParameters["blend"] = true;
16348
+ parsedMaterial.glParameters["blendEquation"] = GLEnum.FUNC_ADD;
16349
+ parsedMaterial.glParameters["blendFunc"] = [
16350
+ GLEnum.SRC_ALPHA,
16351
+ GLEnum.ONE_MINUS_SRC_ALPHA,
16352
+ GLEnum.ONE,
16353
+ GLEnum.ONE_MINUS_SRC_ALPHA
16354
+ ];
16355
+ }
16356
+ function applyTransmissionBlendApproximation(parsedMaterial) {
16357
+ parsedMaterial.parameters.blend = true;
16358
+ parsedMaterial.parameters.depthWriteEnabled = false;
16359
+ parsedMaterial.parameters.blendColorOperation = "add";
16360
+ parsedMaterial.parameters.blendColorSrcFactor = "one";
16361
+ parsedMaterial.parameters.blendColorDstFactor = "one-minus-src-alpha";
16362
+ parsedMaterial.parameters.blendAlphaOperation = "add";
16363
+ parsedMaterial.parameters.blendAlphaSrcFactor = "one";
16364
+ parsedMaterial.parameters.blendAlphaDstFactor = "one-minus-src-alpha";
16365
+ parsedMaterial.glParameters["blend"] = true;
16366
+ parsedMaterial.glParameters["depthMask"] = false;
16367
+ parsedMaterial.glParameters["blendEquation"] = GLEnum.FUNC_ADD;
16368
+ parsedMaterial.glParameters["blendFunc"] = [
16369
+ GLEnum.ONE,
16370
+ GLEnum.ONE_MINUS_SRC_ALPHA,
16371
+ GLEnum.ONE,
16372
+ GLEnum.ONE_MINUS_SRC_ALPHA
16373
+ ];
16374
+ }
16375
+ function parsePbrMetallicRoughness(device, pbrMetallicRoughness, parsedMaterial, gltf) {
16235
16376
  if (pbrMetallicRoughness.baseColorTexture) {
16236
- addTexture(device, pbrMetallicRoughness.baseColorTexture, "pbr_baseColorSampler", "HAS_BASECOLORMAP", parsedMaterial);
16377
+ addTexture(device, pbrMetallicRoughness.baseColorTexture, "pbr_baseColorSampler", parsedMaterial, {
16378
+ featureOptions: {
16379
+ define: "HAS_BASECOLORMAP",
16380
+ enabledUniformName: "baseColorMapEnabled"
16381
+ },
16382
+ gltf
16383
+ });
16237
16384
  }
16238
16385
  parsedMaterial.uniforms.baseColorFactor = pbrMetallicRoughness.baseColorFactor || [1, 1, 1, 1];
16239
16386
  if (pbrMetallicRoughness.metallicRoughnessTexture) {
16240
- addTexture(device, pbrMetallicRoughness.metallicRoughnessTexture, "pbr_metallicRoughnessSampler", "HAS_METALROUGHNESSMAP", parsedMaterial);
16387
+ addTexture(device, pbrMetallicRoughness.metallicRoughnessTexture, "pbr_metallicRoughnessSampler", parsedMaterial, {
16388
+ featureOptions: {
16389
+ define: "HAS_METALROUGHNESSMAP",
16390
+ enabledUniformName: "metallicRoughnessMapEnabled"
16391
+ },
16392
+ gltf
16393
+ });
16241
16394
  }
16242
16395
  const { metallicFactor = 1, roughnessFactor = 1 } = pbrMetallicRoughness;
16243
16396
  parsedMaterial.uniforms.metallicRoughnessValues = [metallicFactor, roughnessFactor];
16244
16397
  }
16245
- function addTexture(device, gltfTexture, uniformName, define2, parsedMaterial) {
16246
- const image = gltfTexture.texture.source.image;
16398
+ function parseMaterialExtensions(device, extensions, parsedMaterial, gltf) {
16399
+ if (!extensions) {
16400
+ return;
16401
+ }
16402
+ if (hasMaterialExtensionShading(extensions)) {
16403
+ parsedMaterial.defines["USE_MATERIAL_EXTENSIONS"] = true;
16404
+ }
16405
+ parseSpecularExtension(device, extensions.KHR_materials_specular, parsedMaterial, gltf);
16406
+ parseIorExtension(extensions.KHR_materials_ior, parsedMaterial);
16407
+ parseTransmissionExtension(device, extensions.KHR_materials_transmission, parsedMaterial, gltf);
16408
+ parseVolumeExtension(device, extensions.KHR_materials_volume, parsedMaterial, gltf);
16409
+ parseClearcoatExtension(device, extensions.KHR_materials_clearcoat, parsedMaterial, gltf);
16410
+ parseSheenExtension(device, extensions.KHR_materials_sheen, parsedMaterial, gltf);
16411
+ parseIridescenceExtension(device, extensions.KHR_materials_iridescence, parsedMaterial, gltf);
16412
+ parseAnisotropyExtension(device, extensions.KHR_materials_anisotropy, parsedMaterial, gltf);
16413
+ parseEmissiveStrengthExtension(extensions.KHR_materials_emissive_strength, parsedMaterial);
16414
+ }
16415
+ function hasMaterialExtensionShading(extensions) {
16416
+ return Boolean(extensions.KHR_materials_specular || extensions.KHR_materials_ior || extensions.KHR_materials_transmission || extensions.KHR_materials_volume || extensions.KHR_materials_clearcoat || extensions.KHR_materials_sheen || extensions.KHR_materials_iridescence || extensions.KHR_materials_anisotropy);
16417
+ }
16418
+ function parseSpecularExtension(device, extension, parsedMaterial, gltf) {
16419
+ if (!extension) {
16420
+ return;
16421
+ }
16422
+ if (extension.specularColorFactor) {
16423
+ parsedMaterial.uniforms.specularColorFactor = extension.specularColorFactor;
16424
+ }
16425
+ if (extension.specularFactor !== void 0) {
16426
+ parsedMaterial.uniforms.specularIntensityFactor = extension.specularFactor;
16427
+ }
16428
+ if (extension.specularColorTexture) {
16429
+ addTexture(device, extension.specularColorTexture, "pbr_specularColorSampler", parsedMaterial, {
16430
+ featureOptions: {
16431
+ define: "HAS_SPECULARCOLORMAP",
16432
+ enabledUniformName: "specularColorMapEnabled"
16433
+ },
16434
+ gltf
16435
+ });
16436
+ }
16437
+ if (extension.specularTexture) {
16438
+ addTexture(device, extension.specularTexture, "pbr_specularIntensitySampler", parsedMaterial, {
16439
+ featureOptions: {
16440
+ define: "HAS_SPECULARINTENSITYMAP",
16441
+ enabledUniformName: "specularIntensityMapEnabled"
16442
+ },
16443
+ gltf
16444
+ });
16445
+ }
16446
+ }
16447
+ function parseIorExtension(extension, parsedMaterial) {
16448
+ if (extension?.ior !== void 0) {
16449
+ parsedMaterial.uniforms.ior = extension.ior;
16450
+ }
16451
+ }
16452
+ function parseTransmissionExtension(device, extension, parsedMaterial, gltf) {
16453
+ if (!extension) {
16454
+ return;
16455
+ }
16456
+ if (extension.transmissionFactor !== void 0) {
16457
+ parsedMaterial.uniforms.transmissionFactor = extension.transmissionFactor;
16458
+ }
16459
+ if (extension.transmissionTexture) {
16460
+ addTexture(device, extension.transmissionTexture, "pbr_transmissionSampler", parsedMaterial, {
16461
+ featureOptions: {
16462
+ define: "HAS_TRANSMISSIONMAP",
16463
+ enabledUniformName: "transmissionMapEnabled"
16464
+ },
16465
+ gltf
16466
+ });
16467
+ }
16468
+ if ((extension.transmissionFactor ?? 0) > 0 || extension.transmissionTexture) {
16469
+ import_core20.log.warn("KHR_materials_transmission uses a premultiplied-alpha blending approximation and may require mesh sorting")();
16470
+ applyTransmissionBlendApproximation(parsedMaterial);
16471
+ }
16472
+ }
16473
+ function parseVolumeExtension(device, extension, parsedMaterial, gltf) {
16474
+ if (!extension) {
16475
+ return;
16476
+ }
16477
+ if (extension.thicknessFactor !== void 0) {
16478
+ parsedMaterial.uniforms.thicknessFactor = extension.thicknessFactor;
16479
+ }
16480
+ if (extension.thicknessTexture) {
16481
+ addTexture(device, extension.thicknessTexture, "pbr_thicknessSampler", parsedMaterial, {
16482
+ featureOptions: {
16483
+ define: "HAS_THICKNESSMAP"
16484
+ },
16485
+ gltf
16486
+ });
16487
+ }
16488
+ if (extension.attenuationDistance !== void 0) {
16489
+ parsedMaterial.uniforms.attenuationDistance = extension.attenuationDistance;
16490
+ }
16491
+ if (extension.attenuationColor) {
16492
+ parsedMaterial.uniforms.attenuationColor = extension.attenuationColor;
16493
+ }
16494
+ }
16495
+ function parseClearcoatExtension(device, extension, parsedMaterial, gltf) {
16496
+ if (!extension) {
16497
+ return;
16498
+ }
16499
+ if (extension.clearcoatFactor !== void 0) {
16500
+ parsedMaterial.uniforms.clearcoatFactor = extension.clearcoatFactor;
16501
+ }
16502
+ if (extension.clearcoatRoughnessFactor !== void 0) {
16503
+ parsedMaterial.uniforms.clearcoatRoughnessFactor = extension.clearcoatRoughnessFactor;
16504
+ }
16505
+ if (extension.clearcoatTexture) {
16506
+ addTexture(device, extension.clearcoatTexture, "pbr_clearcoatSampler", parsedMaterial, {
16507
+ featureOptions: {
16508
+ define: "HAS_CLEARCOATMAP",
16509
+ enabledUniformName: "clearcoatMapEnabled"
16510
+ },
16511
+ gltf
16512
+ });
16513
+ }
16514
+ if (extension.clearcoatRoughnessTexture) {
16515
+ addTexture(device, extension.clearcoatRoughnessTexture, "pbr_clearcoatRoughnessSampler", parsedMaterial, {
16516
+ featureOptions: {
16517
+ define: "HAS_CLEARCOATROUGHNESSMAP",
16518
+ enabledUniformName: "clearcoatRoughnessMapEnabled"
16519
+ },
16520
+ gltf
16521
+ });
16522
+ }
16523
+ if (extension.clearcoatNormalTexture) {
16524
+ addTexture(device, extension.clearcoatNormalTexture, "pbr_clearcoatNormalSampler", parsedMaterial, {
16525
+ featureOptions: {
16526
+ define: "HAS_CLEARCOATNORMALMAP"
16527
+ },
16528
+ gltf
16529
+ });
16530
+ }
16531
+ }
16532
+ function parseSheenExtension(device, extension, parsedMaterial, gltf) {
16533
+ if (!extension) {
16534
+ return;
16535
+ }
16536
+ if (extension.sheenColorFactor) {
16537
+ parsedMaterial.uniforms.sheenColorFactor = extension.sheenColorFactor;
16538
+ }
16539
+ if (extension.sheenRoughnessFactor !== void 0) {
16540
+ parsedMaterial.uniforms.sheenRoughnessFactor = extension.sheenRoughnessFactor;
16541
+ }
16542
+ if (extension.sheenColorTexture) {
16543
+ addTexture(device, extension.sheenColorTexture, "pbr_sheenColorSampler", parsedMaterial, {
16544
+ featureOptions: {
16545
+ define: "HAS_SHEENCOLORMAP",
16546
+ enabledUniformName: "sheenColorMapEnabled"
16547
+ },
16548
+ gltf
16549
+ });
16550
+ }
16551
+ if (extension.sheenRoughnessTexture) {
16552
+ addTexture(device, extension.sheenRoughnessTexture, "pbr_sheenRoughnessSampler", parsedMaterial, {
16553
+ featureOptions: {
16554
+ define: "HAS_SHEENROUGHNESSMAP",
16555
+ enabledUniformName: "sheenRoughnessMapEnabled"
16556
+ },
16557
+ gltf
16558
+ });
16559
+ }
16560
+ }
16561
+ function parseIridescenceExtension(device, extension, parsedMaterial, gltf) {
16562
+ if (!extension) {
16563
+ return;
16564
+ }
16565
+ if (extension.iridescenceFactor !== void 0) {
16566
+ parsedMaterial.uniforms.iridescenceFactor = extension.iridescenceFactor;
16567
+ }
16568
+ if (extension.iridescenceIor !== void 0) {
16569
+ parsedMaterial.uniforms.iridescenceIor = extension.iridescenceIor;
16570
+ }
16571
+ if (extension.iridescenceThicknessMinimum !== void 0 || extension.iridescenceThicknessMaximum !== void 0) {
16572
+ parsedMaterial.uniforms.iridescenceThicknessRange = [
16573
+ extension.iridescenceThicknessMinimum ?? 100,
16574
+ extension.iridescenceThicknessMaximum ?? 400
16575
+ ];
16576
+ }
16577
+ if (extension.iridescenceTexture) {
16578
+ addTexture(device, extension.iridescenceTexture, "pbr_iridescenceSampler", parsedMaterial, {
16579
+ featureOptions: {
16580
+ define: "HAS_IRIDESCENCEMAP",
16581
+ enabledUniformName: "iridescenceMapEnabled"
16582
+ },
16583
+ gltf
16584
+ });
16585
+ }
16586
+ if (extension.iridescenceThicknessTexture) {
16587
+ addTexture(device, extension.iridescenceThicknessTexture, "pbr_iridescenceThicknessSampler", parsedMaterial, {
16588
+ featureOptions: {
16589
+ define: "HAS_IRIDESCENCETHICKNESSMAP"
16590
+ },
16591
+ gltf
16592
+ });
16593
+ }
16594
+ }
16595
+ function parseAnisotropyExtension(device, extension, parsedMaterial, gltf) {
16596
+ if (!extension) {
16597
+ return;
16598
+ }
16599
+ if (extension.anisotropyStrength !== void 0) {
16600
+ parsedMaterial.uniforms.anisotropyStrength = extension.anisotropyStrength;
16601
+ }
16602
+ if (extension.anisotropyRotation !== void 0) {
16603
+ parsedMaterial.uniforms.anisotropyRotation = extension.anisotropyRotation;
16604
+ }
16605
+ if (extension.anisotropyTexture) {
16606
+ addTexture(device, extension.anisotropyTexture, "pbr_anisotropySampler", parsedMaterial, {
16607
+ featureOptions: {
16608
+ define: "HAS_ANISOTROPYMAP",
16609
+ enabledUniformName: "anisotropyMapEnabled"
16610
+ },
16611
+ gltf
16612
+ });
16613
+ }
16614
+ }
16615
+ function parseEmissiveStrengthExtension(extension, parsedMaterial) {
16616
+ if (extension?.emissiveStrength !== void 0) {
16617
+ parsedMaterial.uniforms.emissiveStrength = extension.emissiveStrength;
16618
+ }
16619
+ }
16620
+ function addTexture(device, gltfTexture, uniformName, parsedMaterial, textureParseOptions = {}) {
16621
+ const { featureOptions = {}, gltf } = textureParseOptions;
16622
+ const { define: define2, enabledUniformName } = featureOptions;
16623
+ const resolvedTextureInfo = resolveTextureInfo(gltfTexture, gltf);
16624
+ const image = resolvedTextureInfo.texture?.source?.image;
16625
+ if (!image) {
16626
+ import_core20.log.warn(`Skipping unresolved glTF texture for ${String(uniformName)}`)();
16627
+ return;
16628
+ }
16247
16629
  const gltfSampler = {
16248
16630
  wrapS: 10497,
16249
16631
  // default REPEAT S (U) wrapping mode.
@@ -16253,10 +16635,10 @@ out float vTime;
16253
16635
  // default LINEAR filtering
16254
16636
  magFilter: 9729,
16255
16637
  // default LINEAR filtering
16256
- ...gltfTexture?.texture?.sampler
16638
+ ...resolvedTextureInfo?.texture?.sampler
16257
16639
  };
16258
16640
  const baseOptions = {
16259
- id: gltfTexture.uniformName || gltfTexture.id,
16641
+ id: resolvedTextureInfo.uniformName || resolvedTextureInfo.id,
16260
16642
  sampler: convertSampler(gltfSampler)
16261
16643
  };
16262
16644
  let texture;
@@ -16274,8 +16656,34 @@ out float vTime;
16274
16656
  parsedMaterial.bindings[uniformName] = texture;
16275
16657
  if (define2)
16276
16658
  parsedMaterial.defines[define2] = true;
16659
+ if (enabledUniformName) {
16660
+ parsedMaterial.uniforms[enabledUniformName] = true;
16661
+ }
16277
16662
  parsedMaterial.generatedTextures.push(texture);
16278
16663
  }
16664
+ function resolveTextureInfo(gltfTexture, gltf) {
16665
+ if (gltfTexture.texture || gltfTexture.index === void 0 || !gltf?.textures) {
16666
+ return gltfTexture;
16667
+ }
16668
+ const resolvedTextureEntry = gltf.textures[gltfTexture.index];
16669
+ if (!resolvedTextureEntry) {
16670
+ return gltfTexture;
16671
+ }
16672
+ if ("texture" in resolvedTextureEntry && resolvedTextureEntry.texture) {
16673
+ return {
16674
+ ...resolvedTextureEntry,
16675
+ ...gltfTexture,
16676
+ texture: resolvedTextureEntry.texture
16677
+ };
16678
+ }
16679
+ if (!("source" in resolvedTextureEntry)) {
16680
+ return gltfTexture;
16681
+ }
16682
+ return {
16683
+ ...gltfTexture,
16684
+ texture: resolvedTextureEntry
16685
+ };
16686
+ }
16279
16687
  function createCompressedTextureFallback(device, baseOptions) {
16280
16688
  return device.createTexture({
16281
16689
  ...baseOptions,
@@ -16385,77 +16793,51 @@ struct PointLight {
16385
16793
  vec3 attenuation; // 2nd order x:Constant-y:Linear-z:Exponential
16386
16794
  };
16387
16795
 
16796
+ struct SpotLight {
16797
+ vec3 color;
16798
+ vec3 position;
16799
+ vec3 direction;
16800
+ vec3 attenuation;
16801
+ vec2 coneCos;
16802
+ };
16803
+
16388
16804
  struct DirectionalLight {
16389
16805
  vec3 color;
16390
16806
  vec3 direction;
16391
16807
  };
16392
16808
 
16393
- uniform lightingUniforms {
16394
- int enabled;
16395
- int lightType;
16809
+ struct UniformLight {
16810
+ vec3 color;
16811
+ vec3 position;
16812
+ vec3 direction;
16813
+ vec3 attenuation;
16814
+ vec2 coneCos;
16815
+ };
16396
16816
 
16817
+ layout(std140) uniform lightingUniforms {
16818
+ int enabled;
16397
16819
  int directionalLightCount;
16398
16820
  int pointLightCount;
16399
-
16821
+ int spotLightCount;
16400
16822
  vec3 ambientColor;
16401
-
16402
- vec3 lightColor0;
16403
- vec3 lightPosition0;
16404
- vec3 lightDirection0;
16405
- vec3 lightAttenuation0;
16406
-
16407
- vec3 lightColor1;
16408
- vec3 lightPosition1;
16409
- vec3 lightDirection1;
16410
- vec3 lightAttenuation1;
16411
-
16412
- vec3 lightColor2;
16413
- vec3 lightPosition2;
16414
- vec3 lightDirection2;
16415
- vec3 lightAttenuation2;
16416
-
16417
- vec3 lightColor3;
16418
- vec3 lightPosition3;
16419
- vec3 lightDirection3;
16420
- vec3 lightAttenuation3;
16421
-
16422
- vec3 lightColor4;
16423
- vec3 lightPosition4;
16424
- vec3 lightDirection4;
16425
- vec3 lightAttenuation4;
16823
+ UniformLight lights[5];
16426
16824
  } lighting;
16427
16825
 
16428
16826
  PointLight lighting_getPointLight(int index) {
16429
- switch (index) {
16430
- case 0:
16431
- return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
16432
- case 1:
16433
- return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
16434
- case 2:
16435
- return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
16436
- case 3:
16437
- return PointLight(lighting.lightColor3, lighting.lightPosition3, lighting.lightAttenuation3);
16438
- case 4:
16439
- default:
16440
- return PointLight(lighting.lightColor4, lighting.lightPosition4, lighting.lightAttenuation4);
16441
- }
16827
+ UniformLight light = lighting.lights[index];
16828
+ return PointLight(light.color, light.position, light.attenuation);
16829
+ }
16830
+
16831
+ SpotLight lighting_getSpotLight(int index) {
16832
+ UniformLight light = lighting.lights[lighting.pointLightCount + index];
16833
+ return SpotLight(light.color, light.position, light.direction, light.attenuation, light.coneCos);
16442
16834
  }
16443
16835
 
16444
16836
  DirectionalLight lighting_getDirectionalLight(int index) {
16445
- switch (index) {
16446
- case 0:
16447
- return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
16448
- case 1:
16449
- return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
16450
- case 2:
16451
- return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
16452
- case 3:
16453
- return DirectionalLight(lighting.lightColor3, lighting.lightDirection3);
16454
- case 4:
16455
- default:
16456
- return DirectionalLight(lighting.lightColor4, lighting.lightDirection4);
16457
- }
16458
- }
16837
+ UniformLight light =
16838
+ lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];
16839
+ return DirectionalLight(light.color, light.direction);
16840
+ }
16459
16841
 
16460
16842
  float getPointLightAttenuation(PointLight pointLight, float distance) {
16461
16843
  return pointLight.attenuation.x
@@ -16463,6 +16845,20 @@ float getPointLightAttenuation(PointLight pointLight, float distance) {
16463
16845
  + pointLight.attenuation.z * distance * distance;
16464
16846
  }
16465
16847
 
16848
+ float getSpotLightAttenuation(SpotLight spotLight, vec3 positionWorldspace) {
16849
+ vec3 light_direction = normalize(positionWorldspace - spotLight.position);
16850
+ float coneFactor = smoothstep(
16851
+ spotLight.coneCos.y,
16852
+ spotLight.coneCos.x,
16853
+ dot(normalize(spotLight.direction), light_direction)
16854
+ );
16855
+ float distanceAttenuation = getPointLightAttenuation(
16856
+ PointLight(spotLight.color, spotLight.position, spotLight.attenuation),
16857
+ distance(spotLight.position, positionWorldspace)
16858
+ );
16859
+ return distanceAttenuation / max(coneFactor, 0.0001);
16860
+ }
16861
+
16466
16862
  // #endif
16467
16863
  `
16468
16864
  );
@@ -16483,105 +16879,85 @@ struct PointLight {
16483
16879
  attenuation: vec3<f32>, // 2nd order x:Constant-y:Linear-z:Exponential
16484
16880
  };
16485
16881
 
16882
+ struct SpotLight {
16883
+ color: vec3<f32>,
16884
+ position: vec3<f32>,
16885
+ direction: vec3<f32>,
16886
+ attenuation: vec3<f32>,
16887
+ coneCos: vec2<f32>,
16888
+ };
16889
+
16486
16890
  struct DirectionalLight {
16487
16891
  color: vec3<f32>,
16488
16892
  direction: vec3<f32>,
16489
16893
  };
16490
16894
 
16895
+ struct UniformLight {
16896
+ color: vec3<f32>,
16897
+ position: vec3<f32>,
16898
+ direction: vec3<f32>,
16899
+ attenuation: vec3<f32>,
16900
+ coneCos: vec2<f32>,
16901
+ };
16902
+
16491
16903
  struct lightingUniforms {
16492
16904
  enabled: i32,
16493
- lightType: i32,
16494
-
16495
16905
  directionalLightCount: i32,
16496
16906
  pointLightCount: i32,
16497
-
16907
+ spotLightCount: i32,
16498
16908
  ambientColor: vec3<f32>,
16499
-
16500
- lightColor0: vec3<f32>,
16501
- lightPosition0: vec3<f32>,
16502
- lightDirection0: vec3<f32>,
16503
- lightAttenuation0: vec3<f32>,
16504
-
16505
- lightColor1: vec3<f32>,
16506
- lightPosition1: vec3<f32>,
16507
- lightDirection1: vec3<f32>,
16508
- lightAttenuation1: vec3<f32>,
16509
-
16510
- lightColor2: vec3<f32>,
16511
- lightPosition2: vec3<f32>,
16512
- lightDirection2: vec3<f32>,
16513
- lightAttenuation2: vec3<f32>,
16514
-
16515
- lightColor3: vec3<f32>,
16516
- lightPosition3: vec3<f32>,
16517
- lightDirection3: vec3<f32>,
16518
- lightAttenuation3: vec3<f32>,
16519
-
16520
- lightColor4: vec3<f32>,
16521
- lightPosition4: vec3<f32>,
16522
- lightDirection4: vec3<f32>,
16523
- lightAttenuation4: vec3<f32>,
16909
+ lights: array<UniformLight, 5>,
16524
16910
  };
16525
16911
 
16526
- // Binding 0:1 is reserved for lighting (Note: could go into separate bind group as it is stable across draw calls)
16527
- @binding(1) @group(0) var<uniform> lighting : lightingUniforms;
16912
+ @group(2) @binding(auto) var<uniform> lighting : lightingUniforms;
16528
16913
 
16529
16914
  fn lighting_getPointLight(index: i32) -> PointLight {
16530
- switch (index) {
16531
- case 0: {
16532
- return PointLight(lighting.lightColor0, lighting.lightPosition0, lighting.lightAttenuation0);
16533
- }
16534
- case 1: {
16535
- return PointLight(lighting.lightColor1, lighting.lightPosition1, lighting.lightAttenuation1);
16536
- }
16537
- case 2: {
16538
- return PointLight(lighting.lightColor2, lighting.lightPosition2, lighting.lightAttenuation2);
16539
- }
16540
- case 3: {
16541
- return PointLight(lighting.lightColor3, lighting.lightPosition3, lighting.lightAttenuation3);
16542
- }
16543
- case 4, default: {
16544
- return PointLight(lighting.lightColor4, lighting.lightPosition4, lighting.lightAttenuation4);
16545
- }
16546
- }
16915
+ let light = lighting.lights[index];
16916
+ return PointLight(light.color, light.position, light.attenuation);
16917
+ }
16918
+
16919
+ fn lighting_getSpotLight(index: i32) -> SpotLight {
16920
+ let light = lighting.lights[lighting.pointLightCount + index];
16921
+ return SpotLight(light.color, light.position, light.direction, light.attenuation, light.coneCos);
16547
16922
  }
16548
16923
 
16549
16924
  fn lighting_getDirectionalLight(index: i32) -> DirectionalLight {
16550
- switch (index) {
16551
- case 0: {
16552
- return DirectionalLight(lighting.lightColor0, lighting.lightDirection0);
16553
- }
16554
- case 1: {
16555
- return DirectionalLight(lighting.lightColor1, lighting.lightDirection1);
16556
- }
16557
- case 2: {
16558
- return DirectionalLight(lighting.lightColor2, lighting.lightDirection2);
16559
- }
16560
- case 3: {
16561
- return DirectionalLight(lighting.lightColor3, lighting.lightDirection3);
16562
- }
16563
- case 4, default: {
16564
- return DirectionalLight(lighting.lightColor4, lighting.lightDirection4);
16565
- }
16566
- }
16567
- }
16925
+ let light = lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];
16926
+ return DirectionalLight(light.color, light.direction);
16927
+ }
16568
16928
 
16569
16929
  fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
16570
16930
  return pointLight.attenuation.x
16571
16931
  + pointLight.attenuation.y * distance
16572
16932
  + pointLight.attenuation.z * distance * distance;
16573
16933
  }
16934
+
16935
+ fn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3<f32>) -> f32 {
16936
+ let lightDirection = normalize(positionWorldspace - spotLight.position);
16937
+ let coneFactor = smoothstep(
16938
+ spotLight.coneCos.y,
16939
+ spotLight.coneCos.x,
16940
+ dot(normalize(spotLight.direction), lightDirection)
16941
+ );
16942
+ let distanceAttenuation = getPointLightAttenuation(
16943
+ PointLight(spotLight.color, spotLight.position, spotLight.attenuation),
16944
+ distance(spotLight.position, positionWorldspace)
16945
+ );
16946
+ return distanceAttenuation / max(coneFactor, 0.0001);
16947
+ }
16574
16948
  `
16575
16949
  );
16576
16950
 
16577
16951
  // ../../node_modules/@luma.gl/shadertools/dist/modules/lighting/lights/lighting.js
16578
16952
  var MAX_LIGHTS = 5;
16579
16953
  var COLOR_FACTOR = 255;
16580
- var LIGHT_TYPE;
16581
- (function(LIGHT_TYPE2) {
16582
- LIGHT_TYPE2[LIGHT_TYPE2["POINT"] = 0] = "POINT";
16583
- LIGHT_TYPE2[LIGHT_TYPE2["DIRECTIONAL"] = 1] = "DIRECTIONAL";
16584
- })(LIGHT_TYPE || (LIGHT_TYPE = {}));
16954
+ var LIGHT_UNIFORM_TYPE = {
16955
+ color: "vec3<f32>",
16956
+ position: "vec3<f32>",
16957
+ direction: "vec3<f32>",
16958
+ attenuation: "vec3<f32>",
16959
+ coneCos: "vec2<f32>"
16960
+ };
16585
16961
  var lighting = {
16586
16962
  props: {},
16587
16963
  uniforms: {},
@@ -16591,127 +16967,104 @@ fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
16591
16967
  },
16592
16968
  uniformTypes: {
16593
16969
  enabled: "i32",
16594
- lightType: "i32",
16595
16970
  directionalLightCount: "i32",
16596
16971
  pointLightCount: "i32",
16972
+ spotLightCount: "i32",
16597
16973
  ambientColor: "vec3<f32>",
16598
- // TODO define as arrays once we have appropriate uniformTypes
16599
- lightColor0: "vec3<f32>",
16600
- lightPosition0: "vec3<f32>",
16601
- // TODO - could combine direction and attenuation
16602
- lightDirection0: "vec3<f32>",
16603
- lightAttenuation0: "vec3<f32>",
16604
- lightColor1: "vec3<f32>",
16605
- lightPosition1: "vec3<f32>",
16606
- lightDirection1: "vec3<f32>",
16607
- lightAttenuation1: "vec3<f32>",
16608
- lightColor2: "vec3<f32>",
16609
- lightPosition2: "vec3<f32>",
16610
- lightDirection2: "vec3<f32>",
16611
- lightAttenuation2: "vec3<f32>",
16612
- lightColor3: "vec3<f32>",
16613
- lightPosition3: "vec3<f32>",
16614
- lightDirection3: "vec3<f32>",
16615
- lightAttenuation3: "vec3<f32>",
16616
- lightColor4: "vec3<f32>",
16617
- lightPosition4: "vec3<f32>",
16618
- lightDirection4: "vec3<f32>",
16619
- lightAttenuation4: "vec3<f32>"
16620
- },
16621
- defaultUniforms: {
16622
- enabled: 1,
16623
- lightType: LIGHT_TYPE.POINT,
16624
- directionalLightCount: 0,
16625
- pointLightCount: 0,
16626
- ambientColor: [0.1, 0.1, 0.1],
16627
- lightColor0: [1, 1, 1],
16628
- lightPosition0: [1, 1, 2],
16629
- // TODO - could combine direction and attenuation
16630
- lightDirection0: [1, 1, 1],
16631
- lightAttenuation0: [1, 0, 0],
16632
- lightColor1: [1, 1, 1],
16633
- lightPosition1: [1, 1, 2],
16634
- lightDirection1: [1, 1, 1],
16635
- lightAttenuation1: [1, 0, 0],
16636
- lightColor2: [1, 1, 1],
16637
- lightPosition2: [1, 1, 2],
16638
- lightDirection2: [1, 1, 1],
16639
- lightAttenuation2: [1, 0, 0],
16640
- lightColor3: [1, 1, 1],
16641
- lightPosition3: [1, 1, 2],
16642
- lightDirection3: [1, 1, 1],
16643
- lightAttenuation3: [1, 0, 0],
16644
- lightColor4: [1, 1, 1],
16645
- lightPosition4: [1, 1, 2],
16646
- lightDirection4: [1, 1, 1],
16647
- lightAttenuation4: [1, 0, 0]
16974
+ lights: [LIGHT_UNIFORM_TYPE, MAX_LIGHTS]
16648
16975
  },
16976
+ defaultUniforms: createDefaultLightingUniforms(),
16977
+ bindingLayout: [{ name: "lighting", group: 2 }],
16978
+ firstBindingSlot: 0,
16649
16979
  source: lightingUniformsWGSL,
16650
16980
  vs: lightingUniformsGLSL,
16651
16981
  fs: lightingUniformsGLSL,
16652
16982
  getUniforms
16653
16983
  };
16654
- function getUniforms(props, prevUniforms = {}) {
16984
+ function getUniforms(props, _prevUniforms = {}) {
16655
16985
  props = props ? { ...props } : props;
16656
16986
  if (!props) {
16657
- return { ...lighting.defaultUniforms };
16987
+ return createDefaultLightingUniforms();
16658
16988
  }
16659
16989
  if (props.lights) {
16660
16990
  props = { ...props, ...extractLightTypes(props.lights), lights: void 0 };
16661
16991
  }
16662
- const { ambientLight, pointLights, directionalLights } = props || {};
16663
- const hasLights = ambientLight || pointLights && pointLights.length > 0 || directionalLights && directionalLights.length > 0;
16992
+ const { ambientLight, pointLights, spotLights, directionalLights } = props || {};
16993
+ const hasLights = ambientLight || pointLights && pointLights.length > 0 || spotLights && spotLights.length > 0 || directionalLights && directionalLights.length > 0;
16664
16994
  if (!hasLights) {
16665
- return { ...lighting.defaultUniforms, enabled: 0 };
16995
+ return {
16996
+ ...createDefaultLightingUniforms(),
16997
+ enabled: 0
16998
+ };
16666
16999
  }
16667
17000
  const uniforms = {
16668
- ...lighting.defaultUniforms,
16669
- ...prevUniforms,
16670
- ...getLightSourceUniforms({ ambientLight, pointLights, directionalLights })
17001
+ ...createDefaultLightingUniforms(),
17002
+ ...getLightSourceUniforms({ ambientLight, pointLights, spotLights, directionalLights })
16671
17003
  };
16672
17004
  if (props.enabled !== void 0) {
16673
17005
  uniforms.enabled = props.enabled ? 1 : 0;
16674
17006
  }
16675
17007
  return uniforms;
16676
17008
  }
16677
- function getLightSourceUniforms({ ambientLight, pointLights = [], directionalLights = [] }) {
16678
- const lightSourceUniforms = {};
16679
- lightSourceUniforms.ambientColor = convertColor(ambientLight);
17009
+ function getLightSourceUniforms({ ambientLight, pointLights = [], spotLights = [], directionalLights = [] }) {
17010
+ const lights = createDefaultLightUniforms();
16680
17011
  let currentLight = 0;
16681
17012
  let pointLightCount = 0;
17013
+ let spotLightCount = 0;
16682
17014
  let directionalLightCount = 0;
16683
17015
  for (const pointLight of pointLights) {
16684
17016
  if (currentLight >= MAX_LIGHTS) {
16685
17017
  break;
16686
17018
  }
16687
- lightSourceUniforms.lightType = LIGHT_TYPE.POINT;
16688
- const i = currentLight;
16689
- lightSourceUniforms[`lightColor${i}`] = convertColor(pointLight);
16690
- lightSourceUniforms[`lightPosition${i}`] = pointLight.position;
16691
- lightSourceUniforms[`lightAttenuation${i}`] = pointLight.attenuation || [1, 0, 0];
17019
+ lights[currentLight] = {
17020
+ ...lights[currentLight],
17021
+ color: convertColor(pointLight),
17022
+ position: pointLight.position,
17023
+ attenuation: pointLight.attenuation || [1, 0, 0]
17024
+ };
16692
17025
  currentLight++;
16693
17026
  pointLightCount++;
16694
17027
  }
17028
+ for (const spotLight of spotLights) {
17029
+ if (currentLight >= MAX_LIGHTS) {
17030
+ break;
17031
+ }
17032
+ lights[currentLight] = {
17033
+ ...lights[currentLight],
17034
+ color: convertColor(spotLight),
17035
+ position: spotLight.position,
17036
+ direction: spotLight.direction,
17037
+ attenuation: spotLight.attenuation || [1, 0, 0],
17038
+ coneCos: getSpotConeCos(spotLight)
17039
+ };
17040
+ currentLight++;
17041
+ spotLightCount++;
17042
+ }
16695
17043
  for (const directionalLight of directionalLights) {
16696
17044
  if (currentLight >= MAX_LIGHTS) {
16697
17045
  break;
16698
17046
  }
16699
- lightSourceUniforms.lightType = LIGHT_TYPE.DIRECTIONAL;
16700
- const i = currentLight;
16701
- lightSourceUniforms[`lightColor${i}`] = convertColor(directionalLight);
16702
- lightSourceUniforms[`lightDirection${i}`] = directionalLight.direction;
17047
+ lights[currentLight] = {
17048
+ ...lights[currentLight],
17049
+ color: convertColor(directionalLight),
17050
+ direction: directionalLight.direction
17051
+ };
16703
17052
  currentLight++;
16704
17053
  directionalLightCount++;
16705
17054
  }
16706
- if (pointLights.length + directionalLights.length > MAX_LIGHTS) {
17055
+ if (pointLights.length + spotLights.length + directionalLights.length > MAX_LIGHTS) {
16707
17056
  import_core21.log.warn(`MAX_LIGHTS exceeded, truncating to ${MAX_LIGHTS}`)();
16708
17057
  }
16709
- lightSourceUniforms.directionalLightCount = directionalLightCount;
16710
- lightSourceUniforms.pointLightCount = pointLightCount;
16711
- return lightSourceUniforms;
17058
+ return {
17059
+ ambientColor: convertColor(ambientLight),
17060
+ directionalLightCount,
17061
+ pointLightCount,
17062
+ spotLightCount,
17063
+ lights
17064
+ };
16712
17065
  }
16713
17066
  function extractLightTypes(lights) {
16714
- const lightSources = { pointLights: [], directionalLights: [] };
17067
+ const lightSources = { pointLights: [], spotLights: [], directionalLights: [] };
16715
17068
  for (const light of lights || []) {
16716
17069
  switch (light.type) {
16717
17070
  case "ambient":
@@ -16723,6 +17076,9 @@ fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
16723
17076
  case "point":
16724
17077
  lightSources.pointLights?.push(light);
16725
17078
  break;
17079
+ case "spot":
17080
+ lightSources.spotLights?.push(light);
17081
+ break;
16726
17082
  default:
16727
17083
  }
16728
17084
  }
@@ -16732,6 +17088,68 @@ fn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {
16732
17088
  const { color = [0, 0, 0], intensity = 1 } = colorDef;
16733
17089
  return color.map((component) => component * intensity / COLOR_FACTOR);
16734
17090
  }
17091
+ function createDefaultLightingUniforms() {
17092
+ return {
17093
+ enabled: 1,
17094
+ directionalLightCount: 0,
17095
+ pointLightCount: 0,
17096
+ spotLightCount: 0,
17097
+ ambientColor: [0.1, 0.1, 0.1],
17098
+ lights: createDefaultLightUniforms()
17099
+ };
17100
+ }
17101
+ function createDefaultLightUniforms() {
17102
+ return Array.from({ length: MAX_LIGHTS }, () => createDefaultLightUniform());
17103
+ }
17104
+ function createDefaultLightUniform() {
17105
+ return {
17106
+ color: [1, 1, 1],
17107
+ position: [1, 1, 2],
17108
+ direction: [1, 1, 1],
17109
+ attenuation: [1, 0, 0],
17110
+ coneCos: [1, 0]
17111
+ };
17112
+ }
17113
+ function getSpotConeCos(spotLight) {
17114
+ const innerConeAngle = spotLight.innerConeAngle ?? 0;
17115
+ const outerConeAngle = spotLight.outerConeAngle ?? Math.PI / 4;
17116
+ return [Math.cos(innerConeAngle), Math.cos(outerConeAngle)];
17117
+ }
17118
+
17119
+ // ../../node_modules/@luma.gl/shadertools/dist/modules/lighting/ibl/ibl.js
17120
+ var iblWGSL = (
17121
+ /* wgsl */
17122
+ `#ifdef USE_IBL
17123
+ @group(2) @binding(auto) var pbr_diffuseEnvSampler: texture_cube<f32>;
17124
+ @group(2) @binding(auto) var pbr_diffuseEnvSamplerSampler: sampler;
17125
+ @group(2) @binding(auto) var pbr_specularEnvSampler: texture_cube<f32>;
17126
+ @group(2) @binding(auto) var pbr_specularEnvSamplerSampler: sampler;
17127
+ @group(2) @binding(auto) var pbr_brdfLUT: texture_2d<f32>;
17128
+ @group(2) @binding(auto) var pbr_brdfLUTSampler: sampler;
17129
+ #endif
17130
+ `
17131
+ );
17132
+ var iblGLSL = (
17133
+ /* glsl */
17134
+ `#ifdef USE_IBL
17135
+ uniform samplerCube pbr_diffuseEnvSampler;
17136
+ uniform samplerCube pbr_specularEnvSampler;
17137
+ uniform sampler2D pbr_brdfLUT;
17138
+ #endif
17139
+ `
17140
+ );
17141
+ var ibl = {
17142
+ name: "ibl",
17143
+ firstBindingSlot: 32,
17144
+ bindingLayout: [
17145
+ { name: "pbr_diffuseEnvSampler", group: 2 },
17146
+ { name: "pbr_specularEnvSampler", group: 2 },
17147
+ { name: "pbr_brdfLUT", group: 2 }
17148
+ ],
17149
+ source: iblWGSL,
17150
+ vs: iblGLSL,
17151
+ fs: iblGLSL
17152
+ };
16735
17153
 
16736
17154
  // ../../node_modules/@luma.gl/shadertools/dist/modules/lighting/pbr-material/pbr-material-glsl.js
16737
17155
  var vs = (
@@ -16775,7 +17193,7 @@ void pbr_setPositionNormalTangentUV(vec4 position, vec4 normal, vec4 tangent, ve
16775
17193
  /* glsl */
16776
17194
  `precision highp float;
16777
17195
 
16778
- uniform pbrMaterialUniforms {
17196
+ layout(std140) uniform pbrMaterialUniforms {
16779
17197
  // Material is unlit
16780
17198
  bool unlit;
16781
17199
 
@@ -16815,10 +17233,12 @@ uniform pbrMaterialUniforms {
16815
17233
  float clearcoatFactor;
16816
17234
  float clearcoatRoughnessFactor;
16817
17235
  bool clearcoatMapEnabled;
17236
+ bool clearcoatRoughnessMapEnabled;
16818
17237
 
16819
17238
  vec3 sheenColorFactor;
16820
17239
  float sheenRoughnessFactor;
16821
17240
  bool sheenColorMapEnabled;
17241
+ bool sheenRoughnessMapEnabled;
16822
17242
 
16823
17243
  float iridescenceFactor;
16824
17244
  float iridescenceIor;
@@ -16868,26 +17288,33 @@ uniform sampler2D pbr_specularIntensitySampler;
16868
17288
  #ifdef HAS_TRANSMISSIONMAP
16869
17289
  uniform sampler2D pbr_transmissionSampler;
16870
17290
  #endif
17291
+ #ifdef HAS_THICKNESSMAP
17292
+ uniform sampler2D pbr_thicknessSampler;
17293
+ #endif
16871
17294
  #ifdef HAS_CLEARCOATMAP
16872
17295
  uniform sampler2D pbr_clearcoatSampler;
17296
+ #endif
17297
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
16873
17298
  uniform sampler2D pbr_clearcoatRoughnessSampler;
16874
17299
  #endif
17300
+ #ifdef HAS_CLEARCOATNORMALMAP
17301
+ uniform sampler2D pbr_clearcoatNormalSampler;
17302
+ #endif
16875
17303
  #ifdef HAS_SHEENCOLORMAP
16876
17304
  uniform sampler2D pbr_sheenColorSampler;
17305
+ #endif
17306
+ #ifdef HAS_SHEENROUGHNESSMAP
16877
17307
  uniform sampler2D pbr_sheenRoughnessSampler;
16878
17308
  #endif
16879
17309
  #ifdef HAS_IRIDESCENCEMAP
16880
17310
  uniform sampler2D pbr_iridescenceSampler;
16881
17311
  #endif
17312
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
17313
+ uniform sampler2D pbr_iridescenceThicknessSampler;
17314
+ #endif
16882
17315
  #ifdef HAS_ANISOTROPYMAP
16883
17316
  uniform sampler2D pbr_anisotropySampler;
16884
17317
  #endif
16885
- #ifdef USE_IBL
16886
- uniform samplerCube pbr_diffuseEnvSampler;
16887
- uniform samplerCube pbr_specularEnvSampler;
16888
- uniform sampler2D pbr_brdfLUT;
16889
- #endif
16890
-
16891
17318
  // Inputs from vertex shader
16892
17319
 
16893
17320
  in vec3 pbr_vPosition;
@@ -16924,6 +17351,8 @@ struct PBRInfo {
16924
17351
  const float M_PI = 3.141592653589793;
16925
17352
  const float c_MinRoughness = 0.04;
16926
17353
 
17354
+ vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor);
17355
+
16927
17356
  vec4 SRGBtoLINEAR(vec4 srgbIn)
16928
17357
  {
16929
17358
  #ifdef MANUAL_SRGB
@@ -16939,11 +17368,9 @@ vec4 SRGBtoLINEAR(vec4 srgbIn)
16939
17368
  #endif //MANUAL_SRGB
16940
17369
  }
16941
17370
 
16942
- // Find the normal for this fragment, pulling either from a predefined normal map
16943
- // or from the interpolated mesh normal and tangent attributes.
16944
- vec3 getNormal()
17371
+ // Build the tangent basis from interpolated attributes or screen-space derivatives.
17372
+ mat3 getTBN()
16945
17373
  {
16946
- // Retrieve the tangent space matrix
16947
17374
  #ifndef HAS_TANGENTS
16948
17375
  vec3 pos_dx = dFdx(pbr_vPosition);
16949
17376
  vec3 pos_dy = dFdy(pbr_vPosition);
@@ -16964,9 +17391,21 @@ vec3 getNormal()
16964
17391
  mat3 tbn = pbr_vTBN;
16965
17392
  #endif
16966
17393
 
17394
+ return tbn;
17395
+ }
17396
+
17397
+ // Find the normal for this fragment, pulling either from a predefined normal map
17398
+ // or from the interpolated mesh normal and tangent attributes.
17399
+ vec3 getMappedNormal(sampler2D normalSampler, mat3 tbn, float normalScale)
17400
+ {
17401
+ vec3 n = texture(normalSampler, pbr_vUV).rgb;
17402
+ return normalize(tbn * ((2.0 * n - 1.0) * vec3(normalScale, normalScale, 1.0)));
17403
+ }
17404
+
17405
+ vec3 getNormal(mat3 tbn)
17406
+ {
16967
17407
  #ifdef HAS_NORMALMAP
16968
- vec3 n = texture(pbr_normalSampler, pbr_vUV).rgb;
16969
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
17408
+ vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale);
16970
17409
  #else
16971
17410
  // The tbn matrix is linearly interpolated, so we need to re-normalize
16972
17411
  vec3 n = normalize(tbn[2].xyz);
@@ -16975,6 +17414,15 @@ vec3 getNormal()
16975
17414
  return n;
16976
17415
  }
16977
17416
 
17417
+ vec3 getClearcoatNormal(mat3 tbn, vec3 baseNormal)
17418
+ {
17419
+ #ifdef HAS_CLEARCOATNORMALMAP
17420
+ return getMappedNormal(pbr_clearcoatNormalSampler, tbn, 1.0);
17421
+ #else
17422
+ return baseNormal;
17423
+ #endif
17424
+ }
17425
+
16978
17426
  // Calculation of the lighting contribution from an optional Image Based Light source.
16979
17427
  // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
16980
17428
  // See our README.md on Environment Maps [3] for additional discussion.
@@ -17050,6 +17498,169 @@ float microfacetDistribution(PBRInfo pbrInfo)
17050
17498
  return roughnessSq / (M_PI * f * f);
17051
17499
  }
17052
17500
 
17501
+ float maxComponent(vec3 value)
17502
+ {
17503
+ return max(max(value.r, value.g), value.b);
17504
+ }
17505
+
17506
+ float getDielectricF0(float ior)
17507
+ {
17508
+ float clampedIor = max(ior, 1.0);
17509
+ float ratio = (clampedIor - 1.0) / (clampedIor + 1.0);
17510
+ return ratio * ratio;
17511
+ }
17512
+
17513
+ vec2 normalizeDirection(vec2 direction)
17514
+ {
17515
+ float directionLength = length(direction);
17516
+ return directionLength > 0.0001 ? direction / directionLength : vec2(1.0, 0.0);
17517
+ }
17518
+
17519
+ vec2 rotateDirection(vec2 direction, float rotation)
17520
+ {
17521
+ float s = sin(rotation);
17522
+ float c = cos(rotation);
17523
+ return vec2(direction.x * c - direction.y * s, direction.x * s + direction.y * c);
17524
+ }
17525
+
17526
+ vec3 getIridescenceTint(float iridescence, float thickness, float NdotV)
17527
+ {
17528
+ if (iridescence <= 0.0) {
17529
+ return vec3(1.0);
17530
+ }
17531
+
17532
+ float phase = 0.015 * thickness * pbrMaterial.iridescenceIor + (1.0 - NdotV) * 6.0;
17533
+ vec3 thinFilmTint =
17534
+ 0.5 + 0.5 * cos(vec3(phase, phase + 2.0943951, phase + 4.1887902));
17535
+ return mix(vec3(1.0), thinFilmTint, iridescence);
17536
+ }
17537
+
17538
+ vec3 getVolumeAttenuation(float thickness)
17539
+ {
17540
+ if (thickness <= 0.0) {
17541
+ return vec3(1.0);
17542
+ }
17543
+
17544
+ vec3 attenuationCoefficient =
17545
+ -log(max(pbrMaterial.attenuationColor, vec3(0.0001))) /
17546
+ max(pbrMaterial.attenuationDistance, 0.0001);
17547
+ return exp(-attenuationCoefficient * thickness);
17548
+ }
17549
+
17550
+ PBRInfo createClearcoatPBRInfo(PBRInfo basePBRInfo, vec3 clearcoatNormal, float clearcoatRoughness)
17551
+ {
17552
+ float perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
17553
+ float alphaRoughness = perceptualRoughness * perceptualRoughness;
17554
+ float NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);
17555
+
17556
+ return PBRInfo(
17557
+ basePBRInfo.NdotL,
17558
+ NdotV,
17559
+ basePBRInfo.NdotH,
17560
+ basePBRInfo.LdotH,
17561
+ basePBRInfo.VdotH,
17562
+ perceptualRoughness,
17563
+ 0.0,
17564
+ vec3(0.04),
17565
+ vec3(1.0),
17566
+ alphaRoughness,
17567
+ vec3(0.0),
17568
+ vec3(0.04),
17569
+ clearcoatNormal,
17570
+ basePBRInfo.v
17571
+ );
17572
+ }
17573
+
17574
+ vec3 calculateClearcoatContribution(
17575
+ PBRInfo pbrInfo,
17576
+ vec3 lightColor,
17577
+ vec3 clearcoatNormal,
17578
+ float clearcoatFactor,
17579
+ float clearcoatRoughness
17580
+ ) {
17581
+ if (clearcoatFactor <= 0.0) {
17582
+ return vec3(0.0);
17583
+ }
17584
+
17585
+ PBRInfo clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
17586
+ return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;
17587
+ }
17588
+
17589
+ #ifdef USE_IBL
17590
+ vec3 calculateClearcoatIBLContribution(
17591
+ PBRInfo pbrInfo,
17592
+ vec3 clearcoatNormal,
17593
+ vec3 reflection,
17594
+ float clearcoatFactor,
17595
+ float clearcoatRoughness
17596
+ ) {
17597
+ if (clearcoatFactor <= 0.0) {
17598
+ return vec3(0.0);
17599
+ }
17600
+
17601
+ PBRInfo clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
17602
+ return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;
17603
+ }
17604
+ #endif
17605
+
17606
+ vec3 calculateSheenContribution(
17607
+ PBRInfo pbrInfo,
17608
+ vec3 lightColor,
17609
+ vec3 sheenColor,
17610
+ float sheenRoughness
17611
+ ) {
17612
+ if (maxComponent(sheenColor) <= 0.0) {
17613
+ return vec3(0.0);
17614
+ }
17615
+
17616
+ float sheenFresnel = pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
17617
+ float sheenVisibility = mix(1.0, pbrInfo.NdotL * pbrInfo.NdotV, sheenRoughness);
17618
+ return pbrInfo.NdotL *
17619
+ lightColor *
17620
+ sheenColor *
17621
+ (0.25 + 0.75 * sheenFresnel) *
17622
+ sheenVisibility *
17623
+ (1.0 - pbrInfo.metalness);
17624
+ }
17625
+
17626
+ float calculateAnisotropyBoost(
17627
+ PBRInfo pbrInfo,
17628
+ vec3 anisotropyTangent,
17629
+ float anisotropyStrength
17630
+ ) {
17631
+ if (anisotropyStrength <= 0.0) {
17632
+ return 1.0;
17633
+ }
17634
+
17635
+ vec3 anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));
17636
+ float bitangentViewAlignment = abs(dot(pbrInfo.v, anisotropyBitangent));
17637
+ return mix(1.0, 0.65 + 0.7 * bitangentViewAlignment, anisotropyStrength);
17638
+ }
17639
+
17640
+ vec3 calculateMaterialLightColor(
17641
+ PBRInfo pbrInfo,
17642
+ vec3 lightColor,
17643
+ vec3 clearcoatNormal,
17644
+ float clearcoatFactor,
17645
+ float clearcoatRoughness,
17646
+ vec3 sheenColor,
17647
+ float sheenRoughness,
17648
+ vec3 anisotropyTangent,
17649
+ float anisotropyStrength
17650
+ ) {
17651
+ float anisotropyBoost = calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
17652
+ vec3 color = calculateFinalColor(pbrInfo, lightColor) * anisotropyBoost;
17653
+ color += calculateClearcoatContribution(
17654
+ pbrInfo,
17655
+ lightColor,
17656
+ clearcoatNormal,
17657
+ clearcoatFactor,
17658
+ clearcoatRoughness
17659
+ );
17660
+ color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);
17661
+ return color;
17662
+ }
17663
+
17053
17664
  void PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {
17054
17665
  pbrInfo.NdotL = 1.0;
17055
17666
  pbrInfo.NdotH = 0.0;
@@ -17074,6 +17685,11 @@ void PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) {
17074
17685
  PBRInfo_setDirectionalLight(pbrInfo, light_direction);
17075
17686
  }
17076
17687
 
17688
+ void PBRInfo_setSpotLight(inout PBRInfo pbrInfo, SpotLight spotLight) {
17689
+ vec3 light_direction = normalize(spotLight.position - pbr_vPosition);
17690
+ PBRInfo_setDirectionalLight(pbrInfo, light_direction);
17691
+ }
17692
+
17077
17693
  vec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {
17078
17694
  // Calculate the shading terms for the microfacet specular shading model
17079
17695
  vec3 F = specularReflection(pbrInfo);
@@ -17096,40 +17712,280 @@ vec4 pbr_filterColor(vec4 colorUnused)
17096
17712
  vec4 baseColor = pbrMaterial.baseColorFactor;
17097
17713
  #endif
17098
17714
 
17099
- #ifdef ALPHA_CUTOFF
17100
- if (baseColor.a < pbrMaterial.alphaCutoff) {
17101
- discard;
17102
- }
17715
+ #ifdef ALPHA_CUTOFF
17716
+ if (baseColor.a < pbrMaterial.alphaCutoff) {
17717
+ discard;
17718
+ }
17719
+ #endif
17720
+
17721
+ vec3 color = vec3(0, 0, 0);
17722
+
17723
+ float transmission = 0.0;
17724
+
17725
+ if(pbrMaterial.unlit){
17726
+ color.rgb = baseColor.rgb;
17727
+ }
17728
+ else{
17729
+ // Metallic and Roughness material properties are packed together
17730
+ // In glTF, these factors can be specified by fixed scalar values
17731
+ // or from a metallic-roughness map
17732
+ float perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;
17733
+ float metallic = pbrMaterial.metallicRoughnessValues.x;
17734
+ #ifdef HAS_METALROUGHNESSMAP
17735
+ // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
17736
+ // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
17737
+ vec4 mrSample = texture(pbr_metallicRoughnessSampler, pbr_vUV);
17738
+ perceptualRoughness = mrSample.g * perceptualRoughness;
17739
+ metallic = mrSample.b * metallic;
17740
+ #endif
17741
+ perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
17742
+ metallic = clamp(metallic, 0.0, 1.0);
17743
+ mat3 tbn = getTBN();
17744
+ vec3 n = getNormal(tbn); // normal at surface point
17745
+ vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
17746
+ float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
17747
+ #ifdef USE_MATERIAL_EXTENSIONS
17748
+ bool useExtendedPBR =
17749
+ pbrMaterial.specularColorMapEnabled ||
17750
+ pbrMaterial.specularIntensityMapEnabled ||
17751
+ abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||
17752
+ maxComponent(abs(pbrMaterial.specularColorFactor - vec3(1.0))) > 0.0001 ||
17753
+ abs(pbrMaterial.ior - 1.5) > 0.0001 ||
17754
+ pbrMaterial.transmissionMapEnabled ||
17755
+ pbrMaterial.transmissionFactor > 0.0001 ||
17756
+ pbrMaterial.clearcoatMapEnabled ||
17757
+ pbrMaterial.clearcoatRoughnessMapEnabled ||
17758
+ pbrMaterial.clearcoatFactor > 0.0001 ||
17759
+ pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||
17760
+ pbrMaterial.sheenColorMapEnabled ||
17761
+ pbrMaterial.sheenRoughnessMapEnabled ||
17762
+ maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||
17763
+ pbrMaterial.sheenRoughnessFactor > 0.0001 ||
17764
+ pbrMaterial.iridescenceMapEnabled ||
17765
+ pbrMaterial.iridescenceFactor > 0.0001 ||
17766
+ abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||
17767
+ abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||
17768
+ abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||
17769
+ pbrMaterial.anisotropyMapEnabled ||
17770
+ pbrMaterial.anisotropyStrength > 0.0001 ||
17771
+ abs(pbrMaterial.anisotropyRotation) > 0.0001 ||
17772
+ length(pbrMaterial.anisotropyDirection - vec2(1.0, 0.0)) > 0.0001;
17773
+ #else
17774
+ bool useExtendedPBR = false;
17775
+ #endif
17776
+
17777
+ if (!useExtendedPBR) {
17778
+ // Keep the baseline metallic-roughness implementation byte-for-byte equivalent in behavior.
17779
+ float alphaRoughness = perceptualRoughness * perceptualRoughness;
17780
+
17781
+ vec3 f0 = vec3(0.04);
17782
+ vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
17783
+ diffuseColor *= 1.0 - metallic;
17784
+ vec3 specularColor = mix(f0, baseColor.rgb, metallic);
17785
+
17786
+ float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
17787
+ float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
17788
+ vec3 specularEnvironmentR0 = specularColor.rgb;
17789
+ vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
17790
+ vec3 reflection = -normalize(reflect(v, n));
17791
+
17792
+ PBRInfo pbrInfo = PBRInfo(
17793
+ 0.0, // NdotL
17794
+ NdotV,
17795
+ 0.0, // NdotH
17796
+ 0.0, // LdotH
17797
+ 0.0, // VdotH
17798
+ perceptualRoughness,
17799
+ metallic,
17800
+ specularEnvironmentR0,
17801
+ specularEnvironmentR90,
17802
+ alphaRoughness,
17803
+ diffuseColor,
17804
+ specularColor,
17805
+ n,
17806
+ v
17807
+ );
17808
+
17809
+ #ifdef USE_LIGHTS
17810
+ PBRInfo_setAmbientLight(pbrInfo);
17811
+ color += calculateFinalColor(pbrInfo, lighting.ambientColor);
17812
+
17813
+ for(int i = 0; i < lighting.directionalLightCount; i++) {
17814
+ if (i < lighting.directionalLightCount) {
17815
+ PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
17816
+ color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
17817
+ }
17818
+ }
17819
+
17820
+ for(int i = 0; i < lighting.pointLightCount; i++) {
17821
+ if (i < lighting.pointLightCount) {
17822
+ PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
17823
+ float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
17824
+ color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
17825
+ }
17826
+ }
17827
+
17828
+ for(int i = 0; i < lighting.spotLightCount; i++) {
17829
+ if (i < lighting.spotLightCount) {
17830
+ PBRInfo_setSpotLight(pbrInfo, lighting_getSpotLight(i));
17831
+ float attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), pbr_vPosition);
17832
+ color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color / attenuation);
17833
+ }
17834
+ }
17835
+ #endif
17836
+
17837
+ #ifdef USE_IBL
17838
+ if (pbrMaterial.IBLenabled) {
17839
+ color += getIBLContribution(pbrInfo, n, reflection);
17840
+ }
17841
+ #endif
17842
+
17843
+ #ifdef HAS_OCCLUSIONMAP
17844
+ if (pbrMaterial.occlusionMapEnabled) {
17845
+ float ao = texture(pbr_occlusionSampler, pbr_vUV).r;
17846
+ color = mix(color, color * ao, pbrMaterial.occlusionStrength);
17847
+ }
17848
+ #endif
17849
+
17850
+ vec3 emissive = pbrMaterial.emissiveFactor;
17851
+ #ifdef HAS_EMISSIVEMAP
17852
+ if (pbrMaterial.emissiveMapEnabled) {
17853
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
17854
+ }
17855
+ #endif
17856
+ color += emissive * pbrMaterial.emissiveStrength;
17857
+
17858
+ #ifdef PBR_DEBUG
17859
+ color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
17860
+ color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);
17861
+ color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
17862
+ #endif
17863
+
17864
+ return vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a);
17865
+ }
17866
+
17867
+ float specularIntensity = pbrMaterial.specularIntensityFactor;
17868
+ #ifdef HAS_SPECULARINTENSITYMAP
17869
+ if (pbrMaterial.specularIntensityMapEnabled) {
17870
+ specularIntensity *= texture(pbr_specularIntensitySampler, pbr_vUV).a;
17871
+ }
17872
+ #endif
17873
+
17874
+ vec3 specularFactor = pbrMaterial.specularColorFactor;
17875
+ #ifdef HAS_SPECULARCOLORMAP
17876
+ if (pbrMaterial.specularColorMapEnabled) {
17877
+ specularFactor *= SRGBtoLINEAR(texture(pbr_specularColorSampler, pbr_vUV)).rgb;
17878
+ }
17879
+ #endif
17880
+
17881
+ transmission = pbrMaterial.transmissionFactor;
17882
+ #ifdef HAS_TRANSMISSIONMAP
17883
+ if (pbrMaterial.transmissionMapEnabled) {
17884
+ transmission *= texture(pbr_transmissionSampler, pbr_vUV).r;
17885
+ }
17886
+ #endif
17887
+ transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);
17888
+ float thickness = max(pbrMaterial.thicknessFactor, 0.0);
17889
+ #ifdef HAS_THICKNESSMAP
17890
+ thickness *= texture(pbr_thicknessSampler, pbr_vUV).g;
17891
+ #endif
17892
+
17893
+ float clearcoatFactor = pbrMaterial.clearcoatFactor;
17894
+ float clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;
17895
+ #ifdef HAS_CLEARCOATMAP
17896
+ if (pbrMaterial.clearcoatMapEnabled) {
17897
+ clearcoatFactor *= texture(pbr_clearcoatSampler, pbr_vUV).r;
17898
+ }
17899
+ #endif
17900
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
17901
+ if (pbrMaterial.clearcoatRoughnessMapEnabled) {
17902
+ clearcoatRoughness *= texture(pbr_clearcoatRoughnessSampler, pbr_vUV).g;
17903
+ }
17904
+ #endif
17905
+ clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
17906
+ clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
17907
+ vec3 clearcoatNormal = getClearcoatNormal(tbn, n);
17908
+
17909
+ vec3 sheenColor = pbrMaterial.sheenColorFactor;
17910
+ float sheenRoughness = pbrMaterial.sheenRoughnessFactor;
17911
+ #ifdef HAS_SHEENCOLORMAP
17912
+ if (pbrMaterial.sheenColorMapEnabled) {
17913
+ sheenColor *= SRGBtoLINEAR(texture(pbr_sheenColorSampler, pbr_vUV)).rgb;
17914
+ }
17915
+ #endif
17916
+ #ifdef HAS_SHEENROUGHNESSMAP
17917
+ if (pbrMaterial.sheenRoughnessMapEnabled) {
17918
+ sheenRoughness *= texture(pbr_sheenRoughnessSampler, pbr_vUV).a;
17919
+ }
17103
17920
  #endif
17921
+ sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);
17104
17922
 
17105
- vec3 color = vec3(0, 0, 0);
17923
+ float iridescence = pbrMaterial.iridescenceFactor;
17924
+ #ifdef HAS_IRIDESCENCEMAP
17925
+ if (pbrMaterial.iridescenceMapEnabled) {
17926
+ iridescence *= texture(pbr_iridescenceSampler, pbr_vUV).r;
17927
+ }
17928
+ #endif
17929
+ iridescence = clamp(iridescence, 0.0, 1.0);
17930
+ float iridescenceThickness = mix(
17931
+ pbrMaterial.iridescenceThicknessRange.x,
17932
+ pbrMaterial.iridescenceThicknessRange.y,
17933
+ 0.5
17934
+ );
17935
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
17936
+ iridescenceThickness = mix(
17937
+ pbrMaterial.iridescenceThicknessRange.x,
17938
+ pbrMaterial.iridescenceThicknessRange.y,
17939
+ texture(pbr_iridescenceThicknessSampler, pbr_vUV).g
17940
+ );
17941
+ #endif
17106
17942
 
17107
- if(pbrMaterial.unlit){
17108
- color.rgb = baseColor.rgb;
17109
- }
17110
- else{
17111
- // Metallic and Roughness material properties are packed together
17112
- // In glTF, these factors can be specified by fixed scalar values
17113
- // or from a metallic-roughness map
17114
- float perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;
17115
- float metallic = pbrMaterial.metallicRoughnessValues.x;
17116
- #ifdef HAS_METALROUGHNESSMAP
17117
- // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.
17118
- // This layout intentionally reserves the 'r' channel for (optional) occlusion map data
17119
- vec4 mrSample = texture(pbr_metallicRoughnessSampler, pbr_vUV);
17120
- perceptualRoughness = mrSample.g * perceptualRoughness;
17121
- metallic = mrSample.b * metallic;
17943
+ float anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);
17944
+ vec2 anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);
17945
+ #ifdef HAS_ANISOTROPYMAP
17946
+ if (pbrMaterial.anisotropyMapEnabled) {
17947
+ vec3 anisotropySample = texture(pbr_anisotropySampler, pbr_vUV).rgb;
17948
+ anisotropyStrength *= anisotropySample.b;
17949
+ vec2 mappedDirection = anisotropySample.rg * 2.0 - 1.0;
17950
+ if (length(mappedDirection) > 0.0001) {
17951
+ anisotropyDirection = normalize(mappedDirection);
17952
+ }
17953
+ }
17122
17954
  #endif
17123
- perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
17124
- metallic = clamp(metallic, 0.0, 1.0);
17955
+ anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);
17956
+ vec3 anisotropyTangent = normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);
17957
+ if (length(anisotropyTangent) < 0.0001) {
17958
+ anisotropyTangent = normalize(tbn[0]);
17959
+ }
17960
+ float anisotropyViewAlignment = abs(dot(v, anisotropyTangent));
17961
+ perceptualRoughness = mix(
17962
+ perceptualRoughness,
17963
+ clamp(perceptualRoughness * (1.0 - 0.6 * anisotropyViewAlignment), c_MinRoughness, 1.0),
17964
+ anisotropyStrength
17965
+ );
17966
+
17125
17967
  // Roughness is authored as perceptual roughness; as is convention,
17126
17968
  // convert to material roughness by squaring the perceptual roughness [2].
17127
17969
  float alphaRoughness = perceptualRoughness * perceptualRoughness;
17128
17970
 
17129
- vec3 f0 = vec3(0.04);
17130
- vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
17131
- diffuseColor *= 1.0 - metallic;
17132
- vec3 specularColor = mix(f0, baseColor.rgb, metallic);
17971
+ float dielectricF0 = getDielectricF0(pbrMaterial.ior);
17972
+ vec3 dielectricSpecularF0 = min(
17973
+ vec3(dielectricF0) * specularFactor * specularIntensity,
17974
+ vec3(1.0)
17975
+ );
17976
+ vec3 iridescenceTint = getIridescenceTint(iridescence, iridescenceThickness, NdotV);
17977
+ dielectricSpecularF0 = mix(
17978
+ dielectricSpecularF0,
17979
+ dielectricSpecularF0 * iridescenceTint,
17980
+ iridescence
17981
+ );
17982
+ vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - dielectricSpecularF0);
17983
+ diffuseColor *= (1.0 - metallic) * (1.0 - transmission);
17984
+ vec3 specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);
17985
+
17986
+ float baseLayerEnergy = 1.0 - clearcoatFactor * 0.25;
17987
+ diffuseColor *= baseLayerEnergy;
17988
+ specularColor *= baseLayerEnergy;
17133
17989
 
17134
17990
  // Compute reflectance.
17135
17991
  float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
@@ -17141,11 +17997,6 @@ vec4 pbr_filterColor(vec4 colorUnused)
17141
17997
  float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
17142
17998
  vec3 specularEnvironmentR0 = specularColor.rgb;
17143
17999
  vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;
17144
-
17145
- vec3 n = getNormal(); // normal at surface point
17146
- vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera
17147
-
17148
- float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
17149
18000
  vec3 reflection = -normalize(reflect(v, n));
17150
18001
 
17151
18002
  PBRInfo pbrInfo = PBRInfo(
@@ -17169,13 +18020,33 @@ vec4 pbr_filterColor(vec4 colorUnused)
17169
18020
  #ifdef USE_LIGHTS
17170
18021
  // Apply ambient light
17171
18022
  PBRInfo_setAmbientLight(pbrInfo);
17172
- color += calculateFinalColor(pbrInfo, lighting.ambientColor);
18023
+ color += calculateMaterialLightColor(
18024
+ pbrInfo,
18025
+ lighting.ambientColor,
18026
+ clearcoatNormal,
18027
+ clearcoatFactor,
18028
+ clearcoatRoughness,
18029
+ sheenColor,
18030
+ sheenRoughness,
18031
+ anisotropyTangent,
18032
+ anisotropyStrength
18033
+ );
17173
18034
 
17174
18035
  // Apply directional light
17175
18036
  for(int i = 0; i < lighting.directionalLightCount; i++) {
17176
18037
  if (i < lighting.directionalLightCount) {
17177
18038
  PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);
17178
- color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
18039
+ color += calculateMaterialLightColor(
18040
+ pbrInfo,
18041
+ lighting_getDirectionalLight(i).color,
18042
+ clearcoatNormal,
18043
+ clearcoatFactor,
18044
+ clearcoatRoughness,
18045
+ sheenColor,
18046
+ sheenRoughness,
18047
+ anisotropyTangent,
18048
+ anisotropyStrength
18049
+ );
17179
18050
  }
17180
18051
  }
17181
18052
 
@@ -17184,7 +18055,35 @@ vec4 pbr_filterColor(vec4 colorUnused)
17184
18055
  if (i < lighting.pointLightCount) {
17185
18056
  PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));
17186
18057
  float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));
17187
- color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
18058
+ color += calculateMaterialLightColor(
18059
+ pbrInfo,
18060
+ lighting_getPointLight(i).color / attenuation,
18061
+ clearcoatNormal,
18062
+ clearcoatFactor,
18063
+ clearcoatRoughness,
18064
+ sheenColor,
18065
+ sheenRoughness,
18066
+ anisotropyTangent,
18067
+ anisotropyStrength
18068
+ );
18069
+ }
18070
+ }
18071
+
18072
+ for(int i = 0; i < lighting.spotLightCount; i++) {
18073
+ if (i < lighting.spotLightCount) {
18074
+ PBRInfo_setSpotLight(pbrInfo, lighting_getSpotLight(i));
18075
+ float attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), pbr_vPosition);
18076
+ color += calculateMaterialLightColor(
18077
+ pbrInfo,
18078
+ lighting_getSpotLight(i).color / attenuation,
18079
+ clearcoatNormal,
18080
+ clearcoatFactor,
18081
+ clearcoatRoughness,
18082
+ sheenColor,
18083
+ sheenRoughness,
18084
+ anisotropyTangent,
18085
+ anisotropyStrength
18086
+ );
17188
18087
  }
17189
18088
  }
17190
18089
  #endif
@@ -17192,7 +18091,16 @@ vec4 pbr_filterColor(vec4 colorUnused)
17192
18091
  // Calculate lighting contribution from image based lighting source (IBL)
17193
18092
  #ifdef USE_IBL
17194
18093
  if (pbrMaterial.IBLenabled) {
17195
- color += getIBLContribution(pbrInfo, n, reflection);
18094
+ color += getIBLContribution(pbrInfo, n, reflection) *
18095
+ calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
18096
+ color += calculateClearcoatIBLContribution(
18097
+ pbrInfo,
18098
+ clearcoatNormal,
18099
+ -normalize(reflect(v, clearcoatNormal)),
18100
+ clearcoatFactor,
18101
+ clearcoatRoughness
18102
+ );
18103
+ color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;
17196
18104
  }
17197
18105
  #endif
17198
18106
 
@@ -17204,12 +18112,17 @@ vec4 pbr_filterColor(vec4 colorUnused)
17204
18112
  }
17205
18113
  #endif
17206
18114
 
18115
+ vec3 emissive = pbrMaterial.emissiveFactor;
17207
18116
  #ifdef HAS_EMISSIVEMAP
17208
18117
  if (pbrMaterial.emissiveMapEnabled) {
17209
- vec3 emissive = SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb * pbrMaterial.emissiveFactor;
17210
- color += emissive;
18118
+ emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, pbr_vUV)).rgb;
17211
18119
  }
17212
18120
  #endif
18121
+ color += emissive * pbrMaterial.emissiveStrength;
18122
+
18123
+ if (transmission > 0.0) {
18124
+ color = mix(color, color * getVolumeAttenuation(thickness), transmission);
18125
+ }
17213
18126
 
17214
18127
  // This section uses mix to override final color for reference app visualization
17215
18128
  // of various parameters in the lighting equation.
@@ -17229,7 +18142,8 @@ vec4 pbr_filterColor(vec4 colorUnused)
17229
18142
 
17230
18143
  }
17231
18144
 
17232
- return vec4(pow(color,vec3(1.0/2.2)), baseColor.a);
18145
+ float alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);
18146
+ return vec4(pow(color,vec3(1.0/2.2)), alpha);
17233
18147
  }
17234
18148
  `
17235
18149
  );
@@ -17295,6 +18209,42 @@ struct pbrMaterialUniforms {
17295
18209
 
17296
18210
  alphaCutoffEnabled: i32,
17297
18211
  alphaCutoff: f32, // #ifdef ALPHA_CUTOFF
18212
+
18213
+ specularColorFactor: vec3f,
18214
+ specularIntensityFactor: f32,
18215
+ specularColorMapEnabled: i32,
18216
+ specularIntensityMapEnabled: i32,
18217
+
18218
+ ior: f32,
18219
+
18220
+ transmissionFactor: f32,
18221
+ transmissionMapEnabled: i32,
18222
+
18223
+ thicknessFactor: f32,
18224
+ attenuationDistance: f32,
18225
+ attenuationColor: vec3f,
18226
+
18227
+ clearcoatFactor: f32,
18228
+ clearcoatRoughnessFactor: f32,
18229
+ clearcoatMapEnabled: i32,
18230
+ clearcoatRoughnessMapEnabled: i32,
18231
+
18232
+ sheenColorFactor: vec3f,
18233
+ sheenRoughnessFactor: f32,
18234
+ sheenColorMapEnabled: i32,
18235
+ sheenRoughnessMapEnabled: i32,
18236
+
18237
+ iridescenceFactor: f32,
18238
+ iridescenceIor: f32,
18239
+ iridescenceThicknessRange: vec2f,
18240
+ iridescenceMapEnabled: i32,
18241
+
18242
+ anisotropyStrength: f32,
18243
+ anisotropyRotation: f32,
18244
+ anisotropyDirection: vec2f,
18245
+ anisotropyMapEnabled: i32,
18246
+
18247
+ emissiveStrength: f32,
17298
18248
 
17299
18249
  // IBL
17300
18250
  IBLenabled: i32,
@@ -17307,38 +18257,77 @@ struct pbrMaterialUniforms {
17307
18257
  // #endif
17308
18258
  }
17309
18259
 
17310
- @binding(2) @group(0) var<uniform> pbrMaterial : pbrMaterialUniforms;
18260
+ @group(3) @binding(auto) var<uniform> pbrMaterial : pbrMaterialUniforms;
17311
18261
 
17312
18262
  // Samplers
17313
18263
  #ifdef HAS_BASECOLORMAP
17314
- @binding(3) @group(0) var pbr_baseColorSampler: texture_2d<f32>;
17315
- @binding(4) @group(0) var pbr_baseColorSamplerSampler: sampler;
18264
+ @group(3) @binding(auto) var pbr_baseColorSampler: texture_2d<f32>;
18265
+ @group(3) @binding(auto) var pbr_baseColorSamplerSampler: sampler;
17316
18266
  #endif
17317
18267
  #ifdef HAS_NORMALMAP
17318
- @binding(5) @group(0) var pbr_normalSampler: texture_2d<f32>;
17319
- @binding(6) @group(0) var pbr_normalSamplerSampler: sampler;
18268
+ @group(3) @binding(auto) var pbr_normalSampler: texture_2d<f32>;
18269
+ @group(3) @binding(auto) var pbr_normalSamplerSampler: sampler;
17320
18270
  #endif
17321
18271
  #ifdef HAS_EMISSIVEMAP
17322
- @binding(7) @group(0) var pbr_emissiveSampler: texture_2d<f32>;
17323
- @binding(8) @group(0) var pbr_emissiveSamplerSampler: sampler;
18272
+ @group(3) @binding(auto) var pbr_emissiveSampler: texture_2d<f32>;
18273
+ @group(3) @binding(auto) var pbr_emissiveSamplerSampler: sampler;
17324
18274
  #endif
17325
18275
  #ifdef HAS_METALROUGHNESSMAP
17326
- @binding(9) @group(0) var pbr_metallicRoughnessSampler: texture_2d<f32>;
17327
- @binding(10) @group(0) var pbr_metallicRoughnessSamplerSampler: sampler;
18276
+ @group(3) @binding(auto) var pbr_metallicRoughnessSampler: texture_2d<f32>;
18277
+ @group(3) @binding(auto) var pbr_metallicRoughnessSamplerSampler: sampler;
17328
18278
  #endif
17329
18279
  #ifdef HAS_OCCLUSIONMAP
17330
- @binding(11) @group(0) var pbr_occlusionSampler: texture_2d<f32>;
17331
- @binding(12) @group(0) var pbr_occlusionSamplerSampler: sampler;
18280
+ @group(3) @binding(auto) var pbr_occlusionSampler: texture_2d<f32>;
18281
+ @group(3) @binding(auto) var pbr_occlusionSamplerSampler: sampler;
17332
18282
  #endif
17333
- #ifdef USE_IBL
17334
- @binding(13) @group(0) var pbr_diffuseEnvSampler: texture_cube<f32>;
17335
- @binding(14) @group(0) var pbr_diffuseEnvSamplerSampler: sampler;
17336
- @binding(15) @group(0) var pbr_specularEnvSampler: texture_cube<f32>;
17337
- @binding(16) @group(0) var pbr_specularEnvSamplerSampler: sampler;
17338
- @binding(17) @group(0) var pbr_BrdfLUT: texture_2d<f32>;
17339
- @binding(18) @group(0) var pbr_BrdfLUTSampler: sampler;
18283
+ #ifdef HAS_SPECULARCOLORMAP
18284
+ @group(3) @binding(auto) var pbr_specularColorSampler: texture_2d<f32>;
18285
+ @group(3) @binding(auto) var pbr_specularColorSamplerSampler: sampler;
18286
+ #endif
18287
+ #ifdef HAS_SPECULARINTENSITYMAP
18288
+ @group(3) @binding(auto) var pbr_specularIntensitySampler: texture_2d<f32>;
18289
+ @group(3) @binding(auto) var pbr_specularIntensitySamplerSampler: sampler;
18290
+ #endif
18291
+ #ifdef HAS_TRANSMISSIONMAP
18292
+ @group(3) @binding(auto) var pbr_transmissionSampler: texture_2d<f32>;
18293
+ @group(3) @binding(auto) var pbr_transmissionSamplerSampler: sampler;
18294
+ #endif
18295
+ #ifdef HAS_THICKNESSMAP
18296
+ @group(3) @binding(auto) var pbr_thicknessSampler: texture_2d<f32>;
18297
+ @group(3) @binding(auto) var pbr_thicknessSamplerSampler: sampler;
18298
+ #endif
18299
+ #ifdef HAS_CLEARCOATMAP
18300
+ @group(3) @binding(auto) var pbr_clearcoatSampler: texture_2d<f32>;
18301
+ @group(3) @binding(auto) var pbr_clearcoatSamplerSampler: sampler;
18302
+ #endif
18303
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
18304
+ @group(3) @binding(auto) var pbr_clearcoatRoughnessSampler: texture_2d<f32>;
18305
+ @group(3) @binding(auto) var pbr_clearcoatRoughnessSamplerSampler: sampler;
18306
+ #endif
18307
+ #ifdef HAS_CLEARCOATNORMALMAP
18308
+ @group(3) @binding(auto) var pbr_clearcoatNormalSampler: texture_2d<f32>;
18309
+ @group(3) @binding(auto) var pbr_clearcoatNormalSamplerSampler: sampler;
18310
+ #endif
18311
+ #ifdef HAS_SHEENCOLORMAP
18312
+ @group(3) @binding(auto) var pbr_sheenColorSampler: texture_2d<f32>;
18313
+ @group(3) @binding(auto) var pbr_sheenColorSamplerSampler: sampler;
18314
+ #endif
18315
+ #ifdef HAS_SHEENROUGHNESSMAP
18316
+ @group(3) @binding(auto) var pbr_sheenRoughnessSampler: texture_2d<f32>;
18317
+ @group(3) @binding(auto) var pbr_sheenRoughnessSamplerSampler: sampler;
18318
+ #endif
18319
+ #ifdef HAS_IRIDESCENCEMAP
18320
+ @group(3) @binding(auto) var pbr_iridescenceSampler: texture_2d<f32>;
18321
+ @group(3) @binding(auto) var pbr_iridescenceSamplerSampler: sampler;
18322
+ #endif
18323
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
18324
+ @group(3) @binding(auto) var pbr_iridescenceThicknessSampler: texture_2d<f32>;
18325
+ @group(3) @binding(auto) var pbr_iridescenceThicknessSamplerSampler: sampler;
18326
+ #endif
18327
+ #ifdef HAS_ANISOTROPYMAP
18328
+ @group(3) @binding(auto) var pbr_anisotropySampler: texture_2d<f32>;
18329
+ @group(3) @binding(auto) var pbr_anisotropySamplerSampler: sampler;
17340
18330
  #endif
17341
-
17342
18331
  // Encapsulate the various inputs used by the various functions in the shading equation
17343
18332
  // We store values in this struct to simplify the integration of alternative implementations
17344
18333
  // of the shading terms, outlined in the Readme.MD Appendix.
@@ -17379,11 +18368,9 @@ fn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f
17379
18368
  return vec4f(linOut, srgbIn.w);
17380
18369
  }
17381
18370
 
17382
- // Find the normal for this fragment, pulling either from a predefined normal map
17383
- // or from the interpolated mesh normal and tangent attributes.
17384
- fn getNormal() -> vec3f
18371
+ // Build the tangent basis from interpolated attributes or screen-space derivatives.
18372
+ fn getTBN() -> mat3x3f
17385
18373
  {
17386
- // Retrieve the tangent space matrix
17387
18374
  let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);
17388
18375
  let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);
17389
18376
  let tex_dx: vec3f = dpdx(vec3f(fragmentInputs.pbr_vUV, 0.0));
@@ -17401,16 +18388,52 @@ fn getNormal() -> vec3f
17401
18388
  tbn = fragmentInputs.pbr_vTBN;
17402
18389
  #endif
17403
18390
 
18391
+ return tbn;
18392
+ }
18393
+
18394
+ // Find the normal for this fragment, pulling either from a predefined normal map
18395
+ // or from the interpolated mesh normal and tangent attributes.
18396
+ fn getMappedNormal(
18397
+ normalSampler: texture_2d<f32>,
18398
+ normalSamplerBinding: sampler,
18399
+ tbn: mat3x3f,
18400
+ normalScale: f32
18401
+ ) -> vec3f
18402
+ {
18403
+ let n = textureSample(normalSampler, normalSamplerBinding, fragmentInputs.pbr_vUV).rgb;
18404
+ return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));
18405
+ }
18406
+
18407
+ fn getNormal(tbn: mat3x3f) -> vec3f
18408
+ {
17404
18409
  // The tbn matrix is linearly interpolated, so we need to re-normalize
17405
18410
  var n: vec3f = normalize(tbn[2].xyz);
17406
18411
  #ifdef HAS_NORMALMAP
17407
- n = textureSample(pbr_normalSampler, pbr_normalSamplerSampler, fragmentInputs.pbr_vUV).rgb;
17408
- n = normalize(tbn * ((2.0 * n - 1.0) * vec3f(pbrMaterial.normalScale, pbrMaterial.normalScale, 1.0)));
18412
+ n = getMappedNormal(
18413
+ pbr_normalSampler,
18414
+ pbr_normalSamplerSampler,
18415
+ tbn,
18416
+ pbrMaterial.normalScale
18417
+ );
17409
18418
  #endif
17410
18419
 
17411
18420
  return n;
17412
18421
  }
17413
18422
 
18423
+ fn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f) -> vec3f
18424
+ {
18425
+ #ifdef HAS_CLEARCOATNORMALMAP
18426
+ return getMappedNormal(
18427
+ pbr_clearcoatNormalSampler,
18428
+ pbr_clearcoatNormalSamplerSampler,
18429
+ tbn,
18430
+ 1.0
18431
+ );
18432
+ #else
18433
+ return baseNormal;
18434
+ #endif
18435
+ }
18436
+
17414
18437
  // Calculation of the lighting contribution from an optional Image Based Light source.
17415
18438
  // Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].
17416
18439
  // See our README.md on Environment Maps [3] for additional discussion.
@@ -17421,17 +18444,25 @@ fn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f
17421
18444
  let lod: f32 = pbrInfo.perceptualRoughness * mipCount;
17422
18445
  // retrieve a scale and bias to F0. See [1], Figure 3
17423
18446
  let brdf = SRGBtoLINEAR(
17424
- textureSample(
17425
- pbr_BrdfLUT,
17426
- pbr_BrdfLUTSampler,
17427
- vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness)
18447
+ textureSampleLevel(
18448
+ pbr_brdfLUT,
18449
+ pbr_brdfLUTSampler,
18450
+ vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness),
18451
+ 0.0
17428
18452
  )
17429
18453
  ).rgb;
17430
18454
  let diffuseLight =
17431
- SRGBtoLINEAR(textureSample(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, n)).rgb;
17432
- let specularLightDefault =
17433
- SRGBtoLINEAR(textureSample(pbr_specularEnvSampler, pbr_specularEnvSamplerSampler, reflection)).rgb;
17434
- var specularLight = specularLightDefault;
18455
+ SRGBtoLINEAR(
18456
+ textureSampleLevel(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, n, 0.0)
18457
+ ).rgb;
18458
+ var specularLight = SRGBtoLINEAR(
18459
+ textureSampleLevel(
18460
+ pbr_specularEnvSampler,
18461
+ pbr_specularEnvSamplerSampler,
18462
+ reflection,
18463
+ 0.0
18464
+ )
18465
+ ).rgb;
17435
18466
  #ifdef USE_TEX_LOD
17436
18467
  specularLight = SRGBtoLINEAR(
17437
18468
  textureSampleLevel(
@@ -17492,6 +18523,172 @@ fn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {
17492
18523
  return roughnessSq / (M_PI * f * f);
17493
18524
  }
17494
18525
 
18526
+ fn maxComponent(value: vec3f) -> f32 {
18527
+ return max(max(value.r, value.g), value.b);
18528
+ }
18529
+
18530
+ fn getDielectricF0(ior: f32) -> f32 {
18531
+ let clampedIor = max(ior, 1.0);
18532
+ let ratio = (clampedIor - 1.0) / (clampedIor + 1.0);
18533
+ return ratio * ratio;
18534
+ }
18535
+
18536
+ fn normalizeDirection(direction: vec2f) -> vec2f {
18537
+ let directionLength = length(direction);
18538
+ if (directionLength > 0.0001) {
18539
+ return direction / directionLength;
18540
+ }
18541
+
18542
+ return vec2f(1.0, 0.0);
18543
+ }
18544
+
18545
+ fn rotateDirection(direction: vec2f, rotation: f32) -> vec2f {
18546
+ let s = sin(rotation);
18547
+ let c = cos(rotation);
18548
+ return vec2f(direction.x * c - direction.y * s, direction.x * s + direction.y * c);
18549
+ }
18550
+
18551
+ fn getIridescenceTint(iridescence: f32, thickness: f32, NdotV: f32) -> vec3f {
18552
+ if (iridescence <= 0.0) {
18553
+ return vec3f(1.0);
18554
+ }
18555
+
18556
+ let phase = 0.015 * thickness * pbrMaterial.iridescenceIor + (1.0 - NdotV) * 6.0;
18557
+ let thinFilmTint =
18558
+ 0.5 +
18559
+ 0.5 *
18560
+ cos(vec3f(phase, phase + 2.0943951, phase + 4.1887902));
18561
+ return mix(vec3f(1.0), thinFilmTint, iridescence);
18562
+ }
18563
+
18564
+ fn getVolumeAttenuation(thickness: f32) -> vec3f {
18565
+ if (thickness <= 0.0) {
18566
+ return vec3f(1.0);
18567
+ }
18568
+
18569
+ let attenuationCoefficient =
18570
+ -log(max(pbrMaterial.attenuationColor, vec3f(0.0001))) /
18571
+ max(pbrMaterial.attenuationDistance, 0.0001);
18572
+ return exp(-attenuationCoefficient * thickness);
18573
+ }
18574
+
18575
+ fn createClearcoatPBRInfo(
18576
+ basePBRInfo: PBRInfo,
18577
+ clearcoatNormal: vec3f,
18578
+ clearcoatRoughness: f32
18579
+ ) -> PBRInfo {
18580
+ let perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
18581
+ let alphaRoughness = perceptualRoughness * perceptualRoughness;
18582
+ let NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);
18583
+
18584
+ return PBRInfo(
18585
+ basePBRInfo.NdotL,
18586
+ NdotV,
18587
+ basePBRInfo.NdotH,
18588
+ basePBRInfo.LdotH,
18589
+ basePBRInfo.VdotH,
18590
+ perceptualRoughness,
18591
+ 0.0,
18592
+ vec3f(0.04),
18593
+ vec3f(1.0),
18594
+ alphaRoughness,
18595
+ vec3f(0.0),
18596
+ vec3f(0.04),
18597
+ clearcoatNormal,
18598
+ basePBRInfo.v
18599
+ );
18600
+ }
18601
+
18602
+ fn calculateClearcoatContribution(
18603
+ pbrInfo: PBRInfo,
18604
+ lightColor: vec3f,
18605
+ clearcoatNormal: vec3f,
18606
+ clearcoatFactor: f32,
18607
+ clearcoatRoughness: f32
18608
+ ) -> vec3f {
18609
+ if (clearcoatFactor <= 0.0) {
18610
+ return vec3f(0.0);
18611
+ }
18612
+
18613
+ let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
18614
+ return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;
18615
+ }
18616
+
18617
+ #ifdef USE_IBL
18618
+ fn calculateClearcoatIBLContribution(
18619
+ pbrInfo: PBRInfo,
18620
+ clearcoatNormal: vec3f,
18621
+ reflection: vec3f,
18622
+ clearcoatFactor: f32,
18623
+ clearcoatRoughness: f32
18624
+ ) -> vec3f {
18625
+ if (clearcoatFactor <= 0.0) {
18626
+ return vec3f(0.0);
18627
+ }
18628
+
18629
+ let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);
18630
+ return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;
18631
+ }
18632
+ #endif
18633
+
18634
+ fn calculateSheenContribution(
18635
+ pbrInfo: PBRInfo,
18636
+ lightColor: vec3f,
18637
+ sheenColor: vec3f,
18638
+ sheenRoughness: f32
18639
+ ) -> vec3f {
18640
+ if (maxComponent(sheenColor) <= 0.0) {
18641
+ return vec3f(0.0);
18642
+ }
18643
+
18644
+ let sheenFresnel = pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);
18645
+ let sheenVisibility = mix(1.0, pbrInfo.NdotL * pbrInfo.NdotV, sheenRoughness);
18646
+ return pbrInfo.NdotL *
18647
+ lightColor *
18648
+ sheenColor *
18649
+ (0.25 + 0.75 * sheenFresnel) *
18650
+ sheenVisibility *
18651
+ (1.0 - pbrInfo.metalness);
18652
+ }
18653
+
18654
+ fn calculateAnisotropyBoost(
18655
+ pbrInfo: PBRInfo,
18656
+ anisotropyTangent: vec3f,
18657
+ anisotropyStrength: f32
18658
+ ) -> f32 {
18659
+ if (anisotropyStrength <= 0.0) {
18660
+ return 1.0;
18661
+ }
18662
+
18663
+ let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));
18664
+ let bitangentViewAlignment = abs(dot(pbrInfo.v, anisotropyBitangent));
18665
+ return mix(1.0, 0.65 + 0.7 * bitangentViewAlignment, anisotropyStrength);
18666
+ }
18667
+
18668
+ fn calculateMaterialLightColor(
18669
+ pbrInfo: PBRInfo,
18670
+ lightColor: vec3f,
18671
+ clearcoatNormal: vec3f,
18672
+ clearcoatFactor: f32,
18673
+ clearcoatRoughness: f32,
18674
+ sheenColor: vec3f,
18675
+ sheenRoughness: f32,
18676
+ anisotropyTangent: vec3f,
18677
+ anisotropyStrength: f32
18678
+ ) -> vec3f {
18679
+ let anisotropyBoost = calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
18680
+ var color = calculateFinalColor(pbrInfo, lightColor) * anisotropyBoost;
18681
+ color += calculateClearcoatContribution(
18682
+ pbrInfo,
18683
+ lightColor,
18684
+ clearcoatNormal,
18685
+ clearcoatFactor,
18686
+ clearcoatRoughness
18687
+ );
18688
+ color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);
18689
+ return color;
18690
+ }
18691
+
17495
18692
  fn PBRInfo_setAmbientLight(pbrInfo: ptr<function, PBRInfo>) {
17496
18693
  (*pbrInfo).NdotL = 1.0;
17497
18694
  (*pbrInfo).NdotH = 0.0;
@@ -17516,6 +18713,11 @@ fn PBRInfo_setPointLight(pbrInfo: ptr<function, PBRInfo>, pointLight: PointLight
17516
18713
  PBRInfo_setDirectionalLight(pbrInfo, light_direction);
17517
18714
  }
17518
18715
 
18716
+ fn PBRInfo_setSpotLight(pbrInfo: ptr<function, PBRInfo>, spotLight: SpotLight) {
18717
+ let light_direction = normalize(spotLight.position - fragmentInputs.pbr_vPosition);
18718
+ PBRInfo_setDirectionalLight(pbrInfo, light_direction);
18719
+ }
18720
+
17519
18721
  fn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3<f32>) -> vec3<f32> {
17520
18722
  // Calculate the shading terms for the microfacet specular shading model
17521
18723
  let F = specularReflection(pbrInfo);
@@ -17545,6 +18747,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17545
18747
  #endif
17546
18748
 
17547
18749
  var color = vec3<f32>(0.0, 0.0, 0.0);
18750
+ var transmission = 0.0;
17548
18751
 
17549
18752
  if (pbrMaterial.unlit != 0u) {
17550
18753
  color = baseColor.rgb;
@@ -17567,14 +18770,308 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17567
18770
  #endif
17568
18771
  perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
17569
18772
  metallic = clamp(metallic, 0.0, 1.0);
18773
+ let tbn = getTBN();
18774
+ let n = getNormal(tbn); // normal at surface point
18775
+ let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
18776
+ let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
18777
+ var useExtendedPBR = false;
18778
+ #ifdef USE_MATERIAL_EXTENSIONS
18779
+ useExtendedPBR =
18780
+ pbrMaterial.specularColorMapEnabled != 0 ||
18781
+ pbrMaterial.specularIntensityMapEnabled != 0 ||
18782
+ abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||
18783
+ maxComponent(abs(pbrMaterial.specularColorFactor - vec3f(1.0))) > 0.0001 ||
18784
+ abs(pbrMaterial.ior - 1.5) > 0.0001 ||
18785
+ pbrMaterial.transmissionMapEnabled != 0 ||
18786
+ pbrMaterial.transmissionFactor > 0.0001 ||
18787
+ pbrMaterial.clearcoatMapEnabled != 0 ||
18788
+ pbrMaterial.clearcoatRoughnessMapEnabled != 0 ||
18789
+ pbrMaterial.clearcoatFactor > 0.0001 ||
18790
+ pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||
18791
+ pbrMaterial.sheenColorMapEnabled != 0 ||
18792
+ pbrMaterial.sheenRoughnessMapEnabled != 0 ||
18793
+ maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||
18794
+ pbrMaterial.sheenRoughnessFactor > 0.0001 ||
18795
+ pbrMaterial.iridescenceMapEnabled != 0 ||
18796
+ pbrMaterial.iridescenceFactor > 0.0001 ||
18797
+ abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||
18798
+ abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||
18799
+ abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||
18800
+ pbrMaterial.anisotropyMapEnabled != 0 ||
18801
+ pbrMaterial.anisotropyStrength > 0.0001 ||
18802
+ abs(pbrMaterial.anisotropyRotation) > 0.0001 ||
18803
+ length(pbrMaterial.anisotropyDirection - vec2f(1.0, 0.0)) > 0.0001;
18804
+ #endif
18805
+
18806
+ if (!useExtendedPBR) {
18807
+ let alphaRoughness = perceptualRoughness * perceptualRoughness;
18808
+
18809
+ let f0 = vec3<f32>(0.04);
18810
+ var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
18811
+ diffuseColor *= 1.0 - metallic;
18812
+ let specularColor = mix(f0, baseColor.rgb, metallic);
18813
+
18814
+ let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
18815
+ let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
18816
+ let specularEnvironmentR0 = specularColor;
18817
+ let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
18818
+ let reflection = -normalize(reflect(v, n));
18819
+
18820
+ var pbrInfo = PBRInfo(
18821
+ 0.0, // NdotL
18822
+ NdotV,
18823
+ 0.0, // NdotH
18824
+ 0.0, // LdotH
18825
+ 0.0, // VdotH
18826
+ perceptualRoughness,
18827
+ metallic,
18828
+ specularEnvironmentR0,
18829
+ specularEnvironmentR90,
18830
+ alphaRoughness,
18831
+ diffuseColor,
18832
+ specularColor,
18833
+ n,
18834
+ v
18835
+ );
18836
+
18837
+ #ifdef USE_LIGHTS
18838
+ PBRInfo_setAmbientLight(&pbrInfo);
18839
+ color += calculateFinalColor(pbrInfo, lighting.ambientColor);
18840
+
18841
+ for (var i = 0; i < lighting.directionalLightCount; i++) {
18842
+ if (i < lighting.directionalLightCount) {
18843
+ PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
18844
+ color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
18845
+ }
18846
+ }
18847
+
18848
+ for (var i = 0; i < lighting.pointLightCount; i++) {
18849
+ if (i < lighting.pointLightCount) {
18850
+ PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));
18851
+ let attenuation = getPointLightAttenuation(
18852
+ lighting_getPointLight(i),
18853
+ distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
18854
+ );
18855
+ color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
18856
+ }
18857
+ }
18858
+
18859
+ for (var i = 0; i < lighting.spotLightCount; i++) {
18860
+ if (i < lighting.spotLightCount) {
18861
+ PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));
18862
+ let attenuation = getSpotLightAttenuation(
18863
+ lighting_getSpotLight(i),
18864
+ fragmentInputs.pbr_vPosition
18865
+ );
18866
+ color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color / attenuation);
18867
+ }
18868
+ }
18869
+ #endif
18870
+
18871
+ #ifdef USE_IBL
18872
+ if (pbrMaterial.IBLenabled != 0) {
18873
+ color += getIBLContribution(pbrInfo, n, reflection);
18874
+ }
18875
+ #endif
18876
+
18877
+ #ifdef HAS_OCCLUSIONMAP
18878
+ if (pbrMaterial.occlusionMapEnabled != 0) {
18879
+ let ao =
18880
+ textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, fragmentInputs.pbr_vUV).r;
18881
+ color = mix(color, color * ao, pbrMaterial.occlusionStrength);
18882
+ }
18883
+ #endif
18884
+
18885
+ var emissive = pbrMaterial.emissiveFactor;
18886
+ #ifdef HAS_EMISSIVEMAP
18887
+ if (pbrMaterial.emissiveMapEnabled != 0u) {
18888
+ emissive *= SRGBtoLINEAR(
18889
+ textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
18890
+ ).rgb;
18891
+ }
18892
+ #endif
18893
+ color += emissive * pbrMaterial.emissiveStrength;
18894
+
18895
+ #ifdef PBR_DEBUG
18896
+ color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);
18897
+ color = mix(color, vec3<f32>(metallic), pbrMaterial.scaleDiffBaseMR.z);
18898
+ color = mix(color, vec3<f32>(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);
18899
+ #endif
18900
+
18901
+ return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), baseColor.a);
18902
+ }
18903
+
18904
+ var specularIntensity = pbrMaterial.specularIntensityFactor;
18905
+ #ifdef HAS_SPECULARINTENSITYMAP
18906
+ if (pbrMaterial.specularIntensityMapEnabled != 0) {
18907
+ specularIntensity *= textureSample(
18908
+ pbr_specularIntensitySampler,
18909
+ pbr_specularIntensitySamplerSampler,
18910
+ fragmentInputs.pbr_vUV
18911
+ ).a;
18912
+ }
18913
+ #endif
18914
+
18915
+ var specularFactor = pbrMaterial.specularColorFactor;
18916
+ #ifdef HAS_SPECULARCOLORMAP
18917
+ if (pbrMaterial.specularColorMapEnabled != 0) {
18918
+ specularFactor *= SRGBtoLINEAR(
18919
+ textureSample(
18920
+ pbr_specularColorSampler,
18921
+ pbr_specularColorSamplerSampler,
18922
+ fragmentInputs.pbr_vUV
18923
+ )
18924
+ ).rgb;
18925
+ }
18926
+ #endif
18927
+
18928
+ transmission = pbrMaterial.transmissionFactor;
18929
+ #ifdef HAS_TRANSMISSIONMAP
18930
+ if (pbrMaterial.transmissionMapEnabled != 0) {
18931
+ transmission *= textureSample(
18932
+ pbr_transmissionSampler,
18933
+ pbr_transmissionSamplerSampler,
18934
+ fragmentInputs.pbr_vUV
18935
+ ).r;
18936
+ }
18937
+ #endif
18938
+ transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);
18939
+ var thickness = max(pbrMaterial.thicknessFactor, 0.0);
18940
+ #ifdef HAS_THICKNESSMAP
18941
+ thickness *= textureSample(
18942
+ pbr_thicknessSampler,
18943
+ pbr_thicknessSamplerSampler,
18944
+ fragmentInputs.pbr_vUV
18945
+ ).g;
18946
+ #endif
18947
+
18948
+ var clearcoatFactor = pbrMaterial.clearcoatFactor;
18949
+ var clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;
18950
+ #ifdef HAS_CLEARCOATMAP
18951
+ if (pbrMaterial.clearcoatMapEnabled != 0) {
18952
+ clearcoatFactor *= textureSample(
18953
+ pbr_clearcoatSampler,
18954
+ pbr_clearcoatSamplerSampler,
18955
+ fragmentInputs.pbr_vUV
18956
+ ).r;
18957
+ }
18958
+ #endif
18959
+ #ifdef HAS_CLEARCOATROUGHNESSMAP
18960
+ if (pbrMaterial.clearcoatRoughnessMapEnabled != 0) {
18961
+ clearcoatRoughness *= textureSample(
18962
+ pbr_clearcoatRoughnessSampler,
18963
+ pbr_clearcoatRoughnessSamplerSampler,
18964
+ fragmentInputs.pbr_vUV
18965
+ ).g;
18966
+ }
18967
+ #endif
18968
+ clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);
18969
+ clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);
18970
+ let clearcoatNormal = getClearcoatNormal(tbn, n);
18971
+
18972
+ var sheenColor = pbrMaterial.sheenColorFactor;
18973
+ var sheenRoughness = pbrMaterial.sheenRoughnessFactor;
18974
+ #ifdef HAS_SHEENCOLORMAP
18975
+ if (pbrMaterial.sheenColorMapEnabled != 0) {
18976
+ sheenColor *= SRGBtoLINEAR(
18977
+ textureSample(
18978
+ pbr_sheenColorSampler,
18979
+ pbr_sheenColorSamplerSampler,
18980
+ fragmentInputs.pbr_vUV
18981
+ )
18982
+ ).rgb;
18983
+ }
18984
+ #endif
18985
+ #ifdef HAS_SHEENROUGHNESSMAP
18986
+ if (pbrMaterial.sheenRoughnessMapEnabled != 0) {
18987
+ sheenRoughness *= textureSample(
18988
+ pbr_sheenRoughnessSampler,
18989
+ pbr_sheenRoughnessSamplerSampler,
18990
+ fragmentInputs.pbr_vUV
18991
+ ).a;
18992
+ }
18993
+ #endif
18994
+ sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);
18995
+
18996
+ var iridescence = pbrMaterial.iridescenceFactor;
18997
+ #ifdef HAS_IRIDESCENCEMAP
18998
+ if (pbrMaterial.iridescenceMapEnabled != 0) {
18999
+ iridescence *= textureSample(
19000
+ pbr_iridescenceSampler,
19001
+ pbr_iridescenceSamplerSampler,
19002
+ fragmentInputs.pbr_vUV
19003
+ ).r;
19004
+ }
19005
+ #endif
19006
+ iridescence = clamp(iridescence, 0.0, 1.0);
19007
+ var iridescenceThickness = mix(
19008
+ pbrMaterial.iridescenceThicknessRange.x,
19009
+ pbrMaterial.iridescenceThicknessRange.y,
19010
+ 0.5
19011
+ );
19012
+ #ifdef HAS_IRIDESCENCETHICKNESSMAP
19013
+ iridescenceThickness = mix(
19014
+ pbrMaterial.iridescenceThicknessRange.x,
19015
+ pbrMaterial.iridescenceThicknessRange.y,
19016
+ textureSample(
19017
+ pbr_iridescenceThicknessSampler,
19018
+ pbr_iridescenceThicknessSamplerSampler,
19019
+ fragmentInputs.pbr_vUV
19020
+ ).g
19021
+ );
19022
+ #endif
19023
+
19024
+ var anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);
19025
+ var anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);
19026
+ #ifdef HAS_ANISOTROPYMAP
19027
+ if (pbrMaterial.anisotropyMapEnabled != 0) {
19028
+ let anisotropySample = textureSample(
19029
+ pbr_anisotropySampler,
19030
+ pbr_anisotropySamplerSampler,
19031
+ fragmentInputs.pbr_vUV
19032
+ ).rgb;
19033
+ anisotropyStrength *= anisotropySample.b;
19034
+ let mappedDirection = anisotropySample.rg * 2.0 - 1.0;
19035
+ if (length(mappedDirection) > 0.0001) {
19036
+ anisotropyDirection = normalize(mappedDirection);
19037
+ }
19038
+ }
19039
+ #endif
19040
+ anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);
19041
+ var anisotropyTangent =
19042
+ normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);
19043
+ if (length(anisotropyTangent) < 0.0001) {
19044
+ anisotropyTangent = normalize(tbn[0]);
19045
+ }
19046
+ let anisotropyViewAlignment = abs(dot(v, anisotropyTangent));
19047
+ perceptualRoughness = mix(
19048
+ perceptualRoughness,
19049
+ clamp(perceptualRoughness * (1.0 - 0.6 * anisotropyViewAlignment), c_MinRoughness, 1.0),
19050
+ anisotropyStrength
19051
+ );
19052
+
17570
19053
  // Roughness is authored as perceptual roughness; as is convention,
17571
19054
  // convert to material roughness by squaring the perceptual roughness [2].
17572
19055
  let alphaRoughness = perceptualRoughness * perceptualRoughness;
17573
19056
 
17574
- let f0 = vec3<f32>(0.04);
17575
- var diffuseColor = baseColor.rgb * (vec3<f32>(1.0) - f0);
17576
- diffuseColor *= 1.0 - metallic;
17577
- let specularColor = mix(f0, baseColor.rgb, metallic);
19057
+ let dielectricF0 = getDielectricF0(pbrMaterial.ior);
19058
+ var dielectricSpecularF0 = min(
19059
+ vec3f(dielectricF0) * specularFactor * specularIntensity,
19060
+ vec3f(1.0)
19061
+ );
19062
+ let iridescenceTint = getIridescenceTint(iridescence, iridescenceThickness, NdotV);
19063
+ dielectricSpecularF0 = mix(
19064
+ dielectricSpecularF0,
19065
+ dielectricSpecularF0 * iridescenceTint,
19066
+ iridescence
19067
+ );
19068
+ var diffuseColor = baseColor.rgb * (vec3f(1.0) - dielectricSpecularF0);
19069
+ diffuseColor *= (1.0 - metallic) * (1.0 - transmission);
19070
+ var specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);
19071
+
19072
+ let baseLayerEnergy = 1.0 - clearcoatFactor * 0.25;
19073
+ diffuseColor *= baseLayerEnergy;
19074
+ specularColor *= baseLayerEnergy;
17578
19075
 
17579
19076
  // Compute reflectance.
17580
19077
  let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
@@ -17586,11 +19083,6 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17586
19083
  let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
17587
19084
  let specularEnvironmentR0 = specularColor;
17588
19085
  let specularEnvironmentR90 = vec3<f32>(1.0, 1.0, 1.0) * reflectance90;
17589
-
17590
- let n = getNormal(); // normal at surface point
17591
- let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera
17592
-
17593
- let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);
17594
19086
  let reflection = -normalize(reflect(v, n));
17595
19087
 
17596
19088
  var pbrInfo = PBRInfo(
@@ -17613,13 +19105,33 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17613
19105
  #ifdef USE_LIGHTS
17614
19106
  // Apply ambient light
17615
19107
  PBRInfo_setAmbientLight(&pbrInfo);
17616
- color += calculateFinalColor(pbrInfo, lighting.ambientColor);
19108
+ color += calculateMaterialLightColor(
19109
+ pbrInfo,
19110
+ lighting.ambientColor,
19111
+ clearcoatNormal,
19112
+ clearcoatFactor,
19113
+ clearcoatRoughness,
19114
+ sheenColor,
19115
+ sheenRoughness,
19116
+ anisotropyTangent,
19117
+ anisotropyStrength
19118
+ );
17617
19119
 
17618
19120
  // Apply directional light
17619
19121
  for (var i = 0; i < lighting.directionalLightCount; i++) {
17620
19122
  if (i < lighting.directionalLightCount) {
17621
19123
  PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);
17622
- color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);
19124
+ color += calculateMaterialLightColor(
19125
+ pbrInfo,
19126
+ lighting_getDirectionalLight(i).color,
19127
+ clearcoatNormal,
19128
+ clearcoatFactor,
19129
+ clearcoatRoughness,
19130
+ sheenColor,
19131
+ sheenRoughness,
19132
+ anisotropyTangent,
19133
+ anisotropyStrength
19134
+ );
17623
19135
  }
17624
19136
  }
17625
19137
 
@@ -17631,7 +19143,35 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17631
19143
  lighting_getPointLight(i),
17632
19144
  distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)
17633
19145
  );
17634
- color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);
19146
+ color += calculateMaterialLightColor(
19147
+ pbrInfo,
19148
+ lighting_getPointLight(i).color / attenuation,
19149
+ clearcoatNormal,
19150
+ clearcoatFactor,
19151
+ clearcoatRoughness,
19152
+ sheenColor,
19153
+ sheenRoughness,
19154
+ anisotropyTangent,
19155
+ anisotropyStrength
19156
+ );
19157
+ }
19158
+ }
19159
+
19160
+ for (var i = 0; i < lighting.spotLightCount; i++) {
19161
+ if (i < lighting.spotLightCount) {
19162
+ PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));
19163
+ let attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), fragmentInputs.pbr_vPosition);
19164
+ color += calculateMaterialLightColor(
19165
+ pbrInfo,
19166
+ lighting_getSpotLight(i).color / attenuation,
19167
+ clearcoatNormal,
19168
+ clearcoatFactor,
19169
+ clearcoatRoughness,
19170
+ sheenColor,
19171
+ sheenRoughness,
19172
+ anisotropyTangent,
19173
+ anisotropyStrength
19174
+ );
17635
19175
  }
17636
19176
  }
17637
19177
  #endif
@@ -17639,7 +19179,16 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17639
19179
  // Calculate lighting contribution from image based lighting source (IBL)
17640
19180
  #ifdef USE_IBL
17641
19181
  if (pbrMaterial.IBLenabled != 0) {
17642
- color += getIBLContribution(pbrInfo, n, reflection);
19182
+ color += getIBLContribution(pbrInfo, n, reflection) *
19183
+ calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);
19184
+ color += calculateClearcoatIBLContribution(
19185
+ pbrInfo,
19186
+ clearcoatNormal,
19187
+ -normalize(reflect(v, clearcoatNormal)),
19188
+ clearcoatFactor,
19189
+ clearcoatRoughness
19190
+ );
19191
+ color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;
17643
19192
  }
17644
19193
  #endif
17645
19194
 
@@ -17652,14 +19201,19 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17652
19201
  }
17653
19202
  #endif
17654
19203
 
19204
+ var emissive = pbrMaterial.emissiveFactor;
17655
19205
  #ifdef HAS_EMISSIVEMAP
17656
19206
  if (pbrMaterial.emissiveMapEnabled != 0u) {
17657
- let emissive = SRGBtoLINEAR(
19207
+ emissive *= SRGBtoLINEAR(
17658
19208
  textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, fragmentInputs.pbr_vUV)
17659
- ).rgb * pbrMaterial.emissiveFactor;
17660
- color += emissive;
19209
+ ).rgb;
17661
19210
  }
17662
19211
  #endif
19212
+ color += emissive * pbrMaterial.emissiveStrength;
19213
+
19214
+ if (transmission > 0.0) {
19215
+ color = mix(color, color * getVolumeAttenuation(thickness), transmission);
19216
+ }
17663
19217
 
17664
19218
  // This section uses mix to override final color for reference app visualization
17665
19219
  // of various parameters in the lighting equation.
@@ -17678,7 +19232,8 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17678
19232
  #endif
17679
19233
  }
17680
19234
 
17681
- return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), baseColor.a);
19235
+ let alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);
19236
+ return vec4<f32>(pow(color, vec3<f32>(1.0 / 2.2)), alpha);
17682
19237
  }
17683
19238
  `
17684
19239
  );
@@ -17686,7 +19241,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17686
19241
  // ../../node_modules/@luma.gl/shadertools/dist/modules/lighting/pbr-material/pbr-projection.js
17687
19242
  var uniformBlock2 = (
17688
19243
  /* glsl */
17689
- `uniform pbrProjectionUniforms {
19244
+ `layout(std140) uniform pbrProjectionUniforms {
17690
19245
  mat4 modelViewProjectionMatrix;
17691
19246
  mat4 modelMatrix;
17692
19247
  mat4 normalMatrix;
@@ -17703,11 +19258,12 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17703
19258
  camera: vec3<f32>
17704
19259
  };
17705
19260
 
17706
- @binding(0) @group(0) var<uniform> pbrProjection: pbrProjectionUniforms;
19261
+ @group(0) @binding(auto) var<uniform> pbrProjection: pbrProjectionUniforms;
17707
19262
  `
17708
19263
  );
17709
19264
  var pbrProjection = {
17710
19265
  name: "pbrProjection",
19266
+ bindingLayout: [{ name: "pbrProjection", group: 0 }],
17711
19267
  source: wgslUniformBlock,
17712
19268
  vs: uniformBlock2,
17713
19269
  fs: uniformBlock2,
@@ -17725,8 +19281,75 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17725
19281
  var pbrMaterial = {
17726
19282
  props: {},
17727
19283
  uniforms: {},
19284
+ defaultUniforms: {
19285
+ unlit: false,
19286
+ baseColorMapEnabled: false,
19287
+ baseColorFactor: [1, 1, 1, 1],
19288
+ normalMapEnabled: false,
19289
+ normalScale: 1,
19290
+ emissiveMapEnabled: false,
19291
+ emissiveFactor: [0, 0, 0],
19292
+ metallicRoughnessValues: [1, 1],
19293
+ metallicRoughnessMapEnabled: false,
19294
+ occlusionMapEnabled: false,
19295
+ occlusionStrength: 1,
19296
+ alphaCutoffEnabled: false,
19297
+ alphaCutoff: 0.5,
19298
+ IBLenabled: false,
19299
+ scaleIBLAmbient: [1, 1],
19300
+ scaleDiffBaseMR: [0, 0, 0, 0],
19301
+ scaleFGDSpec: [0, 0, 0, 0],
19302
+ specularColorFactor: [1, 1, 1],
19303
+ specularIntensityFactor: 1,
19304
+ specularColorMapEnabled: false,
19305
+ specularIntensityMapEnabled: false,
19306
+ ior: 1.5,
19307
+ transmissionFactor: 0,
19308
+ transmissionMapEnabled: false,
19309
+ thicknessFactor: 0,
19310
+ attenuationDistance: 1e9,
19311
+ attenuationColor: [1, 1, 1],
19312
+ clearcoatFactor: 0,
19313
+ clearcoatRoughnessFactor: 0,
19314
+ clearcoatMapEnabled: false,
19315
+ clearcoatRoughnessMapEnabled: false,
19316
+ sheenColorFactor: [0, 0, 0],
19317
+ sheenRoughnessFactor: 0,
19318
+ sheenColorMapEnabled: false,
19319
+ sheenRoughnessMapEnabled: false,
19320
+ iridescenceFactor: 0,
19321
+ iridescenceIor: 1.3,
19322
+ iridescenceThicknessRange: [100, 400],
19323
+ iridescenceMapEnabled: false,
19324
+ anisotropyStrength: 0,
19325
+ anisotropyRotation: 0,
19326
+ anisotropyDirection: [1, 0],
19327
+ anisotropyMapEnabled: false,
19328
+ emissiveStrength: 1
19329
+ },
17728
19330
  name: "pbrMaterial",
17729
- dependencies: [lighting, pbrProjection],
19331
+ firstBindingSlot: 0,
19332
+ bindingLayout: [
19333
+ { name: "pbrMaterial", group: 3 },
19334
+ { name: "pbr_baseColorSampler", group: 3 },
19335
+ { name: "pbr_normalSampler", group: 3 },
19336
+ { name: "pbr_emissiveSampler", group: 3 },
19337
+ { name: "pbr_metallicRoughnessSampler", group: 3 },
19338
+ { name: "pbr_occlusionSampler", group: 3 },
19339
+ { name: "pbr_specularColorSampler", group: 3 },
19340
+ { name: "pbr_specularIntensitySampler", group: 3 },
19341
+ { name: "pbr_transmissionSampler", group: 3 },
19342
+ { name: "pbr_thicknessSampler", group: 3 },
19343
+ { name: "pbr_clearcoatSampler", group: 3 },
19344
+ { name: "pbr_clearcoatRoughnessSampler", group: 3 },
19345
+ { name: "pbr_clearcoatNormalSampler", group: 3 },
19346
+ { name: "pbr_sheenColorSampler", group: 3 },
19347
+ { name: "pbr_sheenRoughnessSampler", group: 3 },
19348
+ { name: "pbr_iridescenceSampler", group: 3 },
19349
+ { name: "pbr_iridescenceThicknessSampler", group: 3 },
19350
+ { name: "pbr_anisotropySampler", group: 3 }
19351
+ ],
19352
+ dependencies: [lighting, ibl, pbrProjection],
17730
19353
  source,
17731
19354
  vs,
17732
19355
  fs,
@@ -17740,10 +19363,16 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17740
19363
  HAS_SPECULARCOLORMAP: false,
17741
19364
  HAS_SPECULARINTENSITYMAP: false,
17742
19365
  HAS_TRANSMISSIONMAP: false,
19366
+ HAS_THICKNESSMAP: false,
17743
19367
  HAS_CLEARCOATMAP: false,
19368
+ HAS_CLEARCOATROUGHNESSMAP: false,
19369
+ HAS_CLEARCOATNORMALMAP: false,
17744
19370
  HAS_SHEENCOLORMAP: false,
19371
+ HAS_SHEENROUGHNESSMAP: false,
17745
19372
  HAS_IRIDESCENCEMAP: false,
19373
+ HAS_IRIDESCENCETHICKNESSMAP: false,
17746
19374
  HAS_ANISOTROPYMAP: false,
19375
+ USE_MATERIAL_EXTENSIONS: false,
17747
19376
  ALPHA_CUTOFF: false,
17748
19377
  USE_IBL: false,
17749
19378
  PBR_DEBUG: false
@@ -17769,14 +19398,6 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17769
19398
  alphaCutoffEnabled: "i32",
17770
19399
  alphaCutoff: "f32",
17771
19400
  // #ifdef ALPHA_CUTOFF
17772
- // IBL
17773
- IBLenabled: "i32",
17774
- scaleIBLAmbient: "vec2<f32>",
17775
- // #ifdef USE_IBL
17776
- // debugging flags used for shader output of intermediate PBR variables
17777
- // #ifdef PBR_DEBUG
17778
- scaleDiffBaseMR: "vec4<f32>",
17779
- scaleFGDSpec: "vec4<f32>",
17780
19401
  specularColorFactor: "vec3<f32>",
17781
19402
  specularIntensityFactor: "f32",
17782
19403
  specularColorMapEnabled: "i32",
@@ -17790,9 +19411,11 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17790
19411
  clearcoatFactor: "f32",
17791
19412
  clearcoatRoughnessFactor: "f32",
17792
19413
  clearcoatMapEnabled: "i32",
19414
+ clearcoatRoughnessMapEnabled: "i32",
17793
19415
  sheenColorFactor: "vec3<f32>",
17794
19416
  sheenRoughnessFactor: "f32",
17795
19417
  sheenColorMapEnabled: "i32",
19418
+ sheenRoughnessMapEnabled: "i32",
17796
19419
  iridescenceFactor: "f32",
17797
19420
  iridescenceIor: "f32",
17798
19421
  iridescenceThicknessRange: "vec2<f32>",
@@ -17801,7 +19424,15 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17801
19424
  anisotropyRotation: "f32",
17802
19425
  anisotropyDirection: "vec2<f32>",
17803
19426
  anisotropyMapEnabled: "i32",
17804
- emissiveStrength: "f32"
19427
+ emissiveStrength: "f32",
19428
+ // IBL
19429
+ IBLenabled: "i32",
19430
+ scaleIBLAmbient: "vec2<f32>",
19431
+ // #ifdef USE_IBL
19432
+ // debugging flags used for shader output of intermediate PBR variables
19433
+ // #ifdef PBR_DEBUG
19434
+ scaleDiffBaseMR: "vec4<f32>",
19435
+ scaleFGDSpec: "vec4<f32>"
17805
19436
  }
17806
19437
  };
17807
19438
 
@@ -17810,7 +19441,7 @@ fn pbr_filterColor(colorUnused: vec4<f32>) -> vec4<f32> {
17810
19441
  var import_mesh_layers = __toESM(require_mesh_layers(), 1);
17811
19442
 
17812
19443
  // src/mesh-layer/mesh-layer-uniforms.ts
17813
- var uniformBlock3 = `uniform meshUniforms {
19444
+ var uniformBlock3 = `layout(std140) uniform meshUniforms {
17814
19445
  bool pickFeatureIds;
17815
19446
  } mesh;
17816
19447
  `;
@@ -28254,6 +29885,14 @@ void main(void) {
28254
29885
  }
28255
29886
  }
28256
29887
  }
29888
+ finalizeState(context) {
29889
+ this.state.tileset3d?.destroy();
29890
+ this.state.tileset3d = null;
29891
+ this.state.layerMap = {};
29892
+ this.state.activeViewports = {};
29893
+ this.state.lastUpdatedViewports = null;
29894
+ super.finalizeState(context);
29895
+ }
28257
29896
  activateViewport(viewport) {
28258
29897
  const { activeViewports, lastUpdatedViewports } = this.state;
28259
29898
  this.internalState.viewport = viewport;
@@ -31612,17 +33251,20 @@ void main(void) {
31612
33251
  const { fetch: fetch2 } = this.props;
31613
33252
  loadOptions = {
31614
33253
  ...loadOptions,
31615
- mimeType: "application/x-protobuf",
33254
+ core: {
33255
+ ...loadOptions?.core,
33256
+ mimeType: "application/x-protobuf"
33257
+ },
31616
33258
  mvt: {
31617
33259
  ...loadOptions?.mvt,
33260
+ shape: binary ? "binary" : "geojson",
31618
33261
  coordinates: this.context.viewport.resolution ? "wgs84" : "local",
31619
33262
  tileIndex: index
31620
33263
  // Local worker debug
31621
33264
  // workerUrl: `modules/mvt/dist/mvt-loader.worker.js`
31622
33265
  // Set worker to null to skip web workers
31623
33266
  // workerUrl: null
31624
- },
31625
- gis: binary ? { format: "binary" } : {}
33267
+ }
31626
33268
  };
31627
33269
  return fetch2(url, { propName: "data", layer: this, loadOptions, signal });
31628
33270
  }