@babylonjs/lite 1.9.0 → 1.10.0
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/CHANGELOG.md +26 -0
- package/dist/index.js +596 -526
- package/dist/index.js.map +1 -1
- package/index.d.ts +107 -4
- package/lib/engine/engine.js +1 -1
- package/lib/engine/engine.js.map +1 -1
- package/lib/frame-graph/render-task.js +6 -4
- package/lib/frame-graph/render-task.js.map +1 -1
- package/lib/index.js +4 -1
- package/lib/index.js.map +1 -1
- package/lib/loader-gltf/gltf-ext-quantization.js +4 -1
- package/lib/loader-gltf/gltf-ext-quantization.js.map +1 -1
- package/lib/loader-gltf/gltf-feature-registry.js +11 -1
- package/lib/loader-gltf/gltf-feature-registry.js.map +1 -1
- package/lib/loader-gltf/gltf-feature-variants.js +11 -1
- package/lib/loader-gltf/gltf-feature-variants.js.map +1 -1
- package/lib/loader-gltf/gltf-json-asset.js +8 -1
- package/lib/loader-gltf/gltf-json-asset.js.map +1 -1
- package/lib/loader-gltf/gltf-material.js +4 -29
- package/lib/loader-gltf/gltf-material.js.map +1 -1
- package/lib/loader-gltf/gltf-parser.js +1 -8
- package/lib/loader-gltf/gltf-parser.js.map +1 -1
- package/lib/loader-gltf/gltf-pbr-builder.js +1 -15
- package/lib/loader-gltf/gltf-pbr-builder.js.map +1 -1
- package/lib/loader-gltf/gltf-variants.js +5 -10
- package/lib/loader-gltf/gltf-variants.js.map +1 -1
- package/lib/loader-gltf/load-gltf.js +19 -29
- package/lib/loader-gltf/load-gltf.js.map +1 -1
- package/lib/material/pbr/background-dds-skybox.js +35 -93
- package/lib/material/pbr/background-dds-skybox.js.map +1 -1
- package/lib/material/pbr/background-ground.js +13 -18
- package/lib/material/pbr/background-ground.js.map +1 -1
- package/lib/material/pbr/background-hdr-skybox.js +35 -93
- package/lib/material/pbr/background-hdr-skybox.js.map +1 -1
- package/lib/material/pbr/background-solid-skybox.js +35 -93
- package/lib/material/pbr/background-solid-skybox.js.map +1 -1
- package/lib/material/pbr/fragments/clearcoat-fragment.js +5 -1
- package/lib/material/pbr/fragments/clearcoat-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/iridescence-fragment.js +4 -1
- package/lib/material/pbr/fragments/iridescence-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/refraction-rtt-fragment.js +7 -2
- package/lib/material/pbr/fragments/refraction-rtt-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/sheen-fragment.js +2 -1
- package/lib/material/pbr/fragments/sheen-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/subsurface-fragment.js +2 -1
- package/lib/material/pbr/fragments/subsurface-fragment.js.map +1 -1
- package/lib/material/pbr/fragments/unlit-fragment.js +1 -2
- package/lib/material/pbr/fragments/unlit-fragment.js.map +1 -1
- package/lib/material/pbr/pbr-compose.js +2 -0
- package/lib/material/pbr/pbr-compose.js.map +1 -1
- package/lib/material/pbr/pbr-flag-bits.js +1 -16
- package/lib/material/pbr/pbr-flag-bits.js.map +1 -1
- package/lib/material/pbr/pbr-flags.js +1 -1
- package/lib/material/pbr/pbr-fog-wgsl.js +1 -1
- package/lib/material/pbr/pbr-fog-wgsl.js.map +1 -1
- package/lib/material/pbr/pbr-geometry-output-shader.js +2 -1
- package/lib/material/pbr/pbr-geometry-output-shader.js.map +1 -1
- package/lib/material/pbr/pbr-geometry-view.js +2 -1
- package/lib/material/pbr/pbr-geometry-view.js.map +1 -1
- package/lib/material/pbr/pbr-renderable.js +4 -0
- package/lib/material/pbr/pbr-renderable.js.map +1 -1
- package/lib/material/pbr/pbr-template-gamma.js +7 -0
- package/lib/material/pbr/pbr-template-gamma.js.map +1 -0
- package/lib/material/pbr/pbr-template.js +2 -2
- package/lib/material/pbr/pbr-template.js.map +1 -1
- package/lib/material/standard/skybox-cubemap.js +1 -1
- package/lib/material/standard/skybox-cubemap.js.map +1 -1
- package/lib/material/standard/standard-template.js +1 -1
- package/lib/material/standard/standard-template.js.map +1 -1
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline-sh.js +3 -5
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline-sh.js.map +1 -1
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline.js +3 -5
- package/lib/mesh/GaussianSplatting/gaussian-splatting-pipeline.js.map +1 -1
- package/lib/particle/node/blocks/particle-condition-block.js +55 -0
- package/lib/particle/node/blocks/particle-condition-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-float-to-int-block.js +28 -0
- package/lib/particle/node/blocks/particle-float-to-int-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-gradient-block.js +32 -0
- package/lib/particle/node/blocks/particle-gradient-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-gradient-value-block.js +11 -0
- package/lib/particle/node/blocks/particle-gradient-value-block.js.map +1 -0
- package/lib/particle/node/blocks/particle-lerp-block.js +2 -24
- package/lib/particle/node/blocks/particle-lerp-block.js.map +1 -1
- package/lib/particle/node/blocks/particle-lerp.js +27 -0
- package/lib/particle/node/blocks/particle-lerp.js.map +1 -0
- package/lib/particle/node/blocks/particle-vector-length-block.js +30 -0
- package/lib/particle/node/blocks/particle-vector-length-block.js.map +1 -0
- package/lib/particle/node/blocks/system-block.js +13 -3
- package/lib/particle/node/blocks/system-block.js.map +1 -1
- package/lib/particle/node/blocks/texture-source-block.js +2 -1
- package/lib/particle/node/blocks/texture-source-block.js.map +1 -1
- package/lib/particle/node/blocks/update-size-block.js +19 -0
- package/lib/particle/node/blocks/update-size-block.js.map +1 -0
- package/lib/particle/node/npe-build-state.js +10 -0
- package/lib/particle/node/npe-build-state.js.map +1 -1
- package/lib/particle/node/npe-registry.js +12 -0
- package/lib/particle/node/npe-registry.js.map +1 -1
- package/lib/particle/particle-system.js +7 -2
- package/lib/particle/particle-system.js.map +1 -1
- package/lib/picking/billboard-pick-pipeline.js +269 -0
- package/lib/picking/billboard-pick-pipeline.js.map +1 -0
- package/lib/picking/gpu-picker.js +37 -37
- package/lib/picking/gpu-picker.js.map +1 -1
- package/lib/picking/gs-picking-pipeline.js +26 -1
- package/lib/picking/gs-picking-pipeline.js.map +1 -1
- package/lib/picking/pick-contributor.js +13 -0
- package/lib/picking/pick-contributor.js.map +1 -0
- package/lib/picking/picking-info.js.map +1 -1
- package/lib/scene/scene-core.js +2 -2
- package/lib/scene/scene-core.js.map +1 -1
- package/lib/shader/wgsl-fog.js +18 -0
- package/lib/shader/wgsl-fog.js.map +1 -0
- package/lib/shader/wgsl-helpers.js +1 -16
- package/lib/shader/wgsl-helpers.js.map +1 -1
- package/lib/sprite/billboard-scene.js +2 -0
- package/lib/sprite/billboard-scene.js.map +1 -1
- package/lib/sprite/picking/pick-billboard.js +16 -0
- package/lib/sprite/picking/pick-billboard.js.map +1 -0
- package/lib/sprite/picking/pick-sprite-2d.js +41 -0
- package/lib/sprite/picking/pick-sprite-2d.js.map +1 -0
- package/lib/sprite/shared/sprite-atlas.js +4 -1
- package/lib/sprite/shared/sprite-atlas.js.map +1 -1
- package/lib/sprite/sprite-2d.js.map +1 -1
- package/lib/sprite/sprite-pipeline.js +18 -1
- package/lib/sprite/sprite-pipeline.js.map +1 -1
- package/lib/sprite/sprite-renderer.js +12 -6
- package/lib/sprite/sprite-renderer.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refraction-rtt-fragment.js","sources":["../../../../../src/material/pbr/fragments/refraction-rtt-fragment.ts"],"sourcesContent":["import type { ShaderFragment, UboField } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SubSurfaceProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { getTrilinearAnisotropicSampler } from \"../../../resource/trilinear-anisotropic-sampler.js\";\nimport {\n PBR_HAS_THICKNESS_MAP,\n PBR2_HAS_DISPERSION,\n PBR2_HAS_REFRACTION,\n PBR2_HAS_REFRACTION_MAP,\n PBR2_HAS_THICKNESS_GLTF_CHANNEL,\n PBR2_HAS_VOLUME,\n PBR2_LINEAR_IMAGE_PROCESSING,\n} from \"../pbr-flag-bits.js\";\n\ntype TransmissionMat = PbrMaterialProps & { _linearImageProcessing?: boolean };\nconst LINEAR_IMAGE_PROCESSING_SLOTS = { NI: `if(scene.vImageInfos.w>=0.0){`, BC: `}` };\n\nfunction makeRefractionMod(\n hasVolume: boolean,\n hasMap: boolean,\n hasThicknessMap: boolean,\n useGltfThicknessChannel: boolean,\n hasDispersion: boolean,\n dispersionSampleWgsl: string | undefined\n): string {\n const thicknessScaleLine = hasVolume || hasThicknessMap ? `let ts=max(length(mesh.world[0].xyz),max(length(mesh.world[1].xyz),length(mesh.world[2].xyz)));` : ``;\n const mapUvDecl = hasMap\n ? `let refractionMapUV=vec2<f32>(dot(material.refractionMapUVm.xy,input.uv),dot(material.refractionMapUVm.zw,input.uv))+material.refractionMapUVt.xy;\\n`\n : ``;\n const thickUvDecl = hasThicknessMap\n ? `let thicknessUV=vec2<f32>(dot(material.thicknessUVm.xy,input.uv),dot(material.thicknessUVm.zw,input.uv))+material.thicknessUVt.xy;\\n`\n : ``;\n const thicknessLine = hasThicknessMap\n ? `let ths=textureSample(thicknessTexture_,thicknessSampler_,thicknessUV).${useGltfThicknessChannel ? \"g\" : \"r\"};\nlet th=(material.thicknessParams.x+ths*material.thicknessParams.y)*ts;`\n : hasVolume\n ? `let th=material.refractionParams.z*ts;`\n : `let th=material.refractionParams.z;`;\n const textureLine = hasMap\n ? `let ri=material.refractionParams.x*textureSample(refractionMapTexture,refractionMapSampler,refractionMapUV).r;`\n : `let ri=material.refractionParams.x;`;\n const absorptionLine = hasVolume ? `let ab=exp(material.volumeParams.rgb*th);` : ``;\n const refractionLine = hasVolume\n ? `let fr=er*surfaceAlbedo*(ri*ab)*(vec3<f32>(1.0)-colorSpecularEnvReflectance.rgb);`\n : `let fr=er*surfaceAlbedo*ri*(vec3<f32>(1.0)-colorSpecularEnvReflectance.rgb);`;\n\n // Refracted environment sample. Dispersion splits the refracted ray into\n // per-RGB index-of-refraction offsets (chromatic aberration); that 3-ray WGSL\n // is injected from a dynamically-imported module (see refraction-dispersion-wgsl.ts)\n // so non-dispersion transmission scenes keep the lean single-ray path below.\n const sampleLines =\n hasDispersion && dispersionSampleWgsl\n ? dispersionSampleWgsl\n : `let rd=refract(-V,N,material.refractionParams.y);\nlet cp=scene.viewProjection*vec4<f32>(input.worldPos+rd*th,1.0);\nlet ruv=(cp.xy/cp.w)*vec2<f32>(0.5,-0.5)+vec2<f32>(0.5,0.5);\nlet er=textureSampleLevel(refractionTexture,refractionSampler_,ruv,lv).rgb*material.environmentIntensity;`;\n\n return `{\n${thicknessScaleLine}\n${mapUvDecl}${thickUvDecl}${textureLine}\n${thicknessLine}\nlet ro=1.0-ri;\nlet ra=mix(alphaG,0.0,clamp(material.refractionParams.w*3.0-2.0,0.0,1.0));\nlet lv=clamp(log2(f32(textureDimensions(refractionTexture).x)*ra)-4.0,0.0,f32(textureNumLevels(refractionTexture)-1));\n${sampleLines}\n${absorptionLine}\n${refractionLine}\ncolor=finalIrradiance*ro*ro+finalRadianceScaled+finalSpecularScaled+directDiffuse*ro*ro+fr+emissive;\n}`;\n}\n\nfunction createRefractionRttFragment(\n hasVolume: boolean,\n hasMap: boolean,\n hasThicknessMap: boolean,\n useGltfThicknessChannel: boolean,\n linearImageProcessing: boolean,\n hasDispersion: boolean,\n dispersionSampleWgsl: string | undefined\n): ShaderFragment {\n const uboFields: UboField[] = [{ _name: \"refractionParams\", _type: \"vec4<f32>\" as const }];\n if (hasVolume) {\n uboFields.push({ _name: \"volumeParams\", _type: \"vec4<f32>\" as const });\n }\n if (hasThicknessMap) {\n uboFields.push({ _name: \"thicknessParams\", _type: \"vec4<f32>\" as const });\n }\n // Per-texture UV transforms (KHR_texture_transform on transmissionTexture / thicknessTexture),\n // animatable via KHR_animation_pointer. Emitted whenever the map is present; identity when the\n // texture carries no transform (sample at input.uv), so non-transformed scenes are unchanged.\n if (hasMap) {\n uboFields.push({ _name: \"refractionMapUVm\", _type: \"vec4<f32>\" as const }, { _name: \"refractionMapUVt\", _type: \"vec4<f32>\" as const });\n }\n if (hasThicknessMap) {\n uboFields.push({ _name: \"thicknessUVm\", _type: \"vec4<f32>\" as const }, { _name: \"thicknessUVt\", _type: \"vec4<f32>\" as const });\n }\n const bindings = [\n { _name: \"refractionTexture\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" } as const, _visibility: 2 },\n { _name: \"refractionSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" } as const, _visibility: 2 },\n ];\n if (hasMap) {\n bindings.push(\n { _name: \"refractionMapTexture\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" } as const, _visibility: 2 },\n { _name: \"refractionMapSampler\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" } as const, _visibility: 2 }\n );\n }\n if (hasThicknessMap) {\n bindings.push(\n { _name: \"thicknessTexture_\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" } as const, _visibility: 2 },\n { _name: \"thicknessSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" } as const, _visibility: 2 }\n );\n }\n return {\n _id: \"refraction\",\n _dependencies: [\"ibl\"],\n _uboFields: uboFields,\n _bindings: bindings,\n _fragmentSlots: linearImageProcessing\n ? { AI: makeRefractionMod(hasVolume, hasMap, hasThicknessMap, useGltfThicknessChannel, hasDispersion, dispersionSampleWgsl), ...LINEAR_IMAGE_PROCESSING_SLOTS }\n : { AI: makeRefractionMod(hasVolume, hasMap, hasThicknessMap, useGltfThicknessChannel, hasDispersion, dispersionSampleWgsl) },\n };\n}\n\nfunction writeRefractionUvTransform(\n data: Float32Array,\n offsets: ReadonlyMap<string, number>,\n name: string,\n tex: { uScale?: number; vScale?: number; uAng?: number; uOffset?: number; vOffset?: number } | undefined\n): void {\n const mOff = offsets.get(`${name}m`);\n const tOff = offsets.get(`${name}t`);\n if (mOff === undefined || tOff === undefined) {\n return;\n }\n const mi = mOff / 4;\n const ti = tOff / 4;\n const sx = tex?.uScale ?? 1;\n const sy = tex?.vScale ?? 1;\n const ang = tex?.uAng ?? 0;\n if (ang === 0) {\n data[mi] = sx;\n data[mi + 1] = 0;\n data[mi + 2] = 0;\n data[mi + 3] = sy;\n } else {\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n data[mi] = c * sx;\n data[mi + 1] = s * sy;\n data[mi + 2] = -s * sx;\n data[mi + 3] = c * sy;\n }\n data[ti] = tex?.uOffset ?? 0;\n data[ti + 1] = tex?.vOffset ?? 0;\n data[ti + 2] = 0;\n data[ti + 3] = 0;\n}\n\nfunction writeRefractionUBO(data: Float32Array, mat: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n const ss = mat.subsurface as SubSurfaceProps | undefined;\n const refr = ss?.refraction;\n if (!refr) {\n return;\n }\n const off = offsets.get(\"refractionParams\");\n if (off === undefined) {\n return;\n }\n const o = off / 4;\n data[o] = refr.intensity ?? 0;\n const ior = refr.indexOfRefraction ?? 1.5;\n const thick = ss!.thickness;\n data[o + 1] = 1.0 / (refr.useThicknessAsDepth && thick?.max ? ior : 1.0);\n data[o + 2] = refr.useThicknessAsDepth ? (thick?.max ?? 0.0) : 0.0;\n data[o + 3] = 1.0 / ior;\n\n const vOff = offsets.get(\"volumeParams\");\n if (vOff !== undefined) {\n const vo = vOff / 4;\n const tint = ss!.tint?.color ?? [1, 1, 1];\n const dist = Math.max(ss!.tint?.atDistance ?? 1, 0.0001);\n data[vo] = Math.log(Math.max(tint[0]!, 1e-6)) / dist;\n data[vo + 1] = Math.log(Math.max(tint[1]!, 1e-6)) / dist;\n data[vo + 2] = Math.log(Math.max(tint[2]!, 1e-6)) / dist;\n // w carries the chromatic dispersion strength (0 when no KHR_materials_dispersion).\n data[vo + 3] = refr.dispersion ?? 0;\n }\n\n const tOff = offsets.get(\"thicknessParams\");\n if (tOff !== undefined) {\n const to = tOff / 4;\n const min = thick?.min ?? 0;\n const max = thick?.max ?? 1;\n data[to] = min;\n data[to + 1] = max - min;\n }\n\n writeRefractionUvTransform(data, offsets, \"refractionMapUV\", refr.texture);\n writeRefractionUvTransform(data, offsets, \"thicknessUV\", thick?.texture);\n}\n\n/** Build the PBR refraction/transmission extension. When the scene contains a\n * dispersive material, `dispersionSampleWgsl` carries the per-RGB 3-ray sample\n * WGSL (dynamically imported, scene-isolated); otherwise it is undefined and the\n * lean single-ray refraction path is emitted. */\nexport function makeRefractionRttExt(dispersionSampleWgsl?: string): PbrExt {\n return {\n id: \"refraction\",\n phase: \"fragment\",\n detect(mat) {\n const m = mat as TransmissionMat;\n const ss = m.subsurface as SubSurfaceProps | undefined;\n const refr = ss?.refraction;\n const linearImageProcessing = m._linearImageProcessing ? PBR2_LINEAR_IMAGE_PROCESSING : 0;\n const intensity = m.transmissive ? (refr?.intensity ?? 0) : 0;\n if (intensity <= 0) {\n return { f: 0, f2: linearImageProcessing };\n }\n let f = 0;\n let f2 = linearImageProcessing | PBR2_HAS_REFRACTION;\n if (refr?.texture) {\n f2 |= PBR2_HAS_REFRACTION_MAP;\n }\n if (ss?.thickness?.texture) {\n f |= PBR_HAS_THICKNESS_MAP;\n }\n if (ss?.thickness?.useGlTFChannel) {\n f2 |= PBR2_HAS_THICKNESS_GLTF_CHANNEL;\n }\n if (ss?.tint?.atDistance !== undefined) {\n f2 |= PBR2_HAS_VOLUME;\n // Dispersion requires the volume path (per-channel etas + volumeParams.w storage).\n if (refr?.dispersion) {\n f2 |= PBR2_HAS_DISPERSION;\n }\n }\n return { f, f2 };\n },\n frag(ctx) {\n const linearImageProcessing = (ctx._features2 & PBR2_LINEAR_IMAGE_PROCESSING) !== 0;\n if (!(ctx._features2 & PBR2_HAS_REFRACTION)) {\n return linearImageProcessing ? { _id: \"linear\", _fragmentSlots: LINEAR_IMAGE_PROCESSING_SLOTS } : null;\n }\n return createRefractionRttFragment(\n (ctx._features2 & PBR2_HAS_VOLUME) !== 0,\n (ctx._features2 & PBR2_HAS_REFRACTION_MAP) !== 0,\n (ctx._features & PBR_HAS_THICKNESS_MAP) !== 0,\n (ctx._features2 & PBR2_HAS_THICKNESS_GLTF_CHANNEL) !== 0,\n linearImageProcessing,\n (ctx._features2 & PBR2_HAS_DISPERSION) !== 0,\n dispersionSampleWgsl\n );\n },\n writeUbo(data, mat, offsets) {\n writeRefractionUBO(data, mat as PbrMaterialProps, offsets);\n },\n bind(ctx, entries, b) {\n if (!(ctx._features2 & PBR2_HAS_REFRACTION)) {\n return b;\n }\n const texture = ctx._refractionTexture;\n if (!texture) {\n throw new Error(\"PBR transmission requires a frame-graph refraction texture.\");\n }\n entries.push({ binding: b++, resource: texture.view });\n entries.push({ binding: b++, resource: texture.sampler });\n if ((ctx._features2 & PBR2_HAS_REFRACTION_MAP) !== 0) {\n const map = ((ctx._material as PbrMaterialProps).subsurface?.refraction as SubSurfaceProps[\"refraction\"] | undefined)?.texture!;\n entries.push({ binding: b++, resource: map.view });\n entries.push({ binding: b++, resource: getTrilinearAnisotropicSampler(ctx._engine) });\n }\n if ((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0) {\n const thickness = (ctx._material as PbrMaterialProps).subsurface?.thickness?.texture!;\n entries.push({ binding: b++, resource: thickness.view });\n entries.push({ binding: b++, resource: thickness.sampler });\n }\n return b;\n },\n textures(mat, out) {\n const tex = (mat as PbrMaterialProps).subsurface?.refraction?.texture;\n if (tex) {\n out.push(tex);\n }\n const thickness = (mat as PbrMaterialProps).subsurface?.thickness?.texture;\n if (thickness) {\n out.push(thickness);\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"refraction-rtt-fragment.js","sources":["../../../../../src/material/pbr/fragments/refraction-rtt-fragment.ts"],"sourcesContent":["import type { ShaderFragment, UboField } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SubSurfaceProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { getTrilinearAnisotropicSampler } from \"../../../resource/trilinear-anisotropic-sampler.js\";\nimport { PBR_HAS_THICKNESS_MAP, PBR2_HAS_REFRACTION } from \"../pbr-flag-bits.js\";\n\ntype TransmissionMat = PbrMaterialProps & { _linearImageProcessing?: boolean };\nexport const PBR2_HAS_VOLUME = 1 << 5;\nexport const PBR2_HAS_REFRACTION_MAP = 1 << 6;\nconst PBR2_HAS_THICKNESS_GLTF_CHANNEL = 1 << 7;\nconst PBR2_LINEAR_IMAGE_PROCESSING = 1 << 14;\nconst PBR2_HAS_DISPERSION = 1 << 20;\nconst LINEAR_IMAGE_PROCESSING_SLOTS = { NI: `if(scene.vImageInfos.w>=0.0){`, BC: `}` };\n\nfunction makeRefractionMod(\n hasVolume: boolean,\n hasMap: boolean,\n hasThicknessMap: boolean,\n useGltfThicknessChannel: boolean,\n hasDispersion: boolean,\n dispersionSampleWgsl: string | undefined\n): string {\n const thicknessScaleLine = hasVolume || hasThicknessMap ? `let ts=max(length(mesh.world[0].xyz),max(length(mesh.world[1].xyz),length(mesh.world[2].xyz)));` : ``;\n const mapUvDecl = hasMap\n ? `let refractionMapUV=vec2<f32>(dot(material.refractionMapUVm.xy,input.uv),dot(material.refractionMapUVm.zw,input.uv))+material.refractionMapUVt.xy;\\n`\n : ``;\n const thickUvDecl = hasThicknessMap\n ? `let thicknessUV=vec2<f32>(dot(material.thicknessUVm.xy,input.uv),dot(material.thicknessUVm.zw,input.uv))+material.thicknessUVt.xy;\\n`\n : ``;\n const thicknessLine = hasThicknessMap\n ? `let ths=textureSample(thicknessTexture_,thicknessSampler_,thicknessUV).${useGltfThicknessChannel ? \"g\" : \"r\"};\nlet th=(material.thicknessParams.x+ths*material.thicknessParams.y)*ts;`\n : hasVolume\n ? `let th=material.refractionParams.z*ts;`\n : `let th=material.refractionParams.z;`;\n const textureLine = hasMap\n ? `let ri=material.refractionParams.x*textureSample(refractionMapTexture,refractionMapSampler,refractionMapUV).r;`\n : `let ri=material.refractionParams.x;`;\n const absorptionLine = hasVolume ? `let ab=exp(material.volumeParams.rgb*th);` : ``;\n const refractionLine = hasVolume\n ? `let fr=er*surfaceAlbedo*(ri*ab)*(vec3<f32>(1.0)-colorSpecularEnvReflectance.rgb);`\n : `let fr=er*surfaceAlbedo*ri*(vec3<f32>(1.0)-colorSpecularEnvReflectance.rgb);`;\n\n // Refracted environment sample. Dispersion splits the refracted ray into\n // per-RGB index-of-refraction offsets (chromatic aberration); that 3-ray WGSL\n // is injected from a dynamically-imported module (see refraction-dispersion-wgsl.ts)\n // so non-dispersion transmission scenes keep the lean single-ray path below.\n const sampleLines =\n hasDispersion && dispersionSampleWgsl\n ? dispersionSampleWgsl\n : `let rd=refract(-V,N,material.refractionParams.y);\nlet cp=scene.viewProjection*vec4<f32>(input.worldPos+rd*th,1.0);\nlet ruv=(cp.xy/cp.w)*vec2<f32>(0.5,-0.5)+vec2<f32>(0.5,0.5);\nlet er=textureSampleLevel(refractionTexture,refractionSampler_,ruv,lv).rgb*material.environmentIntensity;`;\n\n return `{\n${thicknessScaleLine}\n${mapUvDecl}${thickUvDecl}${textureLine}\n${thicknessLine}\nlet ro=1.0-ri;\nlet ra=mix(alphaG,0.0,clamp(material.refractionParams.w*3.0-2.0,0.0,1.0));\nlet lv=clamp(log2(f32(textureDimensions(refractionTexture).x)*ra)-4.0,0.0,f32(textureNumLevels(refractionTexture)-1));\n${sampleLines}\n${absorptionLine}\n${refractionLine}\ncolor=finalIrradiance*ro*ro+finalRadianceScaled+finalSpecularScaled+directDiffuse*ro*ro+fr+emissive;\n}`;\n}\n\nfunction createRefractionRttFragment(\n hasVolume: boolean,\n hasMap: boolean,\n hasThicknessMap: boolean,\n useGltfThicknessChannel: boolean,\n linearImageProcessing: boolean,\n hasDispersion: boolean,\n dispersionSampleWgsl: string | undefined\n): ShaderFragment {\n const uboFields: UboField[] = [{ _name: \"refractionParams\", _type: \"vec4<f32>\" as const }];\n if (hasVolume) {\n uboFields.push({ _name: \"volumeParams\", _type: \"vec4<f32>\" as const });\n }\n if (hasThicknessMap) {\n uboFields.push({ _name: \"thicknessParams\", _type: \"vec4<f32>\" as const });\n }\n // Per-texture UV transforms (KHR_texture_transform on transmissionTexture / thicknessTexture),\n // animatable via KHR_animation_pointer. Emitted whenever the map is present; identity when the\n // texture carries no transform (sample at input.uv), so non-transformed scenes are unchanged.\n if (hasMap) {\n uboFields.push({ _name: \"refractionMapUVm\", _type: \"vec4<f32>\" as const }, { _name: \"refractionMapUVt\", _type: \"vec4<f32>\" as const });\n }\n if (hasThicknessMap) {\n uboFields.push({ _name: \"thicknessUVm\", _type: \"vec4<f32>\" as const }, { _name: \"thicknessUVt\", _type: \"vec4<f32>\" as const });\n }\n const bindings = [\n { _name: \"refractionTexture\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" } as const, _visibility: 2 },\n { _name: \"refractionSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" } as const, _visibility: 2 },\n ];\n if (hasMap) {\n bindings.push(\n { _name: \"refractionMapTexture\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" } as const, _visibility: 2 },\n { _name: \"refractionMapSampler\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" } as const, _visibility: 2 }\n );\n }\n if (hasThicknessMap) {\n bindings.push(\n { _name: \"thicknessTexture_\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" } as const, _visibility: 2 },\n { _name: \"thicknessSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" } as const, _visibility: 2 }\n );\n }\n return {\n _id: \"refraction\",\n _dependencies: [\"ibl\"],\n _uboFields: uboFields,\n _bindings: bindings,\n _fragmentSlots: linearImageProcessing\n ? { AI: makeRefractionMod(hasVolume, hasMap, hasThicknessMap, useGltfThicknessChannel, hasDispersion, dispersionSampleWgsl), ...LINEAR_IMAGE_PROCESSING_SLOTS }\n : { AI: makeRefractionMod(hasVolume, hasMap, hasThicknessMap, useGltfThicknessChannel, hasDispersion, dispersionSampleWgsl) },\n };\n}\n\nfunction writeRefractionUvTransform(\n data: Float32Array,\n offsets: ReadonlyMap<string, number>,\n name: string,\n tex: { uScale?: number; vScale?: number; uAng?: number; uOffset?: number; vOffset?: number } | undefined\n): void {\n const mOff = offsets.get(`${name}m`);\n const tOff = offsets.get(`${name}t`);\n if (mOff === undefined || tOff === undefined) {\n return;\n }\n const mi = mOff / 4;\n const ti = tOff / 4;\n const sx = tex?.uScale ?? 1;\n const sy = tex?.vScale ?? 1;\n const ang = tex?.uAng ?? 0;\n if (ang === 0) {\n data[mi] = sx;\n data[mi + 1] = 0;\n data[mi + 2] = 0;\n data[mi + 3] = sy;\n } else {\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n data[mi] = c * sx;\n data[mi + 1] = s * sy;\n data[mi + 2] = -s * sx;\n data[mi + 3] = c * sy;\n }\n data[ti] = tex?.uOffset ?? 0;\n data[ti + 1] = tex?.vOffset ?? 0;\n data[ti + 2] = 0;\n data[ti + 3] = 0;\n}\n\nfunction writeRefractionUBO(data: Float32Array, mat: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n const ss = mat.subsurface as SubSurfaceProps | undefined;\n const refr = ss?.refraction;\n if (!refr) {\n return;\n }\n const off = offsets.get(\"refractionParams\");\n if (off === undefined) {\n return;\n }\n const o = off / 4;\n data[o] = refr.intensity ?? 0;\n const ior = refr.indexOfRefraction ?? 1.5;\n const thick = ss!.thickness;\n data[o + 1] = 1.0 / (refr.useThicknessAsDepth && thick?.max ? ior : 1.0);\n data[o + 2] = refr.useThicknessAsDepth ? (thick?.max ?? 0.0) : 0.0;\n data[o + 3] = 1.0 / ior;\n\n const vOff = offsets.get(\"volumeParams\");\n if (vOff !== undefined) {\n const vo = vOff / 4;\n const tint = ss!.tint?.color ?? [1, 1, 1];\n const dist = Math.max(ss!.tint?.atDistance ?? 1, 0.0001);\n data[vo] = Math.log(Math.max(tint[0]!, 1e-6)) / dist;\n data[vo + 1] = Math.log(Math.max(tint[1]!, 1e-6)) / dist;\n data[vo + 2] = Math.log(Math.max(tint[2]!, 1e-6)) / dist;\n // w carries the chromatic dispersion strength (0 when no KHR_materials_dispersion).\n data[vo + 3] = refr.dispersion ?? 0;\n }\n\n const tOff = offsets.get(\"thicknessParams\");\n if (tOff !== undefined) {\n const to = tOff / 4;\n const min = thick?.min ?? 0;\n const max = thick?.max ?? 1;\n data[to] = min;\n data[to + 1] = max - min;\n }\n\n writeRefractionUvTransform(data, offsets, \"refractionMapUV\", refr.texture);\n writeRefractionUvTransform(data, offsets, \"thicknessUV\", thick?.texture);\n}\n\n/** Build the PBR refraction/transmission extension. When the scene contains a\n * dispersive material, `dispersionSampleWgsl` carries the per-RGB 3-ray sample\n * WGSL (dynamically imported, scene-isolated); otherwise it is undefined and the\n * lean single-ray refraction path is emitted. */\nexport function makeRefractionRttExt(dispersionSampleWgsl?: string): PbrExt {\n return {\n id: \"refraction\",\n phase: \"fragment\",\n detect(mat) {\n const m = mat as TransmissionMat;\n const ss = m.subsurface as SubSurfaceProps | undefined;\n const refr = ss?.refraction;\n const linearImageProcessing = m._linearImageProcessing ? PBR2_LINEAR_IMAGE_PROCESSING : 0;\n const intensity = m.transmissive ? (refr?.intensity ?? 0) : 0;\n if (intensity <= 0) {\n return { f: 0, f2: linearImageProcessing };\n }\n let f = 0;\n let f2 = linearImageProcessing | PBR2_HAS_REFRACTION;\n if (refr?.texture) {\n f2 |= PBR2_HAS_REFRACTION_MAP;\n }\n if (ss?.thickness?.texture) {\n f |= PBR_HAS_THICKNESS_MAP;\n }\n if (ss?.thickness?.useGlTFChannel) {\n f2 |= PBR2_HAS_THICKNESS_GLTF_CHANNEL;\n }\n if (ss?.tint?.atDistance !== undefined) {\n f2 |= PBR2_HAS_VOLUME;\n // Dispersion requires the volume path (per-channel etas + volumeParams.w storage).\n if (refr?.dispersion) {\n f2 |= PBR2_HAS_DISPERSION;\n }\n }\n return { f, f2 };\n },\n frag(ctx) {\n const linearImageProcessing = (ctx._features2 & PBR2_LINEAR_IMAGE_PROCESSING) !== 0;\n if (!(ctx._features2 & PBR2_HAS_REFRACTION)) {\n return linearImageProcessing ? { _id: \"linear\", _fragmentSlots: LINEAR_IMAGE_PROCESSING_SLOTS } : null;\n }\n return createRefractionRttFragment(\n (ctx._features2 & PBR2_HAS_VOLUME) !== 0,\n (ctx._features2 & PBR2_HAS_REFRACTION_MAP) !== 0,\n (ctx._features & PBR_HAS_THICKNESS_MAP) !== 0,\n (ctx._features2 & PBR2_HAS_THICKNESS_GLTF_CHANNEL) !== 0,\n linearImageProcessing,\n (ctx._features2 & PBR2_HAS_DISPERSION) !== 0,\n dispersionSampleWgsl\n );\n },\n writeUbo(data, mat, offsets) {\n writeRefractionUBO(data, mat as PbrMaterialProps, offsets);\n },\n bind(ctx, entries, b) {\n if (!(ctx._features2 & PBR2_HAS_REFRACTION)) {\n return b;\n }\n const texture = ctx._refractionTexture;\n if (!texture) {\n throw new Error(\"PBR transmission requires a frame-graph refraction texture.\");\n }\n entries.push({ binding: b++, resource: texture.view });\n entries.push({ binding: b++, resource: texture.sampler });\n if ((ctx._features2 & PBR2_HAS_REFRACTION_MAP) !== 0) {\n const map = ((ctx._material as PbrMaterialProps).subsurface?.refraction as SubSurfaceProps[\"refraction\"] | undefined)?.texture!;\n entries.push({ binding: b++, resource: map.view });\n entries.push({ binding: b++, resource: getTrilinearAnisotropicSampler(ctx._engine) });\n }\n if ((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0) {\n const thickness = (ctx._material as PbrMaterialProps).subsurface?.thickness?.texture!;\n entries.push({ binding: b++, resource: thickness.view });\n entries.push({ binding: b++, resource: thickness.sampler });\n }\n return b;\n },\n textures(mat, out) {\n const tex = (mat as PbrMaterialProps).subsurface?.refraction?.texture;\n if (tex) {\n out.push(tex);\n }\n const thickness = (mat as PbrMaterialProps).subsurface?.thickness?.texture;\n if (thickness) {\n out.push(thickness);\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { PBR_HAS_SHEEN_TEXTURE, PBR_HAS_SHEEN,
|
|
1
|
+
import { PBR_HAS_SHEEN_TEXTURE, PBR_HAS_SHEEN, PBR_HAS_SHEEN_ALBEDO_SCALING } from '../pbr-flag-bits.js';
|
|
2
2
|
|
|
3
3
|
const STAGE_FRAGMENT = 2;
|
|
4
|
+
const PBR2_HAS_SHEEN_UV_TX = 1 << 13;
|
|
4
5
|
const PBR2_HAS_SHEEN_ROUGH_TEX = 1 << 29;
|
|
5
6
|
const SHEEN_HELPERS = `
|
|
6
7
|
fn normalDistributionFunction_CharlieSheen(NdotH_sh: f32, alphaG_sh: f32) -> f32 {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sheen-fragment.js","sources":["../../../../../src/material/pbr/fragments/sheen-fragment.ts"],"sourcesContent":["/**\n * Sheen Fragment\n *\n * Adds a soft velvet-like sheen layer (fabric, cloth).\n * Only bundled when a scene uses PbrMaterialProps.sheen.\n *\n * Math follows BJS PBRSheenConfiguration:\n * - Charlie NDF (sheen distribution)\n * - Ashikhmin visibility\n * - IBL: environment sampled at sheen roughness, BRDF LUT blue channel\n * - Energy conservation: albedo scaled by (1 - maxSheenColor * brdf.b)\n */\n\nimport type { ShaderFragment, BindingDecl, UboField } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SheenProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_SHEEN, PBR_HAS_SHEEN_TEXTURE, PBR_HAS_SHEEN_ALBEDO_SCALING, PBR2_HAS_SHEEN_UV_TX } from \"../pbr-flag-bits.js\";\n\nconst STAGE_FRAGMENT = 0x2;\n\n// Extension-local features2 bit (defined here, not in the shared flag module, so scenes\n// without a separate sheen roughness texture carry zero bytes for it). Set when the material\n// has a KHR_materials_sheen sheenRoughnessTexture distinct from sheenColorTexture: sheen\n// roughness is then read from that texture's A channel at its own (animatable) UV transform.\nconst PBR2_HAS_SHEEN_ROUGH_TEX = 1 << 29;\n\nconst SHEEN_HELPERS = `\nfn normalDistributionFunction_CharlieSheen(NdotH_sh: f32, alphaG_sh: f32) -> f32 {\nlet invR = 1.0 / alphaG_sh;\nlet cos2h = NdotH_sh * NdotH_sh;\nlet sin2h = 1.0 - cos2h;\nreturn (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * 3.141592653589793);\n}\nfn visibility_Ashikhmin(NdotL_sh: f32, NdotV_sh: f32) -> f32 {\nreturn 1.0 / (4.0 * (NdotL_sh + NdotV_sh - NdotL_sh * NdotV_sh));\n}\n`;\n\nconst SHEEN_DIRECT_MOD = (intensityExpr: string): string => `\n{\nlet shIntensity = ${intensityExpr};\nlet shColorScaled = sheenColorFinal * shIntensity;\nlet shRoughness_clamped = max(sheenRoughnessAdjusted, AA_factor_x);\nlet shAlphaG = shRoughness_clamped * shRoughness_clamped + 0.0005;\nlet shD = normalDistributionFunction_CharlieSheen(NdotH, shAlphaG);\nlet shV = visibility_Ashikhmin(NdotL, NdotV);\nsheenDirectTerm = shColorScaled * shD * shV * NdotL * lightColor * lightAtten * material.directIntensity;\n}\n`;\n\nconst SHEEN_IBL_MOD = (intensityExpr: string, albedoScaling: boolean): string => `\n{\nlet shIntensity_ibl = ${intensityExpr};\nlet shColorScaled = sheenColorFinal * shIntensity_ibl;\nlet shRoughness_ibl = sheenRoughnessAdjusted;\nlet shAlphaG_ibl = shRoughness_ibl * shRoughness_ibl + 0.0005 + AA_factor_y;\nvar shSpecLod = log2(cubemapDim * shAlphaG_ibl) * scene.vImageInfos.z;\nlet shEnvRadiance = textureSampleLevel(iblTexture, iblSampler, R, clamp(shSpecLod, 0.0, maxLod)).rgb * material.environmentIntensity;\nlet shBrdf = textureSampleLevel(brdfLUT, brdfSampler_, vec2<f32>(NdotV, shRoughness_ibl), 0.0);\nlet shEnvReflectance = shColorScaled * shBrdf.b${albedoScaling ? \" * seo * eho\" : \"\"};\nsheenIblTerm = shEnvRadiance * shEnvReflectance;\n${albedoScaling ? \"let shMax = max(shColorScaled.r, max(shColorScaled.g, shColorScaled.b));\\nsheenAlbedoScaling = 1.0 - shMax * shBrdf.b;\" : \"\"}\n}\n`;\n\nconst SHEEN_IBL_COLOR_MOD = (albedoScaling: boolean): string =>\n albedoScaling\n ? `\n{\ncolor = (finalIrradiance\n + finalRadianceScaled\n + finalSpecularScaled\n + directDiffuse) * sheenAlbedoScaling\n + sheenDirectTerm\n + sheenIblTerm\n + emissive;\n}\n`\n : `\n{\ncolor = finalIrradiance\n + finalRadianceScaled\n + finalSpecularScaled\n + directDiffuse\n + sheenDirectTerm\n + sheenIblTerm\n + emissive;\n}\n`;\n\nconst SHEEN_NON_IBL_MOD = `\n{\ncolor = color + sheenDirectTerm;\n}\n`;\n\n/**\n * Create a sheen fragment.\n * @param hasSheenTexture - Whether the material has a sheen texture.\n * @param hasIbl - Whether IBL is active for this pipeline.\n * @param hasAlbedoScaling - When true, uses BJS-spec sheen math (no F0 attenuation,\n * proper base-layer albedo scaling, treats sheen texture as linear — upload\n * as sRGB so the sampler does the conversion). When false (legacy), applies\n * pow(rgb, 2.2) to the texture and uses (1-F0) as the sheen intensity scalar.\n */\nexport function createSheenFragment(\n hasSheenTexture: boolean,\n hasIbl: boolean = false,\n hasAlbedoScaling: boolean = false,\n hasSheenUvTx: boolean = false,\n hasSheenRoughTex: boolean = false\n): ShaderFragment {\n let scopeVars = `var sheenDirectTerm = vec3<f32>(0.0);\nvar sheenIblTerm = vec3<f32>(0.0);\nvar sheenAlbedoScaling = 1.0;\nvar sheenColorFinal = material.sheenParams.rgb;\nvar sheenRoughnessAdjusted = material.sheenParams2.x;`;\n if (hasSheenTexture) {\n const gammaStmt = hasAlbedoScaling ? \"sheenMapData.rgb\" : \"pow(sheenMapData.rgb, vec3<f32>(2.2))\";\n const sheenUvDecl = hasSheenUvTx\n ? \"let sheenUV = vec2<f32>(dot(material.sheenUVm.xy, input.uv), dot(material.sheenUVm.zw, input.uv)) + material.sheenUVt.xy;\"\n : \"let sheenUV = input.uv;\";\n // Roughness from the colour texture's alpha only when there is no distinct\n // sheenRoughnessTexture (BJS useRoughnessFromMainTexture); otherwise it is read below.\n const roughFromColor = hasSheenRoughTex ? \"\" : \"\\nsheenRoughnessAdjusted *= sheenMapData.a;\";\n scopeVars += `\n{\n${sheenUvDecl}\nlet sheenMapData = textureSample(sheenTexture_, sheenSampler_, sheenUV);\nsheenColorFinal *= ${gammaStmt};${roughFromColor}\n}`;\n }\n if (hasSheenRoughTex) {\n // Distinct sheenRoughnessTexture: roughness from its A channel at its own animatable UV.\n scopeVars += `\n{\nlet sheenRoughUV = vec2<f32>(dot(material.sheenRoughUVm.xy, input.uv), dot(material.sheenRoughUVm.zw, input.uv)) + material.sheenRoughUVt.xy;\nsheenRoughnessAdjusted *= textureSample(sheenRoughTexture_, sheenRoughSampler_, sheenRoughUV).a;\n}`;\n }\n\n const intensityExpr = hasAlbedoScaling ? \"material.sheenParams.a\" : \"material.sheenParams.a * (1.0 - dielectricF0)\";\n const slots: Partial<Record<string, string>> = {\n SV: scopeVars,\n AD: SHEEN_DIRECT_MOD(intensityExpr),\n };\n // AI and NI are mutually exclusive — only one path runs\n if (hasIbl) {\n slots.AI = SHEEN_IBL_MOD(intensityExpr, hasAlbedoScaling) + SHEEN_IBL_COLOR_MOD(hasAlbedoScaling);\n } else {\n slots.NI = SHEEN_NON_IBL_MOD;\n }\n\n const bindings: BindingDecl[] = [];\n if (hasSheenTexture) {\n bindings.push(\n { _name: \"sheenTexture_\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" }, _visibility: STAGE_FRAGMENT },\n { _name: \"sheenSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" }, _visibility: STAGE_FRAGMENT }\n );\n }\n if (hasSheenRoughTex) {\n bindings.push(\n { _name: \"sheenRoughTexture_\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" }, _visibility: STAGE_FRAGMENT },\n { _name: \"sheenRoughSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" }, _visibility: STAGE_FRAGMENT }\n );\n }\n\n const uboFields: UboField[] = [\n { _name: \"sheenParams\", _type: \"vec4<f32>\" },\n { _name: \"sheenParams2\", _type: \"vec4<f32>\" },\n ];\n if (hasSheenUvTx) {\n uboFields.push({ _name: \"sheenUVm\", _type: \"vec4<f32>\" }, { _name: \"sheenUVt\", _type: \"vec4<f32>\" });\n }\n if (hasSheenRoughTex) {\n uboFields.push({ _name: \"sheenRoughUVm\", _type: \"vec4<f32>\" }, { _name: \"sheenRoughUVt\", _type: \"vec4<f32>\" });\n }\n\n return {\n _id: \"sheen\",\n _dependencies: hasIbl ? [\"ibl\"] : undefined,\n\n _uboFields: uboFields,\n\n _bindings: bindings,\n\n _helperFunctions: SHEEN_HELPERS,\n\n _fragmentSlots: slots,\n };\n}\n\n/** Write the sheen material-UBO slice (sheenParams, sheenParams2, optional UV transform). */\nexport function writeSheenUBO(data: Float32Array, material: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n const sh = material.sheen as SheenProps | undefined;\n if (!sh?.isEnabled || !offsets.has(\"sheenParams\")) {\n return;\n }\n const off = offsets.get(\"sheenParams\")! / 4;\n const color = sh.color ?? [1, 1, 1];\n data[off] = color[0]!;\n data[off + 1] = color[1]!;\n data[off + 2] = color[2]!;\n data[off + 3] = sh.intensity ?? 1.0;\n data[off + 4] = sh.roughness ?? 0.0;\n data[off + 5] = sh.texture ? 1.0 : 0.0;\n\n // Optional per-texture UV transforms (KHR_texture_transform), each animatable.\n writeSheenUvTransform(data, offsets, \"sheenUVm\", \"sheenUVt\", sh.texture);\n writeSheenUvTransform(data, offsets, \"sheenRoughUVm\", \"sheenRoughUVt\", sh.roughnessTexture);\n}\n\nfunction writeSheenUvTransform(\n data: Float32Array,\n offsets: ReadonlyMap<string, number>,\n mName: string,\n tName: string,\n tex: { uScale?: number; vScale?: number; uAng?: number; uOffset?: number; vOffset?: number } | undefined\n): void {\n const mOff = offsets.get(mName);\n const tOff = offsets.get(tName);\n if (mOff === undefined || tOff === undefined) {\n return;\n }\n const sx = tex?.uScale ?? 1;\n const sy = tex?.vScale ?? 1;\n const ang = tex?.uAng ?? 0;\n const mi = mOff / 4;\n const ti = tOff / 4;\n if (ang === 0) {\n data[mi] = sx;\n data[mi + 1] = 0;\n data[mi + 2] = 0;\n data[mi + 3] = sy;\n } else {\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n data[mi] = c * sx;\n data[mi + 1] = s * sy;\n data[mi + 2] = -s * sx;\n data[mi + 3] = c * sy;\n }\n data[ti] = tex?.uOffset ?? 0;\n data[ti + 1] = tex?.vOffset ?? 0;\n data[ti + 2] = 0;\n data[ti + 3] = 0;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"sheen\",\n phase: \"base-tex\",\n detect(mat) {\n const sh = (mat as PbrMaterialProps).sheen as SheenProps | undefined;\n if (!sh?.isEnabled) {\n return { f: 0, f2: 0 };\n }\n let f = PBR_HAS_SHEEN;\n let f2 = 0;\n if (sh.texture) {\n f |= PBR_HAS_SHEEN_TEXTURE;\n if ((sh.texture as { _hasTx?: boolean })._hasTx) {\n f2 |= PBR2_HAS_SHEEN_UV_TX;\n }\n }\n if (sh.roughnessTexture) {\n f2 |= PBR2_HAS_SHEEN_ROUGH_TEX;\n }\n if (sh.albedoScaling) {\n f |= PBR_HAS_SHEEN_ALBEDO_SCALING;\n }\n return { f, f2 };\n },\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_SHEEN)) {\n return null;\n }\n return createSheenFragment(\n (ctx._features & PBR_HAS_SHEEN_TEXTURE) !== 0,\n ctx._hasIbl,\n (ctx._features & PBR_HAS_SHEEN_ALBEDO_SCALING) !== 0,\n (ctx._features2 & PBR2_HAS_SHEEN_UV_TX) !== 0,\n (ctx._features2 & PBR2_HAS_SHEEN_ROUGH_TEX) !== 0\n );\n },\n writeUbo: writeSheenUBO as PbrExt[\"writeUbo\"],\n bind(ctx, entries, b) {\n const sh = (ctx._material as PbrMaterialProps).sheen as SheenProps | undefined;\n if ((ctx._features & PBR_HAS_SHEEN_TEXTURE) !== 0 && sh?.texture) {\n entries.push({ binding: b++, resource: sh.texture.view });\n entries.push({ binding: b++, resource: sh.texture.sampler });\n }\n if ((ctx._features2 & PBR2_HAS_SHEEN_ROUGH_TEX) !== 0 && sh?.roughnessTexture) {\n entries.push({ binding: b++, resource: sh.roughnessTexture.view });\n entries.push({ binding: b++, resource: sh.roughnessTexture.sampler });\n }\n return b;\n },\n textures(mat, out) {\n const sh = (mat as PbrMaterialProps).sheen;\n if (sh?.texture) {\n out.push(sh.texture);\n }\n if (sh?.roughnessTexture) {\n out.push(sh.roughnessTexture);\n }\n },\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sheen-fragment.js","sources":["../../../../../src/material/pbr/fragments/sheen-fragment.ts"],"sourcesContent":["/**\n * Sheen Fragment\n *\n * Adds a soft velvet-like sheen layer (fabric, cloth).\n * Only bundled when a scene uses PbrMaterialProps.sheen.\n *\n * Math follows BJS PBRSheenConfiguration:\n * - Charlie NDF (sheen distribution)\n * - Ashikhmin visibility\n * - IBL: environment sampled at sheen roughness, BRDF LUT blue channel\n * - Energy conservation: albedo scaled by (1 - maxSheenColor * brdf.b)\n */\n\nimport type { ShaderFragment, BindingDecl, UboField } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SheenProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_SHEEN, PBR_HAS_SHEEN_TEXTURE, PBR_HAS_SHEEN_ALBEDO_SCALING } from \"../pbr-flag-bits.js\";\n\nconst STAGE_FRAGMENT = 0x2;\nconst PBR2_HAS_SHEEN_UV_TX = 1 << 13;\n\n// Extension-local features2 bit (defined here, not in the shared flag module, so scenes\n// without a separate sheen roughness texture carry zero bytes for it). Set when the material\n// has a KHR_materials_sheen sheenRoughnessTexture distinct from sheenColorTexture: sheen\n// roughness is then read from that texture's A channel at its own (animatable) UV transform.\nconst PBR2_HAS_SHEEN_ROUGH_TEX = 1 << 29;\n\nconst SHEEN_HELPERS = `\nfn normalDistributionFunction_CharlieSheen(NdotH_sh: f32, alphaG_sh: f32) -> f32 {\nlet invR = 1.0 / alphaG_sh;\nlet cos2h = NdotH_sh * NdotH_sh;\nlet sin2h = 1.0 - cos2h;\nreturn (2.0 + invR) * pow(sin2h, invR * 0.5) / (2.0 * 3.141592653589793);\n}\nfn visibility_Ashikhmin(NdotL_sh: f32, NdotV_sh: f32) -> f32 {\nreturn 1.0 / (4.0 * (NdotL_sh + NdotV_sh - NdotL_sh * NdotV_sh));\n}\n`;\n\nconst SHEEN_DIRECT_MOD = (intensityExpr: string): string => `\n{\nlet shIntensity = ${intensityExpr};\nlet shColorScaled = sheenColorFinal * shIntensity;\nlet shRoughness_clamped = max(sheenRoughnessAdjusted, AA_factor_x);\nlet shAlphaG = shRoughness_clamped * shRoughness_clamped + 0.0005;\nlet shD = normalDistributionFunction_CharlieSheen(NdotH, shAlphaG);\nlet shV = visibility_Ashikhmin(NdotL, NdotV);\nsheenDirectTerm = shColorScaled * shD * shV * NdotL * lightColor * lightAtten * material.directIntensity;\n}\n`;\n\nconst SHEEN_IBL_MOD = (intensityExpr: string, albedoScaling: boolean): string => `\n{\nlet shIntensity_ibl = ${intensityExpr};\nlet shColorScaled = sheenColorFinal * shIntensity_ibl;\nlet shRoughness_ibl = sheenRoughnessAdjusted;\nlet shAlphaG_ibl = shRoughness_ibl * shRoughness_ibl + 0.0005 + AA_factor_y;\nvar shSpecLod = log2(cubemapDim * shAlphaG_ibl) * scene.vImageInfos.z;\nlet shEnvRadiance = textureSampleLevel(iblTexture, iblSampler, R, clamp(shSpecLod, 0.0, maxLod)).rgb * material.environmentIntensity;\nlet shBrdf = textureSampleLevel(brdfLUT, brdfSampler_, vec2<f32>(NdotV, shRoughness_ibl), 0.0);\nlet shEnvReflectance = shColorScaled * shBrdf.b${albedoScaling ? \" * seo * eho\" : \"\"};\nsheenIblTerm = shEnvRadiance * shEnvReflectance;\n${albedoScaling ? \"let shMax = max(shColorScaled.r, max(shColorScaled.g, shColorScaled.b));\\nsheenAlbedoScaling = 1.0 - shMax * shBrdf.b;\" : \"\"}\n}\n`;\n\nconst SHEEN_IBL_COLOR_MOD = (albedoScaling: boolean): string =>\n albedoScaling\n ? `\n{\ncolor = (finalIrradiance\n + finalRadianceScaled\n + finalSpecularScaled\n + directDiffuse) * sheenAlbedoScaling\n + sheenDirectTerm\n + sheenIblTerm\n + emissive;\n}\n`\n : `\n{\ncolor = finalIrradiance\n + finalRadianceScaled\n + finalSpecularScaled\n + directDiffuse\n + sheenDirectTerm\n + sheenIblTerm\n + emissive;\n}\n`;\n\nconst SHEEN_NON_IBL_MOD = `\n{\ncolor = color + sheenDirectTerm;\n}\n`;\n\n/**\n * Create a sheen fragment.\n * @param hasSheenTexture - Whether the material has a sheen texture.\n * @param hasIbl - Whether IBL is active for this pipeline.\n * @param hasAlbedoScaling - When true, uses BJS-spec sheen math (no F0 attenuation,\n * proper base-layer albedo scaling, treats sheen texture as linear — upload\n * as sRGB so the sampler does the conversion). When false (legacy), applies\n * pow(rgb, 2.2) to the texture and uses (1-F0) as the sheen intensity scalar.\n */\nexport function createSheenFragment(\n hasSheenTexture: boolean,\n hasIbl: boolean = false,\n hasAlbedoScaling: boolean = false,\n hasSheenUvTx: boolean = false,\n hasSheenRoughTex: boolean = false\n): ShaderFragment {\n let scopeVars = `var sheenDirectTerm = vec3<f32>(0.0);\nvar sheenIblTerm = vec3<f32>(0.0);\nvar sheenAlbedoScaling = 1.0;\nvar sheenColorFinal = material.sheenParams.rgb;\nvar sheenRoughnessAdjusted = material.sheenParams2.x;`;\n if (hasSheenTexture) {\n const gammaStmt = hasAlbedoScaling ? \"sheenMapData.rgb\" : \"pow(sheenMapData.rgb, vec3<f32>(2.2))\";\n const sheenUvDecl = hasSheenUvTx\n ? \"let sheenUV = vec2<f32>(dot(material.sheenUVm.xy, input.uv), dot(material.sheenUVm.zw, input.uv)) + material.sheenUVt.xy;\"\n : \"let sheenUV = input.uv;\";\n // Roughness from the colour texture's alpha only when there is no distinct\n // sheenRoughnessTexture (BJS useRoughnessFromMainTexture); otherwise it is read below.\n const roughFromColor = hasSheenRoughTex ? \"\" : \"\\nsheenRoughnessAdjusted *= sheenMapData.a;\";\n scopeVars += `\n{\n${sheenUvDecl}\nlet sheenMapData = textureSample(sheenTexture_, sheenSampler_, sheenUV);\nsheenColorFinal *= ${gammaStmt};${roughFromColor}\n}`;\n }\n if (hasSheenRoughTex) {\n // Distinct sheenRoughnessTexture: roughness from its A channel at its own animatable UV.\n scopeVars += `\n{\nlet sheenRoughUV = vec2<f32>(dot(material.sheenRoughUVm.xy, input.uv), dot(material.sheenRoughUVm.zw, input.uv)) + material.sheenRoughUVt.xy;\nsheenRoughnessAdjusted *= textureSample(sheenRoughTexture_, sheenRoughSampler_, sheenRoughUV).a;\n}`;\n }\n\n const intensityExpr = hasAlbedoScaling ? \"material.sheenParams.a\" : \"material.sheenParams.a * (1.0 - dielectricF0)\";\n const slots: Partial<Record<string, string>> = {\n SV: scopeVars,\n AD: SHEEN_DIRECT_MOD(intensityExpr),\n };\n // AI and NI are mutually exclusive — only one path runs\n if (hasIbl) {\n slots.AI = SHEEN_IBL_MOD(intensityExpr, hasAlbedoScaling) + SHEEN_IBL_COLOR_MOD(hasAlbedoScaling);\n } else {\n slots.NI = SHEEN_NON_IBL_MOD;\n }\n\n const bindings: BindingDecl[] = [];\n if (hasSheenTexture) {\n bindings.push(\n { _name: \"sheenTexture_\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" }, _visibility: STAGE_FRAGMENT },\n { _name: \"sheenSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" }, _visibility: STAGE_FRAGMENT }\n );\n }\n if (hasSheenRoughTex) {\n bindings.push(\n { _name: \"sheenRoughTexture_\", _type: { _kind: \"texture\", _textureType: \"texture_2d<f32>\" }, _visibility: STAGE_FRAGMENT },\n { _name: \"sheenRoughSampler_\", _type: { _kind: \"sampler\", _samplerType: \"sampler\" }, _visibility: STAGE_FRAGMENT }\n );\n }\n\n const uboFields: UboField[] = [\n { _name: \"sheenParams\", _type: \"vec4<f32>\" },\n { _name: \"sheenParams2\", _type: \"vec4<f32>\" },\n ];\n if (hasSheenUvTx) {\n uboFields.push({ _name: \"sheenUVm\", _type: \"vec4<f32>\" }, { _name: \"sheenUVt\", _type: \"vec4<f32>\" });\n }\n if (hasSheenRoughTex) {\n uboFields.push({ _name: \"sheenRoughUVm\", _type: \"vec4<f32>\" }, { _name: \"sheenRoughUVt\", _type: \"vec4<f32>\" });\n }\n\n return {\n _id: \"sheen\",\n _dependencies: hasIbl ? [\"ibl\"] : undefined,\n\n _uboFields: uboFields,\n\n _bindings: bindings,\n\n _helperFunctions: SHEEN_HELPERS,\n\n _fragmentSlots: slots,\n };\n}\n\n/** Write the sheen material-UBO slice (sheenParams, sheenParams2, optional UV transform). */\nexport function writeSheenUBO(data: Float32Array, material: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n const sh = material.sheen as SheenProps | undefined;\n if (!sh?.isEnabled || !offsets.has(\"sheenParams\")) {\n return;\n }\n const off = offsets.get(\"sheenParams\")! / 4;\n const color = sh.color ?? [1, 1, 1];\n data[off] = color[0]!;\n data[off + 1] = color[1]!;\n data[off + 2] = color[2]!;\n data[off + 3] = sh.intensity ?? 1.0;\n data[off + 4] = sh.roughness ?? 0.0;\n data[off + 5] = sh.texture ? 1.0 : 0.0;\n\n // Optional per-texture UV transforms (KHR_texture_transform), each animatable.\n writeSheenUvTransform(data, offsets, \"sheenUVm\", \"sheenUVt\", sh.texture);\n writeSheenUvTransform(data, offsets, \"sheenRoughUVm\", \"sheenRoughUVt\", sh.roughnessTexture);\n}\n\nfunction writeSheenUvTransform(\n data: Float32Array,\n offsets: ReadonlyMap<string, number>,\n mName: string,\n tName: string,\n tex: { uScale?: number; vScale?: number; uAng?: number; uOffset?: number; vOffset?: number } | undefined\n): void {\n const mOff = offsets.get(mName);\n const tOff = offsets.get(tName);\n if (mOff === undefined || tOff === undefined) {\n return;\n }\n const sx = tex?.uScale ?? 1;\n const sy = tex?.vScale ?? 1;\n const ang = tex?.uAng ?? 0;\n const mi = mOff / 4;\n const ti = tOff / 4;\n if (ang === 0) {\n data[mi] = sx;\n data[mi + 1] = 0;\n data[mi + 2] = 0;\n data[mi + 3] = sy;\n } else {\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n data[mi] = c * sx;\n data[mi + 1] = s * sy;\n data[mi + 2] = -s * sx;\n data[mi + 3] = c * sy;\n }\n data[ti] = tex?.uOffset ?? 0;\n data[ti + 1] = tex?.vOffset ?? 0;\n data[ti + 2] = 0;\n data[ti + 3] = 0;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"sheen\",\n phase: \"base-tex\",\n detect(mat) {\n const sh = (mat as PbrMaterialProps).sheen as SheenProps | undefined;\n if (!sh?.isEnabled) {\n return { f: 0, f2: 0 };\n }\n let f = PBR_HAS_SHEEN;\n let f2 = 0;\n if (sh.texture) {\n f |= PBR_HAS_SHEEN_TEXTURE;\n if ((sh.texture as { _hasTx?: boolean })._hasTx) {\n f2 |= PBR2_HAS_SHEEN_UV_TX;\n }\n }\n if (sh.roughnessTexture) {\n f2 |= PBR2_HAS_SHEEN_ROUGH_TEX;\n }\n if (sh.albedoScaling) {\n f |= PBR_HAS_SHEEN_ALBEDO_SCALING;\n }\n return { f, f2 };\n },\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_SHEEN)) {\n return null;\n }\n return createSheenFragment(\n (ctx._features & PBR_HAS_SHEEN_TEXTURE) !== 0,\n ctx._hasIbl,\n (ctx._features & PBR_HAS_SHEEN_ALBEDO_SCALING) !== 0,\n (ctx._features2 & PBR2_HAS_SHEEN_UV_TX) !== 0,\n (ctx._features2 & PBR2_HAS_SHEEN_ROUGH_TEX) !== 0\n );\n },\n writeUbo: writeSheenUBO as PbrExt[\"writeUbo\"],\n bind(ctx, entries, b) {\n const sh = (ctx._material as PbrMaterialProps).sheen as SheenProps | undefined;\n if ((ctx._features & PBR_HAS_SHEEN_TEXTURE) !== 0 && sh?.texture) {\n entries.push({ binding: b++, resource: sh.texture.view });\n entries.push({ binding: b++, resource: sh.texture.sampler });\n }\n if ((ctx._features2 & PBR2_HAS_SHEEN_ROUGH_TEX) !== 0 && sh?.roughnessTexture) {\n entries.push({ binding: b++, resource: sh.roughnessTexture.view });\n entries.push({ binding: b++, resource: sh.roughnessTexture.sampler });\n }\n return b;\n },\n textures(mat, out) {\n const sh = (mat as PbrMaterialProps).sheen;\n if (sh?.texture) {\n out.push(sh.texture);\n }\n if (sh?.roughnessTexture) {\n out.push(sh.roughnessTexture);\n }\n },\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { PBR_HAS_THICKNESS_MAP, PBR_HAS_SUBSURFACE
|
|
1
|
+
import { PBR_HAS_THICKNESS_MAP, PBR_HAS_SUBSURFACE } from '../pbr-flag-bits.js';
|
|
2
2
|
|
|
3
|
+
const PBR2_HAS_THICKNESS_GLTF_CHANNEL = 1 << 7;
|
|
3
4
|
const PBR2_HAS_TRANSLUCENCY_COLOR_MAP = 1 << 22;
|
|
4
5
|
const PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP = 1 << 23;
|
|
5
6
|
const PBR2_HAS_TRANSLUCENCY_UV_TX = 1 << 24;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subsurface-fragment.js","sources":["../../../../../src/material/pbr/fragments/subsurface-fragment.ts"],"sourcesContent":["/**\n * Subsurface Fragment\n *\n * Adds translucency — light passing through thin surfaces.\n * Only bundled when a scene uses PbrMaterialProps.subsurface.\n *\n * Math follows BJS PBRSubSurfaceConfiguration:\n * - Burley transmittance BRDF: exp-based approximation\n * - Thickness from texture (.g channel, BJS glTF-style default)\n * - Direct: wrap-around diffuse scaled by transmittance\n * - IBL: irradiance reduced by (1 - intensity), transmittance-weighted contribution added\n */\n\nimport type { ShaderFragment, BindingDecl, UboField } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SubSurfaceProps } from \"../pbr-material.js\";\nimport type { Texture2D } from \"../../../texture/texture-2d.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_SUBSURFACE, PBR_HAS_THICKNESS_MAP, PBR2_HAS_THICKNESS_GLTF_CHANNEL } from \"../pbr-flag-bits.js\";\n\n// Subsurface-only features2 bits (reserved in pbr-flag-bits.ts). Defined here,\n// not in the shared flag module, so they aren't retained in the entry/shared\n// chunk for scenes that never load this lazy fragment (zero bundle movement).\nconst PBR2_HAS_TRANSLUCENCY_COLOR_MAP = 1 << 22;\nconst PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP = 1 << 23;\nconst PBR2_HAS_TRANSLUCENCY_UV_TX = 1 << 24;\n\nconst SS_HELPERS = `\nfn transmittanceBRDF_Burley(tintColor: vec3<f32>, diffusionDistance: vec3<f32>, thickness: f32) -> vec3<f32> {\nlet S = 1.0 / max(vec3<f32>(0.000001), diffusionDistance);\nlet temp = exp((-0.333333333 * thickness) * S);\nreturn tintColor * 0.25 * (temp * temp * temp + 3.0 * temp);\n}\nfn computeWrappedDiffuseNdotL(NdotL: f32, w: f32) -> f32 {\nlet t = 1.0 + w;\nlet invt2 = 1.0 / (t * t);\nreturn saturate((NdotL + w) * invt2);\n}\n`;\n\n// SV: declare subsurface scope variables\nconst SS_SCOPE_VARS = `var translucencyDirect = vec3<f32>(0.0);\nvar ssTransmittance = vec3<f32>(0.0);\nvar ssIntensity = 0.0;`;\n\n// AT: sample thickness + compute transmittance.\n// Channel: R by default (matches existing non-glTF path); G when the glTF\n// KHR_materials_volume flag is on (spec mandates G channel).\nfunction makeThicknessBlock(hasThicknessMap: boolean, useGltfChannel: boolean, hasColorMap: boolean, hasIntensityMap: boolean, hasUvTx: boolean): string {\n const chan = useGltfChannel ? \"g\" : \"r\";\n const texSample = hasThicknessMap ? `let thicknessSample = textureSample(thicknessTexture_, thicknessSampler_, input.uv).${chan};` : `let thicknessSample = 1.0;`;\n // The translucency color and intensity textures each carry their own\n // KHR_texture_transform (driven live by animation pointers), so they are\n // sampled with independent transformed UVs.\n let uvDecl = \"\";\n let colorUv = \"input.uv\";\n let intensityUv = \"input.uv\";\n if (hasUvTx && hasColorMap) {\n uvDecl += `let ssColorUV = vec2<f32>(dot(material.translucencyColorUVm.xy, input.uv), dot(material.translucencyColorUVm.zw, input.uv)) + material.translucencyColorUVt.xy;\\n`;\n colorUv = \"ssColorUV\";\n }\n if (hasUvTx && hasIntensityMap) {\n uvDecl += `let ssIntUV = vec2<f32>(dot(material.translucencyIntensityUVm.xy, input.uv), dot(material.translucencyIntensityUVm.zw, input.uv)) + material.translucencyIntensityUVt.xy;\\n`;\n intensityUv = \"ssIntUV\";\n }\n const colorMul = hasColorMap ? ` * textureSample(translucencyColorTexture_, translucencyColorSampler_, ${colorUv}).rgb` : ``;\n const intensityMul = hasIntensityMap ? ` * textureSample(translucencyIntensityTexture_, translucencyIntensitySampler_, ${intensityUv}).a` : ``;\n return `${uvDecl}${texSample}\nlet ssThickness = max(material.subsurfaceParams.y + thicknessSample * material.subsurfaceParams.z, 0.000001);\nlet ssTranslucencyColor = material.subsurfaceParams3.rgb${colorMul};\nlet ssDiffDist = material.subsurfaceParams2.rgb;\nssIntensity = material.subsurfaceParams.x${intensityMul};\nssTransmittance = transmittanceBRDF_Burley(ssTranslucencyColor, ssDiffDist, ssThickness) * ssIntensity;`;\n}\n\n// AD: direct-light translucency lobe (back-facing only, wrap 0.02, 1/PI diffuse BRDF).\n// BJS also scales the front-facing direct diffuse by (1 - ssIntensity); we cannot easily\n// modify `directDiffuse` at compute time, so compensate via `color -= directDiffuse * ssIntensity`\n// in the AI/NI slot below.\nconst SS_DIRECT = `{\nlet NdotLU = dot(N, L);\nif (NdotLU < 0.0) {\nlet wrapNdotL = computeWrappedDiffuseNdotL(abs(NdotLU), 0.02);\ntranslucencyDirect += (1.0 / PI) * wrapNdotL * ssTransmittance * lightAtten * lightColor * material.directIntensity;\n}\n}`;\n\n// AI: subsurface IBL modification (runs after IBL sets `color`).\n// BJS: finalIrradiance *= (1 - ssI); finalIrradiance += refractionIrradiance;\n// where refractionIrradiance = environmentIrradiance(-N) * transmittance (no albedo by default).\n// AO/occlusion applies to the full finalIrradiance in BJS.\n// Also: scale direct diffuse by (1-ssI) and add translucencyDirect lobe.\nconst SS_IBL_MOD = `{\nlet N_back = -N_env;\nlet envIrrBack = (scene.vSphericalL00.rgb\n + scene.vSphericalL1_1.rgb * N_back.y + scene.vSphericalL10.rgb * N_back.z + scene.vSphericalL11.rgb * N_back.x\n + scene.vSphericalL2_2.rgb * (N_back.y * N_back.x) + scene.vSphericalL2_1.rgb * (N_back.y * N_back.z)\n + scene.vSphericalL20.rgb * (3.0 * N_back.z * N_back.z - 1.0) + scene.vSphericalL21.rgb * (N_back.z * N_back.x)\n + scene.vSphericalL22.rgb * (N_back.x * N_back.x - N_back.y * N_back.y)) * material.environmentIntensity;\nlet refractionIrradiance = envIrrBack * ssTransmittance;\ncolor -= finalIrradiance * ssIntensity;\ncolor += refractionIrradiance * occlusion;\ncolor -= directDiffuse * ssIntensity;\ncolor += translucencyDirect * occlusion;\n}`;\n\n// NI: no-IBL path — just scale direct diffuse and add translucency lobe.\nconst SS_NO_IBL_MOD = `color -= directDiffuse * ssIntensity;\ncolor += translucencyDirect;`;\n\nconst STAGE_FRAGMENT = 0x2;\n\n/**\n * Create a subsurface translucency fragment.\n * @param hasThicknessMap - Whether the material has a thickness texture.\n * @param hasIbl - Whether the scene has IBL.\n * @param useGltfThicknessChannel - Sample the thickness texture's G channel\n * (KHR_materials_volume) instead of R (BJS default).\n */\nexport function createSubsurfaceFragment(\n hasThicknessMap: boolean,\n hasIbl: boolean,\n useGltfThicknessChannel: boolean,\n hasColorMap: boolean,\n hasIntensityMap: boolean,\n hasUvTx: boolean\n): ShaderFragment {\n const tex2d = { _kind: \"texture\" as const, _textureType: \"texture_2d<f32>\" as const };\n const samp = { _kind: \"sampler\" as const, _samplerType: \"sampler\" as const };\n const bindings: BindingDecl[] = [];\n if (hasThicknessMap) {\n bindings.push({ _name: \"thicknessTexture_\", _type: tex2d, _visibility: STAGE_FRAGMENT }, { _name: \"thicknessSampler_\", _type: samp, _visibility: STAGE_FRAGMENT });\n }\n if (hasColorMap) {\n bindings.push(\n { _name: \"translucencyColorTexture_\", _type: tex2d, _visibility: STAGE_FRAGMENT },\n { _name: \"translucencyColorSampler_\", _type: samp, _visibility: STAGE_FRAGMENT }\n );\n }\n if (hasIntensityMap) {\n bindings.push(\n { _name: \"translucencyIntensityTexture_\", _type: tex2d, _visibility: STAGE_FRAGMENT },\n { _name: \"translucencyIntensitySampler_\", _type: samp, _visibility: STAGE_FRAGMENT }\n );\n }\n\n const uboFields: UboField[] = [\n { _name: \"subsurfaceParams\", _type: \"vec4<f32>\" },\n { _name: \"subsurfaceParams2\", _type: \"vec4<f32>\" },\n { _name: \"subsurfaceParams3\", _type: \"vec4<f32>\" },\n ];\n if (hasUvTx && hasColorMap) {\n uboFields.push({ _name: \"translucencyColorUVm\", _type: \"vec4<f32>\" }, { _name: \"translucencyColorUVt\", _type: \"vec4<f32>\" });\n }\n if (hasUvTx && hasIntensityMap) {\n uboFields.push({ _name: \"translucencyIntensityUVm\", _type: \"vec4<f32>\" }, { _name: \"translucencyIntensityUVt\", _type: \"vec4<f32>\" });\n }\n\n const slots: Partial<Record<string, string>> = {\n SV: SS_SCOPE_VARS,\n AT: makeThicknessBlock(hasThicknessMap, useGltfThicknessChannel, hasColorMap, hasIntensityMap, hasUvTx),\n AD: SS_DIRECT,\n };\n if (hasIbl) {\n slots.AI = SS_IBL_MOD;\n } else {\n slots.NI = SS_NO_IBL_MOD;\n }\n\n const deps: string[] = [];\n if (hasIbl) {\n deps.push(\"ibl\");\n }\n\n return {\n _id: \"subsurface\",\n _dependencies: deps.length > 0 ? deps : undefined,\n _bindings: bindings.length > 0 ? bindings : undefined,\n _uboFields: uboFields,\n _helperFunctions: SS_HELPERS,\n _fragmentSlots: slots,\n };\n}\n\n/** Write subsurface UBO data. Called from pbr-renderable.ts only when subsurface is active. */\nexport function writeSubsurfaceUBO(data: Float32Array, ss: SubSurfaceProps, offsets: ReadonlyMap<string, number>): void {\n const trans = ss.translucency!;\n const thick = ss.thickness;\n\n const off = offsets.get(\"subsurfaceParams\")! / 4;\n data[off] = trans.intensity ?? 1.0;\n const minThick = thick?.min ?? 0;\n const maxThick = thick?.max ?? 1.0;\n data[off + 1] = minThick;\n data[off + 2] = maxThick - minThick;\n\n const off2 = offsets.get(\"subsurfaceParams2\")! / 4;\n const dd = trans.diffusionDistance ?? [1, 1, 1];\n data[off2] = dd[0]!;\n data[off2 + 1] = dd[1]!;\n data[off2 + 2] = dd[2]!;\n\n const off3 = offsets.get(\"subsurfaceParams3\")! / 4;\n const tc = trans.color ?? [1, 1, 1];\n data[off3] = tc[0]!;\n data[off3 + 1] = tc[1]!;\n data[off3 + 2] = tc[2]!;\n\n // Per-texture UV transforms (each KHR_texture_transform driven live by\n // animation pointers). Same mat2+translate layout as the iridescence writer.\n writeSsUvTransform(data, offsets, \"translucencyColorUV\", trans.colorTexture);\n writeSsUvTransform(data, offsets, \"translucencyIntensityUV\", trans.intensityTexture);\n}\n\n/** Write a 2x2 UV matrix (vec4) + translate (vec4) for a translucency texture. */\nfunction writeSsUvTransform(\n data: Float32Array,\n offsets: ReadonlyMap<string, number>,\n name: string,\n tex: { uScale?: number; vScale?: number; uAng?: number; uOffset?: number; vOffset?: number } | undefined\n): void {\n const mOff = offsets.get(`${name}m`);\n const tOff = offsets.get(`${name}t`);\n if (mOff === undefined || tOff === undefined) {\n return;\n }\n const sx = tex?.uScale ?? 1;\n const sy = tex?.vScale ?? 1;\n const ang = tex?.uAng ?? 0;\n const mi = mOff / 4;\n if (ang === 0) {\n data[mi] = sx;\n data[mi + 1] = 0;\n data[mi + 2] = 0;\n data[mi + 3] = sy;\n } else {\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n data[mi] = c * sx;\n data[mi + 1] = s * sy;\n data[mi + 2] = -s * sx;\n data[mi + 3] = c * sy;\n }\n const ti = tOff / 4;\n data[ti] = tex?.uOffset ?? 0;\n data[ti + 1] = tex?.vOffset ?? 0;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"subsurface\",\n phase: \"fragment\",\n detect(mat) {\n const m = mat as PbrMaterialProps;\n const trans = m.subsurface?.translucency;\n if (!trans) {\n return { f: 0, f2: 0 };\n }\n let f = PBR_HAS_SUBSURFACE;\n let f2 = 0;\n if (m.subsurface!.thickness?.texture) {\n f |= PBR_HAS_THICKNESS_MAP;\n }\n if (m.subsurface!.thickness?.useGlTFChannel) {\n f2 |= PBR2_HAS_THICKNESS_GLTF_CHANNEL;\n }\n if (trans.colorTexture) {\n f2 |= PBR2_HAS_TRANSLUCENCY_COLOR_MAP;\n }\n if (trans.intensityTexture) {\n f2 |= PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP;\n }\n if ((trans.colorTexture as { _hasTx?: boolean } | undefined)?._hasTx || (trans.intensityTexture as { _hasTx?: boolean } | undefined)?._hasTx) {\n f2 |= PBR2_HAS_TRANSLUCENCY_UV_TX;\n }\n return { f, f2 };\n },\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_SUBSURFACE)) {\n return null;\n }\n return createSubsurfaceFragment(\n (ctx._features & PBR_HAS_THICKNESS_MAP) !== 0,\n ctx._hasIbl,\n (ctx._features2 & PBR2_HAS_THICKNESS_GLTF_CHANNEL) !== 0,\n (ctx._features2 & PBR2_HAS_TRANSLUCENCY_COLOR_MAP) !== 0,\n (ctx._features2 & PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP) !== 0,\n (ctx._features2 & PBR2_HAS_TRANSLUCENCY_UV_TX) !== 0\n );\n },\n writeUbo(data, mat, offsets) {\n const m = mat as PbrMaterialProps;\n if (m.subsurface?.translucency && offsets.has(\"subsurfaceParams\")) {\n writeSubsurfaceUBO(data, m.subsurface as SubSurfaceProps, offsets);\n }\n },\n bind(ctx, entries, b) {\n const ss = (ctx._material as PbrMaterialProps).subsurface;\n if ((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0) {\n const tex = ss?.thickness?.texture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n if ((ctx._features2 & PBR2_HAS_TRANSLUCENCY_COLOR_MAP) !== 0) {\n const tex = ss?.translucency?.colorTexture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n if ((ctx._features2 & PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP) !== 0) {\n const tex = ss?.translucency?.intensityTexture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n return b;\n },\n textures(mat, out) {\n const ss = (mat as PbrMaterialProps).subsurface;\n if (ss?.thickness?.texture) {\n out.push(ss.thickness.texture);\n }\n if (ss?.translucency?.colorTexture) {\n out.push(ss.translucency.colorTexture);\n }\n if (ss?.translucency?.intensityTexture) {\n out.push(ss.translucency.intensityTexture);\n }\n },\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"subsurface-fragment.js","sources":["../../../../../src/material/pbr/fragments/subsurface-fragment.ts"],"sourcesContent":["/**\n * Subsurface Fragment\n *\n * Adds translucency — light passing through thin surfaces.\n * Only bundled when a scene uses PbrMaterialProps.subsurface.\n *\n * Math follows BJS PBRSubSurfaceConfiguration:\n * - Burley transmittance BRDF: exp-based approximation\n * - Thickness from texture (.g channel, BJS glTF-style default)\n * - Direct: wrap-around diffuse scaled by transmittance\n * - IBL: irradiance reduced by (1 - intensity), transmittance-weighted contribution added\n */\n\nimport type { ShaderFragment, BindingDecl, UboField } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps, SubSurfaceProps } from \"../pbr-material.js\";\nimport type { Texture2D } from \"../../../texture/texture-2d.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\nimport { PBR_HAS_SUBSURFACE, PBR_HAS_THICKNESS_MAP } from \"../pbr-flag-bits.js\";\n\n// Subsurface-only features2 bits (reserved in pbr-flag-bits.ts). Defined here,\n// not in the shared flag module, so they aren't retained in the entry/shared\n// chunk for scenes that never load this lazy fragment (zero bundle movement).\nconst PBR2_HAS_THICKNESS_GLTF_CHANNEL = 1 << 7;\nconst PBR2_HAS_TRANSLUCENCY_COLOR_MAP = 1 << 22;\nconst PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP = 1 << 23;\nconst PBR2_HAS_TRANSLUCENCY_UV_TX = 1 << 24;\n\nconst SS_HELPERS = `\nfn transmittanceBRDF_Burley(tintColor: vec3<f32>, diffusionDistance: vec3<f32>, thickness: f32) -> vec3<f32> {\nlet S = 1.0 / max(vec3<f32>(0.000001), diffusionDistance);\nlet temp = exp((-0.333333333 * thickness) * S);\nreturn tintColor * 0.25 * (temp * temp * temp + 3.0 * temp);\n}\nfn computeWrappedDiffuseNdotL(NdotL: f32, w: f32) -> f32 {\nlet t = 1.0 + w;\nlet invt2 = 1.0 / (t * t);\nreturn saturate((NdotL + w) * invt2);\n}\n`;\n\n// SV: declare subsurface scope variables\nconst SS_SCOPE_VARS = `var translucencyDirect = vec3<f32>(0.0);\nvar ssTransmittance = vec3<f32>(0.0);\nvar ssIntensity = 0.0;`;\n\n// AT: sample thickness + compute transmittance.\n// Channel: R by default (matches existing non-glTF path); G when the glTF\n// KHR_materials_volume flag is on (spec mandates G channel).\nfunction makeThicknessBlock(hasThicknessMap: boolean, useGltfChannel: boolean, hasColorMap: boolean, hasIntensityMap: boolean, hasUvTx: boolean): string {\n const chan = useGltfChannel ? \"g\" : \"r\";\n const texSample = hasThicknessMap ? `let thicknessSample = textureSample(thicknessTexture_, thicknessSampler_, input.uv).${chan};` : `let thicknessSample = 1.0;`;\n // The translucency color and intensity textures each carry their own\n // KHR_texture_transform (driven live by animation pointers), so they are\n // sampled with independent transformed UVs.\n let uvDecl = \"\";\n let colorUv = \"input.uv\";\n let intensityUv = \"input.uv\";\n if (hasUvTx && hasColorMap) {\n uvDecl += `let ssColorUV = vec2<f32>(dot(material.translucencyColorUVm.xy, input.uv), dot(material.translucencyColorUVm.zw, input.uv)) + material.translucencyColorUVt.xy;\\n`;\n colorUv = \"ssColorUV\";\n }\n if (hasUvTx && hasIntensityMap) {\n uvDecl += `let ssIntUV = vec2<f32>(dot(material.translucencyIntensityUVm.xy, input.uv), dot(material.translucencyIntensityUVm.zw, input.uv)) + material.translucencyIntensityUVt.xy;\\n`;\n intensityUv = \"ssIntUV\";\n }\n const colorMul = hasColorMap ? ` * textureSample(translucencyColorTexture_, translucencyColorSampler_, ${colorUv}).rgb` : ``;\n const intensityMul = hasIntensityMap ? ` * textureSample(translucencyIntensityTexture_, translucencyIntensitySampler_, ${intensityUv}).a` : ``;\n return `${uvDecl}${texSample}\nlet ssThickness = max(material.subsurfaceParams.y + thicknessSample * material.subsurfaceParams.z, 0.000001);\nlet ssTranslucencyColor = material.subsurfaceParams3.rgb${colorMul};\nlet ssDiffDist = material.subsurfaceParams2.rgb;\nssIntensity = material.subsurfaceParams.x${intensityMul};\nssTransmittance = transmittanceBRDF_Burley(ssTranslucencyColor, ssDiffDist, ssThickness) * ssIntensity;`;\n}\n\n// AD: direct-light translucency lobe (back-facing only, wrap 0.02, 1/PI diffuse BRDF).\n// BJS also scales the front-facing direct diffuse by (1 - ssIntensity); we cannot easily\n// modify `directDiffuse` at compute time, so compensate via `color -= directDiffuse * ssIntensity`\n// in the AI/NI slot below.\nconst SS_DIRECT = `{\nlet NdotLU = dot(N, L);\nif (NdotLU < 0.0) {\nlet wrapNdotL = computeWrappedDiffuseNdotL(abs(NdotLU), 0.02);\ntranslucencyDirect += (1.0 / PI) * wrapNdotL * ssTransmittance * lightAtten * lightColor * material.directIntensity;\n}\n}`;\n\n// AI: subsurface IBL modification (runs after IBL sets `color`).\n// BJS: finalIrradiance *= (1 - ssI); finalIrradiance += refractionIrradiance;\n// where refractionIrradiance = environmentIrradiance(-N) * transmittance (no albedo by default).\n// AO/occlusion applies to the full finalIrradiance in BJS.\n// Also: scale direct diffuse by (1-ssI) and add translucencyDirect lobe.\nconst SS_IBL_MOD = `{\nlet N_back = -N_env;\nlet envIrrBack = (scene.vSphericalL00.rgb\n + scene.vSphericalL1_1.rgb * N_back.y + scene.vSphericalL10.rgb * N_back.z + scene.vSphericalL11.rgb * N_back.x\n + scene.vSphericalL2_2.rgb * (N_back.y * N_back.x) + scene.vSphericalL2_1.rgb * (N_back.y * N_back.z)\n + scene.vSphericalL20.rgb * (3.0 * N_back.z * N_back.z - 1.0) + scene.vSphericalL21.rgb * (N_back.z * N_back.x)\n + scene.vSphericalL22.rgb * (N_back.x * N_back.x - N_back.y * N_back.y)) * material.environmentIntensity;\nlet refractionIrradiance = envIrrBack * ssTransmittance;\ncolor -= finalIrradiance * ssIntensity;\ncolor += refractionIrradiance * occlusion;\ncolor -= directDiffuse * ssIntensity;\ncolor += translucencyDirect * occlusion;\n}`;\n\n// NI: no-IBL path — just scale direct diffuse and add translucency lobe.\nconst SS_NO_IBL_MOD = `color -= directDiffuse * ssIntensity;\ncolor += translucencyDirect;`;\n\nconst STAGE_FRAGMENT = 0x2;\n\n/**\n * Create a subsurface translucency fragment.\n * @param hasThicknessMap - Whether the material has a thickness texture.\n * @param hasIbl - Whether the scene has IBL.\n * @param useGltfThicknessChannel - Sample the thickness texture's G channel\n * (KHR_materials_volume) instead of R (BJS default).\n */\nexport function createSubsurfaceFragment(\n hasThicknessMap: boolean,\n hasIbl: boolean,\n useGltfThicknessChannel: boolean,\n hasColorMap: boolean,\n hasIntensityMap: boolean,\n hasUvTx: boolean\n): ShaderFragment {\n const tex2d = { _kind: \"texture\" as const, _textureType: \"texture_2d<f32>\" as const };\n const samp = { _kind: \"sampler\" as const, _samplerType: \"sampler\" as const };\n const bindings: BindingDecl[] = [];\n if (hasThicknessMap) {\n bindings.push({ _name: \"thicknessTexture_\", _type: tex2d, _visibility: STAGE_FRAGMENT }, { _name: \"thicknessSampler_\", _type: samp, _visibility: STAGE_FRAGMENT });\n }\n if (hasColorMap) {\n bindings.push(\n { _name: \"translucencyColorTexture_\", _type: tex2d, _visibility: STAGE_FRAGMENT },\n { _name: \"translucencyColorSampler_\", _type: samp, _visibility: STAGE_FRAGMENT }\n );\n }\n if (hasIntensityMap) {\n bindings.push(\n { _name: \"translucencyIntensityTexture_\", _type: tex2d, _visibility: STAGE_FRAGMENT },\n { _name: \"translucencyIntensitySampler_\", _type: samp, _visibility: STAGE_FRAGMENT }\n );\n }\n\n const uboFields: UboField[] = [\n { _name: \"subsurfaceParams\", _type: \"vec4<f32>\" },\n { _name: \"subsurfaceParams2\", _type: \"vec4<f32>\" },\n { _name: \"subsurfaceParams3\", _type: \"vec4<f32>\" },\n ];\n if (hasUvTx && hasColorMap) {\n uboFields.push({ _name: \"translucencyColorUVm\", _type: \"vec4<f32>\" }, { _name: \"translucencyColorUVt\", _type: \"vec4<f32>\" });\n }\n if (hasUvTx && hasIntensityMap) {\n uboFields.push({ _name: \"translucencyIntensityUVm\", _type: \"vec4<f32>\" }, { _name: \"translucencyIntensityUVt\", _type: \"vec4<f32>\" });\n }\n\n const slots: Partial<Record<string, string>> = {\n SV: SS_SCOPE_VARS,\n AT: makeThicknessBlock(hasThicknessMap, useGltfThicknessChannel, hasColorMap, hasIntensityMap, hasUvTx),\n AD: SS_DIRECT,\n };\n if (hasIbl) {\n slots.AI = SS_IBL_MOD;\n } else {\n slots.NI = SS_NO_IBL_MOD;\n }\n\n const deps: string[] = [];\n if (hasIbl) {\n deps.push(\"ibl\");\n }\n\n return {\n _id: \"subsurface\",\n _dependencies: deps.length > 0 ? deps : undefined,\n _bindings: bindings.length > 0 ? bindings : undefined,\n _uboFields: uboFields,\n _helperFunctions: SS_HELPERS,\n _fragmentSlots: slots,\n };\n}\n\n/** Write subsurface UBO data. Called from pbr-renderable.ts only when subsurface is active. */\nexport function writeSubsurfaceUBO(data: Float32Array, ss: SubSurfaceProps, offsets: ReadonlyMap<string, number>): void {\n const trans = ss.translucency!;\n const thick = ss.thickness;\n\n const off = offsets.get(\"subsurfaceParams\")! / 4;\n data[off] = trans.intensity ?? 1.0;\n const minThick = thick?.min ?? 0;\n const maxThick = thick?.max ?? 1.0;\n data[off + 1] = minThick;\n data[off + 2] = maxThick - minThick;\n\n const off2 = offsets.get(\"subsurfaceParams2\")! / 4;\n const dd = trans.diffusionDistance ?? [1, 1, 1];\n data[off2] = dd[0]!;\n data[off2 + 1] = dd[1]!;\n data[off2 + 2] = dd[2]!;\n\n const off3 = offsets.get(\"subsurfaceParams3\")! / 4;\n const tc = trans.color ?? [1, 1, 1];\n data[off3] = tc[0]!;\n data[off3 + 1] = tc[1]!;\n data[off3 + 2] = tc[2]!;\n\n // Per-texture UV transforms (each KHR_texture_transform driven live by\n // animation pointers). Same mat2+translate layout as the iridescence writer.\n writeSsUvTransform(data, offsets, \"translucencyColorUV\", trans.colorTexture);\n writeSsUvTransform(data, offsets, \"translucencyIntensityUV\", trans.intensityTexture);\n}\n\n/** Write a 2x2 UV matrix (vec4) + translate (vec4) for a translucency texture. */\nfunction writeSsUvTransform(\n data: Float32Array,\n offsets: ReadonlyMap<string, number>,\n name: string,\n tex: { uScale?: number; vScale?: number; uAng?: number; uOffset?: number; vOffset?: number } | undefined\n): void {\n const mOff = offsets.get(`${name}m`);\n const tOff = offsets.get(`${name}t`);\n if (mOff === undefined || tOff === undefined) {\n return;\n }\n const sx = tex?.uScale ?? 1;\n const sy = tex?.vScale ?? 1;\n const ang = tex?.uAng ?? 0;\n const mi = mOff / 4;\n if (ang === 0) {\n data[mi] = sx;\n data[mi + 1] = 0;\n data[mi + 2] = 0;\n data[mi + 3] = sy;\n } else {\n const c = Math.cos(ang);\n const s = Math.sin(ang);\n data[mi] = c * sx;\n data[mi + 1] = s * sy;\n data[mi + 2] = -s * sx;\n data[mi + 3] = c * sy;\n }\n const ti = tOff / 4;\n data[ti] = tex?.uOffset ?? 0;\n data[ti + 1] = tex?.vOffset ?? 0;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"subsurface\",\n phase: \"fragment\",\n detect(mat) {\n const m = mat as PbrMaterialProps;\n const trans = m.subsurface?.translucency;\n if (!trans) {\n return { f: 0, f2: 0 };\n }\n let f = PBR_HAS_SUBSURFACE;\n let f2 = 0;\n if (m.subsurface!.thickness?.texture) {\n f |= PBR_HAS_THICKNESS_MAP;\n }\n if (m.subsurface!.thickness?.useGlTFChannel) {\n f2 |= PBR2_HAS_THICKNESS_GLTF_CHANNEL;\n }\n if (trans.colorTexture) {\n f2 |= PBR2_HAS_TRANSLUCENCY_COLOR_MAP;\n }\n if (trans.intensityTexture) {\n f2 |= PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP;\n }\n if ((trans.colorTexture as { _hasTx?: boolean } | undefined)?._hasTx || (trans.intensityTexture as { _hasTx?: boolean } | undefined)?._hasTx) {\n f2 |= PBR2_HAS_TRANSLUCENCY_UV_TX;\n }\n return { f, f2 };\n },\n frag(ctx) {\n if (!(ctx._features & PBR_HAS_SUBSURFACE)) {\n return null;\n }\n return createSubsurfaceFragment(\n (ctx._features & PBR_HAS_THICKNESS_MAP) !== 0,\n ctx._hasIbl,\n (ctx._features2 & PBR2_HAS_THICKNESS_GLTF_CHANNEL) !== 0,\n (ctx._features2 & PBR2_HAS_TRANSLUCENCY_COLOR_MAP) !== 0,\n (ctx._features2 & PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP) !== 0,\n (ctx._features2 & PBR2_HAS_TRANSLUCENCY_UV_TX) !== 0\n );\n },\n writeUbo(data, mat, offsets) {\n const m = mat as PbrMaterialProps;\n if (m.subsurface?.translucency && offsets.has(\"subsurfaceParams\")) {\n writeSubsurfaceUBO(data, m.subsurface as SubSurfaceProps, offsets);\n }\n },\n bind(ctx, entries, b) {\n const ss = (ctx._material as PbrMaterialProps).subsurface;\n if ((ctx._features & PBR_HAS_THICKNESS_MAP) !== 0) {\n const tex = ss?.thickness?.texture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n if ((ctx._features2 & PBR2_HAS_TRANSLUCENCY_COLOR_MAP) !== 0) {\n const tex = ss?.translucency?.colorTexture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n if ((ctx._features2 & PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP) !== 0) {\n const tex = ss?.translucency?.intensityTexture as Texture2D | undefined;\n if (tex) {\n entries.push({ binding: b++, resource: tex.view });\n entries.push({ binding: b++, resource: tex.sampler });\n }\n }\n return b;\n },\n textures(mat, out) {\n const ss = (mat as PbrMaterialProps).subsurface;\n if (ss?.thickness?.texture) {\n out.push(ss.thickness.texture);\n }\n if (ss?.translucency?.colorTexture) {\n out.push(ss.translucency.colorTexture);\n }\n if (ss?.translucency?.intensityTexture) {\n out.push(ss.translucency.intensityTexture);\n }\n },\n};\n"],"names":[],"mappings":";;AAsBA,MAAM,kCAAkC,CAAA,IAAK,CAAA;AAC7C,MAAM,kCAAkC,CAAA,IAAK,EAAA;AAC7C,MAAM,sCAAsC,CAAA,IAAK,EAAA;AACjD,MAAM,8BAA8B,CAAA,IAAK,EAAA;AAEzC,MAAM,UAAA,GAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAcnB,MAAM,aAAA,GAAgB,CAAA;AAAA;AAAA,sBAAA,CAAA;AAOtB,SAAS,kBAAA,CAAmB,eAAA,EAA0B,cAAA,EAAyB,WAAA,EAAsB,iBAA0B,OAAA,EAA0B;AACrJ,EAAA,MAAM,IAAA,GAAO,iBAAiB,GAAA,GAAM,GAAA;AACpC,EAAA,MAAM,SAAA,GAAY,eAAA,GAAkB,CAAA,oFAAA,EAAuF,IAAI,CAAA,CAAA,CAAA,GAAM,CAAA,0BAAA,CAAA;AAIrI,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,IAAI,OAAA,GAAU,UAAA;AACd,EAAA,IAAI,WAAA,GAAc,UAAA;AAClB,EAAA,IAAI,WAAW,WAAA,EAAa;AACxB,IAAA,MAAA,IAAU,CAAA;AAAA,CAAA;AACV,IAAA,OAAA,GAAU,WAAA;AAAA,EACd;AACA,EAAA,IAAI,WAAW,eAAA,EAAiB;AAC5B,IAAA,MAAA,IAAU,CAAA;AAAA,CAAA;AACV,IAAA,WAAA,GAAc,SAAA;AAAA,EAClB;AACA,EAAA,MAAM,QAAA,GAAW,WAAA,GAAc,CAAA,uEAAA,EAA0E,OAAO,CAAA,KAAA,CAAA,GAAU,CAAA,CAAA;AAC1H,EAAA,MAAM,YAAA,GAAe,eAAA,GAAkB,CAAA,+EAAA,EAAkF,WAAW,CAAA,GAAA,CAAA,GAAQ,CAAA,CAAA;AAC5I,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,SAAS;AAAA;AAAA,wDAAA,EAE0B,QAAQ,CAAA;AAAA;AAAA,yCAAA,EAEvB,YAAY,CAAA;AAAA,uGAAA,CAAA;AAEvD;AAMA,MAAM,SAAA,GAAY,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAalB,MAAM,UAAA,GAAa,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAAA;AAenB,MAAM,aAAA,GAAgB,CAAA;AAAA,4BAAA,CAAA;AAGtB,MAAM,cAAA,GAAiB,CAAA;AAShB,SAAS,yBACZ,eAAA,EACA,MAAA,EACA,uBAAA,EACA,WAAA,EACA,iBACA,OAAA,EACc;AACd,EAAA,MAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,SAAA,EAAoB,cAAc,iBAAA,EAA2B;AACpF,EAAA,MAAM,IAAA,GAAO,EAAE,KAAA,EAAO,SAAA,EAAoB,cAAc,SAAA,EAAmB;AAC3E,EAAA,MAAM,WAA0B,EAAC;AACjC,EAAA,IAAI,eAAA,EAAiB;AACjB,IAAA,QAAA,CAAS,KAAK,EAAE,KAAA,EAAO,mBAAA,EAAqB,KAAA,EAAO,OAAO,WAAA,EAAa,cAAA,EAAe,EAAG,EAAE,OAAO,mBAAA,EAAqB,KAAA,EAAO,IAAA,EAAM,WAAA,EAAa,gBAAgB,CAAA;AAAA,EACrK;AACA,EAAA,IAAI,WAAA,EAAa;AACb,IAAA,QAAA,CAAS,IAAA;AAAA,MACL,EAAE,KAAA,EAAO,2BAAA,EAA6B,KAAA,EAAO,KAAA,EAAO,aAAa,cAAA,EAAe;AAAA,MAChF,EAAE,KAAA,EAAO,2BAAA,EAA6B,KAAA,EAAO,IAAA,EAAM,aAAa,cAAA;AAAe,KACnF;AAAA,EACJ;AACA,EAAA,IAAI,eAAA,EAAiB;AACjB,IAAA,QAAA,CAAS,IAAA;AAAA,MACL,EAAE,KAAA,EAAO,+BAAA,EAAiC,KAAA,EAAO,KAAA,EAAO,aAAa,cAAA,EAAe;AAAA,MACpF,EAAE,KAAA,EAAO,+BAAA,EAAiC,KAAA,EAAO,IAAA,EAAM,aAAa,cAAA;AAAe,KACvF;AAAA,EACJ;AAEA,EAAA,MAAM,SAAA,GAAwB;AAAA,IAC1B,EAAE,KAAA,EAAO,kBAAA,EAAoB,KAAA,EAAO,WAAA,EAAY;AAAA,IAChD,EAAE,KAAA,EAAO,mBAAA,EAAqB,KAAA,EAAO,WAAA,EAAY;AAAA,IACjD,EAAE,KAAA,EAAO,mBAAA,EAAqB,KAAA,EAAO,WAAA;AAAY,GACrD;AACA,EAAA,IAAI,WAAW,WAAA,EAAa;AACxB,IAAA,SAAA,CAAU,IAAA,CAAK,EAAE,KAAA,EAAO,sBAAA,EAAwB,KAAA,EAAO,WAAA,EAAY,EAAG,EAAE,KAAA,EAAO,sBAAA,EAAwB,KAAA,EAAO,WAAA,EAAa,CAAA;AAAA,EAC/H;AACA,EAAA,IAAI,WAAW,eAAA,EAAiB;AAC5B,IAAA,SAAA,CAAU,IAAA,CAAK,EAAE,KAAA,EAAO,0BAAA,EAA4B,KAAA,EAAO,WAAA,EAAY,EAAG,EAAE,KAAA,EAAO,0BAAA,EAA4B,KAAA,EAAO,WAAA,EAAa,CAAA;AAAA,EACvI;AAEA,EAAA,MAAM,KAAA,GAAyC;AAAA,IAC3C,EAAA,EAAI,aAAA;AAAA,IACJ,IAAI,kBAAA,CAAmB,eAAA,EAAiB,uBAAA,EAAyB,WAAA,EAAa,iBAAiB,OAAO,CAAA;AAAA,IACtG,EAAA,EAAI;AAAA,GACR;AACA,EAAA,IAAI,MAAA,EAAQ;AACR,IAAA,KAAA,CAAM,EAAA,GAAK,UAAA;AAAA,EACf,CAAA,MAAO;AACH,IAAA,KAAA,CAAM,EAAA,GAAK,aAAA;AAAA,EACf;AAEA,EAAA,MAAM,OAAiB,EAAC;AACxB,EAAA,IAAI,MAAA,EAAQ;AACR,IAAA,IAAA,CAAK,KAAK,KAAK,CAAA;AAAA,EACnB;AAEA,EAAA,OAAO;AAAA,IACH,GAAA,EAAK,YAAA;AAAA,IACL,aAAA,EAAe,IAAA,CAAK,MAAA,GAAS,CAAA,GAAI,IAAA,GAAO,MAAA;AAAA,IACxC,SAAA,EAAW,QAAA,CAAS,MAAA,GAAS,CAAA,GAAI,QAAA,GAAW,MAAA;AAAA,IAC5C,UAAA,EAAY,SAAA;AAAA,IACZ,gBAAA,EAAkB,UAAA;AAAA,IAClB,cAAA,EAAgB;AAAA,GACpB;AACJ;AAGO,SAAS,kBAAA,CAAmB,IAAA,EAAoB,EAAA,EAAqB,OAAA,EAA4C;AACpH,EAAA,MAAM,QAAQ,EAAA,CAAG,YAAA;AACjB,EAAA,MAAM,QAAQ,EAAA,CAAG,SAAA;AAEjB,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAA,GAAK,CAAA;AAC/C,EAAA,IAAA,CAAK,GAAG,CAAA,GAAI,KAAA,CAAM,SAAA,IAAa,CAAA;AAC/B,EAAA,MAAM,QAAA,GAAW,OAAO,GAAA,IAAO,CAAA;AAC/B,EAAA,MAAM,QAAA,GAAW,OAAO,GAAA,IAAO,CAAA;AAC/B,EAAA,IAAA,CAAK,GAAA,GAAM,CAAC,CAAA,GAAI,QAAA;AAChB,EAAA,IAAA,CAAK,GAAA,GAAM,CAAC,CAAA,GAAI,QAAA,GAAW,QAAA;AAE3B,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,mBAAmB,CAAA,GAAK,CAAA;AACjD,EAAA,MAAM,KAAK,KAAA,CAAM,iBAAA,IAAqB,CAAC,CAAA,EAAG,GAAG,CAAC,CAAA;AAC9C,EAAA,IAAA,CAAK,IAAI,CAAA,GAAI,EAAA,CAAG,CAAC,CAAA;AACjB,EAAA,IAAA,CAAK,IAAA,GAAO,CAAC,CAAA,GAAI,EAAA,CAAG,CAAC,CAAA;AACrB,EAAA,IAAA,CAAK,IAAA,GAAO,CAAC,CAAA,GAAI,EAAA,CAAG,CAAC,CAAA;AAErB,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,mBAAmB,CAAA,GAAK,CAAA;AACjD,EAAA,MAAM,KAAK,KAAA,CAAM,KAAA,IAAS,CAAC,CAAA,EAAG,GAAG,CAAC,CAAA;AAClC,EAAA,IAAA,CAAK,IAAI,CAAA,GAAI,EAAA,CAAG,CAAC,CAAA;AACjB,EAAA,IAAA,CAAK,IAAA,GAAO,CAAC,CAAA,GAAI,EAAA,CAAG,CAAC,CAAA;AACrB,EAAA,IAAA,CAAK,IAAA,GAAO,CAAC,CAAA,GAAI,EAAA,CAAG,CAAC,CAAA;AAIrB,EAAA,kBAAA,CAAmB,IAAA,EAAM,OAAA,EAAS,qBAAA,EAAuB,KAAA,CAAM,YAAY,CAAA;AAC3E,EAAA,kBAAA,CAAmB,IAAA,EAAM,OAAA,EAAS,yBAAA,EAA2B,KAAA,CAAM,gBAAgB,CAAA;AACvF;AAGA,SAAS,kBAAA,CACL,IAAA,EACA,OAAA,EACA,IAAA,EACA,GAAA,EACI;AACJ,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAA;AACnC,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,IAAI,CAAA,CAAA,CAAG,CAAA;AACnC,EAAA,IAAI,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,MAAA,EAAW;AAC1C,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,EAAA,GAAK,KAAK,MAAA,IAAU,CAAA;AAC1B,EAAA,MAAM,EAAA,GAAK,KAAK,MAAA,IAAU,CAAA;AAC1B,EAAA,MAAM,GAAA,GAAM,KAAK,IAAA,IAAQ,CAAA;AACzB,EAAA,MAAM,KAAK,IAAA,GAAO,CAAA;AAClB,EAAA,IAAI,QAAQ,CAAA,EAAG;AACX,IAAA,IAAA,CAAK,EAAE,CAAA,GAAI,EAAA;AACX,IAAA,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA,GAAI,CAAA;AACf,IAAA,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA,GAAI,CAAA;AACf,IAAA,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA,GAAI,EAAA;AAAA,EACnB,CAAA,MAAO;AACH,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AACtB,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA;AACtB,IAAA,IAAA,CAAK,EAAE,IAAI,CAAA,GAAI,EAAA;AACf,IAAA,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA,GAAI,CAAA,GAAI,EAAA;AACnB,IAAA,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA,GAAI,CAAC,CAAA,GAAI,EAAA;AACpB,IAAA,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA,GAAI,CAAA,GAAI,EAAA;AAAA,EACvB;AACA,EAAA,MAAM,KAAK,IAAA,GAAO,CAAA;AAClB,EAAA,IAAA,CAAK,EAAE,CAAA,GAAI,GAAA,EAAK,OAAA,IAAW,CAAA;AAC3B,EAAA,IAAA,CAAK,EAAA,GAAK,CAAC,CAAA,GAAI,GAAA,EAAK,OAAA,IAAW,CAAA;AACnC;AAEO,MAAM,MAAA,GAAiB;AAAA,EAC1B,EAAA,EAAI,YAAA;AAAA,EACJ,KAAA,EAAO,UAAA;AAAA,EACP,OAAO,GAAA,EAAK;AACR,IAAA,MAAM,CAAA,GAAI,GAAA;AACV,IAAA,MAAM,KAAA,GAAQ,EAAE,UAAA,EAAY,YAAA;AAC5B,IAAA,IAAI,CAAC,KAAA,EAAO;AACR,MAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,CAAA,EAAE;AAAA,IACzB;AACA,IAAA,IAAI,CAAA,GAAI,kBAAA;AACR,IAAA,IAAI,EAAA,GAAK,CAAA;AACT,IAAA,IAAI,CAAA,CAAE,UAAA,CAAY,SAAA,EAAW,OAAA,EAAS;AAClC,MAAA,CAAA,IAAK,qBAAA;AAAA,IACT;AACA,IAAA,IAAI,CAAA,CAAE,UAAA,CAAY,SAAA,EAAW,cAAA,EAAgB;AACzC,MAAA,EAAA,IAAM,+BAAA;AAAA,IACV;AACA,IAAA,IAAI,MAAM,YAAA,EAAc;AACpB,MAAA,EAAA,IAAM,+BAAA;AAAA,IACV;AACA,IAAA,IAAI,MAAM,gBAAA,EAAkB;AACxB,MAAA,EAAA,IAAM,mCAAA;AAAA,IACV;AACA,IAAA,IAAK,KAAA,CAAM,YAAA,EAAmD,MAAA,IAAW,KAAA,CAAM,kBAAuD,MAAA,EAAQ;AAC1I,MAAA,EAAA,IAAM,2BAAA;AAAA,IACV;AACA,IAAA,OAAO,EAAE,GAAG,EAAA,EAAG;AAAA,EACnB,CAAA;AAAA,EACA,KAAK,GAAA,EAAK;AACN,IAAA,IAAI,EAAE,GAAA,CAAI,SAAA,GAAY,kBAAA,CAAA,EAAqB;AACvC,MAAA,OAAO,IAAA;AAAA,IACX;AACA,IAAA,OAAO,wBAAA;AAAA,MAAA,CACF,GAAA,CAAI,YAAY,qBAAA,MAA2B,CAAA;AAAA,MAC5C,GAAA,CAAI,OAAA;AAAA,MAAA,CACH,GAAA,CAAI,aAAa,+BAAA,MAAqC,CAAA;AAAA,MAAA,CACtD,GAAA,CAAI,aAAa,+BAAA,MAAqC,CAAA;AAAA,MAAA,CACtD,GAAA,CAAI,aAAa,mCAAA,MAAyC,CAAA;AAAA,MAAA,CAC1D,GAAA,CAAI,aAAa,2BAAA,MAAiC;AAAA,KACvD;AAAA,EACJ,CAAA;AAAA,EACA,QAAA,CAAS,IAAA,EAAM,GAAA,EAAK,OAAA,EAAS;AACzB,IAAA,MAAM,CAAA,GAAI,GAAA;AACV,IAAA,IAAI,EAAE,UAAA,EAAY,YAAA,IAAgB,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAA,EAAG;AAC/D,MAAA,kBAAA,CAAmB,IAAA,EAAM,CAAA,CAAE,UAAA,EAA+B,OAAO,CAAA;AAAA,IACrE;AAAA,EACJ,CAAA;AAAA,EACA,IAAA,CAAK,GAAA,EAAK,OAAA,EAAS,CAAA,EAAG;AAClB,IAAA,MAAM,EAAA,GAAM,IAAI,SAAA,CAA+B,UAAA;AAC/C,IAAA,IAAA,CAAK,GAAA,CAAI,SAAA,GAAY,qBAAA,MAA2B,CAAA,EAAG;AAC/C,MAAA,MAAM,GAAA,GAAM,IAAI,SAAA,EAAW,OAAA;AAC3B,MAAA,IAAI,GAAA,EAAK;AACL,QAAA,OAAA,CAAQ,KAAK,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,MAAM,CAAA;AACjD,QAAA,OAAA,CAAQ,KAAK,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,SAAS,CAAA;AAAA,MACxD;AAAA,IACJ;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,UAAA,GAAa,+BAAA,MAAqC,CAAA,EAAG;AAC1D,MAAA,MAAM,GAAA,GAAM,IAAI,YAAA,EAAc,YAAA;AAC9B,MAAA,IAAI,GAAA,EAAK;AACL,QAAA,OAAA,CAAQ,KAAK,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,MAAM,CAAA;AACjD,QAAA,OAAA,CAAQ,KAAK,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,SAAS,CAAA;AAAA,MACxD;AAAA,IACJ;AACA,IAAA,IAAA,CAAK,GAAA,CAAI,UAAA,GAAa,mCAAA,MAAyC,CAAA,EAAG;AAC9D,MAAA,MAAM,GAAA,GAAM,IAAI,YAAA,EAAc,gBAAA;AAC9B,MAAA,IAAI,GAAA,EAAK;AACL,QAAA,OAAA,CAAQ,KAAK,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,MAAM,CAAA;AACjD,QAAA,OAAA,CAAQ,KAAK,EAAE,OAAA,EAAS,KAAK,QAAA,EAAU,GAAA,CAAI,SAAS,CAAA;AAAA,MACxD;AAAA,IACJ;AACA,IAAA,OAAO,CAAA;AAAA,EACX,CAAA;AAAA,EACA,QAAA,CAAS,KAAK,GAAA,EAAK;AACf,IAAA,MAAM,KAAM,GAAA,CAAyB,UAAA;AACrC,IAAA,IAAI,EAAA,EAAI,WAAW,OAAA,EAAS;AACxB,MAAA,GAAA,CAAI,IAAA,CAAK,EAAA,CAAG,SAAA,CAAU,OAAO,CAAA;AAAA,IACjC;AACA,IAAA,IAAI,EAAA,EAAI,cAAc,YAAA,EAAc;AAChC,MAAA,GAAA,CAAI,IAAA,CAAK,EAAA,CAAG,YAAA,CAAa,YAAY,CAAA;AAAA,IACzC;AACA,IAAA,IAAI,EAAA,EAAI,cAAc,gBAAA,EAAkB;AACpC,MAAA,GAAA,CAAI,IAAA,CAAK,EAAA,CAAG,YAAA,CAAa,gBAAgB,CAAA;AAAA,IAC7C;AAAA,EACJ;AACJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unlit-fragment.js","sources":["../../../../../src/material/pbr/fragments/unlit-fragment.ts"],"sourcesContent":["/**\n * Unlit Fragment (KHR_materials_unlit).\n *\n * Replaces the lit-color computation with `baseColor * unlitColor` right\n * before the tonemap/gamma/contrast chain runs. Depends on the IBL fragment\n * when present so our AI injection runs *after* IBL's, overwriting the IBL\n * color contribution. The subsequent tonemap/gamma/contrast stages still\n * apply, matching BJS's unlit output under `createDefaultEnvironment`.\n *\n * Zero bytes in bundles for scenes that don't use unlit materials.\n */\n\nimport type { ShaderFragment } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\
|
|
1
|
+
{"version":3,"file":"unlit-fragment.js","sources":["../../../../../src/material/pbr/fragments/unlit-fragment.ts"],"sourcesContent":["/**\n * Unlit Fragment (KHR_materials_unlit).\n *\n * Replaces the lit-color computation with `baseColor * unlitColor` right\n * before the tonemap/gamma/contrast chain runs. Depends on the IBL fragment\n * when present so our AI injection runs *after* IBL's, overwriting the IBL\n * color contribution. The subsequent tonemap/gamma/contrast stages still\n * apply, matching BJS's unlit output under `createDefaultEnvironment`.\n *\n * Zero bytes in bundles for scenes that don't use unlit materials.\n */\n\nimport type { ShaderFragment } from \"../../../shader/fragment-types.js\";\nimport type { PbrMaterialProps } from \"../pbr-material.js\";\nimport type { PbrExt } from \"../pbr-flags.js\";\n\nconst PBR2_HAS_UNLIT = 1 << 8;\n\nexport function createUnlitFragment(hasIbl: boolean): ShaderFragment {\n const assign = `color = baseColor * material.unlitColor;`;\n return {\n _id: \"unlit\",\n _dependencies: hasIbl ? [\"ibl\"] : undefined,\n _uboFields: [\n { _name: \"unlitColor\", _type: \"vec3<f32>\" },\n { _name: \"_unlitColorPad\", _type: \"f32\" },\n ],\n _fragmentSlots: hasIbl ? { AI: assign } : { NI: assign },\n };\n}\n\n/** Write the unlit material-UBO slice. */\nexport function writeUnlitUBO(data: Float32Array, material: PbrMaterialProps, offsets: ReadonlyMap<string, number>): void {\n if (!material.unlit || !offsets.has(\"unlitColor\")) {\n return;\n }\n const off = offsets.get(\"unlitColor\")! / 4;\n const tint = material.unlitColor ?? [1, 1, 1];\n data[off] = tint[0]!;\n data[off + 1] = tint[1]!;\n data[off + 2] = tint[2]!;\n}\n\nexport const pbrExt: PbrExt = {\n id: \"unlit\",\n phase: \"fragment\",\n detect(mat) {\n return (mat as PbrMaterialProps).unlit ? { f: 0, f2: PBR2_HAS_UNLIT } : { f: 0, f2: 0 };\n },\n frag(ctx) {\n if (!(ctx._features2 & PBR2_HAS_UNLIT)) {\n return null;\n }\n return createUnlitFragment(ctx._hasIbl);\n },\n writeUbo: writeUnlitUBO as PbrExt[\"writeUbo\"],\n};\n"],"names":[],"mappings":"AAgBA,MAAM,iBAAiB,CAAA,IAAK,CAAA;AAErB,SAAS,oBAAoB,MAAA,EAAiC;AACjE,EAAA,MAAM,MAAA,GAAS,CAAA,wCAAA,CAAA;AACf,EAAA,OAAO;AAAA,IACH,GAAA,EAAK,OAAA;AAAA,IACL,aAAA,EAAe,MAAA,GAAS,CAAC,KAAK,CAAA,GAAI,MAAA;AAAA,IAClC,UAAA,EAAY;AAAA,MACR,EAAE,KAAA,EAAO,YAAA,EAAc,KAAA,EAAO,WAAA,EAAY;AAAA,MAC1C,EAAE,KAAA,EAAO,gBAAA,EAAkB,KAAA,EAAO,KAAA;AAAM,KAC5C;AAAA,IACA,cAAA,EAAgB,SAAS,EAAE,EAAA,EAAI,QAAO,GAAI,EAAE,IAAI,MAAA;AAAO,GAC3D;AACJ;AAGO,SAAS,aAAA,CAAc,IAAA,EAAoB,QAAA,EAA4B,OAAA,EAA4C;AACtH,EAAA,IAAI,CAAC,QAAA,CAAS,KAAA,IAAS,CAAC,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,EAAG;AAC/C,IAAA;AAAA,EACJ;AACA,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,GAAK,CAAA;AACzC,EAAA,MAAM,OAAO,QAAA,CAAS,UAAA,IAAc,CAAC,CAAA,EAAG,GAAG,CAAC,CAAA;AAC5C,EAAA,IAAA,CAAK,GAAG,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA;AAClB,EAAA,IAAA,CAAK,GAAA,GAAM,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA;AACtB,EAAA,IAAA,CAAK,GAAA,GAAM,CAAC,CAAA,GAAI,IAAA,CAAK,CAAC,CAAA;AAC1B;AAEO,MAAM,MAAA,GAAiB;AAAA,EAC1B,EAAA,EAAI,OAAA;AAAA,EACJ,KAAA,EAAO,UAAA;AAAA,EACP,OAAO,GAAA,EAAK;AACR,IAAA,OAAQ,GAAA,CAAyB,KAAA,GAAQ,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,cAAA,EAAe,GAAI,EAAE,CAAA,EAAG,CAAA,EAAG,EAAA,EAAI,CAAA,EAAE;AAAA,EAC1F,CAAA;AAAA,EACA,KAAK,GAAA,EAAK;AACN,IAAA,IAAI,EAAE,GAAA,CAAI,UAAA,GAAa,cAAA,CAAA,EAAiB;AACpC,MAAA,OAAO,IAAA;AAAA,IACX;AACA,IAAA,OAAO,mBAAA,CAAoB,IAAI,OAAO,CAAA;AAAA,EAC1C,CAAA;AAAA,EACA,QAAA,EAAU;AACd;;;;"}
|
|
@@ -19,6 +19,7 @@ function createPbrComposer(deps) {
|
|
|
19
19
|
_anisoExt,
|
|
20
20
|
_iblSkyboxCalc,
|
|
21
21
|
_flatNormalWgsl,
|
|
22
|
+
_gammaTemplate,
|
|
22
23
|
_createPbrShadowFragment,
|
|
23
24
|
_shadowLights,
|
|
24
25
|
_createThinInstanceFragment
|
|
@@ -89,6 +90,7 @@ function createPbrComposer(deps) {
|
|
|
89
90
|
_anisoBrdfFunctions: _hasAnisotropy && _anisoExt ? _anisoExt.ANISO_BRDF_FUNCTIONS : "",
|
|
90
91
|
_anisoTBBlock: _hasAnisotropy && _anisoExt ? _anisoExt.makeAnisotropyTBBlock(hasNormal, (features2 & _anisoExt.PBR2_HAS_ANISO_TEX) !== 0) : "",
|
|
91
92
|
_ext,
|
|
93
|
+
_gammaTemplate,
|
|
92
94
|
_noColorOutput: (features2 & PBR2_NO_COLOR_OUTPUT) !== 0,
|
|
93
95
|
_esmShadowOutput: (features2 & PBR2_ESM_SHADOW_OUTPUT) !== 0,
|
|
94
96
|
_esmShadowDepthCode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pbr-compose.js","sources":["../../../../src/material/pbr/pbr-compose.ts"],"sourcesContent":["/** PBR shader composer factory — extracts the per-feature-set shader composition\n * from pbr-renderable.ts. All dynamic dependencies (ACES, anisotropy, shadow,\n * multi-light, template-ext, thin-instance) are passed in via a deps object,\n * already resolved by the caller. Nothing is snapshotted at module load. */\n\nimport type { ShaderFragment, ComposedShader } from \"../../shader/fragment-types.js\";\nimport type { PbrShadowLightSlot } from \"./fragments/pbr-shadow-fragment.js\";\nimport { composeShader } from \"../../shader/shader-composer.js\";\nimport { createPbrTemplate } from \"./pbr-template.js\";\nimport type { MeshVbLayout } from \"../../mesh/mesh.js\";\nimport {\n PBR_HAS_NORMAL_MAP,\n PBR_HAS_ALPHA_BLEND,\n PBR2_HAS_UV_TRANSFORM,\n PBR2_HAS_REFLECTANCE_FACTORS,\n PBR2_HAS_UV2,\n PBR2_HAS_BASE_COLOR_FACTOR,\n PBR_HAS_METALLIC_REFLECTANCE_MAP,\n PBR_HAS_REFLECTANCE_MAP,\n PBR_HAS_SPECULAR_AA,\n PBR_HAS_EMISSIVE_COLOR,\n PBR_HAS_GAMMA_ALBEDO,\n PBR_HAS_ANISOTROPY,\n PBR_HAS_DOUBLE_SIDED,\n PBR_HAS_EMISSIVE,\n PBR_HAS_ENV,\n PBR_HAS_TONEMAP,\n PBR_HAS_FOG,\n PBR_HAS_SPEC_GLOSS,\n PBR_HAS_OCCLUSION,\n PBR_HAS_SKYBOX,\n PBR2_ESM_SHADOW_OUTPUT,\n PBR2_NO_COLOR_OUTPUT,\n} from \"./pbr-flag-bits.js\";\nimport { _getPbrExts, type _PbrFragCtx } from \"./pbr-flags.js\";\nimport {\n MSH_HAS_TANGENTS,\n MSH_HAS_MORPH_TARGETS,\n MSH_RECEIVE_SHADOWS,\n MSH_HAS_THIN_INSTANCES,\n MSH_HAS_INSTANCE_COLOR,\n MSH_HAS_VERTEX_COLOR,\n MSH_HAS_UV2,\n MSH_FLAT_NORMAL,\n} from \"../mesh-features.js\";\n\ninterface PbrComposerDeps {\n readonly _singleLightWGSL: string;\n readonly _getSingleLightBlock: ((type: string) => string) | null;\n readonly _multiLightWGSL: string;\n readonly _multiLightLoop: string;\n readonly _toneMappingHelpers: string;\n readonly _toneMappingCall: string;\n /** Fog WGSL (calcFogFactor helper + blend block), dynamically loaded by pbr-renderable only\n * when scene.fog is set; \"\" otherwise so non-fog scenes bundle zero fog bytes. */\n readonly _fogHelper: string;\n readonly _fogBlock: string;\n readonly _createPbrTemplateExt: typeof import(\"./pbr-template-ext.js\").createPbrTemplateExt | null;\n readonly _anisoExt: typeof import(\"./fragments/anisotropy-fragment.js\") | null;\n readonly _iblSkyboxCalc: string;\n /** Flat-normal WGSL (face normal from derivatives), dynamically loaded by pbr-renderable only\n * when a no-NORMAL mesh is present; \"\" otherwise so normal-having scenes bundle zero bytes. */\n readonly _flatNormalWgsl: string;\n readonly _createPbrShadowFragment: ((slots: PbrShadowLightSlot[]) => ShaderFragment) | null;\n readonly _shadowLights: readonly { readonly lightIndex: number; readonly shadowType: import(\"./fragments/pbr-shadow-fragment.js\").PbrShadowLightSlot[\"shadowType\"] }[];\n readonly _createThinInstanceFragment: ((hasColor: boolean) => ShaderFragment) | null;\n}\n\nexport type PbrLightMode = 0 | 1 | 2;\ntype PbrComposeFn = (\n _features: number,\n _features2?: number,\n _meshFeatures?: number,\n _sceneFeatures?: number,\n _lightMode?: PbrLightMode,\n _singleLightType?: string,\n _esmShadowDepthCode?: string,\n _vbStrides?: MeshVbLayout,\n _vbKey?: string\n) => ComposedShader;\n\n/** Create a memoized shader composer for a given scene's resolved PBR deps. */\nexport function createPbrComposer(deps: PbrComposerDeps): PbrComposeFn {\n const cache = new Map<string, ComposedShader>();\n const {\n _singleLightWGSL,\n _getSingleLightBlock,\n _multiLightWGSL,\n _multiLightLoop,\n _toneMappingHelpers,\n _toneMappingCall,\n _fogHelper,\n _fogBlock,\n _createPbrTemplateExt,\n _anisoExt,\n _iblSkyboxCalc,\n _flatNormalWgsl,\n _createPbrShadowFragment,\n _shadowLights,\n _createThinInstanceFragment,\n } = deps;\n\n return function composePbr(\n features: number,\n features2: number = 0,\n meshFeatures = 0,\n sceneFeatures = 0,\n lightMode: PbrLightMode = 0,\n singleLightType = \"\",\n _esmShadowDepthCode = \"\",\n vbStrides?: MeshVbLayout,\n vbKey = \"\"\n ): ComposedShader {\n const ckey = `${features}:${features2}:${meshFeatures}:${sceneFeatures}:${lightMode}:${singleLightType}${vbKey}`;\n const cached = cache.get(ckey);\n if (cached) {\n return cached;\n }\n\n const has = (bit: number) => (features & bit) !== 0;\n const hasMesh = (bit: number) => (meshFeatures & bit) !== 0;\n const hasScene = (bit: number) => (sceneFeatures & bit) !== 0;\n const hasNormal = has(PBR_HAS_NORMAL_MAP) && hasMesh(MSH_HAS_TANGENTS);\n const hasCotangent = has(PBR_HAS_NORMAL_MAP) && !hasMesh(MSH_HAS_TANGENTS);\n const _hasAnyNormal = hasNormal || hasCotangent;\n const _hasReflectanceExt = has(PBR_HAS_METALLIC_REFLECTANCE_MAP | PBR_HAS_REFLECTANCE_MAP) || (features2 & PBR2_HAS_REFLECTANCE_FACTORS) !== 0;\n const _hasIbl = hasScene(PBR_HAS_ENV);\n const _hasMorph = hasMesh(MSH_HAS_MORPH_TARGETS);\n const hasShadow = hasMesh(MSH_RECEIVE_SHADOWS);\n const _hasAnisotropy = has(PBR_HAS_ANISOTROPY);\n const _hasEmissiveColor = has(PBR_HAS_EMISSIVE_COLOR);\n const _hasEmissiveTexture = has(PBR_HAS_EMISSIVE);\n const hasTI = hasMesh(MSH_HAS_THIN_INSTANCES);\n\n const _hasUvTransform = (features2 & PBR2_HAS_UV_TRANSFORM) !== 0;\n const _hasVertexColor = hasMesh(MSH_HAS_VERTEX_COLOR);\n const _hasUv2 = (features2 & PBR2_HAS_UV2) !== 0 && hasMesh(MSH_HAS_UV2);\n const needsExt = _hasUvTransform || _hasVertexColor || _hasUv2;\n const _hasSpecularAA = has(PBR_HAS_SPECULAR_AA);\n const _ext =\n needsExt && _createPbrTemplateExt\n ? _createPbrTemplateExt({\n _hasUvTransform,\n _hasVertexColor,\n _hasUv2,\n _hasOcclusionUv2: _hasUv2,\n _features2: features2,\n _hasAnyNormal,\n _hasEmissiveTexture,\n _hasSpecGloss: has(PBR_HAS_SPEC_GLOSS),\n })\n : undefined;\n\n const template = createPbrTemplate({\n _hasSingleLight: lightMode === 1,\n _hasMultiLight: lightMode === 2,\n _singleLightWGSL,\n _singleLightBlock: lightMode === 1 && _getSingleLightBlock ? _getSingleLightBlock(singleLightType) : \"\",\n _multiLightWGSL,\n _multiLightLoop,\n _normalMode: hasNormal ? \"tangent\" : hasCotangent ? \"cotangent\" : \"none\",\n _flatGeometricNormal: !_hasAnyNormal && hasMesh(MSH_FLAT_NORMAL),\n _flatNormalWgsl,\n _hasEmissiveTexture,\n _hasSpecGloss: has(PBR_HAS_SPEC_GLOSS),\n _hasDoubleSided: has(PBR_HAS_DOUBLE_SIDED),\n _hasTonemap: hasScene(PBR_HAS_TONEMAP),\n _fogHelper: hasScene(PBR_HAS_FOG) ? _fogHelper : \"\",\n _fogBlock: hasScene(PBR_HAS_FOG) ? _fogBlock : \"\",\n _toneMappingHelpers: _toneMappingHelpers,\n _toneMappingCall: _toneMappingCall,\n _hasAlphaBlend: has(PBR_HAS_ALPHA_BLEND),\n _hasSpecularAA,\n _hasGammaAlbedo: has(PBR_HAS_GAMMA_ALBEDO),\n _hasBaseColorFactor: (features2 & PBR2_HAS_BASE_COLOR_FACTOR) !== 0,\n _hasMorph,\n _hasOcclusion: has(PBR_HAS_OCCLUSION) && !_hasReflectanceExt,\n _hasEmissiveColor,\n _hasReflectanceExt,\n _hasIbl,\n _hasAnisotropy,\n _anisoBrdfFunctions: _hasAnisotropy && _anisoExt ? _anisoExt.ANISO_BRDF_FUNCTIONS : \"\",\n _anisoTBBlock: _hasAnisotropy && _anisoExt ? _anisoExt.makeAnisotropyTBBlock(hasNormal, (features2 & _anisoExt.PBR2_HAS_ANISO_TEX) !== 0) : \"\",\n _ext,\n _noColorOutput: (features2 & PBR2_NO_COLOR_OUTPUT) !== 0,\n _esmShadowOutput: (features2 & PBR2_ESM_SHADOW_OUTPUT) !== 0,\n _esmShadowDepthCode,\n _vbStrides: vbStrides,\n });\n\n const frags: ShaderFragment[] = [];\n const fragCtx: _PbrFragCtx = {\n _features: features,\n _features2: features2,\n _meshFeatures: meshFeatures,\n _hasIbl: _hasIbl,\n _hasAnyNormal,\n _hasSpecularAA,\n _anisoBentNormalCode: _hasAnisotropy && _anisoExt ? _anisoExt.ANISO_BENT_NORMAL : \"\",\n _iblSkyboxCalc: has(PBR_HAS_SKYBOX) ? _iblSkyboxCalc : \"\",\n };\n // Registration order defines iteration order; callers register in composer-matching order.\n let pc: ((composed: ComposedShader) => ComposedShader) | undefined;\n for (const regExt of _getPbrExts().values()) {\n if (regExt.frag) {\n const fr = regExt.frag(fragCtx);\n if (fr) {\n frags.push(fr);\n pc ||= fr._pc;\n }\n }\n }\n if (hasShadow && _createPbrShadowFragment) {\n const slots = _shadowLights.map((sl) => ({ lightIndex: sl.lightIndex, shadowType: sl.shadowType }));\n frags.push(_createPbrShadowFragment(slots));\n }\n if (hasTI && _createThinInstanceFragment) {\n frags.push(_createThinInstanceFragment(hasMesh(MSH_HAS_INSTANCE_COLOR)));\n }\n\n let composed = composeShader(template, frags);\n pc && (composed = pc(composed));\n cache.set(ckey, composed);\n return composed;\n };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pbr-compose.js","sources":["../../../../src/material/pbr/pbr-compose.ts"],"sourcesContent":["/** PBR shader composer factory — extracts the per-feature-set shader composition\n * from pbr-renderable.ts. All dynamic dependencies (ACES, anisotropy, shadow,\n * multi-light, template-ext, thin-instance) are passed in via a deps object,\n * already resolved by the caller. Nothing is snapshotted at module load. */\n\nimport type { ShaderFragment, ComposedShader } from \"../../shader/fragment-types.js\";\nimport type { PbrShadowLightSlot } from \"./fragments/pbr-shadow-fragment.js\";\nimport { composeShader } from \"../../shader/shader-composer.js\";\nimport { createPbrTemplate } from \"./pbr-template.js\";\nimport type { MeshVbLayout } from \"../../mesh/mesh.js\";\nimport {\n PBR_HAS_NORMAL_MAP,\n PBR_HAS_ALPHA_BLEND,\n PBR2_HAS_UV_TRANSFORM,\n PBR2_HAS_REFLECTANCE_FACTORS,\n PBR2_HAS_UV2,\n PBR2_HAS_BASE_COLOR_FACTOR,\n PBR_HAS_METALLIC_REFLECTANCE_MAP,\n PBR_HAS_REFLECTANCE_MAP,\n PBR_HAS_SPECULAR_AA,\n PBR_HAS_EMISSIVE_COLOR,\n PBR_HAS_GAMMA_ALBEDO,\n PBR_HAS_ANISOTROPY,\n PBR_HAS_DOUBLE_SIDED,\n PBR_HAS_EMISSIVE,\n PBR_HAS_ENV,\n PBR_HAS_TONEMAP,\n PBR_HAS_FOG,\n PBR_HAS_SPEC_GLOSS,\n PBR_HAS_OCCLUSION,\n PBR_HAS_SKYBOX,\n PBR2_ESM_SHADOW_OUTPUT,\n PBR2_NO_COLOR_OUTPUT,\n} from \"./pbr-flag-bits.js\";\nimport { _getPbrExts, type _PbrFragCtx } from \"./pbr-flags.js\";\nimport {\n MSH_HAS_TANGENTS,\n MSH_HAS_MORPH_TARGETS,\n MSH_RECEIVE_SHADOWS,\n MSH_HAS_THIN_INSTANCES,\n MSH_HAS_INSTANCE_COLOR,\n MSH_HAS_VERTEX_COLOR,\n MSH_HAS_UV2,\n MSH_FLAT_NORMAL,\n} from \"../mesh-features.js\";\n\ninterface PbrComposerDeps {\n readonly _singleLightWGSL: string;\n readonly _getSingleLightBlock: ((type: string) => string) | null;\n readonly _multiLightWGSL: string;\n readonly _multiLightLoop: string;\n readonly _toneMappingHelpers: string;\n readonly _toneMappingCall: string;\n /** Fog WGSL (calcFogFactor helper + blend block), dynamically loaded by pbr-renderable only\n * when scene.fog is set; \"\" otherwise so non-fog scenes bundle zero fog bytes. */\n readonly _fogHelper: string;\n readonly _fogBlock: string;\n readonly _createPbrTemplateExt: typeof import(\"./pbr-template-ext.js\").createPbrTemplateExt | null;\n readonly _anisoExt: typeof import(\"./fragments/anisotropy-fragment.js\") | null;\n readonly _iblSkyboxCalc: string;\n /** Flat-normal WGSL (face normal from derivatives), dynamically loaded by pbr-renderable only\n * when a no-NORMAL mesh is present; \"\" otherwise so normal-having scenes bundle zero bytes. */\n readonly _flatNormalWgsl: string;\n readonly _gammaTemplate: typeof import(\"./pbr-template-gamma.js\") | null;\n readonly _createPbrShadowFragment: ((slots: PbrShadowLightSlot[]) => ShaderFragment) | null;\n readonly _shadowLights: readonly { readonly lightIndex: number; readonly shadowType: import(\"./fragments/pbr-shadow-fragment.js\").PbrShadowLightSlot[\"shadowType\"] }[];\n readonly _createThinInstanceFragment: ((hasColor: boolean) => ShaderFragment) | null;\n}\n\nexport type PbrLightMode = 0 | 1 | 2;\ntype PbrComposeFn = (\n _features: number,\n _features2?: number,\n _meshFeatures?: number,\n _sceneFeatures?: number,\n _lightMode?: PbrLightMode,\n _singleLightType?: string,\n _esmShadowDepthCode?: string,\n _vbStrides?: MeshVbLayout,\n _vbKey?: string\n) => ComposedShader;\n\n/** Create a memoized shader composer for a given scene's resolved PBR deps. */\nexport function createPbrComposer(deps: PbrComposerDeps): PbrComposeFn {\n const cache = new Map<string, ComposedShader>();\n const {\n _singleLightWGSL,\n _getSingleLightBlock,\n _multiLightWGSL,\n _multiLightLoop,\n _toneMappingHelpers,\n _toneMappingCall,\n _fogHelper,\n _fogBlock,\n _createPbrTemplateExt,\n _anisoExt,\n _iblSkyboxCalc,\n _flatNormalWgsl,\n _gammaTemplate,\n _createPbrShadowFragment,\n _shadowLights,\n _createThinInstanceFragment,\n } = deps;\n\n return function composePbr(\n features: number,\n features2: number = 0,\n meshFeatures = 0,\n sceneFeatures = 0,\n lightMode: PbrLightMode = 0,\n singleLightType = \"\",\n _esmShadowDepthCode = \"\",\n vbStrides?: MeshVbLayout,\n vbKey = \"\"\n ): ComposedShader {\n const ckey = `${features}:${features2}:${meshFeatures}:${sceneFeatures}:${lightMode}:${singleLightType}${vbKey}`;\n const cached = cache.get(ckey);\n if (cached) {\n return cached;\n }\n\n const has = (bit: number) => (features & bit) !== 0;\n const hasMesh = (bit: number) => (meshFeatures & bit) !== 0;\n const hasScene = (bit: number) => (sceneFeatures & bit) !== 0;\n const hasNormal = has(PBR_HAS_NORMAL_MAP) && hasMesh(MSH_HAS_TANGENTS);\n const hasCotangent = has(PBR_HAS_NORMAL_MAP) && !hasMesh(MSH_HAS_TANGENTS);\n const _hasAnyNormal = hasNormal || hasCotangent;\n const _hasReflectanceExt = has(PBR_HAS_METALLIC_REFLECTANCE_MAP | PBR_HAS_REFLECTANCE_MAP) || (features2 & PBR2_HAS_REFLECTANCE_FACTORS) !== 0;\n const _hasIbl = hasScene(PBR_HAS_ENV);\n const _hasMorph = hasMesh(MSH_HAS_MORPH_TARGETS);\n const hasShadow = hasMesh(MSH_RECEIVE_SHADOWS);\n const _hasAnisotropy = has(PBR_HAS_ANISOTROPY);\n const _hasEmissiveColor = has(PBR_HAS_EMISSIVE_COLOR);\n const _hasEmissiveTexture = has(PBR_HAS_EMISSIVE);\n const hasTI = hasMesh(MSH_HAS_THIN_INSTANCES);\n\n const _hasUvTransform = (features2 & PBR2_HAS_UV_TRANSFORM) !== 0;\n const _hasVertexColor = hasMesh(MSH_HAS_VERTEX_COLOR);\n const _hasUv2 = (features2 & PBR2_HAS_UV2) !== 0 && hasMesh(MSH_HAS_UV2);\n const needsExt = _hasUvTransform || _hasVertexColor || _hasUv2;\n const _hasSpecularAA = has(PBR_HAS_SPECULAR_AA);\n const _ext =\n needsExt && _createPbrTemplateExt\n ? _createPbrTemplateExt({\n _hasUvTransform,\n _hasVertexColor,\n _hasUv2,\n _hasOcclusionUv2: _hasUv2,\n _features2: features2,\n _hasAnyNormal,\n _hasEmissiveTexture,\n _hasSpecGloss: has(PBR_HAS_SPEC_GLOSS),\n })\n : undefined;\n\n const template = createPbrTemplate({\n _hasSingleLight: lightMode === 1,\n _hasMultiLight: lightMode === 2,\n _singleLightWGSL,\n _singleLightBlock: lightMode === 1 && _getSingleLightBlock ? _getSingleLightBlock(singleLightType) : \"\",\n _multiLightWGSL,\n _multiLightLoop,\n _normalMode: hasNormal ? \"tangent\" : hasCotangent ? \"cotangent\" : \"none\",\n _flatGeometricNormal: !_hasAnyNormal && hasMesh(MSH_FLAT_NORMAL),\n _flatNormalWgsl,\n _hasEmissiveTexture,\n _hasSpecGloss: has(PBR_HAS_SPEC_GLOSS),\n _hasDoubleSided: has(PBR_HAS_DOUBLE_SIDED),\n _hasTonemap: hasScene(PBR_HAS_TONEMAP),\n _fogHelper: hasScene(PBR_HAS_FOG) ? _fogHelper : \"\",\n _fogBlock: hasScene(PBR_HAS_FOG) ? _fogBlock : \"\",\n _toneMappingHelpers: _toneMappingHelpers,\n _toneMappingCall: _toneMappingCall,\n _hasAlphaBlend: has(PBR_HAS_ALPHA_BLEND),\n _hasSpecularAA,\n _hasGammaAlbedo: has(PBR_HAS_GAMMA_ALBEDO),\n _hasBaseColorFactor: (features2 & PBR2_HAS_BASE_COLOR_FACTOR) !== 0,\n _hasMorph,\n _hasOcclusion: has(PBR_HAS_OCCLUSION) && !_hasReflectanceExt,\n _hasEmissiveColor,\n _hasReflectanceExt,\n _hasIbl,\n _hasAnisotropy,\n _anisoBrdfFunctions: _hasAnisotropy && _anisoExt ? _anisoExt.ANISO_BRDF_FUNCTIONS : \"\",\n _anisoTBBlock: _hasAnisotropy && _anisoExt ? _anisoExt.makeAnisotropyTBBlock(hasNormal, (features2 & _anisoExt.PBR2_HAS_ANISO_TEX) !== 0) : \"\",\n _ext,\n _gammaTemplate,\n _noColorOutput: (features2 & PBR2_NO_COLOR_OUTPUT) !== 0,\n _esmShadowOutput: (features2 & PBR2_ESM_SHADOW_OUTPUT) !== 0,\n _esmShadowDepthCode,\n _vbStrides: vbStrides,\n });\n\n const frags: ShaderFragment[] = [];\n const fragCtx: _PbrFragCtx = {\n _features: features,\n _features2: features2,\n _meshFeatures: meshFeatures,\n _hasIbl: _hasIbl,\n _hasAnyNormal,\n _hasSpecularAA,\n _anisoBentNormalCode: _hasAnisotropy && _anisoExt ? _anisoExt.ANISO_BENT_NORMAL : \"\",\n _iblSkyboxCalc: has(PBR_HAS_SKYBOX) ? _iblSkyboxCalc : \"\",\n };\n // Registration order defines iteration order; callers register in composer-matching order.\n let pc: ((composed: ComposedShader) => ComposedShader) | undefined;\n for (const regExt of _getPbrExts().values()) {\n if (regExt.frag) {\n const fr = regExt.frag(fragCtx);\n if (fr) {\n frags.push(fr);\n pc ||= fr._pc;\n }\n }\n }\n if (hasShadow && _createPbrShadowFragment) {\n const slots = _shadowLights.map((sl) => ({ lightIndex: sl.lightIndex, shadowType: sl.shadowType }));\n frags.push(_createPbrShadowFragment(slots));\n }\n if (hasTI && _createThinInstanceFragment) {\n frags.push(_createThinInstanceFragment(hasMesh(MSH_HAS_INSTANCE_COLOR)));\n }\n\n let composed = composeShader(template, frags);\n pc && (composed = pc(composed));\n cache.set(ckey, composed);\n return composed;\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -23,28 +23,13 @@ const PBR_HAS_SUBSURFACE = 1 << 27;
|
|
|
23
23
|
const PBR_HAS_THICKNESS_MAP = 1 << 28;
|
|
24
24
|
const PBR_HAS_SKYBOX = 1 << 29;
|
|
25
25
|
const PBR_HAS_SHEEN_ALBEDO_SCALING = 1 << 30;
|
|
26
|
-
const PBR2_CC_INT_MAP = 1 << 0;
|
|
27
|
-
const PBR2_CC_ROUGH_MAP = 1 << 1;
|
|
28
|
-
const PBR2_CC_NORMAL_MAP = 1 << 2;
|
|
29
|
-
const PBR2_CC_F0_REMAP_OFF = 1 << 3;
|
|
30
26
|
const PBR2_HAS_REFRACTION = 1 << 4;
|
|
31
|
-
const PBR2_HAS_VOLUME = 1 << 5;
|
|
32
|
-
const PBR2_HAS_REFRACTION_MAP = 1 << 6;
|
|
33
|
-
const PBR2_HAS_THICKNESS_GLTF_CHANNEL = 1 << 7;
|
|
34
|
-
const PBR2_HAS_UNLIT = 1 << 8;
|
|
35
27
|
const PBR2_HAS_UV_TRANSFORM = 1 << 9;
|
|
36
28
|
const PBR2_HAS_REFLECTANCE_FACTORS = 1 << 10;
|
|
37
29
|
const PBR2_HAS_UV2 = 1 << 11;
|
|
38
30
|
const PBR2_HAS_BASE_COLOR_FACTOR = 1 << 12;
|
|
39
|
-
const PBR2_HAS_SHEEN_UV_TX = 1 << 13;
|
|
40
|
-
const PBR2_LINEAR_IMAGE_PROCESSING = 1 << 14;
|
|
41
31
|
const PBR2_NO_COLOR_OUTPUT = 1 << 15;
|
|
42
32
|
const PBR2_ESM_SHADOW_OUTPUT = 1 << 16;
|
|
43
|
-
const PBR2_HAS_IRIDESCENCE = 1 << 17;
|
|
44
|
-
const PBR2_HAS_IRIDESCENCE_MAP = 1 << 18;
|
|
45
|
-
const PBR2_HAS_IRIDESCENCE_THICKNESS_MAP = 1 << 19;
|
|
46
|
-
const PBR2_HAS_DISPERSION = 1 << 20;
|
|
47
|
-
const PBR2_GEOMETRY_OUTPUT = 1 << 21;
|
|
48
33
|
|
|
49
|
-
export {
|
|
34
|
+
export { PBR2_ESM_SHADOW_OUTPUT, PBR2_HAS_BASE_COLOR_FACTOR, PBR2_HAS_REFLECTANCE_FACTORS, PBR2_HAS_REFRACTION, PBR2_HAS_UV2, PBR2_HAS_UV_TRANSFORM, PBR2_NO_COLOR_OUTPUT, PBR_HAS_ALPHA_BLEND, PBR_HAS_ALPHA_TEST, PBR_HAS_ANISOTROPY, PBR_HAS_CLEARCOAT, PBR_HAS_COTANGENT_NORMAL, PBR_HAS_DOUBLE_SIDED, PBR_HAS_EMISSIVE, PBR_HAS_EMISSIVE_COLOR, PBR_HAS_ENV, PBR_HAS_FOG, PBR_HAS_GAMMA_ALBEDO, PBR_HAS_METALLIC_REFLECTANCE_MAP, PBR_HAS_NORMAL_MAP, PBR_HAS_OCCLUSION, PBR_HAS_REFLECTANCE_MAP, PBR_HAS_SHEEN, PBR_HAS_SHEEN_ALBEDO_SCALING, PBR_HAS_SHEEN_TEXTURE, PBR_HAS_SKYBOX, PBR_HAS_SPECULAR_AA, PBR_HAS_SPEC_GLOSS, PBR_HAS_SUBSURFACE, PBR_HAS_THICKNESS_MAP, PBR_HAS_TONEMAP, PBR_HAS_USE_ALPHA_ONLY_MR };
|
|
50
35
|
//# sourceMappingURL=pbr-flag-bits.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pbr-flag-bits.js","sources":["../../../../src/material/pbr/pbr-flag-bits.ts"],"sourcesContent":["export const PBR_HAS_NORMAL_MAP = 1 << 0;\nexport const PBR_HAS_EMISSIVE = 1 << 1;\nexport const PBR_HAS_ENV = 1 << 2;\nexport const PBR_HAS_ALPHA_TEST = 1 << 3;\nexport const PBR_HAS_TONEMAP = 1 << 4;\n/** Scene has fog enabled (scene.fog != null). A scene-feature bit (threaded via\n * sceneFeatures), gating the PBR fog blend + calcFogFactor helper into the shader.\n * Compile-time gated so non-fog PBR scenes stay byte-identical. */\nexport const PBR_HAS_FOG = 1 << 5;\nexport const PBR_HAS_ALPHA_BLEND = 1 << 6;\nexport const PBR_HAS_SPEC_GLOSS = 1 << 7;\nexport const PBR_HAS_DOUBLE_SIDED = 1 << 8;\nexport const PBR_HAS_COTANGENT_NORMAL = 1 << 9;\nexport const PBR_HAS_METALLIC_REFLECTANCE_MAP = 1 << 10;\nexport const PBR_HAS_REFLECTANCE_MAP = 1 << 11;\nexport const PBR_HAS_USE_ALPHA_ONLY_MR = 1 << 12;\nexport const PBR_HAS_OCCLUSION = 1 << 15;\nexport const PBR_HAS_SPECULAR_AA = 1 << 17;\nexport const PBR_HAS_CLEARCOAT = 1 << 20;\nexport const PBR_HAS_EMISSIVE_COLOR = 1 << 21;\nexport const PBR_HAS_SHEEN = 1 << 22;\nexport const PBR_HAS_SHEEN_TEXTURE = 1 << 23;\nexport const PBR_HAS_GAMMA_ALBEDO = 1 << 25;\nexport const PBR_HAS_ANISOTROPY = 1 << 26;\nexport const PBR_HAS_SUBSURFACE = 1 << 27;\nexport const PBR_HAS_THICKNESS_MAP = 1 << 28;\nexport const PBR_HAS_SKYBOX = 1 << 29;\nexport const PBR_HAS_SHEEN_ALBEDO_SCALING = 1 << 30;\n\n// ─── features2 (extended feature bits) ──────────────────────────────\n// Used when `features` runs out of bits. Threaded separately through\n// composePbr / getOrCreatePbrPipeline / createPbrMeshBindGroup.\
|
|
1
|
+
{"version":3,"file":"pbr-flag-bits.js","sources":["../../../../src/material/pbr/pbr-flag-bits.ts"],"sourcesContent":["export const PBR_HAS_NORMAL_MAP = 1 << 0;\nexport const PBR_HAS_EMISSIVE = 1 << 1;\nexport const PBR_HAS_ENV = 1 << 2;\nexport const PBR_HAS_ALPHA_TEST = 1 << 3;\nexport const PBR_HAS_TONEMAP = 1 << 4;\n/** Scene has fog enabled (scene.fog != null). A scene-feature bit (threaded via\n * sceneFeatures), gating the PBR fog blend + calcFogFactor helper into the shader.\n * Compile-time gated so non-fog PBR scenes stay byte-identical. */\nexport const PBR_HAS_FOG = 1 << 5;\nexport const PBR_HAS_ALPHA_BLEND = 1 << 6;\nexport const PBR_HAS_SPEC_GLOSS = 1 << 7;\nexport const PBR_HAS_DOUBLE_SIDED = 1 << 8;\nexport const PBR_HAS_COTANGENT_NORMAL = 1 << 9;\nexport const PBR_HAS_METALLIC_REFLECTANCE_MAP = 1 << 10;\nexport const PBR_HAS_REFLECTANCE_MAP = 1 << 11;\nexport const PBR_HAS_USE_ALPHA_ONLY_MR = 1 << 12;\nexport const PBR_HAS_OCCLUSION = 1 << 15;\nexport const PBR_HAS_SPECULAR_AA = 1 << 17;\nexport const PBR_HAS_CLEARCOAT = 1 << 20;\nexport const PBR_HAS_EMISSIVE_COLOR = 1 << 21;\nexport const PBR_HAS_SHEEN = 1 << 22;\nexport const PBR_HAS_SHEEN_TEXTURE = 1 << 23;\nexport const PBR_HAS_GAMMA_ALBEDO = 1 << 25;\nexport const PBR_HAS_ANISOTROPY = 1 << 26;\nexport const PBR_HAS_SUBSURFACE = 1 << 27;\nexport const PBR_HAS_THICKNESS_MAP = 1 << 28;\nexport const PBR_HAS_SKYBOX = 1 << 29;\nexport const PBR_HAS_SHEEN_ALBEDO_SCALING = 1 << 30;\n\n// ─── features2 (extended feature bits) ──────────────────────────────\n// Used when `features` runs out of bits. Threaded separately through\n// composePbr / getOrCreatePbrPipeline / createPbrMeshBindGroup.\n// 1<<0 .. 1<<3 are clearcoat-local (clearcoat-fragment.ts).\n/** Material has KHR_materials_transmission (refraction through surface). */\nexport const PBR2_HAS_REFRACTION = 1 << 4;\n// 1<<5 .. 1<<7 are refraction/subsurface-local; 1<<8 is unlit-local.\n/** Any bound texture on this material carries a non-identity UV transform\n * (`uScale/vScale/uOffset/vOffset/uAng` on its Texture2D). Enables per-\n * texture UV-transform UBO fields + `txfUV` wrapping in the shader. */\nexport const PBR2_HAS_UV_TRANSFORM = 1 << 9;\n/** Material has non-default metallicF0Factor or metallicReflectanceColor\n * without reflectance textures (factor-only KHR_materials_specular). */\nexport const PBR2_HAS_REFLECTANCE_FACTORS = 1 << 10;\n/** Material samples occlusion from TEXCOORD_1 when the mesh provides UV2. */\nexport const PBR2_HAS_UV2 = 1 << 11;\n/** Material multiplies textured albedo by a non-default glTF baseColorFactor. */\nexport const PBR2_HAS_BASE_COLOR_FACTOR = 1 << 12;\n// 1<<13 is sheen-local; 1<<14 is refraction-local.\n/** Material view runs the fragment shader but declares no color output. */\nexport const PBR2_NO_COLOR_OUTPUT = 1 << 15;\n/** Material view runs discard/clip logic and writes exponential shadow-map color. */\nexport const PBR2_ESM_SHADOW_OUTPUT = 1 << 16;\n// 1<<17 .. 1<<19 are iridescence-local; 1<<20 is refraction-local;\n// 1<<21 is geometry-output-local.\n// ─── Extension-local features2 bits (1<<22 .. 1<<28) ────────────────\n// RESERVED here but DEFINED inside their lazy fragment modules so the constants\n// are never retained in the entry/shared chunk for scenes that don't load those\n// fragments (literally zero bundle movement). Do not reuse these bits.\n// 1<<22 PBR2_HAS_TRANSLUCENCY_COLOR_MAP (subsurface-fragment.ts)\n// 1<<23 PBR2_HAS_TRANSLUCENCY_INTENSITY_MAP (subsurface-fragment.ts)\n// 1<<24 PBR2_HAS_TRANSLUCENCY_UV_TX (subsurface-fragment.ts)\n// 1<<25 PBR2_CC_UV_TX (clearcoat-fragment.ts)\n// 1<<26 PBR2_REFL_UV_TX (reflectance-fragment.ts)\n// 1<<27 PBR2_HAS_ANISO_TEX (anisotropy-fragment.ts)\n// 1<<28 PBR2_OCCL_UV_SPLIT (uv-transform-fragment.ts + pbr-template-ext.ts)\n"],"names":[],"mappings":"AAAO,MAAM,qBAAqB,CAAA,IAAK;AAChC,MAAM,mBAAmB,CAAA,IAAK;AAC9B,MAAM,cAAc,CAAA,IAAK;AACzB,MAAM,qBAAqB,CAAA,IAAK;AAChC,MAAM,kBAAkB,CAAA,IAAK;AAI7B,MAAM,cAAc,CAAA,IAAK;AACzB,MAAM,sBAAsB,CAAA,IAAK;AACjC,MAAM,qBAAqB,CAAA,IAAK;AAChC,MAAM,uBAAuB,CAAA,IAAK;AAClC,MAAM,2BAA2B,CAAA,IAAK;AACtC,MAAM,mCAAmC,CAAA,IAAK;AAC9C,MAAM,0BAA0B,CAAA,IAAK;AACrC,MAAM,4BAA4B,CAAA,IAAK;AACvC,MAAM,oBAAoB,CAAA,IAAK;AAC/B,MAAM,sBAAsB,CAAA,IAAK;AACjC,MAAM,oBAAoB,CAAA,IAAK;AAC/B,MAAM,yBAAyB,CAAA,IAAK;AACpC,MAAM,gBAAgB,CAAA,IAAK;AAC3B,MAAM,wBAAwB,CAAA,IAAK;AACnC,MAAM,uBAAuB,CAAA,IAAK;AAClC,MAAM,qBAAqB,CAAA,IAAK;AAChC,MAAM,qBAAqB,CAAA,IAAK;AAChC,MAAM,wBAAwB,CAAA,IAAK;AACnC,MAAM,iBAAiB,CAAA,IAAK;AAC5B,MAAM,+BAA+B,CAAA,IAAK;AAO1C,MAAM,sBAAsB,CAAA,IAAK;AAKjC,MAAM,wBAAwB,CAAA,IAAK;AAGnC,MAAM,+BAA+B,CAAA,IAAK;AAE1C,MAAM,eAAe,CAAA,IAAK;AAE1B,MAAM,6BAA6B,CAAA,IAAK;AAGxC,MAAM,uBAAuB,CAAA,IAAK;AAElC,MAAM,yBAAyB,CAAA,IAAK;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { PBR2_ESM_SHADOW_OUTPUT, PBR2_HAS_BASE_COLOR_FACTOR, PBR2_HAS_REFLECTANCE_FACTORS, PBR2_HAS_REFRACTION, PBR2_HAS_UV2, PBR2_HAS_UV_TRANSFORM, PBR2_NO_COLOR_OUTPUT, PBR_HAS_ALPHA_BLEND, PBR_HAS_ALPHA_TEST, PBR_HAS_ANISOTROPY, PBR_HAS_CLEARCOAT, PBR_HAS_COTANGENT_NORMAL, PBR_HAS_DOUBLE_SIDED, PBR_HAS_EMISSIVE, PBR_HAS_EMISSIVE_COLOR, PBR_HAS_ENV, PBR_HAS_FOG, PBR_HAS_GAMMA_ALBEDO, PBR_HAS_METALLIC_REFLECTANCE_MAP, PBR_HAS_NORMAL_MAP, PBR_HAS_OCCLUSION, PBR_HAS_REFLECTANCE_MAP, PBR_HAS_SHEEN, PBR_HAS_SHEEN_ALBEDO_SCALING, PBR_HAS_SHEEN_TEXTURE, PBR_HAS_SKYBOX, PBR_HAS_SPECULAR_AA, PBR_HAS_SPEC_GLOSS, PBR_HAS_SUBSURFACE, PBR_HAS_THICKNESS_MAP, PBR_HAS_TONEMAP, PBR_HAS_USE_ALPHA_ONLY_MR } from './pbr-flag-bits.js';
|
|
2
2
|
|
|
3
3
|
let _pbrExts = null;
|
|
4
4
|
let _pbrExtsSorted = null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WGSL_FOG } from '../../shader/wgsl-
|
|
1
|
+
import { WGSL_FOG } from '../../shader/wgsl-fog.js';
|
|
2
2
|
|
|
3
3
|
const PBR_FOG_HELPER = WGSL_FOG;
|
|
4
4
|
const PBR_FOG_BLOCK = `if(scene.vFogInfos.x>0.0){var fogFactor=calcFogFactor((scene.view*vec4<f32>(input.worldPos,1.0)).xyz);fogFactor=pow(fogFactor,2.2);color=mix(pow(scene.vFogColor.rgb,vec3<f32>(2.2)),color,fogFactor);}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pbr-fog-wgsl.js","sources":["../../../../src/material/pbr/pbr-fog-wgsl.ts"],"sourcesContent":["/**\n * PBR fog receiver WGSL — the `calcFogFactor` helper plus the fog blend block.\n *\n * Dynamically imported by `pbr-renderable` ONLY when `scene.fog` is set, then threaded into the\n * PBR template as plain strings (the same pattern the ACES tonemap uses). This keeps every byte of\n * fog WGSL out of the bundles of PBR scenes that don't use fog — a static `import` of the helper\n * into `pbr-template` would defeat tree-shaking and inflate every PBR scene (see GUIDANCE §4c′).\n *\n * Parity notes (matches Babylon.js `pbr.fragment` exactly):\n * - Fog is mixed into the LINEAR HDR colour BEFORE the tonemap / image-processing chain\n * (BJS runs `fogFragment` before `pbrBlockImageProcessing`).\n * - The fog FACTOR is linearised: `fog = toLinearSpace(fog)` = `pow(fog, 2.2)` (default approx sRGB).\n * - The fog COLOUR is linearised too: BJS binds `vFogColor` with `linearSpace = true` for PBR\n * (`BindFogParameters`), whereas the Standard material binds it raw. Lite stores one raw\n * `vFogColor` in the scene UBO (correct for Standard, which has no trailing gamma), so the PBR\n * path linearises it here with `pow(.., 2.2)`; after Lite's trailing gamma encode the fully\n * fogged result returns to the authored fog colour (matching the background), exactly like BJS.\n * - The runtime `vFogInfos.x > 0.0` guard lets `fogMode` toggle none/linear/exp/exp2 at runtime.\n */\n\nimport { WGSL_FOG } from \"../../shader/wgsl-
|
|
1
|
+
{"version":3,"file":"pbr-fog-wgsl.js","sources":["../../../../src/material/pbr/pbr-fog-wgsl.ts"],"sourcesContent":["/**\n * PBR fog receiver WGSL — the `calcFogFactor` helper plus the fog blend block.\n *\n * Dynamically imported by `pbr-renderable` ONLY when `scene.fog` is set, then threaded into the\n * PBR template as plain strings (the same pattern the ACES tonemap uses). This keeps every byte of\n * fog WGSL out of the bundles of PBR scenes that don't use fog — a static `import` of the helper\n * into `pbr-template` would defeat tree-shaking and inflate every PBR scene (see GUIDANCE §4c′).\n *\n * Parity notes (matches Babylon.js `pbr.fragment` exactly):\n * - Fog is mixed into the LINEAR HDR colour BEFORE the tonemap / image-processing chain\n * (BJS runs `fogFragment` before `pbrBlockImageProcessing`).\n * - The fog FACTOR is linearised: `fog = toLinearSpace(fog)` = `pow(fog, 2.2)` (default approx sRGB).\n * - The fog COLOUR is linearised too: BJS binds `vFogColor` with `linearSpace = true` for PBR\n * (`BindFogParameters`), whereas the Standard material binds it raw. Lite stores one raw\n * `vFogColor` in the scene UBO (correct for Standard, which has no trailing gamma), so the PBR\n * path linearises it here with `pow(.., 2.2)`; after Lite's trailing gamma encode the fully\n * fogged result returns to the authored fog colour (matching the background), exactly like BJS.\n * - The runtime `vFogInfos.x > 0.0` guard lets `fogMode` toggle none/linear/exp/exp2 at runtime.\n */\n\nimport { WGSL_FOG } from \"../../shader/wgsl-fog.js\";\n\n/** `calcFogFactor` + `E_FOG` helper WGSL (reads `scene.vFogInfos`). */\nexport const PBR_FOG_HELPER = WGSL_FOG;\n\n/** Fog blend, emitted just before the PBR tonemap block (operates on the linear HDR `color`). */\nexport const PBR_FOG_BLOCK = `if(scene.vFogInfos.x>0.0){var fogFactor=calcFogFactor((scene.view*vec4<f32>(input.worldPos,1.0)).xyz);fogFactor=pow(fogFactor,2.2);color=mix(pow(scene.vFogColor.rgb,vec3<f32>(2.2)),color,fogFactor);}`;\n"],"names":[],"mappings":";;AAuBO,MAAM,cAAA,GAAiB;AAGvB,MAAM,aAAA,GAAgB,CAAA,uMAAA;;;;"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { GeometryTextureType } from '../../frame-graph/geometry-types.js';
|
|
2
2
|
import { _registerPbrExt } from './pbr-flags.js';
|
|
3
|
-
import {
|
|
3
|
+
import { PBR_HAS_ALPHA_BLEND, PBR_HAS_ENV } from './pbr-flag-bits.js';
|
|
4
4
|
|
|
5
5
|
const STAGE_FRAGMENT = 2;
|
|
6
6
|
const STAGE_VERTEX = 1;
|
|
7
|
+
const PBR2_GEOMETRY_OUTPUT = 1 << 21;
|
|
7
8
|
function needsGpUbo(attachments) {
|
|
8
9
|
for (const t of attachments) {
|
|
9
10
|
if (t === GeometryTextureType.NORMALIZED_VIEW_DEPTH || t === GeometryTextureType.LINEAR_VELOCITY) {
|