@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.
197 lines (194 loc) • 7.94 kB
JavaScript
import { Z as PBR_HAS_METALLIC_REFLECTANCE_MAP, $ as PBR_HAS_REFLECTANCE_MAP, a0 as PBR2_HAS_REFLECTANCE_FACTORS, ay as PBR_HAS_USE_ALPHA_ONLY_MR } from './index-By0tcgYN.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) {
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: hasOcclusionUv2 ? `let occlusion = mix(1.0, textureSample(occlusionTexture, occlusionSampler_, input.uv2).r, material.occlusionStrength);` : `let occlusion = mix(1.0, orm.r, 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
);
},
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);
}
}
};
export { createReflectanceFragment, pbrExt, writeReflectanceUBO };
//# sourceMappingURL=reflectance-fragment-BPVyxyKG.esm.js.map