playcanvas
Version:
PlayCanvas WebGL game engine
48 lines (46 loc) • 1.78 kB
JavaScript
var reflectionEnvPS = `
#ifndef ENV_ATLAS
#define ENV_ATLAS
var texture_envAtlas: texture_2d<f32>;
var texture_envAtlasSampler: sampler;
#endif
uniform material_reflectivity: f32;
fn shinyMipLevel(uv: vec2f) -> f32 {
let dx: vec2f = dpdx(uv);
let dy: vec2f = dpdy(uv);
let uv2: vec2f = vec2f(fract(uv.x + 0.5), uv.y);
let dx2: vec2f = dpdx(uv2);
let dy2: vec2f = dpdy(uv2);
let maxd: f32 = min(max(dot(dx, dx), dot(dy, dy)), max(dot(dx2, dx2), dot(dy2, dy2)));
return clamp(0.5 * log2(maxd) - 1.0 + uniform.textureBias, 0.0, 5.0);
}
fn calcReflection(reflDir: vec3f, gloss: f32) -> vec3f {
let dir: vec3f = cubeMapProject(reflDir) * vec3f(-1.0, 1.0, 1.0);
let uv: vec2f = toSphericalUv(dir);
let level: f32 = saturate(1.0 - gloss) * 5.0;
let ilevel: f32 = floor(level);
let level2: f32 = shinyMipLevel(uv * atlasSize);
let ilevel2: f32 = floor(level2);
var uv0: vec2f;
var uv1: vec2f;
var weight: f32;
if (ilevel == 0.0) {
uv0 = mapShinyUv(uv, ilevel2);
uv1 = mapShinyUv(uv, ilevel2 + 1.0);
weight = level2 - ilevel2;
} else {
uv0 = mapRoughnessUv(uv, ilevel);
uv1 = uv0;
weight = 0.0;
}
let linearA: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, uv0));
let linearB: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, uv1));
let linear0: vec3f = mix(linearA, linearB, weight);
let linear1: vec3f = {reflectionDecode}(textureSample(texture_envAtlas, texture_envAtlasSampler, mapRoughnessUv(uv, ilevel + 1.0)));
return processEnvironment(mix(linear0, linear1, level - ilevel));
}
fn addReflection(reflDir: vec3f, gloss: f32) {
dReflection = dReflection + vec4f(calcReflection(reflDir, gloss), uniform.material_reflectivity);
}
`;
export { reflectionEnvPS as default };