import type { Texture } from '@luma.gl/core'; import type { Matrix3, Vector2, Vector3, Vector4, NumberArray2, NumberArray3, NumberArray4, NumberArray9 } from '@math.gl/core'; import { ShaderModule } from "../../../lib/shader-module/shader-module.js"; /** Non-uniform block bindings for pbr module */ export type PBRMaterialBindings = { pbr_baseColorSampler?: Texture | null; pbr_normalSampler?: Texture | null; pbr_emissiveSampler?: Texture | null; pbr_metallicRoughnessSampler?: Texture | null; pbr_occlusionSampler?: Texture | null; pbr_specularColorSampler?: Texture | null; pbr_specularIntensitySampler?: Texture | null; pbr_transmissionSampler?: Texture | null; pbr_thicknessSampler?: Texture | null; pbr_clearcoatSampler?: Texture | null; pbr_clearcoatRoughnessSampler?: Texture | null; pbr_clearcoatNormalSampler?: Texture | null; pbr_sheenColorSampler?: Texture | null; pbr_sheenRoughnessSampler?: Texture | null; pbr_iridescenceSampler?: Texture | null; pbr_iridescenceThicknessSampler?: Texture | null; pbr_anisotropySampler?: Texture | null; }; export type PBRMaterialUniforms = { unlit?: boolean; baseColorMapEnabled?: boolean; baseColorFactor?: Readonly; normalMapEnabled?: boolean; normalScale?: number; emissiveMapEnabled?: boolean; emissiveFactor?: Readonly; metallicRoughnessValues?: Readonly; metallicRoughnessMapEnabled?: boolean; occlusionMapEnabled?: boolean; occlusionStrength?: number; alphaCutoffEnabled?: boolean; alphaCutoff?: number; IBLenabled?: boolean; scaleIBLAmbient?: Readonly; scaleDiffBaseMR?: Readonly; scaleFGDSpec?: Readonly; specularColorFactor?: Readonly; specularIntensityFactor?: number; specularColorMapEnabled?: boolean; specularIntensityMapEnabled?: boolean; ior?: number; transmissionFactor?: number; transmissionMapEnabled?: boolean; thicknessFactor?: number; attenuationDistance?: number; attenuationColor?: Readonly; clearcoatFactor?: number; clearcoatRoughnessFactor?: number; clearcoatMapEnabled?: boolean; clearcoatRoughnessMapEnabled?: boolean; sheenColorFactor?: Readonly; sheenRoughnessFactor?: number; sheenColorMapEnabled?: boolean; sheenRoughnessMapEnabled?: boolean; iridescenceFactor?: number; iridescenceIor?: number; iridescenceThicknessRange?: Readonly; iridescenceMapEnabled?: boolean; anisotropyStrength?: number; anisotropyRotation?: number; anisotropyDirection?: Readonly; anisotropyMapEnabled?: boolean; emissiveStrength?: number; baseColorUVSet?: number; baseColorUVTransform?: Readonly; metallicRoughnessUVSet?: number; metallicRoughnessUVTransform?: Readonly; normalUVSet?: number; normalUVTransform?: Readonly; occlusionUVSet?: number; occlusionUVTransform?: Readonly; emissiveUVSet?: number; emissiveUVTransform?: Readonly; specularColorUVSet?: number; specularColorUVTransform?: Readonly; specularIntensityUVSet?: number; specularIntensityUVTransform?: Readonly; transmissionUVSet?: number; transmissionUVTransform?: Readonly; thicknessUVSet?: number; thicknessUVTransform?: Readonly; clearcoatUVSet?: number; clearcoatUVTransform?: Readonly; clearcoatRoughnessUVSet?: number; clearcoatRoughnessUVTransform?: Readonly; clearcoatNormalUVSet?: number; clearcoatNormalUVTransform?: Readonly; sheenColorUVSet?: number; sheenColorUVTransform?: Readonly; sheenRoughnessUVSet?: number; sheenRoughnessUVTransform?: Readonly; iridescenceUVSet?: number; iridescenceUVTransform?: Readonly; iridescenceThicknessUVSet?: number; iridescenceThicknessUVTransform?: Readonly; anisotropyUVSet?: number; anisotropyUVTransform?: Readonly; }; export type PBRMaterialProps = PBRMaterialBindings & PBRMaterialUniforms; /** * An implementation of PBR (Physically-Based Rendering). * Physically Based Shading of a microfacet surface defined by a glTF material. */ export declare const pbrMaterial: { readonly props: PBRMaterialProps; readonly uniforms: PBRMaterialUniforms; readonly defaultUniforms: Required; readonly name: "pbrMaterial"; readonly firstBindingSlot: 0; readonly bindingLayout: readonly [{ readonly name: "pbrMaterial"; readonly group: 3; }, { readonly name: "pbr_baseColorSampler"; readonly group: 3; }, { readonly name: "pbr_normalSampler"; readonly group: 3; }, { readonly name: "pbr_emissiveSampler"; readonly group: 3; }, { readonly name: "pbr_metallicRoughnessSampler"; readonly group: 3; }, { readonly name: "pbr_occlusionSampler"; readonly group: 3; }, { readonly name: "pbr_specularColorSampler"; readonly group: 3; }, { readonly name: "pbr_specularIntensitySampler"; readonly group: 3; }, { readonly name: "pbr_transmissionSampler"; readonly group: 3; }, { readonly name: "pbr_thicknessSampler"; readonly group: 3; }, { readonly name: "pbr_clearcoatSampler"; readonly group: 3; }, { readonly name: "pbr_clearcoatRoughnessSampler"; readonly group: 3; }, { readonly name: "pbr_clearcoatNormalSampler"; readonly group: 3; }, { readonly name: "pbr_sheenColorSampler"; readonly group: 3; }, { readonly name: "pbr_sheenRoughnessSampler"; readonly group: 3; }, { readonly name: "pbr_iridescenceSampler"; readonly group: 3; }, { readonly name: "pbr_iridescenceThicknessSampler"; readonly group: 3; }, { readonly name: "pbr_anisotropySampler"; readonly group: 3; }]; readonly dependencies: [{ readonly props: import("../lights/lighting").LightingProps; readonly uniforms: import("../lights/lighting").LightingUniforms; readonly name: "lighting"; readonly defines: {}; readonly uniformTypes: { readonly enabled: "i32"; readonly directionalLightCount: "i32"; readonly pointLightCount: "i32"; readonly spotLightCount: "i32"; readonly ambientColor: "vec3"; readonly lights: readonly [{ readonly color: "vec3"; readonly position: "vec3"; readonly direction: "vec3"; readonly attenuation: "vec3"; readonly coneCos: "vec2"; }, 5]; }; readonly defaultUniforms: import("../lights/lighting").LightingUniforms; readonly bindingLayout: readonly [{ readonly name: "lighting"; readonly group: 2; }]; readonly firstBindingSlot: 0; readonly source: "// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))\nconst MAX_LIGHTS: i32 = 5;\n\nstruct AmbientLight {\n color: vec3,\n};\n\nstruct PointLight {\n color: vec3,\n position: vec3,\n attenuation: vec3, // 2nd order x:Constant-y:Linear-z:Exponential\n};\n\nstruct SpotLight {\n color: vec3,\n position: vec3,\n direction: vec3,\n attenuation: vec3,\n coneCos: vec2,\n};\n\nstruct DirectionalLight {\n color: vec3,\n direction: vec3,\n};\n\nstruct UniformLight {\n color: vec3,\n position: vec3,\n direction: vec3,\n attenuation: vec3,\n coneCos: vec2,\n};\n\nstruct lightingUniforms {\n enabled: i32,\n directionalLightCount: i32,\n pointLightCount: i32,\n spotLightCount: i32,\n ambientColor: vec3,\n lights: array,\n};\n\n@group(2) @binding(auto) var lighting : lightingUniforms;\n\nfn lighting_getPointLight(index: i32) -> PointLight {\n let light = lighting.lights[index];\n return PointLight(light.color, light.position, light.attenuation);\n}\n\nfn lighting_getSpotLight(index: i32) -> SpotLight {\n let light = lighting.lights[lighting.pointLightCount + index];\n return SpotLight(light.color, light.position, light.direction, light.attenuation, light.coneCos);\n}\n\nfn lighting_getDirectionalLight(index: i32) -> DirectionalLight {\n let light = lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];\n return DirectionalLight(light.color, light.direction);\n}\n\nfn getPointLightAttenuation(pointLight: PointLight, distance: f32) -> f32 {\n return pointLight.attenuation.x\n + pointLight.attenuation.y * distance\n + pointLight.attenuation.z * distance * distance;\n}\n\nfn getSpotLightAttenuation(spotLight: SpotLight, positionWorldspace: vec3) -> f32 {\n let lightDirection = normalize(positionWorldspace - spotLight.position);\n let coneFactor = smoothstep(\n spotLight.coneCos.y,\n spotLight.coneCos.x,\n dot(normalize(spotLight.direction), lightDirection)\n );\n let distanceAttenuation = getPointLightAttenuation(\n PointLight(spotLight.color, spotLight.position, spotLight.attenuation),\n distance(spotLight.position, positionWorldspace)\n );\n return distanceAttenuation / max(coneFactor, 0.0001);\n}\n"; readonly vs: "precision highp int;\n\n// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))\nstruct AmbientLight {\n vec3 color;\n};\n\nstruct PointLight {\n vec3 color;\n vec3 position;\n vec3 attenuation; // 2nd order x:Constant-y:Linear-z:Exponential\n};\n\nstruct SpotLight {\n vec3 color;\n vec3 position;\n vec3 direction;\n vec3 attenuation;\n vec2 coneCos;\n};\n\nstruct DirectionalLight {\n vec3 color;\n vec3 direction;\n};\n\nstruct UniformLight {\n vec3 color;\n vec3 position;\n vec3 direction;\n vec3 attenuation;\n vec2 coneCos;\n};\n\nlayout(std140) uniform lightingUniforms {\n int enabled;\n int directionalLightCount;\n int pointLightCount;\n int spotLightCount;\n vec3 ambientColor;\n UniformLight lights[5];\n} lighting;\n\nPointLight lighting_getPointLight(int index) {\n UniformLight light = lighting.lights[index];\n return PointLight(light.color, light.position, light.attenuation);\n}\n\nSpotLight lighting_getSpotLight(int index) {\n UniformLight light = lighting.lights[lighting.pointLightCount + index];\n return SpotLight(light.color, light.position, light.direction, light.attenuation, light.coneCos);\n}\n\nDirectionalLight lighting_getDirectionalLight(int index) {\n UniformLight light =\n lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];\n return DirectionalLight(light.color, light.direction);\n}\n\nfloat getPointLightAttenuation(PointLight pointLight, float distance) {\n return pointLight.attenuation.x\n + pointLight.attenuation.y * distance\n + pointLight.attenuation.z * distance * distance;\n}\n\nfloat getSpotLightAttenuation(SpotLight spotLight, vec3 positionWorldspace) {\n vec3 light_direction = normalize(positionWorldspace - spotLight.position);\n float coneFactor = smoothstep(\n spotLight.coneCos.y,\n spotLight.coneCos.x,\n dot(normalize(spotLight.direction), light_direction)\n );\n float distanceAttenuation = getPointLightAttenuation(\n PointLight(spotLight.color, spotLight.position, spotLight.attenuation),\n distance(spotLight.position, positionWorldspace)\n );\n return distanceAttenuation / max(coneFactor, 0.0001);\n}\n\n// #endif\n"; readonly fs: "precision highp int;\n\n// #if (defined(SHADER_TYPE_FRAGMENT) && defined(LIGHTING_FRAGMENT)) || (defined(SHADER_TYPE_VERTEX) && defined(LIGHTING_VERTEX))\nstruct AmbientLight {\n vec3 color;\n};\n\nstruct PointLight {\n vec3 color;\n vec3 position;\n vec3 attenuation; // 2nd order x:Constant-y:Linear-z:Exponential\n};\n\nstruct SpotLight {\n vec3 color;\n vec3 position;\n vec3 direction;\n vec3 attenuation;\n vec2 coneCos;\n};\n\nstruct DirectionalLight {\n vec3 color;\n vec3 direction;\n};\n\nstruct UniformLight {\n vec3 color;\n vec3 position;\n vec3 direction;\n vec3 attenuation;\n vec2 coneCos;\n};\n\nlayout(std140) uniform lightingUniforms {\n int enabled;\n int directionalLightCount;\n int pointLightCount;\n int spotLightCount;\n vec3 ambientColor;\n UniformLight lights[5];\n} lighting;\n\nPointLight lighting_getPointLight(int index) {\n UniformLight light = lighting.lights[index];\n return PointLight(light.color, light.position, light.attenuation);\n}\n\nSpotLight lighting_getSpotLight(int index) {\n UniformLight light = lighting.lights[lighting.pointLightCount + index];\n return SpotLight(light.color, light.position, light.direction, light.attenuation, light.coneCos);\n}\n\nDirectionalLight lighting_getDirectionalLight(int index) {\n UniformLight light =\n lighting.lights[lighting.pointLightCount + lighting.spotLightCount + index];\n return DirectionalLight(light.color, light.direction);\n}\n\nfloat getPointLightAttenuation(PointLight pointLight, float distance) {\n return pointLight.attenuation.x\n + pointLight.attenuation.y * distance\n + pointLight.attenuation.z * distance * distance;\n}\n\nfloat getSpotLightAttenuation(SpotLight spotLight, vec3 positionWorldspace) {\n vec3 light_direction = normalize(positionWorldspace - spotLight.position);\n float coneFactor = smoothstep(\n spotLight.coneCos.y,\n spotLight.coneCos.x,\n dot(normalize(spotLight.direction), light_direction)\n );\n float distanceAttenuation = getPointLightAttenuation(\n PointLight(spotLight.color, spotLight.position, spotLight.attenuation),\n distance(spotLight.position, positionWorldspace)\n );\n return distanceAttenuation / max(coneFactor, 0.0001);\n}\n\n// #endif\n"; readonly getUniforms: (props?: import("../lights/lighting").LightingProps, _prevUniforms?: Partial) => import("../lights/lighting").LightingUniforms; }, { readonly name: "ibl"; readonly firstBindingSlot: 32; readonly bindingLayout: readonly [{ readonly name: "pbr_diffuseEnvSampler"; readonly group: 2; }, { readonly name: "pbr_specularEnvSampler"; readonly group: 2; }, { readonly name: "pbr_brdfLUT"; readonly group: 2; }]; readonly source: "#ifdef USE_IBL\n@group(2) @binding(auto) var pbr_diffuseEnvSampler: texture_cube;\n@group(2) @binding(auto) var pbr_diffuseEnvSamplerSampler: sampler;\n@group(2) @binding(auto) var pbr_specularEnvSampler: texture_cube;\n@group(2) @binding(auto) var pbr_specularEnvSamplerSampler: sampler;\n@group(2) @binding(auto) var pbr_brdfLUT: texture_2d;\n@group(2) @binding(auto) var pbr_brdfLUTSampler: sampler;\n#endif\n"; readonly vs: "#ifdef USE_IBL\nuniform samplerCube pbr_diffuseEnvSampler;\nuniform samplerCube pbr_specularEnvSampler;\nuniform sampler2D pbr_brdfLUT;\n#endif\n"; readonly fs: "#ifdef USE_IBL\nuniform samplerCube pbr_diffuseEnvSampler;\nuniform samplerCube pbr_specularEnvSampler;\nuniform sampler2D pbr_brdfLUT;\n#endif\n"; }, ShaderModule]; readonly source: "struct PBRFragmentInputs {\n pbr_vPosition: vec3f,\n pbr_vUV0: vec2f,\n pbr_vUV1: vec2f,\n pbr_vTBN: mat3x3f,\n pbr_vNormal: vec3f\n};\n\nvar fragmentInputs: PBRFragmentInputs;\n\nfn pbr_setPositionNormalTangentUV(\n position: vec4f,\n normal: vec4f,\n tangent: vec4f,\n uv0: vec2f,\n uv1: vec2f\n)\n{\n var pos: vec4f = pbrProjection.modelMatrix * position;\n fragmentInputs.pbr_vPosition = pos.xyz / pos.w;\n fragmentInputs.pbr_vNormal = vec3f(0.0, 0.0, 1.0);\n fragmentInputs.pbr_vTBN = mat3x3f(\n vec3f(1.0, 0.0, 0.0),\n vec3f(0.0, 1.0, 0.0),\n vec3f(0.0, 0.0, 1.0)\n );\n fragmentInputs.pbr_vUV0 = vec2f(0.0, 0.0);\n fragmentInputs.pbr_vUV1 = uv1;\n\n#ifdef HAS_NORMALS\n let normalW: vec3f = normalize((pbrProjection.normalMatrix * vec4f(normal.xyz, 0.0)).xyz);\n fragmentInputs.pbr_vNormal = normalW;\n#ifdef HAS_TANGENTS\n let tangentW: vec3f = normalize((pbrProjection.modelMatrix * vec4f(tangent.xyz, 0.0)).xyz);\n let bitangentW: vec3f = cross(normalW, tangentW) * tangent.w;\n fragmentInputs.pbr_vTBN = mat3x3f(tangentW, bitangentW, normalW);\n#endif\n#endif\n\n#ifdef HAS_UV\n fragmentInputs.pbr_vUV0 = uv0;\n#endif\n}\n\nstruct pbrMaterialUniforms {\n // Material is unlit\n unlit: u32,\n\n // Base color map\n baseColorMapEnabled: u32,\n baseColorFactor: vec4f,\n\n normalMapEnabled : u32,\n normalScale: f32, // #ifdef HAS_NORMALMAP\n\n emissiveMapEnabled: u32,\n emissiveFactor: vec3f, // #ifdef HAS_EMISSIVEMAP\n\n metallicRoughnessValues: vec2f,\n metallicRoughnessMapEnabled: u32,\n\n occlusionMapEnabled: i32,\n occlusionStrength: f32, // #ifdef HAS_OCCLUSIONMAP\n \n alphaCutoffEnabled: i32,\n alphaCutoff: f32, // #ifdef ALPHA_CUTOFF\n\n specularColorFactor: vec3f,\n specularIntensityFactor: f32,\n specularColorMapEnabled: i32,\n specularIntensityMapEnabled: i32,\n\n ior: f32,\n\n transmissionFactor: f32,\n transmissionMapEnabled: i32,\n\n thicknessFactor: f32,\n attenuationDistance: f32,\n attenuationColor: vec3f,\n\n clearcoatFactor: f32,\n clearcoatRoughnessFactor: f32,\n clearcoatMapEnabled: i32,\n clearcoatRoughnessMapEnabled: i32,\n\n sheenColorFactor: vec3f,\n sheenRoughnessFactor: f32,\n sheenColorMapEnabled: i32,\n sheenRoughnessMapEnabled: i32,\n\n iridescenceFactor: f32,\n iridescenceIor: f32,\n iridescenceThicknessRange: vec2f,\n iridescenceMapEnabled: i32,\n\n anisotropyStrength: f32,\n anisotropyRotation: f32,\n anisotropyDirection: vec2f,\n anisotropyMapEnabled: i32,\n\n emissiveStrength: f32,\n \n // IBL\n IBLenabled: i32,\n scaleIBLAmbient: vec2f, // #ifdef USE_IBL\n \n // debugging flags used for shader output of intermediate PBR variables\n // #ifdef PBR_DEBUG\n scaleDiffBaseMR: vec4f,\n scaleFGDSpec: vec4f,\n // #endif\n\n baseColorUVSet: i32,\n baseColorUVTransform: mat3x3f,\n metallicRoughnessUVSet: i32,\n metallicRoughnessUVTransform: mat3x3f,\n normalUVSet: i32,\n normalUVTransform: mat3x3f,\n occlusionUVSet: i32,\n occlusionUVTransform: mat3x3f,\n emissiveUVSet: i32,\n emissiveUVTransform: mat3x3f,\n specularColorUVSet: i32,\n specularColorUVTransform: mat3x3f,\n specularIntensityUVSet: i32,\n specularIntensityUVTransform: mat3x3f,\n transmissionUVSet: i32,\n transmissionUVTransform: mat3x3f,\n thicknessUVSet: i32,\n thicknessUVTransform: mat3x3f,\n clearcoatUVSet: i32,\n clearcoatUVTransform: mat3x3f,\n clearcoatRoughnessUVSet: i32,\n clearcoatRoughnessUVTransform: mat3x3f,\n clearcoatNormalUVSet: i32,\n clearcoatNormalUVTransform: mat3x3f,\n sheenColorUVSet: i32,\n sheenColorUVTransform: mat3x3f,\n sheenRoughnessUVSet: i32,\n sheenRoughnessUVTransform: mat3x3f,\n iridescenceUVSet: i32,\n iridescenceUVTransform: mat3x3f,\n iridescenceThicknessUVSet: i32,\n iridescenceThicknessUVTransform: mat3x3f,\n anisotropyUVSet: i32,\n anisotropyUVTransform: mat3x3f,\n}\n\n@group(3) @binding(auto) var pbrMaterial : pbrMaterialUniforms;\n\n// Samplers\n#ifdef HAS_BASECOLORMAP\n@group(3) @binding(auto) var pbr_baseColorSampler: texture_2d;\n@group(3) @binding(auto) var pbr_baseColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_NORMALMAP\n@group(3) @binding(auto) var pbr_normalSampler: texture_2d;\n@group(3) @binding(auto) var pbr_normalSamplerSampler: sampler;\n#endif\n#ifdef HAS_EMISSIVEMAP\n@group(3) @binding(auto) var pbr_emissiveSampler: texture_2d;\n@group(3) @binding(auto) var pbr_emissiveSamplerSampler: sampler;\n#endif\n#ifdef HAS_METALROUGHNESSMAP\n@group(3) @binding(auto) var pbr_metallicRoughnessSampler: texture_2d;\n@group(3) @binding(auto) var pbr_metallicRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_OCCLUSIONMAP\n@group(3) @binding(auto) var pbr_occlusionSampler: texture_2d;\n@group(3) @binding(auto) var pbr_occlusionSamplerSampler: sampler;\n#endif\n#ifdef HAS_SPECULARCOLORMAP\n@group(3) @binding(auto) var pbr_specularColorSampler: texture_2d;\n@group(3) @binding(auto) var pbr_specularColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_SPECULARINTENSITYMAP\n@group(3) @binding(auto) var pbr_specularIntensitySampler: texture_2d;\n@group(3) @binding(auto) var pbr_specularIntensitySamplerSampler: sampler;\n#endif\n#ifdef HAS_TRANSMISSIONMAP\n@group(3) @binding(auto) var pbr_transmissionSampler: texture_2d;\n@group(3) @binding(auto) var pbr_transmissionSamplerSampler: sampler;\n#endif\n#ifdef HAS_THICKNESSMAP\n@group(3) @binding(auto) var pbr_thicknessSampler: texture_2d;\n@group(3) @binding(auto) var pbr_thicknessSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATMAP\n@group(3) @binding(auto) var pbr_clearcoatSampler: texture_2d;\n@group(3) @binding(auto) var pbr_clearcoatSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATROUGHNESSMAP\n@group(3) @binding(auto) var pbr_clearcoatRoughnessSampler: texture_2d;\n@group(3) @binding(auto) var pbr_clearcoatRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_CLEARCOATNORMALMAP\n@group(3) @binding(auto) var pbr_clearcoatNormalSampler: texture_2d;\n@group(3) @binding(auto) var pbr_clearcoatNormalSamplerSampler: sampler;\n#endif\n#ifdef HAS_SHEENCOLORMAP\n@group(3) @binding(auto) var pbr_sheenColorSampler: texture_2d;\n@group(3) @binding(auto) var pbr_sheenColorSamplerSampler: sampler;\n#endif\n#ifdef HAS_SHEENROUGHNESSMAP\n@group(3) @binding(auto) var pbr_sheenRoughnessSampler: texture_2d;\n@group(3) @binding(auto) var pbr_sheenRoughnessSamplerSampler: sampler;\n#endif\n#ifdef HAS_IRIDESCENCEMAP\n@group(3) @binding(auto) var pbr_iridescenceSampler: texture_2d;\n@group(3) @binding(auto) var pbr_iridescenceSamplerSampler: sampler;\n#endif\n#ifdef HAS_IRIDESCENCETHICKNESSMAP\n@group(3) @binding(auto) var pbr_iridescenceThicknessSampler: texture_2d;\n@group(3) @binding(auto) var pbr_iridescenceThicknessSamplerSampler: sampler;\n#endif\n#ifdef HAS_ANISOTROPYMAP\n@group(3) @binding(auto) var pbr_anisotropySampler: texture_2d;\n@group(3) @binding(auto) var pbr_anisotropySamplerSampler: sampler;\n#endif\n// Encapsulate the various inputs used by the various functions in the shading equation\n// We store values in this struct to simplify the integration of alternative implementations\n// of the shading terms, outlined in the Readme.MD Appendix.\nstruct PBRInfo {\n NdotL: f32, // cos angle between normal and light direction\n NdotV: f32, // cos angle between normal and view direction\n NdotH: f32, // cos angle between normal and half vector\n LdotH: f32, // cos angle between light direction and half vector\n VdotH: f32, // cos angle between view direction and half vector\n perceptualRoughness: f32, // roughness value, as authored by the model creator (input to shader)\n metalness: f32, // metallic value at the surface\n reflectance0: vec3f, // full reflectance color (normal incidence angle)\n reflectance90: vec3f, // reflectance color at grazing angle\n alphaRoughness: f32, // roughness mapped to a more linear change in the roughness (proposed by [2])\n diffuseColor: vec3f, // color contribution from diffuse lighting\n specularColor: vec3f, // color contribution from specular lighting\n n: vec3f, // normal at surface point\n v: vec3f, // vector from surface point to camera\n};\n\nconst M_PI = 3.141592653589793;\nconst c_MinRoughness = 0.04;\n\nfn SRGBtoLINEAR(srgbIn: vec4f ) -> vec4f\n{\n var linOut: vec3f = srgbIn.xyz;\n#ifdef MANUAL_SRGB\n let bLess: vec3f = step(vec3f(0.04045), srgbIn.xyz);\n linOut = mix(\n srgbIn.xyz / vec3f(12.92),\n pow((srgbIn.xyz + vec3f(0.055)) / vec3f(1.055), vec3f(2.4)),\n bLess\n );\n#ifdef SRGB_FAST_APPROXIMATION\n linOut = pow(srgbIn.xyz, vec3f(2.2));\n#endif\n#endif\n return vec4f(linOut, srgbIn.w);\n}\n\nfn getMaterialUV(uvSet: i32, uvTransform: mat3x3f) -> vec2f\n{\n var baseUV = fragmentInputs.pbr_vUV0;\n if (uvSet == 1) {\n baseUV = fragmentInputs.pbr_vUV1;\n }\n return (uvTransform * vec3f(baseUV, 1.0)).xy;\n}\n\n// Build the tangent basis from interpolated attributes or screen-space derivatives.\nfn getTBN(uv: vec2f) -> mat3x3f\n{\n let pos_dx: vec3f = dpdx(fragmentInputs.pbr_vPosition);\n let pos_dy: vec3f = dpdy(fragmentInputs.pbr_vPosition);\n let tex_dx: vec3f = dpdx(vec3f(uv, 0.0));\n let tex_dy: vec3f = dpdy(vec3f(uv, 0.0));\n var t: vec3f = (tex_dy.y * pos_dx - tex_dx.y * pos_dy) / (tex_dx.x * tex_dy.y - tex_dy.x * tex_dx.y);\n\n var ng: vec3f = cross(pos_dx, pos_dy);\n#ifdef HAS_NORMALS\n ng = normalize(fragmentInputs.pbr_vNormal);\n#endif\n t = normalize(t - ng * dot(ng, t));\n var b: vec3f = normalize(cross(ng, t));\n var tbn: mat3x3f = mat3x3f(t, b, ng);\n#ifdef HAS_TANGENTS\n tbn = fragmentInputs.pbr_vTBN;\n#endif\n\n return tbn;\n}\n\n// Find the normal for this fragment, pulling either from a predefined normal map\n// or from the interpolated mesh normal and tangent attributes.\nfn getMappedNormal(\n normalSampler: texture_2d,\n normalSamplerBinding: sampler,\n tbn: mat3x3f,\n normalScale: f32,\n uv: vec2f\n) -> vec3f\n{\n let n = textureSample(normalSampler, normalSamplerBinding, uv).rgb;\n return normalize(tbn * ((2.0 * n - 1.0) * vec3f(normalScale, normalScale, 1.0)));\n}\n\nfn getNormal(tbn: mat3x3f, uv: vec2f) -> vec3f\n{\n // The tbn matrix is linearly interpolated, so we need to re-normalize\n var n: vec3f = normalize(tbn[2].xyz);\n#ifdef HAS_NORMALMAP\n n = getMappedNormal(\n pbr_normalSampler,\n pbr_normalSamplerSampler,\n tbn,\n pbrMaterial.normalScale,\n uv\n );\n#endif\n\n return n;\n}\n\nfn getClearcoatNormal(tbn: mat3x3f, baseNormal: vec3f, uv: vec2f) -> vec3f\n{\n#ifdef HAS_CLEARCOATNORMALMAP\n return getMappedNormal(\n pbr_clearcoatNormalSampler,\n pbr_clearcoatNormalSamplerSampler,\n tbn,\n 1.0,\n uv\n );\n#else\n return baseNormal;\n#endif\n}\n\n// Calculation of the lighting contribution from an optional Image Based Light source.\n// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].\n// See our README.md on Environment Maps [3] for additional discussion.\n#ifdef USE_IBL\nfn getIBLContribution(pbrInfo: PBRInfo, n: vec3f, reflection: vec3f) -> vec3f\n{\n let mipCount: f32 = 9.0; // resolution of 512x512\n let lod: f32 = pbrInfo.perceptualRoughness * mipCount;\n // retrieve a scale and bias to F0. See [1], Figure 3\n let brdf = SRGBtoLINEAR(\n textureSampleLevel(\n pbr_brdfLUT,\n pbr_brdfLUTSampler,\n vec2f(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness),\n 0.0\n )\n ).rgb;\n let diffuseLight =\n SRGBtoLINEAR(\n textureSampleLevel(pbr_diffuseEnvSampler, pbr_diffuseEnvSamplerSampler, n, 0.0)\n ).rgb;\n var specularLight = SRGBtoLINEAR(\n textureSampleLevel(\n pbr_specularEnvSampler,\n pbr_specularEnvSamplerSampler,\n reflection,\n 0.0\n )\n ).rgb;\n#ifdef USE_TEX_LOD\n specularLight = SRGBtoLINEAR(\n textureSampleLevel(\n pbr_specularEnvSampler,\n pbr_specularEnvSamplerSampler,\n reflection,\n lod\n )\n ).rgb;\n#endif\n\n let diffuse = diffuseLight * pbrInfo.diffuseColor * pbrMaterial.scaleIBLAmbient.x;\n let specular =\n specularLight * (pbrInfo.specularColor * brdf.x + brdf.y) * pbrMaterial.scaleIBLAmbient.y;\n\n return diffuse + specular;\n}\n#endif\n\n// Basic Lambertian diffuse\n// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog\n// See also [1], Equation 1\nfn diffuse(pbrInfo: PBRInfo) -> vec3 {\n return pbrInfo.diffuseColor / M_PI;\n}\n\n// The following equation models the Fresnel reflectance term of the spec equation (aka F())\n// Implementation of fresnel from [4], Equation 15\nfn specularReflection(pbrInfo: PBRInfo) -> vec3 {\n return pbrInfo.reflectance0 +\n (pbrInfo.reflectance90 - pbrInfo.reflectance0) *\n pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);\n}\n\n// This calculates the specular geometric attenuation (aka G()),\n// where rougher material will reflect less light back to the viewer.\n// This implementation is based on [1] Equation 4, and we adopt their modifications to\n// alphaRoughness as input as originally proposed in [2].\nfn geometricOcclusion(pbrInfo: PBRInfo) -> f32 {\n let NdotL: f32 = pbrInfo.NdotL;\n let NdotV: f32 = pbrInfo.NdotV;\n let r: f32 = pbrInfo.alphaRoughness;\n\n let attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));\n let attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));\n return attenuationL * attenuationV;\n}\n\n// The following equation(s) model the distribution of microfacet normals across\n// the area being drawn (aka D())\n// Implementation from \"Average Irregularity Representation of a Roughened Surface\n// for Ray Reflection\" by T. S. Trowbridge, and K. P. Reitz\n// Follows the distribution function recommended in the SIGGRAPH 2013 course notes\n// from EPIC Games [1], Equation 3.\nfn microfacetDistribution(pbrInfo: PBRInfo) -> f32 {\n let roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;\n let f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;\n return roughnessSq / (M_PI * f * f);\n}\n\nfn maxComponent(value: vec3f) -> f32 {\n return max(max(value.r, value.g), value.b);\n}\n\nfn getDielectricF0(ior: f32) -> f32 {\n let clampedIor = max(ior, 1.0);\n let ratio = (clampedIor - 1.0) / (clampedIor + 1.0);\n return ratio * ratio;\n}\n\nfn normalizeDirection(direction: vec2f) -> vec2f {\n let directionLength = length(direction);\n if (directionLength > 0.0001) {\n return direction / directionLength;\n }\n\n return vec2f(1.0, 0.0);\n}\n\nfn rotateDirection(direction: vec2f, rotation: f32) -> vec2f {\n let s = sin(rotation);\n let c = cos(rotation);\n return vec2f(direction.x * c - direction.y * s, direction.x * s + direction.y * c);\n}\n\nfn getIridescenceTint(iridescence: f32, thickness: f32, NdotV: f32) -> vec3f {\n if (iridescence <= 0.0) {\n return vec3f(1.0);\n }\n\n let phase = 0.015 * thickness * pbrMaterial.iridescenceIor + (1.0 - NdotV) * 6.0;\n let thinFilmTint =\n 0.5 +\n 0.5 *\n cos(vec3f(phase, phase + 2.0943951, phase + 4.1887902));\n return mix(vec3f(1.0), thinFilmTint, iridescence);\n}\n\nfn getVolumeAttenuation(thickness: f32) -> vec3f {\n if (thickness <= 0.0) {\n return vec3f(1.0);\n }\n\n let attenuationCoefficient =\n -log(max(pbrMaterial.attenuationColor, vec3f(0.0001))) /\n max(pbrMaterial.attenuationDistance, 0.0001);\n return exp(-attenuationCoefficient * thickness);\n}\n\nfn createClearcoatPBRInfo(\n basePBRInfo: PBRInfo,\n clearcoatNormal: vec3f,\n clearcoatRoughness: f32\n) -> PBRInfo {\n let perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n let NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);\n\n return PBRInfo(\n basePBRInfo.NdotL,\n NdotV,\n basePBRInfo.NdotH,\n basePBRInfo.LdotH,\n basePBRInfo.VdotH,\n perceptualRoughness,\n 0.0,\n vec3f(0.04),\n vec3f(1.0),\n alphaRoughness,\n vec3f(0.0),\n vec3f(0.04),\n clearcoatNormal,\n basePBRInfo.v\n );\n}\n\nfn calculateClearcoatContribution(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n clearcoatNormal: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32\n) -> vec3f {\n if (clearcoatFactor <= 0.0) {\n return vec3f(0.0);\n }\n\n let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;\n}\n\n#ifdef USE_IBL\nfn calculateClearcoatIBLContribution(\n pbrInfo: PBRInfo,\n clearcoatNormal: vec3f,\n reflection: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32\n) -> vec3f {\n if (clearcoatFactor <= 0.0) {\n return vec3f(0.0);\n }\n\n let clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;\n}\n#endif\n\nfn calculateSheenContribution(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n sheenColor: vec3f,\n sheenRoughness: f32\n) -> vec3f {\n if (maxComponent(sheenColor) <= 0.0) {\n return vec3f(0.0);\n }\n\n let sheenFresnel = pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);\n let sheenVisibility = mix(1.0, pbrInfo.NdotL * pbrInfo.NdotV, sheenRoughness);\n return pbrInfo.NdotL *\n lightColor *\n sheenColor *\n (0.25 + 0.75 * sheenFresnel) *\n sheenVisibility *\n (1.0 - pbrInfo.metalness);\n}\n\nfn calculateAnisotropyBoost(\n pbrInfo: PBRInfo,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> f32 {\n if (anisotropyStrength <= 0.0) {\n return 1.0;\n }\n\n let anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));\n let bitangentViewAlignment = abs(dot(pbrInfo.v, anisotropyBitangent));\n return mix(1.0, 0.65 + 0.7 * bitangentViewAlignment, anisotropyStrength);\n}\n\nfn calculateMaterialLightColor(\n pbrInfo: PBRInfo,\n lightColor: vec3f,\n clearcoatNormal: vec3f,\n clearcoatFactor: f32,\n clearcoatRoughness: f32,\n sheenColor: vec3f,\n sheenRoughness: f32,\n anisotropyTangent: vec3f,\n anisotropyStrength: f32\n) -> vec3f {\n let anisotropyBoost = calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);\n var color = calculateFinalColor(pbrInfo, lightColor) * anisotropyBoost;\n color += calculateClearcoatContribution(\n pbrInfo,\n lightColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness\n );\n color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);\n return color;\n}\n\nfn PBRInfo_setAmbientLight(pbrInfo: ptr) {\n (*pbrInfo).NdotL = 1.0;\n (*pbrInfo).NdotH = 0.0;\n (*pbrInfo).LdotH = 0.0;\n (*pbrInfo).VdotH = 1.0;\n}\n\nfn PBRInfo_setDirectionalLight(pbrInfo: ptr, lightDirection: vec3) {\n let n = (*pbrInfo).n;\n let v = (*pbrInfo).v;\n let l = normalize(lightDirection); // Vector from surface point to light\n let h = normalize(l + v); // Half vector between both l and v\n\n (*pbrInfo).NdotL = clamp(dot(n, l), 0.001, 1.0);\n (*pbrInfo).NdotH = clamp(dot(n, h), 0.0, 1.0);\n (*pbrInfo).LdotH = clamp(dot(l, h), 0.0, 1.0);\n (*pbrInfo).VdotH = clamp(dot(v, h), 0.0, 1.0);\n}\n\nfn PBRInfo_setPointLight(pbrInfo: ptr, pointLight: PointLight) {\n let light_direction = normalize(pointLight.position - fragmentInputs.pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nfn PBRInfo_setSpotLight(pbrInfo: ptr, spotLight: SpotLight) {\n let light_direction = normalize(spotLight.position - fragmentInputs.pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nfn calculateFinalColor(pbrInfo: PBRInfo, lightColor: vec3) -> vec3 {\n // Calculate the shading terms for the microfacet specular shading model\n let F = specularReflection(pbrInfo);\n let G = geometricOcclusion(pbrInfo);\n let D = microfacetDistribution(pbrInfo);\n\n // Calculation of analytical lighting contribution\n let diffuseContrib = (1.0 - F) * diffuse(pbrInfo);\n let specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);\n // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)\n return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);\n}\n\nfn pbr_filterColor(colorUnused: vec4) -> vec4 {\n let baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);\n let metallicRoughnessUV = getMaterialUV(\n pbrMaterial.metallicRoughnessUVSet,\n pbrMaterial.metallicRoughnessUVTransform\n );\n let normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);\n let occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);\n let emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);\n let specularColorUV = getMaterialUV(\n pbrMaterial.specularColorUVSet,\n pbrMaterial.specularColorUVTransform\n );\n let specularIntensityUV = getMaterialUV(\n pbrMaterial.specularIntensityUVSet,\n pbrMaterial.specularIntensityUVTransform\n );\n let transmissionUV = getMaterialUV(\n pbrMaterial.transmissionUVSet,\n pbrMaterial.transmissionUVTransform\n );\n let thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);\n let clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);\n let clearcoatRoughnessUV = getMaterialUV(\n pbrMaterial.clearcoatRoughnessUVSet,\n pbrMaterial.clearcoatRoughnessUVTransform\n );\n let clearcoatNormalUV = getMaterialUV(\n pbrMaterial.clearcoatNormalUVSet,\n pbrMaterial.clearcoatNormalUVTransform\n );\n let sheenColorUV = getMaterialUV(\n pbrMaterial.sheenColorUVSet,\n pbrMaterial.sheenColorUVTransform\n );\n let sheenRoughnessUV = getMaterialUV(\n pbrMaterial.sheenRoughnessUVSet,\n pbrMaterial.sheenRoughnessUVTransform\n );\n let iridescenceUV = getMaterialUV(\n pbrMaterial.iridescenceUVSet,\n pbrMaterial.iridescenceUVTransform\n );\n let iridescenceThicknessUV = getMaterialUV(\n pbrMaterial.iridescenceThicknessUVSet,\n pbrMaterial.iridescenceThicknessUVTransform\n );\n let anisotropyUV = getMaterialUV(\n pbrMaterial.anisotropyUVSet,\n pbrMaterial.anisotropyUVTransform\n );\n\n // The albedo may be defined from a base texture or a flat color\n var baseColor: vec4 = pbrMaterial.baseColorFactor;\n #ifdef HAS_BASECOLORMAP\n baseColor = SRGBtoLINEAR(\n textureSample(pbr_baseColorSampler, pbr_baseColorSamplerSampler, baseColorUV)\n ) * pbrMaterial.baseColorFactor;\n #endif\n\n #ifdef ALPHA_CUTOFF\n if (baseColor.a < pbrMaterial.alphaCutoff) {\n discard;\n }\n #endif\n\n var color = vec3(0.0, 0.0, 0.0);\n var transmission = 0.0;\n\n if (pbrMaterial.unlit != 0u) {\n color = baseColor.rgb;\n } else {\n // Metallic and Roughness material properties are packed together\n // In glTF, these factors can be specified by fixed scalar values\n // or from a metallic-roughness map\n var perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;\n var metallic = pbrMaterial.metallicRoughnessValues.x;\n #ifdef HAS_METALROUGHNESSMAP\n // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.\n // This layout intentionally reserves the 'r' channel for (optional) occlusion map data\n let mrSample = textureSample(\n pbr_metallicRoughnessSampler,\n pbr_metallicRoughnessSamplerSampler,\n metallicRoughnessUV\n );\n perceptualRoughness = mrSample.g * perceptualRoughness;\n metallic = mrSample.b * metallic;\n #endif\n perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);\n metallic = clamp(metallic, 0.0, 1.0);\n let tbn = getTBN(normalUV);\n let n = getNormal(tbn, normalUV); // normal at surface point\n let v = normalize(pbrProjection.camera - fragmentInputs.pbr_vPosition); // Vector from surface point to camera\n let NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);\n var useExtendedPBR = false;\n #ifdef USE_MATERIAL_EXTENSIONS\n useExtendedPBR =\n pbrMaterial.specularColorMapEnabled != 0 ||\n pbrMaterial.specularIntensityMapEnabled != 0 ||\n abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||\n maxComponent(abs(pbrMaterial.specularColorFactor - vec3f(1.0))) > 0.0001 ||\n abs(pbrMaterial.ior - 1.5) > 0.0001 ||\n pbrMaterial.transmissionMapEnabled != 0 ||\n pbrMaterial.transmissionFactor > 0.0001 ||\n pbrMaterial.clearcoatMapEnabled != 0 ||\n pbrMaterial.clearcoatRoughnessMapEnabled != 0 ||\n pbrMaterial.clearcoatFactor > 0.0001 ||\n pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||\n pbrMaterial.sheenColorMapEnabled != 0 ||\n pbrMaterial.sheenRoughnessMapEnabled != 0 ||\n maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||\n pbrMaterial.sheenRoughnessFactor > 0.0001 ||\n pbrMaterial.iridescenceMapEnabled != 0 ||\n pbrMaterial.iridescenceFactor > 0.0001 ||\n abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||\n pbrMaterial.anisotropyMapEnabled != 0 ||\n pbrMaterial.anisotropyStrength > 0.0001 ||\n abs(pbrMaterial.anisotropyRotation) > 0.0001 ||\n length(pbrMaterial.anisotropyDirection - vec2f(1.0, 0.0)) > 0.0001;\n #endif\n\n if (!useExtendedPBR) {\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n let f0 = vec3(0.04);\n var diffuseColor = baseColor.rgb * (vec3(1.0) - f0);\n diffuseColor *= 1.0 - metallic;\n let specularColor = mix(f0, baseColor.rgb, metallic);\n\n let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n let specularEnvironmentR0 = specularColor;\n let specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;\n let reflection = -normalize(reflect(v, n));\n\n var pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v\n );\n\n #ifdef USE_LIGHTS\n PBRInfo_setAmbientLight(&pbrInfo);\n color += calculateFinalColor(pbrInfo, lighting.ambientColor);\n\n for (var i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);\n color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);\n }\n }\n\n for (var i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));\n let attenuation = getPointLightAttenuation(\n lighting_getPointLight(i),\n distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)\n );\n color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);\n }\n }\n\n for (var i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));\n let attenuation = getSpotLightAttenuation(\n lighting_getSpotLight(i),\n fragmentInputs.pbr_vPosition\n );\n color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color / attenuation);\n }\n }\n #endif\n\n #ifdef USE_IBL\n if (pbrMaterial.IBLenabled != 0) {\n color += getIBLContribution(pbrInfo, n, reflection);\n }\n #endif\n\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n\n var emissive = pbrMaterial.emissiveFactor;\n #ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled != 0u) {\n emissive *= SRGBtoLINEAR(\n textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)\n ).rgb;\n }\n #endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n #ifdef PBR_DEBUG\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n #endif\n\n return vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a);\n }\n\n var specularIntensity = pbrMaterial.specularIntensityFactor;\n #ifdef HAS_SPECULARINTENSITYMAP\n if (pbrMaterial.specularIntensityMapEnabled != 0) {\n specularIntensity *= textureSample(\n pbr_specularIntensitySampler,\n pbr_specularIntensitySamplerSampler,\n specularIntensityUV\n ).a;\n }\n #endif\n\n var specularFactor = pbrMaterial.specularColorFactor;\n #ifdef HAS_SPECULARCOLORMAP\n if (pbrMaterial.specularColorMapEnabled != 0) {\n specularFactor *= SRGBtoLINEAR(\n textureSample(\n pbr_specularColorSampler,\n pbr_specularColorSamplerSampler,\n specularColorUV\n )\n ).rgb;\n }\n #endif\n\n transmission = pbrMaterial.transmissionFactor;\n #ifdef HAS_TRANSMISSIONMAP\n if (pbrMaterial.transmissionMapEnabled != 0) {\n transmission *= textureSample(\n pbr_transmissionSampler,\n pbr_transmissionSamplerSampler,\n transmissionUV\n ).r;\n }\n #endif\n transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);\n var thickness = max(pbrMaterial.thicknessFactor, 0.0);\n #ifdef HAS_THICKNESSMAP\n thickness *= textureSample(\n pbr_thicknessSampler,\n pbr_thicknessSamplerSampler,\n thicknessUV\n ).g;\n #endif\n\n var clearcoatFactor = pbrMaterial.clearcoatFactor;\n var clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;\n #ifdef HAS_CLEARCOATMAP\n if (pbrMaterial.clearcoatMapEnabled != 0) {\n clearcoatFactor *= textureSample(\n pbr_clearcoatSampler,\n pbr_clearcoatSamplerSampler,\n clearcoatUV\n ).r;\n }\n #endif\n #ifdef HAS_CLEARCOATROUGHNESSMAP\n if (pbrMaterial.clearcoatRoughnessMapEnabled != 0) {\n clearcoatRoughness *= textureSample(\n pbr_clearcoatRoughnessSampler,\n pbr_clearcoatRoughnessSamplerSampler,\n clearcoatRoughnessUV\n ).g;\n }\n #endif\n clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);\n clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n let clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);\n\n var sheenColor = pbrMaterial.sheenColorFactor;\n var sheenRoughness = pbrMaterial.sheenRoughnessFactor;\n #ifdef HAS_SHEENCOLORMAP\n if (pbrMaterial.sheenColorMapEnabled != 0) {\n sheenColor *= SRGBtoLINEAR(\n textureSample(\n pbr_sheenColorSampler,\n pbr_sheenColorSamplerSampler,\n sheenColorUV\n )\n ).rgb;\n }\n #endif\n #ifdef HAS_SHEENROUGHNESSMAP\n if (pbrMaterial.sheenRoughnessMapEnabled != 0) {\n sheenRoughness *= textureSample(\n pbr_sheenRoughnessSampler,\n pbr_sheenRoughnessSamplerSampler,\n sheenRoughnessUV\n ).a;\n }\n #endif\n sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);\n\n var iridescence = pbrMaterial.iridescenceFactor;\n #ifdef HAS_IRIDESCENCEMAP\n if (pbrMaterial.iridescenceMapEnabled != 0) {\n iridescence *= textureSample(\n pbr_iridescenceSampler,\n pbr_iridescenceSamplerSampler,\n iridescenceUV\n ).r;\n }\n #endif\n iridescence = clamp(iridescence, 0.0, 1.0);\n var iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n 0.5\n );\n #ifdef HAS_IRIDESCENCETHICKNESSMAP\n iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n textureSample(\n pbr_iridescenceThicknessSampler,\n pbr_iridescenceThicknessSamplerSampler,\n iridescenceThicknessUV\n ).g\n );\n #endif\n\n var anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);\n var anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);\n #ifdef HAS_ANISOTROPYMAP\n if (pbrMaterial.anisotropyMapEnabled != 0) {\n let anisotropySample = textureSample(\n pbr_anisotropySampler,\n pbr_anisotropySamplerSampler,\n anisotropyUV\n ).rgb;\n anisotropyStrength *= anisotropySample.b;\n let mappedDirection = anisotropySample.rg * 2.0 - 1.0;\n if (length(mappedDirection) > 0.0001) {\n anisotropyDirection = normalize(mappedDirection);\n }\n }\n #endif\n anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);\n var anisotropyTangent =\n normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);\n if (length(anisotropyTangent) < 0.0001) {\n anisotropyTangent = normalize(tbn[0]);\n }\n let anisotropyViewAlignment = abs(dot(v, anisotropyTangent));\n perceptualRoughness = mix(\n perceptualRoughness,\n clamp(perceptualRoughness * (1.0 - 0.6 * anisotropyViewAlignment), c_MinRoughness, 1.0),\n anisotropyStrength\n );\n\n // Roughness is authored as perceptual roughness; as is convention,\n // convert to material roughness by squaring the perceptual roughness [2].\n let alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n let dielectricF0 = getDielectricF0(pbrMaterial.ior);\n var dielectricSpecularF0 = min(\n vec3f(dielectricF0) * specularFactor * specularIntensity,\n vec3f(1.0)\n );\n let iridescenceTint = getIridescenceTint(iridescence, iridescenceThickness, NdotV);\n dielectricSpecularF0 = mix(\n dielectricSpecularF0,\n dielectricSpecularF0 * iridescenceTint,\n iridescence\n );\n var diffuseColor = baseColor.rgb * (vec3f(1.0) - dielectricSpecularF0);\n diffuseColor *= (1.0 - metallic) * (1.0 - transmission);\n var specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);\n\n let baseLayerEnergy = 1.0 - clearcoatFactor * 0.25;\n diffuseColor *= baseLayerEnergy;\n specularColor *= baseLayerEnergy;\n\n // Compute reflectance.\n let reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n\n // For typical incident reflectance range (between 4% to 100%) set the grazing\n // reflectance to 100% for typical fresnel effect.\n // For very low reflectance range on highly diffuse objects (below 4%),\n // incrementally reduce grazing reflectance to 0%.\n let reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n let specularEnvironmentR0 = specularColor;\n let specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;\n let reflection = -normalize(reflect(v, n));\n\n var pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v\n );\n\n #ifdef USE_LIGHTS\n // Apply ambient light\n PBRInfo_setAmbientLight(&pbrInfo);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting.ambientColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n\n // Apply directional light\n for (var i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(&pbrInfo, lighting_getDirectionalLight(i).direction);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getDirectionalLight(i).color,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n }\n }\n\n // Apply point light\n for (var i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(&pbrInfo, lighting_getPointLight(i));\n let attenuation = getPointLightAttenuation(\n lighting_getPointLight(i),\n distance(lighting_getPointLight(i).position, fragmentInputs.pbr_vPosition)\n );\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getPointLight(i).color / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n }\n }\n\n for (var i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(&pbrInfo, lighting_getSpotLight(i));\n let attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), fragmentInputs.pbr_vPosition);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getSpotLight(i).color / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n }\n }\n #endif\n\n // Calculate lighting contribution from image based lighting source (IBL)\n #ifdef USE_IBL\n if (pbrMaterial.IBLenabled != 0) {\n color += getIBLContribution(pbrInfo, n, reflection) *\n calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);\n color += calculateClearcoatIBLContribution(\n pbrInfo,\n clearcoatNormal,\n -normalize(reflect(v, clearcoatNormal)),\n clearcoatFactor,\n clearcoatRoughness\n );\n color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;\n }\n #endif\n\n // Apply optional PBR terms for additional (optional) shading\n #ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled != 0) {\n let ao = textureSample(pbr_occlusionSampler, pbr_occlusionSamplerSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n #endif\n\n var emissive = pbrMaterial.emissiveFactor;\n #ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled != 0u) {\n emissive *= SRGBtoLINEAR(\n textureSample(pbr_emissiveSampler, pbr_emissiveSamplerSampler, emissiveUV)\n ).rgb;\n }\n #endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n if (transmission > 0.0) {\n color = mix(color, color * getVolumeAttenuation(thickness), transmission);\n }\n\n // This section uses mix to override final color for reference app visualization\n // of various parameters in the lighting equation.\n #ifdef PBR_DEBUG\n // TODO: Figure out how to debug multiple lights\n\n // color = mix(color, F, pbr_scaleFGDSpec.x);\n // color = mix(color, vec3(G), pbr_scaleFGDSpec.y);\n // color = mix(color, vec3(D), pbr_scaleFGDSpec.z);\n // color = mix(color, specContrib, pbr_scaleFGDSpec.w);\n\n // color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n #endif\n }\n\n let alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);\n return vec4(pow(color, vec3(1.0 / 2.2)), alpha);\n}\n"; readonly vs: "out vec3 pbr_vPosition;\nout vec2 pbr_vUV0;\nout vec2 pbr_vUV1;\n\n#ifdef HAS_NORMALS\n# ifdef HAS_TANGENTS\nout mat3 pbr_vTBN;\n# else\nout vec3 pbr_vNormal;\n# endif\n#endif\n\nvoid pbr_setPositionNormalTangentUV(\n vec4 position,\n vec4 normal,\n vec4 tangent,\n vec2 uv0,\n vec2 uv1\n)\n{\n vec4 pos = pbrProjection.modelMatrix * position;\n pbr_vPosition = vec3(pos.xyz) / pos.w;\n\n#ifdef HAS_NORMALS\n#ifdef HAS_TANGENTS\n vec3 normalW = normalize(vec3(pbrProjection.normalMatrix * vec4(normal.xyz, 0.0)));\n vec3 tangentW = normalize(vec3(pbrProjection.modelMatrix * vec4(tangent.xyz, 0.0)));\n vec3 bitangentW = cross(normalW, tangentW) * tangent.w;\n pbr_vTBN = mat3(tangentW, bitangentW, normalW);\n#else // HAS_TANGENTS != 1\n pbr_vNormal = normalize(vec3(pbrProjection.modelMatrix * vec4(normal.xyz, 0.0)));\n#endif\n#endif\n\n#ifdef HAS_UV\n pbr_vUV0 = uv0;\n#else\n pbr_vUV0 = vec2(0.,0.);\n#endif\n\n pbr_vUV1 = uv1;\n}\n"; readonly fs: "precision highp float;\n\nlayout(std140) uniform pbrMaterialUniforms {\n // Material is unlit\n bool unlit;\n\n // Base color map\n bool baseColorMapEnabled;\n vec4 baseColorFactor;\n\n bool normalMapEnabled; \n float normalScale; // #ifdef HAS_NORMALMAP\n\n bool emissiveMapEnabled;\n vec3 emissiveFactor; // #ifdef HAS_EMISSIVEMAP\n\n vec2 metallicRoughnessValues;\n bool metallicRoughnessMapEnabled;\n\n bool occlusionMapEnabled;\n float occlusionStrength; // #ifdef HAS_OCCLUSIONMAP\n \n bool alphaCutoffEnabled;\n float alphaCutoff; // #ifdef ALPHA_CUTOFF\n\n vec3 specularColorFactor;\n float specularIntensityFactor;\n bool specularColorMapEnabled;\n bool specularIntensityMapEnabled;\n\n float ior;\n\n float transmissionFactor;\n bool transmissionMapEnabled;\n\n float thicknessFactor;\n float attenuationDistance;\n vec3 attenuationColor;\n\n float clearcoatFactor;\n float clearcoatRoughnessFactor;\n bool clearcoatMapEnabled;\n bool clearcoatRoughnessMapEnabled;\n\n vec3 sheenColorFactor;\n float sheenRoughnessFactor;\n bool sheenColorMapEnabled;\n bool sheenRoughnessMapEnabled;\n\n float iridescenceFactor;\n float iridescenceIor;\n vec2 iridescenceThicknessRange;\n bool iridescenceMapEnabled;\n\n float anisotropyStrength;\n float anisotropyRotation;\n vec2 anisotropyDirection;\n bool anisotropyMapEnabled;\n\n float emissiveStrength;\n \n // IBL\n bool IBLenabled;\n vec2 scaleIBLAmbient; // #ifdef USE_IBL\n \n // debugging flags used for shader output of intermediate PBR variables\n // #ifdef PBR_DEBUG\n vec4 scaleDiffBaseMR;\n vec4 scaleFGDSpec;\n // #endif\n\n int baseColorUVSet;\n mat3 baseColorUVTransform;\n int metallicRoughnessUVSet;\n mat3 metallicRoughnessUVTransform;\n int normalUVSet;\n mat3 normalUVTransform;\n int occlusionUVSet;\n mat3 occlusionUVTransform;\n int emissiveUVSet;\n mat3 emissiveUVTransform;\n int specularColorUVSet;\n mat3 specularColorUVTransform;\n int specularIntensityUVSet;\n mat3 specularIntensityUVTransform;\n int transmissionUVSet;\n mat3 transmissionUVTransform;\n int thicknessUVSet;\n mat3 thicknessUVTransform;\n int clearcoatUVSet;\n mat3 clearcoatUVTransform;\n int clearcoatRoughnessUVSet;\n mat3 clearcoatRoughnessUVTransform;\n int clearcoatNormalUVSet;\n mat3 clearcoatNormalUVTransform;\n int sheenColorUVSet;\n mat3 sheenColorUVTransform;\n int sheenRoughnessUVSet;\n mat3 sheenRoughnessUVTransform;\n int iridescenceUVSet;\n mat3 iridescenceUVTransform;\n int iridescenceThicknessUVSet;\n mat3 iridescenceThicknessUVTransform;\n int anisotropyUVSet;\n mat3 anisotropyUVTransform;\n} pbrMaterial;\n\n// Samplers\n#ifdef HAS_BASECOLORMAP\nuniform sampler2D pbr_baseColorSampler;\n#endif\n#ifdef HAS_NORMALMAP\nuniform sampler2D pbr_normalSampler;\n#endif\n#ifdef HAS_EMISSIVEMAP\nuniform sampler2D pbr_emissiveSampler;\n#endif\n#ifdef HAS_METALROUGHNESSMAP\nuniform sampler2D pbr_metallicRoughnessSampler;\n#endif\n#ifdef HAS_OCCLUSIONMAP\nuniform sampler2D pbr_occlusionSampler;\n#endif\n#ifdef HAS_SPECULARCOLORMAP\nuniform sampler2D pbr_specularColorSampler;\n#endif\n#ifdef HAS_SPECULARINTENSITYMAP\nuniform sampler2D pbr_specularIntensitySampler;\n#endif\n#ifdef HAS_TRANSMISSIONMAP\nuniform sampler2D pbr_transmissionSampler;\n#endif\n#ifdef HAS_THICKNESSMAP\nuniform sampler2D pbr_thicknessSampler;\n#endif\n#ifdef HAS_CLEARCOATMAP\nuniform sampler2D pbr_clearcoatSampler;\n#endif\n#ifdef HAS_CLEARCOATROUGHNESSMAP\nuniform sampler2D pbr_clearcoatRoughnessSampler;\n#endif\n#ifdef HAS_CLEARCOATNORMALMAP\nuniform sampler2D pbr_clearcoatNormalSampler;\n#endif\n#ifdef HAS_SHEENCOLORMAP\nuniform sampler2D pbr_sheenColorSampler;\n#endif\n#ifdef HAS_SHEENROUGHNESSMAP\nuniform sampler2D pbr_sheenRoughnessSampler;\n#endif\n#ifdef HAS_IRIDESCENCEMAP\nuniform sampler2D pbr_iridescenceSampler;\n#endif\n#ifdef HAS_IRIDESCENCETHICKNESSMAP\nuniform sampler2D pbr_iridescenceThicknessSampler;\n#endif\n#ifdef HAS_ANISOTROPYMAP\nuniform sampler2D pbr_anisotropySampler;\n#endif\n// Inputs from vertex shader\n\nin vec3 pbr_vPosition;\nin vec2 pbr_vUV0;\nin vec2 pbr_vUV1;\n\n#ifdef HAS_NORMALS\n#ifdef HAS_TANGENTS\nin mat3 pbr_vTBN;\n#else\nin vec3 pbr_vNormal;\n#endif\n#endif\n\n// Encapsulate the various inputs used by the various functions in the shading equation\n// We store values in this struct to simplify the integration of alternative implementations\n// of the shading terms, outlined in the Readme.MD Appendix.\nstruct PBRInfo {\n float NdotL; // cos angle between normal and light direction\n float NdotV; // cos angle between normal and view direction\n float NdotH; // cos angle between normal and half vector\n float LdotH; // cos angle between light direction and half vector\n float VdotH; // cos angle between view direction and half vector\n float perceptualRoughness; // roughness value, as authored by the model creator (input to shader)\n float metalness; // metallic value at the surface\n vec3 reflectance0; // full reflectance color (normal incidence angle)\n vec3 reflectance90; // reflectance color at grazing angle\n float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2])\n vec3 diffuseColor; // color contribution from diffuse lighting\n vec3 specularColor; // color contribution from specular lighting\n vec3 n; // normal at surface point\n vec3 v; // vector from surface point to camera\n};\n\nconst float M_PI = 3.141592653589793;\nconst float c_MinRoughness = 0.04;\n\nvec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor);\n\nvec4 SRGBtoLINEAR(vec4 srgbIn)\n{\n#ifdef MANUAL_SRGB\n#ifdef SRGB_FAST_APPROXIMATION\n vec3 linOut = pow(srgbIn.xyz,vec3(2.2));\n#else // SRGB_FAST_APPROXIMATION\n vec3 bLess = step(vec3(0.04045),srgbIn.xyz);\n vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );\n#endif //SRGB_FAST_APPROXIMATION\n return vec4(linOut,srgbIn.w);;\n#else //MANUAL_SRGB\n return srgbIn;\n#endif //MANUAL_SRGB\n}\n\nvec2 getMaterialUV(int uvSet, mat3 uvTransform)\n{\n vec2 baseUV = uvSet == 1 ? pbr_vUV1 : pbr_vUV0;\n return (uvTransform * vec3(baseUV, 1.0)).xy;\n}\n\n// Build the tangent basis from interpolated attributes or screen-space derivatives.\nmat3 getTBN(vec2 uv)\n{\n#ifndef HAS_TANGENTS\n vec3 pos_dx = dFdx(pbr_vPosition);\n vec3 pos_dy = dFdy(pbr_vPosition);\n vec3 tex_dx = dFdx(vec3(uv, 0.0));\n vec3 tex_dy = dFdy(vec3(uv, 0.0));\n vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);\n\n#ifdef HAS_NORMALS\n vec3 ng = normalize(pbr_vNormal);\n#else\n vec3 ng = cross(pos_dx, pos_dy);\n#endif\n\n t = normalize(t - ng * dot(ng, t));\n vec3 b = normalize(cross(ng, t));\n mat3 tbn = mat3(t, b, ng);\n#else // HAS_TANGENTS\n mat3 tbn = pbr_vTBN;\n#endif\n\n return tbn;\n}\n\n// Find the normal for this fragment, pulling either from a predefined normal map\n// or from the interpolated mesh normal and tangent attributes.\nvec3 getMappedNormal(sampler2D normalSampler, mat3 tbn, float normalScale, vec2 uv)\n{\n vec3 n = texture(normalSampler, uv).rgb;\n return normalize(tbn * ((2.0 * n - 1.0) * vec3(normalScale, normalScale, 1.0)));\n}\n\nvec3 getNormal(mat3 tbn, vec2 uv)\n{\n#ifdef HAS_NORMALMAP\n vec3 n = getMappedNormal(pbr_normalSampler, tbn, pbrMaterial.normalScale, uv);\n#else\n // The tbn matrix is linearly interpolated, so we need to re-normalize\n vec3 n = normalize(tbn[2].xyz);\n#endif\n\n return n;\n}\n\nvec3 getClearcoatNormal(mat3 tbn, vec3 baseNormal, vec2 uv)\n{\n#ifdef HAS_CLEARCOATNORMALMAP\n return getMappedNormal(pbr_clearcoatNormalSampler, tbn, 1.0, uv);\n#else\n return baseNormal;\n#endif\n}\n\n// Calculation of the lighting contribution from an optional Image Based Light source.\n// Precomputed Environment Maps are required uniform inputs and are computed as outlined in [1].\n// See our README.md on Environment Maps [3] for additional discussion.\n#ifdef USE_IBL\nvec3 getIBLContribution(PBRInfo pbrInfo, vec3 n, vec3 reflection)\n{\n float mipCount = 9.0; // resolution of 512x512\n float lod = (pbrInfo.perceptualRoughness * mipCount);\n // retrieve a scale and bias to F0. See [1], Figure 3\n vec3 brdf = SRGBtoLINEAR(texture(pbr_brdfLUT,\n vec2(pbrInfo.NdotV, 1.0 - pbrInfo.perceptualRoughness))).rgb;\n vec3 diffuseLight = SRGBtoLINEAR(texture(pbr_diffuseEnvSampler, n)).rgb;\n\n#ifdef USE_TEX_LOD\n vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection, lod)).rgb;\n#else\n vec3 specularLight = SRGBtoLINEAR(texture(pbr_specularEnvSampler, reflection)).rgb;\n#endif\n\n vec3 diffuse = diffuseLight * pbrInfo.diffuseColor;\n vec3 specular = specularLight * (pbrInfo.specularColor * brdf.x + brdf.y);\n\n // For presentation, this allows us to disable IBL terms\n diffuse *= pbrMaterial.scaleIBLAmbient.x;\n specular *= pbrMaterial.scaleIBLAmbient.y;\n\n return diffuse + specular;\n}\n#endif\n\n// Basic Lambertian diffuse\n// Implementation from Lambert's Photometria https://archive.org/details/lambertsphotome00lambgoog\n// See also [1], Equation 1\nvec3 diffuse(PBRInfo pbrInfo)\n{\n return pbrInfo.diffuseColor / M_PI;\n}\n\n// The following equation models the Fresnel reflectance term of the spec equation (aka F())\n// Implementation of fresnel from [4], Equation 15\nvec3 specularReflection(PBRInfo pbrInfo)\n{\n return pbrInfo.reflectance0 +\n (pbrInfo.reflectance90 - pbrInfo.reflectance0) *\n pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);\n}\n\n// This calculates the specular geometric attenuation (aka G()),\n// where rougher material will reflect less light back to the viewer.\n// This implementation is based on [1] Equation 4, and we adopt their modifications to\n// alphaRoughness as input as originally proposed in [2].\nfloat geometricOcclusion(PBRInfo pbrInfo)\n{\n float NdotL = pbrInfo.NdotL;\n float NdotV = pbrInfo.NdotV;\n float r = pbrInfo.alphaRoughness;\n\n float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));\n float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));\n return attenuationL * attenuationV;\n}\n\n// The following equation(s) model the distribution of microfacet normals across\n// the area being drawn (aka D())\n// Implementation from \"Average Irregularity Representation of a Roughened Surface\n// for Ray Reflection\" by T. S. Trowbridge, and K. P. Reitz\n// Follows the distribution function recommended in the SIGGRAPH 2013 course notes\n// from EPIC Games [1], Equation 3.\nfloat microfacetDistribution(PBRInfo pbrInfo)\n{\n float roughnessSq = pbrInfo.alphaRoughness * pbrInfo.alphaRoughness;\n float f = (pbrInfo.NdotH * roughnessSq - pbrInfo.NdotH) * pbrInfo.NdotH + 1.0;\n return roughnessSq / (M_PI * f * f);\n}\n\nfloat maxComponent(vec3 value)\n{\n return max(max(value.r, value.g), value.b);\n}\n\nfloat getDielectricF0(float ior)\n{\n float clampedIor = max(ior, 1.0);\n float ratio = (clampedIor - 1.0) / (clampedIor + 1.0);\n return ratio * ratio;\n}\n\nvec2 normalizeDirection(vec2 direction)\n{\n float directionLength = length(direction);\n return directionLength > 0.0001 ? direction / directionLength : vec2(1.0, 0.0);\n}\n\nvec2 rotateDirection(vec2 direction, float rotation)\n{\n float s = sin(rotation);\n float c = cos(rotation);\n return vec2(direction.x * c - direction.y * s, direction.x * s + direction.y * c);\n}\n\nvec3 getIridescenceTint(float iridescence, float thickness, float NdotV)\n{\n if (iridescence <= 0.0) {\n return vec3(1.0);\n }\n\n float phase = 0.015 * thickness * pbrMaterial.iridescenceIor + (1.0 - NdotV) * 6.0;\n vec3 thinFilmTint =\n 0.5 + 0.5 * cos(vec3(phase, phase + 2.0943951, phase + 4.1887902));\n return mix(vec3(1.0), thinFilmTint, iridescence);\n}\n\nvec3 getVolumeAttenuation(float thickness)\n{\n if (thickness <= 0.0) {\n return vec3(1.0);\n }\n\n vec3 attenuationCoefficient =\n -log(max(pbrMaterial.attenuationColor, vec3(0.0001))) /\n max(pbrMaterial.attenuationDistance, 0.0001);\n return exp(-attenuationCoefficient * thickness);\n}\n\nPBRInfo createClearcoatPBRInfo(PBRInfo basePBRInfo, vec3 clearcoatNormal, float clearcoatRoughness)\n{\n float perceptualRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n float alphaRoughness = perceptualRoughness * perceptualRoughness;\n float NdotV = clamp(abs(dot(clearcoatNormal, basePBRInfo.v)), 0.001, 1.0);\n\n return PBRInfo(\n basePBRInfo.NdotL,\n NdotV,\n basePBRInfo.NdotH,\n basePBRInfo.LdotH,\n basePBRInfo.VdotH,\n perceptualRoughness,\n 0.0,\n vec3(0.04),\n vec3(1.0),\n alphaRoughness,\n vec3(0.0),\n vec3(0.04),\n clearcoatNormal,\n basePBRInfo.v\n );\n}\n\nvec3 calculateClearcoatContribution(\n PBRInfo pbrInfo,\n vec3 lightColor,\n vec3 clearcoatNormal,\n float clearcoatFactor,\n float clearcoatRoughness\n) {\n if (clearcoatFactor <= 0.0) {\n return vec3(0.0);\n }\n\n PBRInfo clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return calculateFinalColor(clearcoatPBRInfo, lightColor) * clearcoatFactor;\n}\n\n#ifdef USE_IBL\nvec3 calculateClearcoatIBLContribution(\n PBRInfo pbrInfo,\n vec3 clearcoatNormal,\n vec3 reflection,\n float clearcoatFactor,\n float clearcoatRoughness\n) {\n if (clearcoatFactor <= 0.0) {\n return vec3(0.0);\n }\n\n PBRInfo clearcoatPBRInfo = createClearcoatPBRInfo(pbrInfo, clearcoatNormal, clearcoatRoughness);\n return getIBLContribution(clearcoatPBRInfo, clearcoatNormal, reflection) * clearcoatFactor;\n}\n#endif\n\nvec3 calculateSheenContribution(\n PBRInfo pbrInfo,\n vec3 lightColor,\n vec3 sheenColor,\n float sheenRoughness\n) {\n if (maxComponent(sheenColor) <= 0.0) {\n return vec3(0.0);\n }\n\n float sheenFresnel = pow(clamp(1.0 - pbrInfo.VdotH, 0.0, 1.0), 5.0);\n float sheenVisibility = mix(1.0, pbrInfo.NdotL * pbrInfo.NdotV, sheenRoughness);\n return pbrInfo.NdotL *\n lightColor *\n sheenColor *\n (0.25 + 0.75 * sheenFresnel) *\n sheenVisibility *\n (1.0 - pbrInfo.metalness);\n}\n\nfloat calculateAnisotropyBoost(\n PBRInfo pbrInfo,\n vec3 anisotropyTangent,\n float anisotropyStrength\n) {\n if (anisotropyStrength <= 0.0) {\n return 1.0;\n }\n\n vec3 anisotropyBitangent = normalize(cross(pbrInfo.n, anisotropyTangent));\n float bitangentViewAlignment = abs(dot(pbrInfo.v, anisotropyBitangent));\n return mix(1.0, 0.65 + 0.7 * bitangentViewAlignment, anisotropyStrength);\n}\n\nvec3 calculateMaterialLightColor(\n PBRInfo pbrInfo,\n vec3 lightColor,\n vec3 clearcoatNormal,\n float clearcoatFactor,\n float clearcoatRoughness,\n vec3 sheenColor,\n float sheenRoughness,\n vec3 anisotropyTangent,\n float anisotropyStrength\n) {\n float anisotropyBoost = calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);\n vec3 color = calculateFinalColor(pbrInfo, lightColor) * anisotropyBoost;\n color += calculateClearcoatContribution(\n pbrInfo,\n lightColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness\n );\n color += calculateSheenContribution(pbrInfo, lightColor, sheenColor, sheenRoughness);\n return color;\n}\n\nvoid PBRInfo_setAmbientLight(inout PBRInfo pbrInfo) {\n pbrInfo.NdotL = 1.0;\n pbrInfo.NdotH = 0.0;\n pbrInfo.LdotH = 0.0;\n pbrInfo.VdotH = 1.0;\n}\n\nvoid PBRInfo_setDirectionalLight(inout PBRInfo pbrInfo, vec3 lightDirection) {\n vec3 n = pbrInfo.n;\n vec3 v = pbrInfo.v;\n vec3 l = normalize(lightDirection); // Vector from surface point to light\n vec3 h = normalize(l+v); // Half vector between both l and v\n\n pbrInfo.NdotL = clamp(dot(n, l), 0.001, 1.0);\n pbrInfo.NdotH = clamp(dot(n, h), 0.0, 1.0);\n pbrInfo.LdotH = clamp(dot(l, h), 0.0, 1.0);\n pbrInfo.VdotH = clamp(dot(v, h), 0.0, 1.0);\n}\n\nvoid PBRInfo_setPointLight(inout PBRInfo pbrInfo, PointLight pointLight) {\n vec3 light_direction = normalize(pointLight.position - pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nvoid PBRInfo_setSpotLight(inout PBRInfo pbrInfo, SpotLight spotLight) {\n vec3 light_direction = normalize(spotLight.position - pbr_vPosition);\n PBRInfo_setDirectionalLight(pbrInfo, light_direction);\n}\n\nvec3 calculateFinalColor(PBRInfo pbrInfo, vec3 lightColor) {\n // Calculate the shading terms for the microfacet specular shading model\n vec3 F = specularReflection(pbrInfo);\n float G = geometricOcclusion(pbrInfo);\n float D = microfacetDistribution(pbrInfo);\n\n // Calculation of analytical lighting contribution\n vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInfo);\n vec3 specContrib = F * G * D / (4.0 * pbrInfo.NdotL * pbrInfo.NdotV);\n // Obtain final intensity as reflectance (BRDF) scaled by the energy of the light (cosine law)\n return pbrInfo.NdotL * lightColor * (diffuseContrib + specContrib);\n}\n\nvec4 pbr_filterColor(vec4 colorUnused)\n{\n vec2 baseColorUV = getMaterialUV(pbrMaterial.baseColorUVSet, pbrMaterial.baseColorUVTransform);\n vec2 metallicRoughnessUV = getMaterialUV(\n pbrMaterial.metallicRoughnessUVSet,\n pbrMaterial.metallicRoughnessUVTransform\n );\n vec2 normalUV = getMaterialUV(pbrMaterial.normalUVSet, pbrMaterial.normalUVTransform);\n vec2 occlusionUV = getMaterialUV(pbrMaterial.occlusionUVSet, pbrMaterial.occlusionUVTransform);\n vec2 emissiveUV = getMaterialUV(pbrMaterial.emissiveUVSet, pbrMaterial.emissiveUVTransform);\n vec2 specularColorUV = getMaterialUV(\n pbrMaterial.specularColorUVSet,\n pbrMaterial.specularColorUVTransform\n );\n vec2 specularIntensityUV = getMaterialUV(\n pbrMaterial.specularIntensityUVSet,\n pbrMaterial.specularIntensityUVTransform\n );\n vec2 transmissionUV = getMaterialUV(\n pbrMaterial.transmissionUVSet,\n pbrMaterial.transmissionUVTransform\n );\n vec2 thicknessUV = getMaterialUV(pbrMaterial.thicknessUVSet, pbrMaterial.thicknessUVTransform);\n vec2 clearcoatUV = getMaterialUV(pbrMaterial.clearcoatUVSet, pbrMaterial.clearcoatUVTransform);\n vec2 clearcoatRoughnessUV = getMaterialUV(\n pbrMaterial.clearcoatRoughnessUVSet,\n pbrMaterial.clearcoatRoughnessUVTransform\n );\n vec2 clearcoatNormalUV = getMaterialUV(\n pbrMaterial.clearcoatNormalUVSet,\n pbrMaterial.clearcoatNormalUVTransform\n );\n vec2 sheenColorUV = getMaterialUV(\n pbrMaterial.sheenColorUVSet,\n pbrMaterial.sheenColorUVTransform\n );\n vec2 sheenRoughnessUV = getMaterialUV(\n pbrMaterial.sheenRoughnessUVSet,\n pbrMaterial.sheenRoughnessUVTransform\n );\n vec2 iridescenceUV = getMaterialUV(\n pbrMaterial.iridescenceUVSet,\n pbrMaterial.iridescenceUVTransform\n );\n vec2 iridescenceThicknessUV = getMaterialUV(\n pbrMaterial.iridescenceThicknessUVSet,\n pbrMaterial.iridescenceThicknessUVTransform\n );\n vec2 anisotropyUV = getMaterialUV(\n pbrMaterial.anisotropyUVSet,\n pbrMaterial.anisotropyUVTransform\n );\n\n // The albedo may be defined from a base texture or a flat color\n#ifdef HAS_BASECOLORMAP\n vec4 baseColor =\n SRGBtoLINEAR(texture(pbr_baseColorSampler, baseColorUV)) * pbrMaterial.baseColorFactor;\n#else\n vec4 baseColor = pbrMaterial.baseColorFactor;\n#endif\n\n#ifdef ALPHA_CUTOFF\n if (baseColor.a < pbrMaterial.alphaCutoff) {\n discard;\n }\n#endif\n\n vec3 color = vec3(0, 0, 0);\n\n float transmission = 0.0;\n\n if(pbrMaterial.unlit){\n color.rgb = baseColor.rgb;\n }\n else{\n // Metallic and Roughness material properties are packed together\n // In glTF, these factors can be specified by fixed scalar values\n // or from a metallic-roughness map\n float perceptualRoughness = pbrMaterial.metallicRoughnessValues.y;\n float metallic = pbrMaterial.metallicRoughnessValues.x;\n#ifdef HAS_METALROUGHNESSMAP\n // Roughness is stored in the 'g' channel, metallic is stored in the 'b' channel.\n // This layout intentionally reserves the 'r' channel for (optional) occlusion map data\n vec4 mrSample = texture(pbr_metallicRoughnessSampler, metallicRoughnessUV);\n perceptualRoughness = mrSample.g * perceptualRoughness;\n metallic = mrSample.b * metallic;\n#endif\n perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);\n metallic = clamp(metallic, 0.0, 1.0);\n mat3 tbn = getTBN(normalUV);\n vec3 n = getNormal(tbn, normalUV); // normal at surface point\n vec3 v = normalize(pbrProjection.camera - pbr_vPosition); // Vector from surface point to camera\n float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0);\n#ifdef USE_MATERIAL_EXTENSIONS\n bool useExtendedPBR =\n pbrMaterial.specularColorMapEnabled ||\n pbrMaterial.specularIntensityMapEnabled ||\n abs(pbrMaterial.specularIntensityFactor - 1.0) > 0.0001 ||\n maxComponent(abs(pbrMaterial.specularColorFactor - vec3(1.0))) > 0.0001 ||\n abs(pbrMaterial.ior - 1.5) > 0.0001 ||\n pbrMaterial.transmissionMapEnabled ||\n pbrMaterial.transmissionFactor > 0.0001 ||\n pbrMaterial.clearcoatMapEnabled ||\n pbrMaterial.clearcoatRoughnessMapEnabled ||\n pbrMaterial.clearcoatFactor > 0.0001 ||\n pbrMaterial.clearcoatRoughnessFactor > 0.0001 ||\n pbrMaterial.sheenColorMapEnabled ||\n pbrMaterial.sheenRoughnessMapEnabled ||\n maxComponent(pbrMaterial.sheenColorFactor) > 0.0001 ||\n pbrMaterial.sheenRoughnessFactor > 0.0001 ||\n pbrMaterial.iridescenceMapEnabled ||\n pbrMaterial.iridescenceFactor > 0.0001 ||\n abs(pbrMaterial.iridescenceIor - 1.3) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.x - 100.0) > 0.0001 ||\n abs(pbrMaterial.iridescenceThicknessRange.y - 400.0) > 0.0001 ||\n pbrMaterial.anisotropyMapEnabled ||\n pbrMaterial.anisotropyStrength > 0.0001 ||\n abs(pbrMaterial.anisotropyRotation) > 0.0001 ||\n length(pbrMaterial.anisotropyDirection - vec2(1.0, 0.0)) > 0.0001;\n#else\n bool useExtendedPBR = false;\n#endif\n\n if (!useExtendedPBR) {\n // Keep the baseline metallic-roughness implementation byte-for-byte equivalent in behavior.\n float alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n vec3 f0 = vec3(0.04);\n vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);\n diffuseColor *= 1.0 - metallic;\n vec3 specularColor = mix(f0, baseColor.rgb, metallic);\n\n float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n vec3 specularEnvironmentR0 = specularColor.rgb;\n vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;\n vec3 reflection = -normalize(reflect(v, n));\n\n PBRInfo pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v\n );\n\n#ifdef USE_LIGHTS\n PBRInfo_setAmbientLight(pbrInfo);\n color += calculateFinalColor(pbrInfo, lighting.ambientColor);\n\n for(int i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);\n color += calculateFinalColor(pbrInfo, lighting_getDirectionalLight(i).color);\n }\n }\n\n for(int i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));\n float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));\n color += calculateFinalColor(pbrInfo, lighting_getPointLight(i).color / attenuation);\n }\n }\n\n for(int i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(pbrInfo, lighting_getSpotLight(i));\n float attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), pbr_vPosition);\n color += calculateFinalColor(pbrInfo, lighting_getSpotLight(i).color / attenuation);\n }\n }\n#endif\n\n#ifdef USE_IBL\n if (pbrMaterial.IBLenabled) {\n color += getIBLContribution(pbrInfo, n, reflection);\n }\n#endif\n\n#ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled) {\n float ao = texture(pbr_occlusionSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n#endif\n\n vec3 emissive = pbrMaterial.emissiveFactor;\n#ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled) {\n emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, emissiveUV)).rgb;\n }\n#endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n#ifdef PBR_DEBUG\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n#endif\n\n return vec4(pow(color, vec3(1.0 / 2.2)), baseColor.a);\n }\n\n float specularIntensity = pbrMaterial.specularIntensityFactor;\n#ifdef HAS_SPECULARINTENSITYMAP\n if (pbrMaterial.specularIntensityMapEnabled) {\n specularIntensity *= texture(pbr_specularIntensitySampler, specularIntensityUV).a;\n }\n#endif\n\n vec3 specularFactor = pbrMaterial.specularColorFactor;\n#ifdef HAS_SPECULARCOLORMAP\n if (pbrMaterial.specularColorMapEnabled) {\n specularFactor *= SRGBtoLINEAR(texture(pbr_specularColorSampler, specularColorUV)).rgb;\n }\n#endif\n\n transmission = pbrMaterial.transmissionFactor;\n#ifdef HAS_TRANSMISSIONMAP\n if (pbrMaterial.transmissionMapEnabled) {\n transmission *= texture(pbr_transmissionSampler, transmissionUV).r;\n }\n#endif\n transmission = clamp(transmission * (1.0 - metallic), 0.0, 1.0);\n float thickness = max(pbrMaterial.thicknessFactor, 0.0);\n#ifdef HAS_THICKNESSMAP\n thickness *= texture(pbr_thicknessSampler, thicknessUV).g;\n#endif\n\n float clearcoatFactor = pbrMaterial.clearcoatFactor;\n float clearcoatRoughness = pbrMaterial.clearcoatRoughnessFactor;\n#ifdef HAS_CLEARCOATMAP\n if (pbrMaterial.clearcoatMapEnabled) {\n clearcoatFactor *= texture(pbr_clearcoatSampler, clearcoatUV).r;\n }\n#endif\n#ifdef HAS_CLEARCOATROUGHNESSMAP\n if (pbrMaterial.clearcoatRoughnessMapEnabled) {\n clearcoatRoughness *= texture(pbr_clearcoatRoughnessSampler, clearcoatRoughnessUV).g;\n }\n#endif\n clearcoatFactor = clamp(clearcoatFactor, 0.0, 1.0);\n clearcoatRoughness = clamp(clearcoatRoughness, c_MinRoughness, 1.0);\n vec3 clearcoatNormal = getClearcoatNormal(getTBN(clearcoatNormalUV), n, clearcoatNormalUV);\n\n vec3 sheenColor = pbrMaterial.sheenColorFactor;\n float sheenRoughness = pbrMaterial.sheenRoughnessFactor;\n#ifdef HAS_SHEENCOLORMAP\n if (pbrMaterial.sheenColorMapEnabled) {\n sheenColor *= SRGBtoLINEAR(texture(pbr_sheenColorSampler, sheenColorUV)).rgb;\n }\n#endif\n#ifdef HAS_SHEENROUGHNESSMAP\n if (pbrMaterial.sheenRoughnessMapEnabled) {\n sheenRoughness *= texture(pbr_sheenRoughnessSampler, sheenRoughnessUV).a;\n }\n#endif\n sheenRoughness = clamp(sheenRoughness, c_MinRoughness, 1.0);\n\n float iridescence = pbrMaterial.iridescenceFactor;\n#ifdef HAS_IRIDESCENCEMAP\n if (pbrMaterial.iridescenceMapEnabled) {\n iridescence *= texture(pbr_iridescenceSampler, iridescenceUV).r;\n }\n#endif\n iridescence = clamp(iridescence, 0.0, 1.0);\n float iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n 0.5\n );\n#ifdef HAS_IRIDESCENCETHICKNESSMAP\n iridescenceThickness = mix(\n pbrMaterial.iridescenceThicknessRange.x,\n pbrMaterial.iridescenceThicknessRange.y,\n texture(pbr_iridescenceThicknessSampler, iridescenceThicknessUV).g\n );\n#endif\n\n float anisotropyStrength = clamp(pbrMaterial.anisotropyStrength, 0.0, 1.0);\n vec2 anisotropyDirection = normalizeDirection(pbrMaterial.anisotropyDirection);\n#ifdef HAS_ANISOTROPYMAP\n if (pbrMaterial.anisotropyMapEnabled) {\n vec3 anisotropySample = texture(pbr_anisotropySampler, anisotropyUV).rgb;\n anisotropyStrength *= anisotropySample.b;\n vec2 mappedDirection = anisotropySample.rg * 2.0 - 1.0;\n if (length(mappedDirection) > 0.0001) {\n anisotropyDirection = normalize(mappedDirection);\n }\n }\n#endif\n anisotropyDirection = rotateDirection(anisotropyDirection, pbrMaterial.anisotropyRotation);\n vec3 anisotropyTangent = normalize(tbn[0] * anisotropyDirection.x + tbn[1] * anisotropyDirection.y);\n if (length(anisotropyTangent) < 0.0001) {\n anisotropyTangent = normalize(tbn[0]);\n }\n float anisotropyViewAlignment = abs(dot(v, anisotropyTangent));\n perceptualRoughness = mix(\n perceptualRoughness,\n clamp(perceptualRoughness * (1.0 - 0.6 * anisotropyViewAlignment), c_MinRoughness, 1.0),\n anisotropyStrength\n );\n\n // Roughness is authored as perceptual roughness; as is convention,\n // convert to material roughness by squaring the perceptual roughness [2].\n float alphaRoughness = perceptualRoughness * perceptualRoughness;\n\n float dielectricF0 = getDielectricF0(pbrMaterial.ior);\n vec3 dielectricSpecularF0 = min(\n vec3(dielectricF0) * specularFactor * specularIntensity,\n vec3(1.0)\n );\n vec3 iridescenceTint = getIridescenceTint(iridescence, iridescenceThickness, NdotV);\n dielectricSpecularF0 = mix(\n dielectricSpecularF0,\n dielectricSpecularF0 * iridescenceTint,\n iridescence\n );\n vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - dielectricSpecularF0);\n diffuseColor *= (1.0 - metallic) * (1.0 - transmission);\n vec3 specularColor = mix(dielectricSpecularF0, baseColor.rgb, metallic);\n\n float baseLayerEnergy = 1.0 - clearcoatFactor * 0.25;\n diffuseColor *= baseLayerEnergy;\n specularColor *= baseLayerEnergy;\n\n // Compute reflectance.\n float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\n\n // For typical incident reflectance range (between 4% to 100%) set the grazing\n // reflectance to 100% for typical fresnel effect.\n // For very low reflectance range on highly diffuse objects (below 4%),\n // incrementally reduce grazing reflecance to 0%.\n float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);\n vec3 specularEnvironmentR0 = specularColor.rgb;\n vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;\n vec3 reflection = -normalize(reflect(v, n));\n\n PBRInfo pbrInfo = PBRInfo(\n 0.0, // NdotL\n NdotV,\n 0.0, // NdotH\n 0.0, // LdotH\n 0.0, // VdotH\n perceptualRoughness,\n metallic,\n specularEnvironmentR0,\n specularEnvironmentR90,\n alphaRoughness,\n diffuseColor,\n specularColor,\n n,\n v\n );\n\n\n#ifdef USE_LIGHTS\n // Apply ambient light\n PBRInfo_setAmbientLight(pbrInfo);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting.ambientColor,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n\n // Apply directional light\n for(int i = 0; i < lighting.directionalLightCount; i++) {\n if (i < lighting.directionalLightCount) {\n PBRInfo_setDirectionalLight(pbrInfo, lighting_getDirectionalLight(i).direction);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getDirectionalLight(i).color,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n }\n }\n\n // Apply point light\n for(int i = 0; i < lighting.pointLightCount; i++) {\n if (i < lighting.pointLightCount) {\n PBRInfo_setPointLight(pbrInfo, lighting_getPointLight(i));\n float attenuation = getPointLightAttenuation(lighting_getPointLight(i), distance(lighting_getPointLight(i).position, pbr_vPosition));\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getPointLight(i).color / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n }\n }\n\n for(int i = 0; i < lighting.spotLightCount; i++) {\n if (i < lighting.spotLightCount) {\n PBRInfo_setSpotLight(pbrInfo, lighting_getSpotLight(i));\n float attenuation = getSpotLightAttenuation(lighting_getSpotLight(i), pbr_vPosition);\n color += calculateMaterialLightColor(\n pbrInfo,\n lighting_getSpotLight(i).color / attenuation,\n clearcoatNormal,\n clearcoatFactor,\n clearcoatRoughness,\n sheenColor,\n sheenRoughness,\n anisotropyTangent,\n anisotropyStrength\n );\n }\n }\n#endif\n\n // Calculate lighting contribution from image based lighting source (IBL)\n#ifdef USE_IBL\n if (pbrMaterial.IBLenabled) {\n color += getIBLContribution(pbrInfo, n, reflection) *\n calculateAnisotropyBoost(pbrInfo, anisotropyTangent, anisotropyStrength);\n color += calculateClearcoatIBLContribution(\n pbrInfo,\n clearcoatNormal,\n -normalize(reflect(v, clearcoatNormal)),\n clearcoatFactor,\n clearcoatRoughness\n );\n color += sheenColor * pbrMaterial.scaleIBLAmbient.x * (1.0 - sheenRoughness) * 0.25;\n }\n#endif\n\n // Apply optional PBR terms for additional (optional) shading\n#ifdef HAS_OCCLUSIONMAP\n if (pbrMaterial.occlusionMapEnabled) {\n float ao = texture(pbr_occlusionSampler, occlusionUV).r;\n color = mix(color, color * ao, pbrMaterial.occlusionStrength);\n }\n#endif\n\n vec3 emissive = pbrMaterial.emissiveFactor;\n#ifdef HAS_EMISSIVEMAP\n if (pbrMaterial.emissiveMapEnabled) {\n emissive *= SRGBtoLINEAR(texture(pbr_emissiveSampler, emissiveUV)).rgb;\n }\n#endif\n color += emissive * pbrMaterial.emissiveStrength;\n\n if (transmission > 0.0) {\n color = mix(color, color * getVolumeAttenuation(thickness), transmission);\n }\n\n // This section uses mix to override final color for reference app visualization\n // of various parameters in the lighting equation.\n#ifdef PBR_DEBUG\n // TODO: Figure out how to debug multiple lights\n\n // color = mix(color, F, pbr_scaleFGDSpec.x);\n // color = mix(color, vec3(G), pbr_scaleFGDSpec.y);\n // color = mix(color, vec3(D), pbr_scaleFGDSpec.z);\n // color = mix(color, specContrib, pbr_scaleFGDSpec.w);\n\n // color = mix(color, diffuseContrib, pbr_scaleDiffBaseMR.x);\n color = mix(color, baseColor.rgb, pbrMaterial.scaleDiffBaseMR.y);\n color = mix(color, vec3(metallic), pbrMaterial.scaleDiffBaseMR.z);\n color = mix(color, vec3(perceptualRoughness), pbrMaterial.scaleDiffBaseMR.w);\n#endif\n\n }\n\n float alpha = clamp(baseColor.a * (1.0 - transmission), 0.0, 1.0);\n return vec4(pow(color,vec3(1.0/2.2)), alpha);\n}\n"; readonly defines: { readonly LIGHTING_FRAGMENT: true; readonly HAS_NORMALMAP: false; readonly HAS_EMISSIVEMAP: false; readonly HAS_OCCLUSIONMAP: false; readonly HAS_BASECOLORMAP: false; readonly HAS_METALROUGHNESSMAP: false; readonly HAS_SPECULARCOLORMAP: false; readonly HAS_SPECULARINTENSITYMAP: false; readonly HAS_TRANSMISSIONMAP: false; readonly HAS_THICKNESSMAP: false; readonly HAS_CLEARCOATMAP: false; readonly HAS_CLEARCOATROUGHNESSMAP: false; readonly HAS_CLEARCOATNORMALMAP: false; readonly HAS_SHEENCOLORMAP: false; readonly HAS_SHEENROUGHNESSMAP: false; readonly HAS_IRIDESCENCEMAP: false; readonly HAS_IRIDESCENCETHICKNESSMAP: false; readonly HAS_ANISOTROPYMAP: false; readonly USE_MATERIAL_EXTENSIONS: false; readonly ALPHA_CUTOFF: false; readonly USE_IBL: false; readonly PBR_DEBUG: false; }; readonly getUniforms: (props: Partial) => Partial; readonly uniformTypes: { readonly unlit: "i32"; readonly baseColorMapEnabled: "i32"; readonly baseColorFactor: "vec4"; readonly normalMapEnabled: "i32"; readonly normalScale: "f32"; readonly emissiveMapEnabled: "i32"; readonly emissiveFactor: "vec3"; readonly metallicRoughnessValues: "vec2"; readonly metallicRoughnessMapEnabled: "i32"; readonly occlusionMapEnabled: "i32"; readonly occlusionStrength: "f32"; readonly alphaCutoffEnabled: "i32"; readonly alphaCutoff: "f32"; readonly specularColorFactor: "vec3"; readonly specularIntensityFactor: "f32"; readonly specularColorMapEnabled: "i32"; readonly specularIntensityMapEnabled: "i32"; readonly ior: "f32"; readonly transmissionFactor: "f32"; readonly transmissionMapEnabled: "i32"; readonly thicknessFactor: "f32"; readonly attenuationDistance: "f32"; readonly attenuationColor: "vec3"; readonly clearcoatFactor: "f32"; readonly clearcoatRoughnessFactor: "f32"; readonly clearcoatMapEnabled: "i32"; readonly clearcoatRoughnessMapEnabled: "i32"; readonly sheenColorFactor: "vec3"; readonly sheenRoughnessFactor: "f32"; readonly sheenColorMapEnabled: "i32"; readonly sheenRoughnessMapEnabled: "i32"; readonly iridescenceFactor: "f32"; readonly iridescenceIor: "f32"; readonly iridescenceThicknessRange: "vec2"; readonly iridescenceMapEnabled: "i32"; readonly anisotropyStrength: "f32"; readonly anisotropyRotation: "f32"; readonly anisotropyDirection: "vec2"; readonly anisotropyMapEnabled: "i32"; readonly emissiveStrength: "f32"; readonly IBLenabled: "i32"; readonly scaleIBLAmbient: "vec2"; readonly scaleDiffBaseMR: "vec4"; readonly scaleFGDSpec: "vec4"; readonly baseColorUVSet: "i32"; readonly baseColorUVTransform: "mat3x3"; readonly metallicRoughnessUVSet: "i32"; readonly metallicRoughnessUVTransform: "mat3x3"; readonly normalUVSet: "i32"; readonly normalUVTransform: "mat3x3"; readonly occlusionUVSet: "i32"; readonly occlusionUVTransform: "mat3x3"; readonly emissiveUVSet: "i32"; readonly emissiveUVTransform: "mat3x3"; readonly specularColorUVSet: "i32"; readonly specularColorUVTransform: "mat3x3"; readonly specularIntensityUVSet: "i32"; readonly specularIntensityUVTransform: "mat3x3"; readonly transmissionUVSet: "i32"; readonly transmissionUVTransform: "mat3x3"; readonly thicknessUVSet: "i32"; readonly thicknessUVTransform: "mat3x3"; readonly clearcoatUVSet: "i32"; readonly clearcoatUVTransform: "mat3x3"; readonly clearcoatRoughnessUVSet: "i32"; readonly clearcoatRoughnessUVTransform: "mat3x3"; readonly clearcoatNormalUVSet: "i32"; readonly clearcoatNormalUVTransform: "mat3x3"; readonly sheenColorUVSet: "i32"; readonly sheenColorUVTransform: "mat3x3"; readonly sheenRoughnessUVSet: "i32"; readonly sheenRoughnessUVTransform: "mat3x3"; readonly iridescenceUVSet: "i32"; readonly iridescenceUVTransform: "mat3x3"; readonly iridescenceThicknessUVSet: "i32"; readonly iridescenceThicknessUVTransform: "mat3x3"; readonly anisotropyUVSet: "i32"; readonly anisotropyUVTransform: "mat3x3"; }; }; //# sourceMappingURL=pbr-material.d.ts.map