UNPKG

molstar

Version:

A comprehensive macromolecular library.

132 lines (106 loc) 3.62 kB
"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; #include common uniform sampler2D tDepth; uniform vec2 uTexSize; uniform vec4 uBounds; uniform float uNear; uniform float uFar; #if dLightCount != 0 uniform vec3 uLightDirection[dLightCount]; uniform vec3 uLightColor[dLightCount]; #endif 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) { #if dOrthographic == 1 return orthographicDepthToViewZ(depth, uNear, uFar); #else return perspectiveDepthToViewZ(depth, uNear, uFar); #endif } float getDepth(const in vec2 coords) { #ifdef depthTextureSupport return texture2D(tDepth, coords).r; #else return unpackRGBAToDepth(texture2D(tDepth, coords)); #endif } 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; #if dLightCount != 0 vec3 s; #pragma unroll_loop_start for (int i = 0; i < dLightCount; ++i) { s = screenSpaceShadow(selfViewPos, uLightDirection[i], uLightColor[i], stepLength); l += length(s); a += length(uLightColor[i]); } #pragma unroll_loop_end #endif gl_FragColor = vec4(l / a); } `;