molstar
Version:
A comprehensive macromolecular library.
132 lines (106 loc) • 3.62 kB
JavaScript
"use strict";
/**
* Copyright (c) 2022-2024 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Ludovic Autin <ludovic.autin@gmail.com>
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.shadows_frag = void 0;
exports.shadows_frag = `
precision highp float;
precision highp int;
precision highp sampler2D;
uniform sampler2D tDepth;
uniform vec2 uTexSize;
uniform vec4 uBounds;
uniform float uNear;
uniform float uFar;
uniform vec3 uLightDirection[dLightCount];
uniform vec3 uLightColor[dLightCount];
uniform vec3 uAmbientColor;
uniform mat4 uProjection;
uniform mat4 uInvProjection;
uniform float uMaxDistance;
uniform float uTolerance;
bool isBackground(const in float depth) {
return depth == 1.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 getViewZ(const in float depth) {
return orthographicDepthToViewZ(depth, uNear, uFar);
return perspectiveDepthToViewZ(depth, uNear, uFar);
}
float getDepth(const in vec2 coords) {
return texture2D(tDepth, coords).r;
return unpackRGBAToDepth(texture2D(tDepth, coords));
}
float screenFade(const in vec2 coords) {
vec2 c = (coords - uBounds.xy) / (uBounds.zw - uBounds.xy);
vec2 fade = max(12.0 * abs(c - 0.5) - 5.0, vec2(0.0));
return saturate(1.0 - dot(fade, fade));
}
// based on https://panoskarabelas.com/posts/screen_space_shadows/
vec3 screenSpaceShadow(const in vec3 position, const in vec3 lightDirection, const in vec3 lightColor, const in float stepLength) {
// Ray position and direction (in view-space)
vec3 rayPos = position;
vec3 rayDir = -lightDirection;
// Compute ray step
vec3 rayStep = rayDir * stepLength;
// Ray march towards the light
vec4 rayCoords = vec4(0.0);
for (int i = 0; i < dSteps; ++i) {
// Step the ray
rayPos += rayStep;
rayCoords = uProjection * vec4(rayPos, 1.0);
rayCoords.xyz = (rayCoords.xyz / rayCoords.w) * 0.5 + 0.5;
if (outsideBounds(rayCoords.xy)) {
return lightColor;
}
// Compute the difference between the ray's and the camera's depth
float depth = getDepth(rayCoords.xy);
float viewZ = getViewZ(depth);
float zDelta = rayPos.z - viewZ;
if (zDelta < uTolerance) {
// Fade out as we approach the edges of the screen
return mix(vec3(0.0), lightColor, 1.0 - screenFade(rayCoords.xy));
}
}
return lightColor;
}
void main(void) {
vec2 invTexSize = 1.0 / uTexSize;
vec2 selfCoords = gl_FragCoord.xy * invTexSize;
float selfDepth = getDepth(selfCoords);
if (isBackground(selfDepth)) {
gl_FragColor = vec4(0.0);
return;
}
vec3 selfViewPos = screenSpaceToViewSpace(vec3(selfCoords, selfDepth), uInvProjection);
float stepLength = uMaxDistance / float(dSteps);
float l = length(uAmbientColor);
float a = l;
vec3 s;
for (int i = 0; i < dLightCount; ++i) {
s = screenSpaceShadow(selfViewPos, uLightDirection[i], uLightColor[i], stepLength);
l += length(s);
a += length(uLightColor[i]);
}
gl_FragColor = vec4(l / a);
}
`;