UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

119 lines (98 loc) 5.21 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */ import{ReadDepth as e}from"../output/ReadDepth.glsl.js";import{Float2BindUniform as t}from"../../shaderModules/Float2BindUniform.js";import{FloatBindUniform as o}from"../../shaderModules/FloatBindUniform.js";import{glsl as r}from"../../shaderModules/glsl.js";import{Matrix4BindUniform as i}from"../../shaderModules/Matrix4BindUniform.js";import{Texture2DBindUniform as a}from"../../shaderModules/Texture2DBindUniform.js";function d(d,n){if(!n.screenSpaceReflections)return;const c=d.fragment;c.include(e),c.uniforms.add(new t("nearFar",e=>e.camera.nearFar),new a("depthMap",e=>e.depth?.attachment),new i("proj",e=>e.camera.projectionMatrix),new o("invResolutionHeight",e=>1/e.camera.height),new i("reprojectionMatrix",e=>e.ssr.reprojectionMatrix)).code.add(r` 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); float dDepthBefore = 0.0; for(int i = 0; i < maxSteps-1; i++) { depth = -linearDepthFromTexture(depthMap, P); // 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) { float weight = dDepth / (dDepth - dDepthBefore); vec2 Pf = mix(P - dP, P, 1.0 - weight); if (abs(Pf.y - projectedCoordStart.y) > invResolutionHeight) { return vec3(Pf, depth); } else { return vec3(P, depth); } } // continue with ray marching P = clamp(P + dP, vec2(0.0), vec2(0.999)); Q.z += dQ.z; k += dk; rayDiffZOld = rayDiffZ; dDepthBefore = dDepth; } return vec3(P, 0.0); } `)}export{d as ScreenSpaceReflections};