molstar
Version:
A comprehensive macromolecular library.
110 lines (86 loc) • 3.42 kB
JavaScript
/**
* Copyright (c) 2019-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Ludovic Autin <ludovic.autin@gmail.com>
*/
export const ssaoBlur_frag = `
precision highp float;
precision highp int;
precision highp sampler2D;
uniform sampler2D tSsaoDepth;
uniform vec2 uTexSize;
uniform vec4 uBounds;
uniform float uKernel[dOcclusionKernelSize];
uniform float uBlurDepthBias;
uniform float uBlurDirectionX;
uniform float uBlurDirectionY;
uniform mat4 uInvProjection;
uniform float uNear;
uniform float uFar;
float getViewZ(const in float depth) {
return orthographicDepthToViewZ(depth, uNear, uFar);
return perspectiveDepthToViewZ(depth, uNear, uFar);
}
bool isBackground(const in float depth) {
// checking for 1.0 is not enough, because of precision issues
return depth >= 0.999;
}
bool isNearClip(const in float depth) {
return depth == 0.0;
}
bool outsideBounds(const in vec2 p) {
return p.x < uBounds.x || p.y < uBounds.y || p.x > uBounds.z || p.y > uBounds.w;
}
float getPixelSize(const in vec2 coords, const in float depth) {
vec3 viewPos0 = screenSpaceToViewSpace(vec3(coords, depth), uInvProjection);
vec3 viewPos1 = screenSpaceToViewSpace(vec3(coords + vec2(1.0, 0.0) / uTexSize, depth), uInvProjection);
return distance(viewPos0, viewPos1);
}
void main(void) {
vec2 coords = gl_FragCoord.xy / uTexSize;
vec2 packedDepth = texture2D(tSsaoDepth, coords).zw;
if (outsideBounds(coords)) {
gl_FragColor = vec4(packUnitIntervalToRG(1.0), packedDepth);
return;
}
float selfDepth = unpackRGToUnitInterval(packedDepth);
// (if background and if second pass) or if near clip
if ((isBackground(selfDepth) && uBlurDirectionY != 0.0) || isNearClip(selfDepth)) {
gl_FragColor = vec4(packUnitIntervalToRG(1.0), packedDepth);
return;
}
float selfViewZ = getViewZ(selfDepth);
float pixelSize = getPixelSize(coords, selfDepth);
vec2 offset = vec2(uBlurDirectionX, uBlurDirectionY) / uTexSize;
float sum = 0.0;
float kernelSum = 0.0;
// only if kernelSize is odd
for (int i = -dOcclusionKernelSize / 2; i <= dOcclusionKernelSize / 2; i++) {
if (abs(float(i)) > 1.0 && abs(float(i)) * pixelSize > 0.8) continue;
vec2 sampleCoords = coords + float(i) * offset;
if (outsideBounds(sampleCoords)) {
continue;
}
vec4 sampleSsaoDepth = texture2D(tSsaoDepth, sampleCoords);
float sampleDepth = unpackRGToUnitInterval(sampleSsaoDepth.zw);
if (isBackground(sampleDepth) || isNearClip(sampleDepth)) {
continue;
}
float sampleViewZ = getViewZ(sampleDepth);
if (abs(selfViewZ - sampleViewZ) >= uBlurDepthBias) {
continue;
}
float kernel = uKernel[int(abs(float(i)))]; // abs is not defined for int in webgl1
float sampleValue = unpackRGToUnitInterval(sampleSsaoDepth.xy);
sum += kernel * sampleValue;
kernelSum += kernel;
}
gl_FragColor = vec4(packUnitIntervalToRG(sum / kernelSum), packedDepth);
}
`;