molstar
Version:
A comprehensive macromolecular library.
200 lines (175 loc) • 6.92 kB
JavaScript
"use strict";
/**
* Copyright (c) 2019-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
* @author Áron Samuel Kovács <aron.kovacs@mail.muni.cz>
* @author Gianluca Tomasello <giagitom@gmail.com>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.postprocessing_frag = void 0;
exports.postprocessing_frag = `
precision highp float;
precision highp int;
precision highp sampler2D;
uniform sampler2D tSsaoDepth;
uniform sampler2D tSsaoDepthTransparent;
uniform sampler2D tColor;
uniform sampler2D tTransparentColor;
uniform sampler2D tDepthOpaque;
uniform sampler2D tDepthTransparent;
uniform sampler2D tShadows;
uniform sampler2D tOutlines;
uniform vec2 uTexSize;
uniform float uNear;
uniform float uFar;
uniform float uFogNear;
uniform float uFogFar;
uniform vec3 uFogColor;
uniform vec3 uOutlineColor;
uniform vec3 uOcclusionColor;
uniform bool uTransparentBackground;
uniform vec2 uOcclusionOffset;
float getViewZ(const in float depth) {
return orthographicDepthToViewZ(depth, uNear, uFar);
return perspectiveDepthToViewZ(depth, uNear, uFar);
}
float getDepthOpaque(const in vec2 coords) {
return texture2D(tDepthOpaque, coords).r;
return unpackRGBAToDepth(texture2D(tDepthOpaque, coords));
}
float getDepthTransparent(const in vec2 coords) {
return unpackRGBAToDepthWithAlpha(texture2D(tDepthTransparent, coords)).x;
}
bool isBackground(const in float depth) {
return depth > 0.999; // handle depth packing precision issues
}
int squaredOutlineScale = dOutlineScale * dOutlineScale;
float getOutline(const in vec2 coords, const in float opaqueDepth, const in float transparentDepth, out float closestTexel, out float isTransparent) {
vec2 invTexSize = 1.0 / uTexSize;
float outline = 1.0;
closestTexel = 1.0;
isTransparent = 0.0;
for (int y = -dOutlineScale; y <= dOutlineScale; y++) {
for (int x = -dOutlineScale; x <= dOutlineScale; x++) {
if (x * x + y * y > squaredOutlineScale) {
continue;
}
vec2 sampleCoords = coords + vec2(float(x), float(y)) * invTexSize;
vec4 sampleOutlineCombined = texture2D(tOutlines, sampleCoords);
float sampleOutline = sampleOutlineCombined.r;
float sampleOutlineDepth = unpackRGToUnitInterval(sampleOutlineCombined.gb);
if (sampleOutline == 0.0 && sampleOutlineDepth < closestTexel) {
outline = 0.0;
closestTexel = sampleOutlineDepth;
isTransparent = sampleOutlineCombined.a;
}
}
}
return isTransparent == 0.0 ? outline : (closestTexel > opaqueDepth && closestTexel < transparentDepth) ? 1.0 : outline;
}
float getSsao(vec2 coords) {
float rawSsao = unpackRGToUnitInterval(texture2D(tSsaoDepth, coords).xy);
if (rawSsao > 0.999) {
return 1.0;
} else if (rawSsao > 0.001) {
return rawSsao;
}
// treat values close to 0.0 as errors and return no occlusion
return 1.0;
}
float getSsaoTransparent(vec2 coords) {
float rawSsao = unpackRGToUnitInterval(texture2D(tSsaoDepthTransparent, coords).xy);
if (rawSsao > 0.999) {
return 1.0;
} else if (rawSsao > 0.001) {
return rawSsao;
}
// treat values close to 0.0 as errors and return no occlusion
return 1.0;
}
void main(void) {
vec2 coords = gl_FragCoord.xy / uTexSize;
vec4 color = texture2D(tColor, coords);
float opaqueDepth = getDepthOpaque(coords);
float transparentDepth = 1.0;
bool blendTransparency = true;
vec4 transparentColor = texture2D(tTransparentColor, coords);
transparentDepth = getDepthTransparent(coords);
bool isOpaqueBackground = isBackground(opaqueDepth);
float viewDist = abs(getViewZ(opaqueDepth));
float fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
if (!isOpaqueBackground) {
float occlusionFactor = getSsao(coords + uOcclusionOffset);
if (!uTransparentBackground) {
color.rgb = mix(mix(uOcclusionColor, uFogColor, fogFactor), color.rgb, occlusionFactor);
} else {
color.rgb = mix(uOcclusionColor * (1.0 - fogFactor), color.rgb, occlusionFactor);
}
}
if (!isBackground(transparentDepth)) {
float viewDist = abs(getViewZ(transparentDepth));
float fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
float occlusionFactor = getSsaoTransparent(coords + uOcclusionOffset);
transparentColor.rgb = mix(uOcclusionColor * (1.0 - fogFactor), transparentColor.rgb, occlusionFactor);
}
if (!isOpaqueBackground) {
vec4 shadow = texture2D(tShadows, coords);
if (!uTransparentBackground) {
color.rgb = mix(mix(vec3(0), uFogColor, fogFactor), color.rgb, shadow.a);
} else {
color.rgb = mix(vec3(0) * (1.0 - fogFactor), color.rgb, shadow.a);
}
}
// outline needs to be handled after occlusion and shadow to keep them clean
float closestTexel;
float isTransparentOutline;
float outline = getOutline(coords, opaqueDepth, transparentDepth, closestTexel, isTransparentOutline);
if (outline == 0.0) {
float viewDist = abs(getViewZ(closestTexel));
float fogFactor = smoothstep(uFogNear, uFogFar, viewDist);
if (!uTransparentBackground) {
color.rgb = mix(uOutlineColor, uFogColor, fogFactor);
} else {
color.a = 1.0 - fogFactor;
color.rgb = mix(uOutlineColor, vec3(0.0), fogFactor);
}
if (isTransparentOutline == 1.0 || transparentDepth > closestTexel) {
blendTransparency = false;
}
}
if (blendTransparency) {
float alpha = transparentColor.a;
if (alpha != 0.0) {
// blending
color = transparentColor + color * (1.0 - alpha);
}
}
gl_FragColor = color;
}
`;