@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
168 lines (140 loc) • 12 kB
JavaScript
/*
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};