@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.
90 lines (88 loc) • 4.41 kB
JavaScript
const STAGE_FRAGMENT = 2;
const IBL_HELPERS = `
fn environmentHorizonOcclusion(V: vec3<f32>, N: vec3<f32>, geoN: vec3<f32>) -> f32 {
let R = reflect(V, N);
let temp = saturate(1.0 + 1.1 * dot(R, geoN));
return temp * temp;
}
fn getEnergyConservationFactor(F0: vec3<f32>, brdfY: f32) -> vec3<f32> {
return 1.0 + F0 * (1.0 / brdfY - 1.0);
}
fn rotateY(v: vec3<f32>, angle: f32) -> vec3<f32> {
let c = cos(angle);
let s = sin(angle);
return vec3<f32>(v.x * c + v.z * s, v.y, -v.x * s + v.z * c);
}
`;
function makeIblCalculation(hasNormalMap, anisoBentNormalCode = "", skyboxCalculation = "") {
if (skyboxCalculation) {
return skyboxCalculation;
}
const ehoLine = hasNormalMap ? `let eho = environmentHorizonOcclusion(-V, N, N_geom);` : `let eho = 1.0;`;
const reflectionDir = anisoBentNormalCode ? anisoBentNormalCode : `let R_raw = reflect(-V, N);`;
const irradianceCode = `let environmentIrradiance = (scene.vSphericalL00.rgb
+ scene.vSphericalL1_1.rgb * N_env.y + scene.vSphericalL10.rgb * N_env.z + scene.vSphericalL11.rgb * N_env.x
+ scene.vSphericalL2_2.rgb * (N_env.y * N_env.x) + scene.vSphericalL2_1.rgb * (N_env.y * N_env.z)
+ scene.vSphericalL20.rgb * (3.0 * N_env.z * N_env.z - 1.0) + scene.vSphericalL21.rgb * (N_env.z * N_env.x)
+ scene.vSphericalL22.rgb * (N_env.x * N_env.x - N_env.y * N_env.y)) * material.environmentIntensity;`;
return `${reflectionDir}
let R = rotateY(R_raw, scene.envRotationY);
let N_env = rotateY(N, scene.envRotationY);
let brdf = textureSample(brdfLUT, brdfSampler_, vec2<f32>(NdotV, roughness));
let environmentBrdf = brdf.rgb;
let specularEnvironmentReflectance = (colorF90 - colorF0) * environmentBrdf.x + colorF0 * environmentBrdf.y;
let seo = clamp((NdotVUnclamped + occlusion) * (NdotVUnclamped + occlusion) - 1.0 + occlusion, 0.0, 1.0);
${ehoLine}
let colorSpecularEnvReflectance = specularEnvironmentReflectance * seo * eho;
let energyConservation = getEnergyConservationFactor(colorF0, max(environmentBrdf.y, 0.001));
${irradianceCode}
let maxLod = f32(textureNumLevels(iblTexture) - 1);
let cubemapDim = f32(textureDimensions(iblTexture).x);
var specLod = log2(cubemapDim * alphaG) * scene.vImageInfos.z;
var environmentRadiance = textureSampleLevel(iblTexture, iblSampler, R, clamp(specLod, 0.0, maxLod)).rgb * material.environmentIntensity;
environmentRadiance = mix(environmentRadiance, environmentIrradiance, alphaG);
let finalIrradiance = environmentIrradiance * surfaceAlbedo * occlusion;
let finalSpecularScaled = directSpecular * energyConservation;
let finalRadianceScaled = environmentRadiance * colorSpecularEnvReflectance * energyConservation;
color = finalIrradiance + finalRadianceScaled + finalSpecularScaled + directDiffuse + emissive;`;
}
function createIblFragment(hasNormalMap, anisoBentNormalCode = "", skyboxCalculation = "") {
return {
_id: "ibl",
// SH coefficients are in the PBR template's baseSceneUboFields (not here)
// to preserve fixed scene UBO layout compatibility.
_bindings: [
{ _name: "brdfLUT", _type: { _kind: "texture", _textureType: "texture_2d<f32>" }, _visibility: STAGE_FRAGMENT },
{ _name: "brdfSampler_", _type: { _kind: "sampler", _samplerType: "sampler" }, _visibility: STAGE_FRAGMENT },
{ _name: "iblTexture", _type: { _kind: "texture", _textureType: "texture_cube<f32>" }, _visibility: STAGE_FRAGMENT },
{ _name: "iblSampler", _type: { _kind: "sampler", _samplerType: "sampler" }, _visibility: STAGE_FRAGMENT }
],
_helperFunctions: IBL_HELPERS,
_fragmentSlots: {
AI: makeIblCalculation(hasNormalMap, anisoBentNormalCode, skyboxCalculation),
BA: `luminanceOverAlpha += dot(finalRadianceScaled, vec3<f32>(0.2126, 0.7152, 0.0722));`
}
};
}
const pbrExt = {
id: "ibl",
phase: "ibl",
frag(ctx) {
if (!ctx._hasIbl) {
return null;
}
return createIblFragment(ctx._hasAnyNormal, ctx._anisoBentNormalCode ?? "", ctx._iblSkyboxCalc ?? "");
},
bind(ctx, entries, b) {
if (!ctx._env) {
return b;
}
entries.push({ binding: b++, resource: ctx._env.brdfLutView });
entries.push({ binding: b++, resource: ctx._env.brdfSampler });
entries.push({ binding: b++, resource: ctx._env.specularCubeView });
entries.push({ binding: b++, resource: ctx._env.cubeSampler });
return b;
}
};
export { createIblFragment, pbrExt };
//# sourceMappingURL=ibl-fragment-DmZObtww.esm.js.map