@doegis/core
Version:
DOE GIS API
110 lines (88 loc) • 5.06 kB
JavaScript
import{c as e}from"../../../../../../chunks/mat4f64.js";import{ReadLinearDepth as o}from"../output/ReadLinearDepth.glsl.js";import{Float2PassUniform as t}from"../../shaderModules/Float2PassUniform.js";import{FloatPassUniform as r}from"../../shaderModules/FloatPassUniform.js";import{glsl as a}from"../../shaderModules/interfaces.js";import{Matrix4PassUniform as i}from"../../shaderModules/Matrix4PassUniform.js";import{Texture2DPassUniform as d}from"../../shaderModules/Texture2DPassUniform.js";function n(e,n){const c=e.fragment;c.include(o),c.uniforms.add(new t("nearFar",((e,o)=>o.camera.nearFar))),c.uniforms.add(new d("depthMap",((e,o)=>o.linearDepthTexture))),c.uniforms.add(new i("proj",((e,o)=>o.ssr.camera.projectionMatrix))),c.uniforms.add(new r("invResolutionHeight",((e,o)=>1/o.ssr.camera.height))),c.uniforms.add(new i("reprojectionMatrix",((e,o)=>o.ssr.reprojectionMatrix))),c.code.add(a`
vec2 reprojectionCoordinate(vec3 projectionCoordinate)
{
vec4 zw = proj * vec4(0.0, 0.0, -projectionCoordinate.z, 1.0);
vec4 reprojectedCoord = reprojectionMatrix * vec4(zw.w * (projectionCoordinate.xy * 2.0 - 1.0), zw.z, zw.w);
reprojectedCoord.xy /= reprojectedCoord.w;
return reprojectedCoord.xy * 0.5 + 0.5;
}
const int maxSteps = ${n.highStepCount?"150":"75"};
vec4 applyProjectionMat(mat4 projectionMat, vec3 x)
{
vec4 projectedCoord = projectionMat * vec4(x, 1.0);
projectedCoord.xy /= projectedCoord.w;
projectedCoord.xy = projectedCoord.xy*0.5 + 0.5;
return projectedCoord;
}
vec3 screenSpaceIntersection(vec3 dir, vec3 startPosition, vec3 viewDir, vec3 normal)
{
vec3 viewPos = startPosition;
vec3 viewPosEnd = startPosition;
// Project the start position to the screen
vec4 projectedCoordStart = applyProjectionMat(proj, viewPos);
vec3 Q0 = viewPos / projectedCoordStart.w; // homogeneous camera space
float k0 = 1.0/ projectedCoordStart.w;
// advance the position in the direction of the reflection
viewPos += dir;
vec4 projectedCoordVanishingPoint = applyProjectionMat(proj, dir);
// Project the advanced position to the screen
vec4 projectedCoordEnd = applyProjectionMat(proj, viewPos);
vec3 Q1 = viewPos / projectedCoordEnd.w; // homogeneous camera space
float k1 = 1.0/ projectedCoordEnd.w;
// calculate the reflection direction in the screen space
vec2 projectedCoordDir = (projectedCoordEnd.xy - projectedCoordStart.xy);
vec2 projectedCoordDistVanishingPoint = (projectedCoordVanishingPoint.xy - projectedCoordStart.xy);
float yMod = min(abs(projectedCoordDistVanishingPoint.y), 1.0);
float projectedCoordDirLength = length(projectedCoordDir);
float maxSt = float(maxSteps);
// normalize the projection direction depending on maximum steps
// this determines how blocky the reflection looks
vec2 dP = yMod * (projectedCoordDir)/(maxSt * projectedCoordDirLength);
// Normalize the homogeneous camera space coordinates
vec3 dQ = yMod * (Q1 - Q0)/(maxSt * projectedCoordDirLength);
float dk = yMod * (k1 - k0)/(maxSt * projectedCoordDirLength);
// initialize the variables for ray marching
vec2 P = projectedCoordStart.xy;
vec3 Q = Q0;
float k = k0;
float rayStartZ = -startPosition.z; // estimated ray start depth value
float rayEndZ = -startPosition.z; // estimated ray end depth value
float prevEstimateZ = -startPosition.z;
float rayDiffZ = 0.0;
float dDepth;
float depth;
float rayDiffZOld = 0.0;
// early outs
if (dot(normal, dir) < 0.0 || dot(-viewDir, normal) < 0.0)
return vec3(P, 0.0);
for(int i = 0; i < maxSteps-1; i++)
{
depth = -linearDepthFromTexture(depthMap, P, nearFar); // get linear depth from the depth buffer
// estimate depth of the marching ray
rayStartZ = prevEstimateZ;
dDepth = -rayStartZ - depth;
rayEndZ = (dQ.z * 0.5 + Q.z)/ ((dk * 0.5 + k));
rayDiffZ = rayEndZ- rayStartZ;
prevEstimateZ = rayEndZ;
if(-rayEndZ > nearFar[1] || -rayEndZ < nearFar[0] || P.y < 0.0 || P.y > 1.0 )
{
return vec3(P, 0.);
}
// If we detect a hit - return the intersection point, two conditions:
// - dDepth > 0.0 - sampled point depth is in front of estimated depth
// - if difference between dDepth and rayDiffZOld is not too large
// - if difference between dDepth and 0.025/abs(k) is not too large
// - if the sampled depth is not behind far plane or in front of near plane
if((dDepth) < 0.025/abs(k) + abs(rayDiffZ) && dDepth > 0.0 && depth > nearFar[0] && depth < nearFar[1] && abs(P.y - projectedCoordStart.y) > invResolutionHeight)
{
return vec3(P, depth);
}
// continue with ray marching
P += dP;
Q.z += dQ.z;
k += dk;
rayDiffZOld = rayDiffZ;
}
return vec3(P, 0.0);
}
`)}class c{constructor(){this.enabled=!1,this.fadeFactor=1,this.reprojectionMatrix=e()}}export{c as SSRUniforms,n as ScreenSpaceReflections};