UNPKG

@arcgis/core

Version:

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

84 lines (69 loc) 5.32 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */ import{translate as e}from"../core/libs/gl-matrix-2/math/mat4.js";import{create as t}from"../core/libs/gl-matrix-2/factories/mat4f64.js";import{set as o}from"../core/libs/gl-matrix-2/math/vec2.js";import{create as r}from"../core/libs/gl-matrix-2/factories/vec2f64.js";import{Laserline as a}from"../views/3d/webgl-engine/core/shaderLibrary/Laserline.glsl.js";import{Float2BindUniform as i}from"../views/3d/webgl-engine/core/shaderModules/Float2BindUniform.js";import{FloatBindUniform as n}from"../views/3d/webgl-engine/core/shaderModules/FloatBindUniform.js";import{FloatPassUniform as s}from"../views/3d/webgl-engine/core/shaderModules/FloatPassUniform.js";import{If as l,glsl as d}from"../views/3d/webgl-engine/core/shaderModules/glsl.js";import{Matrix4BindUniform as c}from"../views/3d/webgl-engine/core/shaderModules/Matrix4BindUniform.js";import{Matrix4PassUniform as m}from"../views/3d/webgl-engine/core/shaderModules/Matrix4PassUniform.js";import{ShaderBuilder as v}from"../views/webgl/ShaderBuilder.js";function p(t){const r=new v;r.include(a,t);const{vertex:p,fragment:f}=r;p.uniforms.add(new m("modelView",(t,{camera:o})=>e(g,o.viewMatrix,t.origin)),new c("proj",({camera:e})=>e.projectionMatrix),new s("glowWidth",(e,{camera:t})=>e.glowWidth*t.pixelRatio),new i("pixelToNDC",({camera:e})=>o(w,2/e.fullViewport[2],2/e.fullViewport[3]))),r.attributes.add("start","vec3"),r.attributes.add("end","vec3"),t.spherical&&(r.attributes.add("startUp","vec3"),r.attributes.add("endUp","vec3")),r.attributes.add("extrude","vec2"),r.varyings.add("uv","vec2"),r.varyings.add("vViewStart","vec3"),r.varyings.add("vViewEnd","vec3"),r.varyings.add("vViewSegmentNormal","vec3"),r.varyings.add("vViewStartNormal","vec3"),r.varyings.add("vViewEndNormal","vec3");const u=!t.spherical;return p.main.add(d` vec3 pos = mix(start, end, extrude.x); vec4 viewPos = modelView * vec4(pos, 1); vec4 projPos = proj * viewPos; vec2 ndcPos = projPos.xy / projPos.w; // in planar we hardcode the up vectors to be Z-up */ ${l(u,d`vec3 startUp = vec3(0, 0, 1);`)} ${l(u,d`vec3 endUp = vec3(0, 0, 1);`)} // up vector corresponding to the location of the vertex, selecting either startUp or endUp */ vec3 up = extrude.y * mix(startUp, endUp, extrude.x); vec3 viewUp = (modelView * vec4(up, 0)).xyz; vec4 projPosUp = proj * vec4(viewPos.xyz + viewUp, 1); vec2 projUp = normalize(projPosUp.xy / projPosUp.w - ndcPos); // extrude ndcPos along projUp to the edge of the screen vec2 lxy = abs(sign(projUp) - ndcPos); ndcPos += length(lxy) * projUp; vViewStart = (modelView * vec4(start, 1)).xyz; vViewEnd = (modelView * vec4(end, 1)).xyz; vec3 viewStartEndDir = vViewEnd - vViewStart; vec3 viewStartUp = (modelView * vec4(startUp, 0)).xyz; // the normal of the plane that aligns with the segment and the up vector vViewSegmentNormal = normalize(cross(viewStartUp, viewStartEndDir)); // the normal orthogonal to the segment normal and the start up vector vViewStartNormal = -normalize(cross(vViewSegmentNormal, viewStartUp)); // the normal orthogonal to the segment normal and the end up vector vec3 viewEndUp = (modelView * vec4(endUp, 0)).xyz; vViewEndNormal = normalize(cross(vViewSegmentNormal, viewEndUp)); // Add enough padding in the X screen space direction for "glow" float xPaddingPixels = sign(dot(vViewSegmentNormal, viewPos.xyz)) * (extrude.x * 2.0 - 1.0) * glowWidth; ndcPos.x += xPaddingPixels * pixelToNDC.x; // uv is used to read back depth to reconstruct the position at the fragment uv = ndcPos * 0.5 + 0.5; gl_Position = vec4(ndcPos, 0, 1); `),f.uniforms.add(new n("perScreenPixelRatio",e=>e.camera.perScreenPixelRatio)),f.code.add(d`float planeDistance(vec3 planeNormal, vec3 planeOrigin, vec3 pos) { return dot(planeNormal, pos - planeOrigin); } float segmentDistancePixels(vec3 segmentNormal, vec3 startNormal, vec3 endNormal, vec3 pos, vec3 start, vec3 end) { float distSegmentPlane = planeDistance(segmentNormal, start, pos); float distStartPlane = planeDistance(startNormal, start, pos); float distEndPlane = planeDistance(endNormal, end, pos); float dist = max(max(distStartPlane, distEndPlane), abs(distSegmentPlane)); float width = fwidth(distSegmentPlane); float maxPixelDistance = length(pos) * perScreenPixelRatio * 2.0; float pixelDist = dist / min(width, maxPixelDistance); return abs(pixelDist); }`),f.main.add(d`fragColor = vec4(0.0); vec3 dEndStart = vViewEnd - vViewStart; if (dot(dEndStart, dEndStart) < 1e-5) { return; } vec3 pos; vec3 normal; float angleCutoffAdjust; float depthDiscontinuityAlpha; if (!laserlineReconstructFromDepth(pos, normal, angleCutoffAdjust, depthDiscontinuityAlpha)) { return; } float distance = segmentDistancePixels( vViewSegmentNormal, vViewStartNormal, vViewEndNormal, pos, vViewStart, vViewEnd ); vec4 color = laserlineProfile(distance); float alpha = (1.0 - smoothstep(0.995 - angleCutoffAdjust, 0.999 - angleCutoffAdjust, abs(dot(normal, vViewSegmentNormal)))); fragColor = laserlineOutput(color * alpha * depthDiscontinuityAlpha);`),r}const w=r(),g=t(),f=Object.freeze(Object.defineProperty({__proto__:null,build:p},Symbol.toStringTag,{value:"Module"}));export{f as L,p as b};