UNPKG

@arcgis/core

Version:

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

168 lines (140 loc) • 12 kB
/* All material copyright ESRI, All Rights Reserved, unless otherwise specified. See https://js.arcgis.com/4.32/esri/copyright.txt for details. */ import{set as e,copy as o}from"../core/libs/gl-matrix-2/math/vec2.js";import{create as i}from"../core/libs/gl-matrix-2/factories/vec2f64.js";import{ZEROS as r,fromValues as l}from"../core/libs/gl-matrix-2/factories/vec4f64.js";import{earth as t}from"../geometry/support/Ellipsoid.js";import{ShaderOutput as a}from"../views/3d/webgl-engine/core/shaderLibrary/ShaderOutput.js";import{RejectBySlice as s}from"../views/3d/webgl-engine/core/shaderLibrary/Slice.glsl.js";import{ObjectAndLayerIdColor as n}from"../views/3d/webgl-engine/core/shaderLibrary/attributes/ObjectAndLayerIdColor.glsl.js";import{AlignPixel as c}from"../views/3d/webgl-engine/core/shaderLibrary/hud/AlignPixel.glsl.js";import{HUD as d}from"../views/3d/webgl-engine/core/shaderLibrary/hud/HUD.glsl.js";import{HUDOcclusionPass as u}from"../views/3d/webgl-engine/core/shaderLibrary/hud/HUDOcclusionPass.glsl.js";import{HUDVisibility as p}from"../views/3d/webgl-engine/core/shaderLibrary/hud/HUDVisibility.glsl.js";import{OutputHighlight as f}from"../views/3d/webgl-engine/core/shaderLibrary/output/OutputHighlight.glsl.js";import{VisualVariables as g}from"../views/3d/webgl-engine/core/shaderLibrary/shading/VisualVariables.glsl.js";import{ColorConversion as m}from"../views/3d/webgl-engine/core/shaderLibrary/util/ColorConversion.glsl.js";import{RgbaFloatEncoding as v}from"../views/3d/webgl-engine/core/shaderLibrary/util/RgbaFloatEncoding.glsl.js";import{ScreenSizePerspective as b,addScreenSizePerspective as h,addScreenSizePerspectiveAlignment as w}from"../views/3d/webgl-engine/core/shaderLibrary/util/ScreenSizePerspective.glsl.js";import{addPixelRatio as x}from"../views/3d/webgl-engine/core/shaderLibrary/util/View.glsl.js";import{Float2PassUniform as C}from"../views/3d/webgl-engine/core/shaderModules/Float2PassUniform.js";import{Float4BindUniform as P}from"../views/3d/webgl-engine/core/shaderModules/Float4BindUniform.js";import{Float4DrawUniform as z}from"../views/3d/webgl-engine/core/shaderModules/Float4DrawUniform.js";import{Float4PassUniform as j}from"../views/3d/webgl-engine/core/shaderModules/Float4PassUniform.js";import{FloatBindUniform as S}from"../views/3d/webgl-engine/core/shaderModules/FloatBindUniform.js";import{FloatPassUniform as y}from"../views/3d/webgl-engine/core/shaderModules/FloatPassUniform.js";import{glsl as A,If as O}from"../views/3d/webgl-engine/core/shaderModules/glsl.js";import{Texture2DBindUniform as $}from"../views/3d/webgl-engine/core/shaderModules/Texture2DBindUniform.js";import{Texture2DPassUniform as F}from"../views/3d/webgl-engine/core/shaderModules/Texture2DPassUniform.js";import{OITPass as D}from"../views/3d/webgl-engine/lib/OITPass.js";import{VertexAttribute as T}from"../views/3d/webgl-engine/lib/VertexAttribute.js";import{ShaderBuilder as L}from"../views/webgl/ShaderBuilder.js";import{alphaCutoff as B}from"../webscene/support/AlphaCutoff.js";function E(o){const i=new L,E=o.signedDistanceFieldEnabled;i.include(d,o),i.vertex.include(s,o);const{occlusionPass:H,output:V,oitPass:_}=o;if(H)return i.include(u,o),i;const{vertex:I,fragment:q}=i;i.include(b),i.include(g,o),i.include(n,o),i.include(p),q.include(v),q.include(m),i.varyings.add("vcolor","vec4"),i.varyings.add("vtc","vec2"),i.varyings.add("vsize","vec2");const k=V===a.Highlight,G=k&&o.occlusionTestEnabled;G&&i.varyings.add("voccluded","float"),I.uniforms.add(new P("viewport",(e=>e.camera.fullViewport)),new C("screenOffset",((o,i)=>e(R,2*o.screenOffset[0]*i.camera.pixelRatio,2*o.screenOffset[1]*i.camera.pixelRatio))),new C("anchorPosition",(e=>U(e))),new j("materialColor",(e=>e.color)),new y("materialRotation",(e=>e.rotation))),x(I),E&&(I.uniforms.add(new j("outlineColor",(e=>e.outlineColor))),q.uniforms.add(new j("outlineColor",(e=>M(e)?e.outlineColor:r)),new y("outlineSize",(e=>M(e)?e.outlineSize:0)))),o.horizonCullingEnabled&&I.uniforms.add(new z("pointDistanceSphere",((e,o)=>{const i=o.camera.eye,r=e.origin;return l(r[0]-i[0],r[1]-i[1],r[2]-i[2],t.radius)}))),o.pixelSnappingEnabled&&I.include(c),o.hasScreenSizePerspective&&(h(I),w(I)),o.debugDrawLabelBorder&&i.varyings.add("debugBorderCoords","vec4"),i.attributes.add(T.UV0,"vec2"),i.attributes.add(T.COLOR,"vec4"),i.attributes.add(T.SIZE,"vec2"),i.attributes.add(T.ROTATION,"float"),i.attributes.add(T.FEATUREATTRIBUTE,"vec4"),I.code.add(o.horizonCullingEnabled?A`bool behindHorizon(vec3 posModel) { vec3 camToEarthCenter = pointDistanceSphere.xyz - localOrigin; vec3 camToPos = pointDistanceSphere.xyz + posModel; float earthRadius = pointDistanceSphere.w; float a = dot(camToPos, camToPos); float b = dot(camToPos, camToEarthCenter); float c = dot(camToEarthCenter, camToEarthCenter) - earthRadius * earthRadius; return b > 0.0 && b < a && b * b > a * c; }`:A`bool behindHorizon(vec3 posModel) { return false; }`),I.main.add(A` ProjectHUDAux projectAux; vec4 posProj = projectPositionHUD(projectAux); forwardObjectAndLayerIdColor(); if (rejectBySlice(projectAux.posModel)) { // Project outside of clip plane gl_Position = vec4(1e038, 1e038, 1e038, 1.0); return; } if (behindHorizon(projectAux.posModel)) { // Project outside of clip plane gl_Position = vec4(1e038, 1e038, 1e038, 1.0); return; } vec2 inputSize; ${O(o.hasScreenSizePerspective,A` inputSize = screenSizePerspectiveScaleVec2(size, projectAux.absCosAngle, projectAux.distanceToCamera, screenSizePerspective); vec2 screenOffsetScaled = screenSizePerspectiveScaleVec2(screenOffset, projectAux.absCosAngle, projectAux.distanceToCamera, screenSizePerspectiveAlignment);`,A` inputSize = size; vec2 screenOffsetScaled = screenOffset;`)} ${O(o.vvSize,A`inputSize *= vvScale(featureAttribute).xx;`)} vec2 combinedSize = inputSize * pixelRatio; vec4 quadOffset = vec4(0.0); ${O(o.occlusionTestEnabled,A` bool visible = testHUDVisibility(posProj); if (!visible) { vtc = vec2(0.0); ${O(o.debugDrawLabelBorder,"debugBorderCoords = vec4(0.5, 0.5, 1.5 / combinedSize);")} return; }`)} ${O(G,A`voccluded = visible ? 0.0 : 1.0;`)} `);const N=A` vec2 uv01 = floor(uv0); vec2 uv = uv0 - uv01; quadOffset.xy = (uv01 - anchorPosition) * 2.0 * combinedSize; ${O(o.hasRotation,A` float angle = radians(materialRotation + rotation); float cosAngle = cos(angle); float sinAngle = sin(angle); mat2 rotate = mat2(cosAngle, -sinAngle, sinAngle, cosAngle); quadOffset.xy = rotate * quadOffset.xy; `)} quadOffset.xy = (quadOffset.xy + screenOffsetScaled) / viewport.zw * posProj.w; `,Z=o.pixelSnappingEnabled?E?A`posProj = alignToPixelOrigin(posProj, viewport.zw) + quadOffset;`:A`posProj += quadOffset; if (inputSize.x == size.x) { posProj = alignToPixelOrigin(posProj, viewport.zw); }`:A`posProj += quadOffset;`;I.main.add(A` ${N} ${o.vvColor?"vcolor = interpolateVVColor(featureAttribute.y) * materialColor;":"vcolor = color / 255.0 * materialColor;"} ${O(V===a.ObjectAndLayerIdColor,A`vcolor.a = 1.0;`)} bool alphaDiscard = vcolor.a < ${A.float(B)}; ${O(E,`alphaDiscard = alphaDiscard && outlineColor.a < ${A.float(B)};`)} if (alphaDiscard) { // "early discard" if both symbol color (= fill) and outline color (if applicable) are transparent gl_Position = vec4(1e38, 1e38, 1e38, 1.0); return; } else { ${Z} gl_Position = posProj; } vtc = uv; ${O(o.debugDrawLabelBorder,A`debugBorderCoords = vec4(uv01, 1.5 / combinedSize);`)} vsize = inputSize; `),q.uniforms.add(new F("tex",(e=>e.texture))),o.occludedFragmentFade&&(q.uniforms.add(new $("depthMap",(e=>e.mainDepth))),q.uniforms.add(new S("occludedOpacity",(e=>e.hudOccludedFragmentOpacity))));const J=o.debugDrawLabelBorder?A`(isBorder > 0.0 ? 0.0 : ${A.float(B)})`:A.float(B),K=A` ${O(o.debugDrawLabelBorder,A`float isBorder = float(any(lessThan(debugBorderCoords.xy, debugBorderCoords.zw)) || any(greaterThan(debugBorderCoords.xy, 1.0 - debugBorderCoords.zw)));`)} ${O(o.sampleSignedDistanceFieldTexelCenter,A` float txSize = float(textureSize(tex, 0).x); float texelSize = 1.0 / txSize; // Calculate how much we have to add/subtract to/from each texel to reach the size of an onscreen pixel vec2 scaleFactor = (vsize - txSize) * texelSize; vec2 samplePos = vtc + (vec2(1.0, -1.0) * texelSize) * scaleFactor;`,A`vec2 samplePos = vtc;`)} ${E?A` vec4 fillPixelColor = vcolor; // Get distance and map it into [-0.5, 0.5] float d = rgbaTofloat(texture(tex, samplePos)) - 0.5; // Distance in output units (i.e. pixels) float dist = d * vsize.x; // Create smooth transition from the icon into its outline float fillAlphaFactor = clamp(0.5 - dist, 0.0, 1.0); fillPixelColor.a *= fillAlphaFactor; if (outlineSize > 0.25) { vec4 outlinePixelColor = outlineColor; float clampedOutlineSize = min(outlineSize, 0.5*vsize.x); // Create smooth transition around outline float outlineAlphaFactor = clamp(0.5 - (abs(dist) - 0.5*clampedOutlineSize), 0.0, 1.0); outlinePixelColor.a *= outlineAlphaFactor; if ( outlineAlphaFactor + fillAlphaFactor < ${J} || fillPixelColor.a + outlinePixelColor.a < ${A.float(B)} ) { discard; } // perform un-premultiplied over operator (see https://en.wikipedia.org/wiki/Alpha_compositing#Description) float compositeAlpha = outlinePixelColor.a + fillPixelColor.a * (1.0 - outlinePixelColor.a); vec3 compositeColor = vec3(outlinePixelColor) * outlinePixelColor.a + vec3(fillPixelColor) * fillPixelColor.a * (1.0 - outlinePixelColor.a); ${O(!k,A`fragColor = vec4(compositeColor, compositeAlpha);`)} } else { if (fillAlphaFactor < ${J}) { discard; } ${O(!k,A`fragColor = premultiplyAlpha(fillPixelColor);`)} } // visualize SDF: // fragColor = vec4(clamp(-dist/vsize.x*2.0, 0.0, 1.0), clamp(dist/vsize.x*2.0, 0.0, 1.0), 0.0, 1.0); `:A` vec4 texColor = texture(tex, vtc, -0.5); if (texColor.a < ${J}) { discard; } ${O(!k,A`fragColor = texColor * premultiplyAlpha(vcolor);`)} `} ${O(o.occludedFragmentFade&&!k,A` float zSample = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x; if (zSample < gl_FragCoord.z) { fragColor *= occludedOpacity; } `)} ${O(!k&&o.debugDrawLabelBorder,A`fragColor = mix(fragColor, vec4(1.0, 0.0, 1.0, 1.0), isBorder * 0.5);`)} `;switch(V){case a.Color:case a.ColorEmission:i.outputs.add("fragColor","vec4",0),V===a.ColorEmission&&i.outputs.add("fragEmission","vec4",1),_===D.ColorAlpha&&i.outputs.add("fragAlpha","float",V===a.ColorEmission?2:1),q.main.add(A` ${K} ${O(_===D.FrontFace,A`fragColor.rgb /= fragColor.a;`)} ${O(V===a.ColorEmission,A`fragEmission = vec4(0.0);`)} ${O(_===D.ColorAlpha,A`fragAlpha = fragColor.a;`)}`);break;case a.ObjectAndLayerIdColor:q.main.add(A` ${K} outputObjectAndLayerIdColor();`);break;case a.Highlight:i.include(f,o),q.main.add(A` ${K} outputHighlight(${O(G,A`voccluded == 1.0`,A`false`)});`)}return i}function M(e){return e.outlineColor[3]>0&&e.outlineSize>0}function U(e){return e.textureIsSignedDistanceField?H(e.anchorPosition,e.distanceFieldBoundingBox,R):o(R,e.anchorPosition),R}function H(o,i,r){e(r,o[0]*(i[2]-i[0])+i[0],o[1]*(i[3]-i[1])+i[1])}const R=i(),V=Object.freeze(Object.defineProperty({__proto__:null,build:E,calculateAnchorPosition:U},Symbol.toStringTag,{value:"Module"}));export{V as H,E as b,U as c};