molstar
Version:
A comprehensive macromolecular library.
275 lines (230 loc) • 9.15 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.compose_frag = void 0;
exports.compose_frag = `
precision highp float;
precision highp sampler2D;
uniform sampler2D tShaded;
uniform sampler2D tColor;
uniform sampler2D tNormal;
uniform sampler2D tTransparentColor;
uniform sampler2D tSsaoDepth;
uniform sampler2D tSsaoDepthTransparent;
uniform sampler2D tDepthOpaque;
uniform sampler2D tDepthTransparent;
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 float uDenoiseThreshold;
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;
return 1.0;
}
bool isBackground(const in float depth) {
return depth == 1.0;
}
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;
}
//
// TODO: investigate
// https://interplayoflight.wordpress.com/2022/03/26/raytraced-global-illumination-denoising/
//
// https://github.com/BrutPitt/glslSmartDeNoise
//
// smartDeNoise - parameters
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// sampler2D tex - sampler image / texture
// vec2 uv - actual fragment coord
// float sigma > 0 - sigma Standard Deviation
// float kSigma >= 0 - sigma coefficient
// kSigma * sigma --> radius of the circular kernel
// float threshold - edge sharpening threshold
float NormalWeightStrength = 6.0;
vec4 smartDeNoise(sampler2D tex, vec2 uv) {
float sigma = 3.0;
float kSigma = 2.0;
float threshold = uDenoiseThreshold;
vec4 centrPx = texture2D(tex, uv);
if (threshold == 0.0) return centrPx;
float invSigmaQx2 = 0.5 / (sigma * sigma); // 1.0 / (sigma^2 * 2.0)
float invSigmaQx2PI = INV_PI * invSigmaQx2; // 1.0 / (sqrt(PI) * sigma)
float invThresholdSqx2 = 0.5 / (threshold * threshold); // 1.0 / (sigma^2 * 2.0)
float invThresholdSqrt2PI = INV_SQRT_OF_2PI / threshold; // 1.0 / (sqrt(2*PI) * sigma)
float zBuff = 0.0;
vec4 aBuff = vec4(0.0);
vec3 normal = texture2D(tNormal, uv).xyz;
for (int x = -6; x <= 6; ++x) {
for (int y = -6; y <= 6; ++y) {
vec2 d = vec2(float(x), float(y));
float blurFactor = exp(-dot(d , d) * invSigmaQx2) * invSigmaQx2PI;
vec2 uvSample = uv + d / uTexSize;
vec3 normalSample = texture2D(tNormal, uvSample).xyz;
float normalW = saturate(dot(normal, normalSample));
normalW = pow(normalW, NormalWeightStrength);
blurFactor *= normalW;
vec4 walkPx = texture2D(tex, uvSample);
vec4 dC = walkPx - centrPx;
float deltaFactor = exp(-dot(dC, dC) * invThresholdSqx2) * invThresholdSqrt2PI * blurFactor;
zBuff += deltaFactor;
aBuff += deltaFactor * walkPx;
}
}
return aBuff / zBuff;
}
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;
}
void main() {
vec2 coords = gl_FragCoord.xy / uTexSize;
vec4 color = smartDeNoise(tColor, coords);
vec4 color = texture2D(tColor, coords);
float opaqueDepth = getDepthOpaque(coords);
float backgroundViewZ = 2.0 * uFar;
float opaqueSelfViewZ = isBackground(opaqueDepth) ? backgroundViewZ : getViewZ(opaqueDepth);
float fogFactor = smoothstep(uFogNear, uFogFar, abs(opaqueSelfViewZ));
float fogAlpha = 1.0 - fogFactor;
float transparentDepth = 1.0;
bool blendTransparency = true;
vec4 transparentColor = texture2D(tTransparentColor, coords);
transparentDepth = getDepthTransparent(coords);
float alpha = 1.0;
if (!uTransparentBackground) {
// mix opaque objects with background color
color.rgb = mix(color.rgb, uFogColor, fogFactor);
} else {
// pre-multiplied alpha expected for transparent background
alpha = fogAlpha;
color.rgb *= fogAlpha;
}
if (!isBackground(opaqueDepth)) {
float occlusionFactor = getSsao(coords);
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);
transparentColor.rgb = mix(uOcclusionColor * (1.0 - fogFactor), transparentColor.rgb, occlusionFactor);
}
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 {
alpha = 1.0 - fogFactor;
color.rgb = mix(uOutlineColor, vec3(0.0), fogFactor);
}
if (isTransparentOutline == 1.0 || transparentDepth > closestTexel) {
blendTransparency = false;
}
}
if (blendTransparency) {
if (transparentColor.a != 0.0) {
if (isBackground(opaqueDepth)) {
if (uTransparentBackground) {
color = transparentColor;
alpha = transparentColor.a;
} else {
color.rgb = transparentColor.rgb + uFogColor * (1.0 - transparentColor.a);
alpha = 1.0;
}
} else {
// blending
color = transparentColor + color * (1.0 - transparentColor.a);
alpha = transparentColor.a + alpha * (1.0 - transparentColor.a);
}
}
}
gl_FragColor = vec4(color.rgb, alpha);
}
`;