UNPKG

molstar

Version:

A comprehensive macromolecular library.

275 lines (230 loc) 9.15 kB
"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; #include common float getViewZ(const in float depth) { #if dOrthographic == 1 return orthographicDepthToViewZ(depth, uNear, uFar); #else return perspectiveDepthToViewZ(depth, uNear, uFar); #endif } float getDepthOpaque(const in vec2 coords) { #ifdef depthTextureSupport return texture2D(tDepthOpaque, coords).r; #else return unpackRGBAToDepth(texture2D(tDepthOpaque, coords)); #endif } float getDepthTransparent(const in vec2 coords) { #if defined(dTransparentOutline) || defined(dOcclusionEnable) return unpackRGBAToDepthWithAlpha(texture2D(tDepthTransparent, coords)).x; #else return 1.0; #endif } 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/ // #define INV_SQRT_OF_2PI 0.39894228040143267793994605993439 // 1.0/SQRT_OF_2PI #define INV_PI 0.31830988618379067153776752674503 // 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; #ifdef dDenoise vec4 color = smartDeNoise(tColor, coords); #else vec4 color = texture2D(tColor, coords); #endif 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; #ifdef dBlendTransparency bool blendTransparency = true; vec4 transparentColor = texture2D(tTransparentColor, coords); transparentDepth = getDepthTransparent(coords); #endif 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 defined(dOcclusionEnable) 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); } } #ifdef dBlendTransparency 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); } #endif #endif #ifdef dOutlineEnable 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); } #ifdef dBlendTransparency if (isTransparentOutline == 1.0 || transparentDepth > closestTexel) { blendTransparency = false; } #endif } #endif #ifdef dBlendTransparency 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); } } } #endif gl_FragColor = vec4(color.rgb, alpha); } `;