UNPKG

@babylonjs/viewer

Version:

The Babylon Viewer aims to simplify a specific but common Babylon.js use case: loading, viewing, and interacting with a 3D model.

246 lines (243 loc) 9.45 kB
import { Z as PBR_HAS_METALLIC_REFLECTANCE_MAP, $ as PBR_HAS_REFLECTANCE_MAP, a0 as PBR2_HAS_REFLECTANCE_FACTORS } from './index-By0tcgYN.esm.js'; const STAGE_FRAGMENT = 2; const PBR2_HAS_IRIDESCENCE = 1 << 17; const PBR2_HAS_IRIDESCENCE_MAP = 1 << 18; const PBR2_HAS_IRIDESCENCE_THICKNESS_MAP = 1 << 19; const PBR2_HAS_IRIDESCENCE_UV_TX = 1 << 20; const PBR2_HAS_IRIDESCENCE_THICKNESS_UV_TX = 1 << 21; const PBR2_HAS_IRIDESCENCE_UV2 = 1 << 22; const PBR2_HAS_IRIDESCENCE_THICKNESS_UV2 = 1 << 23; const IRI_MSH_HAS_UV2 = 1 << 7; const IRIDESCENCE_HELPERS = `const IRI_XYZ_TO_REC709:mat3x3<f32>=mat3x3<f32>( 3.2404542,-0.9692660,0.0556434, -1.5371385,1.8760108,-0.2040259, -0.4985314,0.0415560,1.0572252); fn iri_square3(x:vec3<f32>)->vec3<f32>{return x*x;} fn iri_iorFromAirF0(f0:vec3<f32>)->vec3<f32>{ let s=sqrt(clamp(f0,vec3<f32>(0.0),vec3<f32>(0.9999))); return (vec3<f32>(1.0)+s)/(vec3<f32>(1.0)-s); } fn iri_r0FromIor3(iorT:vec3<f32>,iorI:f32)->vec3<f32>{return iri_square3((iorT-vec3<f32>(iorI))/(iorT+vec3<f32>(iorI)));} fn iri_r0FromIor(iorT:f32,iorI:f32)->f32{let r=(iorT-iorI)/(iorT+iorI);return r*r;} fn iri_fresSchlick(c:f32,F0:vec3<f32>,F90:vec3<f32>)->vec3<f32>{ let t=1.0-c; let t2=t*t; return F0+(F90-F0)*(t2*t2*t); } fn iri_evalSensitivity(opd:f32,shift:vec3<f32>)->vec3<f32>{ let phase=6.283185307179586*opd*1.0e-9; let val=vec3<f32>(5.4856e-13,4.4201e-13,5.2481e-13); let pos=vec3<f32>(1.6810e+06,1.7953e+06,2.2084e+06); let vr=vec3<f32>(4.3278e+09,9.3046e+09,6.6121e+09); var xyz=val*sqrt(6.283185307179586*vr)*cos(pos*phase+shift)*exp(-(phase*phase)*vr); xyz.x=xyz.x+9.7470e-14*sqrt(6.283185307179586*4.5282e+09)*cos(2.2399e+06*phase+shift.x)*exp(-4.5282e+09*phase*phase); xyz=xyz/1.0685e-7; return IRI_XYZ_TO_REC709*xyz; } fn iri_eval(outsideIor:f32,eta2:f32,cosTheta1:f32,thickness:f32,baseF0:vec3<f32>)->vec3<f32>{ let iridescenceIor=mix(outsideIor,eta2,smoothstep(0.0,0.03,thickness)); let eta=outsideIor/iridescenceIor; let sinTheta2Sq=eta*eta*(1.0-cosTheta1*cosTheta1); let cosTheta2Sq=1.0-sinTheta2Sq; if(cosTheta2Sq<0.0){return vec3<f32>(1.0);} let cosTheta2=sqrt(cosTheta2Sq); let r0=iri_r0FromIor(iridescenceIor,outsideIor); let r12=iri_fresSchlick(cosTheta1,vec3<f32>(r0),vec3<f32>(1.0)).x; let t121=1.0-r12; var phi12=0.0; if(iridescenceIor<outsideIor){phi12=3.141592653589793;} let phi21=3.141592653589793-phi12; let baseIor=iri_iorFromAirF0(baseF0); let r1=iri_r0FromIor3(baseIor,iridescenceIor); let r23=iri_fresSchlick(cosTheta2,r1,vec3<f32>(1.0)); var phi23=vec3<f32>(0.0); if(baseIor.x<iridescenceIor){phi23.x=3.141592653589793;} if(baseIor.y<iridescenceIor){phi23.y=3.141592653589793;} if(baseIor.z<iridescenceIor){phi23.z=3.141592653589793;} let opd=2.0*iridescenceIor*thickness*cosTheta2; let phi=vec3<f32>(phi21)+phi23; let r123=clamp(vec3<f32>(r12)*r23,vec3<f32>(1e-5),vec3<f32>(0.9999)); let smallR123=sqrt(r123); let rs=(t121*t121)*r23/(vec3<f32>(1.0)-r123); var outI=vec3<f32>(r12)+rs; var cm=rs-vec3<f32>(t121); for(var m:i32=1;m<=2;m=m+1){ cm=cm*smallR123; outI=outI+cm*(2.0*iri_evalSensitivity(f32(m)*opd,f32(m)*phi)); } return max(outI,vec3<f32>(0.0)); }`; const IRI_TEX = [ [PBR2_HAS_IRIDESCENCE_MAP, "texture"], [PBR2_HAS_IRIDESCENCE_THICKNESS_MAP, "thicknessTexture"] ]; function uvBaseExpr(features2, meshFeatures, uv2Flag) { return (features2 & uv2Flag) !== 0 && (meshFeatures & IRI_MSH_HAS_UV2) !== 0 ? "input.uv2" : "input.uv"; } function uvDecl(name, baseUv, hasTx) { return hasTx ? `let ${name}=vec2<f32>(dot(material.${name}m.xy,${baseUv}),dot(material.${name}m.zw,${baseUv}))+material.${name}t.xy;` : `let ${name}=${baseUv};`; } function uvTransformUboFields(name) { return [ { _name: `${name}m`, _type: "vec4<f32>" }, { _name: `${name}t`, _type: "vec4<f32>" } ]; } function writeUvTransform(data, offsets, name, tex) { const mOff = offsets.get(`${name}m`); const tOff = offsets.get(`${name}t`); if (mOff === void 0 || tOff === void 0) { return; } const mi = mOff / 4; const ti = tOff / 4; const sx = tex?.uScale ?? 1; const sy = tex?.vScale ?? 1; const ang = tex?.uAng ?? 0; const ox = tex?.uOffset ?? 0; const oy = tex?.vOffset ?? 0; if (ang === 0) { data[mi] = sx; data[mi + 1] = 0; data[mi + 2] = 0; data[mi + 3] = sy; } else { const c = Math.cos(ang); const s = Math.sin(ang); data[mi] = c * sx; data[mi + 1] = s * sy; data[mi + 2] = -s * sx; data[mi + 3] = c * sy; } data[ti] = ox; data[ti + 1] = oy; data[ti + 2] = 0; data[ti + 3] = 0; } function createIridescenceFragment(features, features2, meshFeatures) { if ((features2 & PBR2_HAS_IRIDESCENCE) === 0) { return null; } const hasIntensityMap = (features2 & PBR2_HAS_IRIDESCENCE_MAP) !== 0; const hasThicknessMap = (features2 & PBR2_HAS_IRIDESCENCE_THICKNESS_MAP) !== 0; const hasIntensityUvTx = (features2 & PBR2_HAS_IRIDESCENCE_UV_TX) !== 0; const hasThicknessUvTx = (features2 & PBR2_HAS_IRIDESCENCE_THICKNESS_UV_TX) !== 0; const bindings = []; const uboFields = [{ _name: "iridescenceParams", _type: "vec4<f32>" }]; if (hasIntensityMap) { bindings.push( { _name: "iridescenceTexture", _type: { _kind: "texture", _textureType: "texture_2d<f32>" }, _visibility: STAGE_FRAGMENT }, { _name: "iridescenceSampler_", _type: { _kind: "sampler", _samplerType: "sampler" }, _visibility: STAGE_FRAGMENT } ); if (hasIntensityUvTx) { uboFields.push(...uvTransformUboFields("iridescenceUV")); } } if (hasThicknessMap) { bindings.push( { _name: "iridescenceThicknessTexture", _type: { _kind: "texture", _textureType: "texture_2d<f32>" }, _visibility: STAGE_FRAGMENT }, { _name: "iridescenceThicknessSampler_", _type: { _kind: "sampler", _samplerType: "sampler" }, _visibility: STAGE_FRAGMENT } ); if (hasThicknessUvTx) { uboFields.push(...uvTransformUboFields("iridescenceThicknessUV")); } } const scopeVars = []; if (hasIntensityMap) { scopeVars.push(uvDecl("iridescenceUV", uvBaseExpr(features2, meshFeatures, PBR2_HAS_IRIDESCENCE_UV2), hasIntensityUvTx)); } if (hasThicknessMap) { scopeVars.push(uvDecl("iridescenceThicknessUV", uvBaseExpr(features2, meshFeatures, PBR2_HAS_IRIDESCENCE_THICKNESS_UV2), hasThicknessUvTx)); } const intensity = hasIntensityMap ? "material.iridescenceParams.x*textureSample(iridescenceTexture,iridescenceSampler_,iridescenceUV).r" : "material.iridescenceParams.x"; const thickness = hasThicknessMap ? "mix(material.iridescenceParams.z,material.iridescenceParams.w,textureSample(iridescenceThicknessTexture,iridescenceThicknessSampler_,iridescenceThicknessUV).g)" : "material.iridescenceParams.w"; return { _id: "iridescence", _dependencies: (features & (PBR_HAS_METALLIC_REFLECTANCE_MAP | PBR_HAS_REFLECTANCE_MAP)) !== 0 || (features2 & PBR2_HAS_REFLECTANCE_FACTORS) !== 0 ? ["reflectance"] : void 0, _uboFields: uboFields, _bindings: bindings, _helperFunctions: IRIDESCENCE_HELPERS, _fragmentSlots: { ...scopeVars.length ? { SV: scopeVars.join("\n") } : void 0, MF: `{ let iriIntensity=clamp(${intensity},0.0,1.0); let iriThickness=max(${thickness},0.0); let iriF0=iri_eval(1.0,max(material.iridescenceParams.y,1.0001),NdotV,iriThickness,colorF0); colorF0=mix(colorF0,iriF0,iriIntensity); }` } }; } function writeIridescenceUBO(data, material, offsets) { const iri = material.iridescence; if (!iri?.isEnabled || !offsets.has("iridescenceParams")) { return; } const off = offsets.get("iridescenceParams") / 4; data[off] = iri.intensity ?? 1; data[off + 1] = iri.indexOfRefraction ?? 1.3; data[off + 2] = iri.minimumThickness ?? 100; data[off + 3] = iri.maximumThickness ?? 400; writeUvTransform(data, offsets, "iridescenceUV", iri.texture); writeUvTransform(data, offsets, "iridescenceThicknessUV", iri.thicknessTexture); } const pbrExt = { id: "iridescence", phase: "base-tex", detect(mat) { const iri = mat.iridescence; if (!iri?.isEnabled) { return { f: 0, f2: 0 }; } let f2 = PBR2_HAS_IRIDESCENCE; if (iri.texture) { f2 |= PBR2_HAS_IRIDESCENCE_MAP; if (iri.texture._hasTx) { f2 |= PBR2_HAS_IRIDESCENCE_UV_TX; } if (iri.texture._texCoord === 1) { f2 |= PBR2_HAS_IRIDESCENCE_UV2; } } if (iri.thicknessTexture) { f2 |= PBR2_HAS_IRIDESCENCE_THICKNESS_MAP; if (iri.thicknessTexture._hasTx) { f2 |= PBR2_HAS_IRIDESCENCE_THICKNESS_UV_TX; } if (iri.thicknessTexture._texCoord === 1) { f2 |= PBR2_HAS_IRIDESCENCE_THICKNESS_UV2; } } return { f: 0, f2 }; }, frag: (ctx) => createIridescenceFragment(ctx._features, ctx._features2, ctx._meshFeatures), writeUbo: writeIridescenceUBO, bind(ctx, entries, b) { const iri = ctx._material.iridescence; if (!iri) { return b; } for (const [flag, key] of IRI_TEX) { const tex = iri[key]; if ((ctx._features2 & flag) !== 0 && tex) { entries.push({ binding: b++, resource: tex.view }); entries.push({ binding: b++, resource: tex.sampler }); } } return b; }, textures(mat, t) { const iri = mat.iridescence; if (!iri) { return; } for (const [, key] of IRI_TEX) { const tex = iri[key]; if (tex) { t.push(tex); } } } }; export { pbrExt, writeIridescenceUBO }; //# sourceMappingURL=iridescence-fragment-DVlPUZac.esm.js.map