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.

225 lines (221 loc) 9.13 kB
import { a4 as PBR_HAS_METALLIC_REFLECTANCE_MAP, a5 as PBR_HAS_REFLECTANCE_MAP, a6 as PBR2_HAS_REFLECTANCE_FACTORS, y as PBR2_HAS_UV_TRANSFORM, bw as PBR_HAS_USE_ALPHA_ONLY_MR, a8 as _registerPbrExt } from './index-DMbDahsc.esm.js'; const PBR2_REFL_UV_TX = 1 << 26; const STAGE_FRAGMENT = 2; const reflUvExpr = (name) => `(vec2<f32>(dot(material.${name}m.xy, input.uv), dot(material.${name}m.zw, input.uv)) + material.${name}t.xy)`; function writeReflUvTransform(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 sx = tex?.uScale ?? 1; const sy = tex?.vScale ?? 1; const ang = tex?.uAng ?? 0; const mi = mOff / 4; 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; } const ti = tOff / 4; data[ti] = tex?.uOffset ?? 0; data[ti + 1] = tex?.vOffset ?? 0; } function writeReflectanceUBO(data, material, offsets) { if (!offsets.has("occlusionStrength")) { return; } const off = offsets.get("occlusionStrength") / 4; data[off] = material.occlusionStrength ?? 1; data[off + 1] = material._metallicF0Factor ?? 1; data[off + 2] = material._specularWeight ?? material._metallicF0Factor ?? 1; const mrc = material._metallicReflectanceColor; data[off + 4] = mrc ? mrc[0] : 1; data[off + 5] = mrc ? mrc[1] : 1; data[off + 6] = mrc ? mrc[2] : 1; writeReflUvTransform(data, offsets, "reflUV", material._reflectanceTexture); writeReflUvTransform(data, offsets, "mrReflUV", material._metallicReflectanceTexture); } function createReflectanceFragment(hasMetallicReflectanceMap, hasReflectanceMap, useAlphaOnlyMR, hasOcclusionUv2 = false, hasUvTx = false, hasOcclusionSplit = false) { const occlusionSample = hasOcclusionUv2 ? "textureSample(occlusionTexture, occlusionSampler_, input.uv2).r" : hasOcclusionSplit ? "textureSample(ormTexture,ormSampler,occlUV).r" : "orm.r"; const bindings = []; if (hasMetallicReflectanceMap) { bindings.push( { _name: "metallicReflectanceMap", _type: { _kind: "texture", _textureType: "texture_2d<f32>" }, _visibility: STAGE_FRAGMENT }, { _name: "metallicReflectanceMapSampler", _type: { _kind: "sampler", _samplerType: "sampler" }, _visibility: STAGE_FRAGMENT } ); } if (hasReflectanceMap) { bindings.push( { _name: "reflectanceMap", _type: { _kind: "texture", _textureType: "texture_2d<f32>" }, _visibility: STAGE_FRAGMENT }, { _name: "reflectanceMapSampler", _type: { _kind: "sampler", _samplerType: "sampler" }, _visibility: STAGE_FRAGMENT } ); } const reflUv = hasUvTx ? reflUvExpr("reflUV") : "input.uv"; const mrReflUv = hasUvTx ? reflUvExpr("mrReflUV") : "input.uv"; let f0Code = `var mrFactors = vec4<f32>(material.metallicReflectanceColor, material.metallicF0Factor); var specularWeight = material.specularWeight;`; if (hasReflectanceMap) { f0Code += ` { let rSample = textureSample(reflectanceMap, reflectanceMapSampler, ${reflUv}); let rLinear = pow(rSample.rgb, vec3<f32>(2.2)); mrFactors = vec4<f32>(mrFactors.rgb * rLinear, mrFactors.a); }`; } if (hasMetallicReflectanceMap) { if (!useAlphaOnlyMR) { f0Code += ` { let mrSample = textureSample(metallicReflectanceMap, metallicReflectanceMapSampler, ${mrReflUv}); let mrLinear = pow(mrSample.rgb, vec3<f32>(2.2)); mrFactors = vec4<f32>(mrFactors.rgb * mrLinear, mrFactors.a * mrSample.a); specularWeight *= mrSample.a; }`; } else { f0Code += ` { let mrSample = textureSample(metallicReflectanceMap, metallicReflectanceMapSampler, ${mrReflUv}); mrFactors = vec4<f32>(mrFactors.rgb, mrFactors.a * mrSample.a); specularWeight *= mrSample.a; }`; } } f0Code += ` let dielectricF0 = material.reflectance * mrFactors.a; let surfaceReflectivityColor = mrFactors.rgb; let dielectricColorF0 = vec3<f32>(dielectricF0) * surfaceReflectivityColor; let metallicColorF0 = baseColor; var colorF0 = mix(dielectricColorF0, metallicColorF0, metallic); let colorF90 = vec3<f32>(mix(specularWeight, 1.0, metallic)); let surfaceAlbedo = baseColor * (vec3<f32>(1.0) - vec3<f32>(dielectricF0) * surfaceReflectivityColor) * (1.0 - metallic);`; const uboFields = [ { _name: "occlusionStrength", _type: "f32" }, { _name: "metallicF0Factor", _type: "f32" }, { _name: "specularWeight", _type: "f32" }, { _name: "_mrPad1", _type: "f32" }, { _name: "metallicReflectanceColor", _type: "vec3<f32>" }, { _name: "_mrPad2", _type: "f32" } ]; if (hasUvTx) { if (hasReflectanceMap) { uboFields.push({ _name: "reflUVm", _type: "vec4<f32>" }, { _name: "reflUVt", _type: "vec4<f32>" }); } if (hasMetallicReflectanceMap) { uboFields.push({ _name: "mrReflUVm", _type: "vec4<f32>" }, { _name: "mrReflUVt", _type: "vec4<f32>" }); } } return { _id: hasUvTx ? "reflectance-U" : "reflectance", _uboFields: uboFields, _bindings: bindings, _fragmentSlots: { MF: f0Code, AT: `let occlusion = mix(1.0, ${occlusionSample}, material.occlusionStrength);` } }; } const pbrExt = { id: "reflectance", phase: "fragment", detect(mat) { const m = mat; let f = 0; let f2 = 0; if (m._metallicReflectanceTexture) { f |= PBR_HAS_METALLIC_REFLECTANCE_MAP; } if (m._reflectanceTexture) { f |= PBR_HAS_REFLECTANCE_MAP; } if (f === 0) { const hasNonDefaultF0 = m._metallicF0Factor != null && Math.abs(m._metallicF0Factor - 1) > 1e-6; const mrc = m._metallicReflectanceColor; const hasNonDefaultColor = mrc != null && (mrc[0] !== 1 || mrc[1] !== 1 || mrc[2] !== 1); if (hasNonDefaultF0 || hasNonDefaultColor || m._occlStrengthAnimated) { f2 |= PBR2_HAS_REFLECTANCE_FACTORS; } } if ((f !== 0 || f2 & PBR2_HAS_REFLECTANCE_FACTORS) && m._useOnlyMetallicFromMetallicReflectanceTexture) { f |= PBR_HAS_USE_ALPHA_ONLY_MR; } const refHasTx = (t) => !!t?._hasTx; if (f !== 0 && (refHasTx(m._reflectanceTexture) || refHasTx(m._metallicReflectanceTexture))) { f2 |= PBR2_REFL_UV_TX; } return { f, f2 }; }, frag(ctx) { const hasMR = (ctx._features & PBR_HAS_METALLIC_REFLECTANCE_MAP) !== 0; const hasR = (ctx._features & PBR_HAS_REFLECTANCE_MAP) !== 0; const hasFactors = (ctx._features2 & PBR2_HAS_REFLECTANCE_FACTORS) !== 0; if (!hasMR && !hasR && !hasFactors) { return null; } return createReflectanceFragment( hasMR, hasR, (ctx._features & PBR_HAS_USE_ALPHA_ONLY_MR) !== 0, // Occlusion-on-UV1 specifically (mask bit 1<<5), not any channel. Must match // createPbrTemplateExt's _hasOcclusionUv2 so the occlusionTexture binding it declares // and this sample agree. ctx._uv2Mask is already zeroed when uv2 isn't present. ((ctx._uv2Mask ?? 0) & 1 << 5) !== 0, (ctx._features2 & PBR2_REFL_UV_TX) !== 0, // Occlusion sampling the ORM texture at its own transformed UV. Must match // createPbrTemplateExt's `_hasOcclusionSplit`, `occlUV` included: this slot // replaces the template's occlusion line, so dropping the arm silently drops // occlusion's transform. (ctx._features2 & PBR2_HAS_UV_TRANSFORM) !== 0 && (ctx._features2 & 1 << 28) !== 0 ); }, writeUbo: writeReflectanceUBO, bind(ctx, entries, b) { if ((ctx._features & (PBR_HAS_METALLIC_REFLECTANCE_MAP | PBR_HAS_REFLECTANCE_MAP)) === 0) { return b; } const m = ctx._material; if (m._metallicReflectanceTexture) { entries.push({ binding: b++, resource: m._metallicReflectanceTexture.view }); entries.push({ binding: b++, resource: m._metallicReflectanceTexture.sampler }); } if (m._reflectanceTexture) { entries.push({ binding: b++, resource: m._reflectanceTexture.view }); entries.push({ binding: b++, resource: m._reflectanceTexture.sampler }); } return b; }, textures(mat, t) { const m = mat; if (m._metallicReflectanceTexture) { t.push(m._metallicReflectanceTexture); } if (m._reflectanceTexture) { t.push(m._reflectanceTexture); } } }; function setPbrMetallicReflectance(mat, options) { if (options.color) { mat._metallicReflectanceColor = options.color; } if (options.texture) { mat._metallicReflectanceTexture = options.texture; } if (options.reflectanceTexture) { mat._reflectanceTexture = options.reflectanceTexture; } if (options.f0Factor !== void 0) { mat._metallicF0Factor = options.f0Factor; } if (options.specularWeight !== void 0) { mat._specularWeight = options.specularWeight; } if (options.useOnlyMetallicFromTexture !== void 0) { mat._useOnlyMetallicFromMetallicReflectanceTexture = options.useOnlyMetallicFromTexture; } _registerPbrExt(pbrExt); } export { setPbrMetallicReflectance }; //# sourceMappingURL=set-metallic-reflectance-Dy2tXW29.esm.js.map