pex-renderer
Version:
Physically Based Renderer for Pex
50 lines (44 loc) • 1.46 kB
JavaScript
module.exports = /* glsl */ `
vec2 envMapOctahedral(vec3 dir) {
dir /= dot(vec3(1.0), abs(dir));
// Add epsylon to avoid bottom face flickering when sampling irradiance
dir += 0.00001;
if (dir.y < 0.0) {
dir.xy = vec2(1.0 - abs(dir.zx)) * sign(dir.xz);
}
else {
dir.xy = dir.xz;
}
dir.xy = dir.xy * 0.5;
dir.xy += 0.5; // move to center
// dir.xy = (dir.xy * 64.0 + 1.0) / 66.0;
return dir.xy;
}
vec2 envMapOctahedral(vec3 dir, float textureSize) {
dir /= dot(vec3(1.0), abs(dir));
if (dir.y < 0.0) {
dir.xy = vec2(1.0 - abs(dir.zx)) * sign(dir.xz);
}
else {
dir.xy = dir.xz;
}
dir.xy = dir.xy * 0.5;
dir.xy += 0.5; // move to center
// center on texels
dir.xy += 0.5 / textureSize;
dir.xy /= textureSize / (textureSize - 1.0);
return dir.xy;
}
vec2 envMapOctahedral(vec3 dir, float mipmapLevel, float roughnessLevel) {
float width = 2048.0;
float maxLevel = 11.0; // this should come from log of size
float levelSizeInPixels = pow(2.0, 1.0 + mipmapLevel + roughnessLevel);
float levelSize = max(64.0, width / levelSizeInPixels);
float roughnessLevelWidth = width / pow(2.0, 1.0 + roughnessLevel);
float vOffset = (width - pow(2.0, maxLevel - roughnessLevel));
float hOffset = 2.0 * roughnessLevelWidth - pow(2.0, log2(2.0 * roughnessLevelWidth) - mipmapLevel);
vec2 uv = envMapOctahedral(dir, levelSize);
uv *= levelSize;
return (uv + vec2(hOffset, vOffset)) / width;
}
`