@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
173 lines (144 loc) • 12 kB
JavaScript
/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.33/esri/copyright.txt for details.
*/
import{copy as e,set 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 t}from"../core/libs/gl-matrix-2/factories/vec4f64.js";import{earth as l}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 f}from"../views/3d/webgl-engine/core/shaderLibrary/hud/HUDVisibility.glsl.js";import{OutputHighlight as p}from"../views/3d/webgl-engine/core/shaderLibrary/output/OutputHighlight.glsl.js";import{VisualVariables as m}from"../views/3d/webgl-engine/core/shaderLibrary/shading/VisualVariables.glsl.js";import{ColorConversion as g}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 x}from"../views/3d/webgl-engine/core/shaderLibrary/util/ScreenSizePerspective.glsl.js";import{addPixelRatio as w}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 S}from"../views/3d/webgl-engine/core/shaderModules/Float4PassUniform.js";import{FloatBindUniform as j}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 T}from"../views/3d/webgl-engine/lib/OITPass.js";import{VertexAttribute as D}from"../views/3d/webgl-engine/lib/VertexAttribute.js";import{ShaderBuilder as E}from"../views/webgl/ShaderBuilder.js";import{alphaCutoff as L}from"../webscene/support/AlphaCutoff.js";function B(e){const i=new E,{signedDistanceFieldEnabled:B,occlusionTestEnabled:H,horizonCullingEnabled:V,pixelSnappingEnabled:_,hasScreenSizePerspective:q,debugDrawLabelBorder:k,vvSize:G,vvColor:N,hasRotation:Z,occludedFragmentFade:J,sampleSignedDistanceFieldTexelCenter:K}=e;i.include(d,e),i.vertex.include(s,e);const{occlusionPass:Q,output:W,oitPass:X}=e;if(Q)return i.include(u,e),i;const{vertex:Y,fragment:ee}=i;i.include(b),i.include(m,e),i.include(n,e),H&&i.include(f),ee.include(v),ee.include(g),i.varyings.add("vcolor","vec4"),i.varyings.add("vtc","vec2"),i.varyings.add("vsize","vec2");const oe=W===a.Highlight,ie=oe&&H;ie&&i.varyings.add("voccluded","float"),Y.uniforms.add(new P("viewport",(e=>e.camera.fullViewport)),new C("screenOffset",((e,i)=>o(R,2*e.screenOffset[0]*i.camera.pixelRatio,2*e.screenOffset[1]*i.camera.pixelRatio))),new C("anchorPosition",(e=>M(e))),new S("materialColor",(e=>e.color)),new y("materialRotation",(e=>e.rotation)),new F("tex",(e=>e.texture))),w(Y),B&&(Y.uniforms.add(new S("outlineColor",(e=>e.outlineColor))),ee.uniforms.add(new S("outlineColor",(e=>U(e)?e.outlineColor:r)),new y("outlineSize",(e=>U(e)?e.outlineSize:0)))),V&&Y.uniforms.add(new z("pointDistanceSphere",((e,o)=>{const i=o.camera.eye,r=e.origin;return t(r[0]-i[0],r[1]-i[1],r[2]-i[2],l.radius)}))),_&&Y.include(c),q&&(h(Y),x(Y)),k&&i.varyings.add("debugBorderCoords","vec4"),i.attributes.add(D.UVI,"vec2"),i.attributes.add(D.COLOR,"vec4"),i.attributes.add(D.SIZE,"vec2"),i.attributes.add(D.ROTATION,"float"),(G||N)&&i.attributes.add(D.FEATUREATTRIBUTE,"vec4"),Y.code.add(V?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; }`),Y.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(q,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(G,A`inputSize *= vvScale(featureAttribute).xx;`)}
vec2 combinedSize = inputSize * pixelRatio;
vec4 quadOffset = vec4(0.0);
${O(H,A`
bool visible = testHUDVisibility(posProj);
if (!visible) {
vtc = vec2(0.0);
${O(k,"debugBorderCoords = vec4(0.5, 0.5, 1.5 / combinedSize);")}
return;
}`)}
${O(ie,A`voccluded = visible ? 0.0 : 1.0;`)}
`);const re=A`
vec2 uvi1 = vec2(uvi.x < 0.0 ? 1.0 : 0.0, uvi.y < 0.0 ? 1.0 : 0.0);
vec2 uv = abs(uvi + uvi1);
vec2 texSize = vec2(textureSize(tex, 0));
uv.x = uv.x >= ${I} ? 1.0 : uv.x / texSize.x;
uv.y = uv.y >= ${I} ? 1.0 : uv.y / texSize.y;
quadOffset.xy = (uvi1 - anchorPosition) * 2.0 * combinedSize;
${O(Z,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;
`,te=_?B?A`posProj = alignToPixelOrigin(posProj, viewport.zw) + quadOffset;`:A`posProj += quadOffset;
if (inputSize.x == size.x) {
posProj = alignToPixelOrigin(posProj, viewport.zw);
}`:A`posProj += quadOffset;`;Y.main.add(A`
${re}
${N?"vcolor = interpolateVVColor(featureAttribute.y) * materialColor;":"vcolor = color / 255.0 * materialColor;"}
${O(W===a.ObjectAndLayerIdColor,A`vcolor.a = 1.0;`)}
bool alphaDiscard = vcolor.a < ${A.float(L)};
${O(B,`alphaDiscard = alphaDiscard && outlineColor.a < ${A.float(L)};`)}
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 {
${te}
gl_Position = posProj;
}
vtc = uv;
${O(k,A`debugBorderCoords = vec4(uv01, 1.5 / combinedSize);`)}
vsize = inputSize;
`),ee.uniforms.add(new F("tex",(e=>e.texture))),J&&!oe&&ee.uniforms.add(new $("depthMap",(e=>e.mainDepth)),new j("occludedOpacity",(e=>e.hudOccludedFragmentOpacity)));const le=k?A`(isBorder > 0.0 ? 0.0 : ${A.float(L)})`:A.float(L),ae=A`
${O(k,A`float isBorder = float(any(lessThan(debugBorderCoords.xy, debugBorderCoords.zw)) || any(greaterThan(debugBorderCoords.xy, 1.0 - debugBorderCoords.zw)));`)}
vec2 samplePos = vtc;
${O(K,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;
samplePos += (vec2(1.0, -1.0) * texelSize) * scaleFactor;`)}
${B?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 < ${le} ||
fillPixelColor.a + outlinePixelColor.a < ${A.float(L)}
) {
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(!oe,A`fragColor = vec4(compositeColor, compositeAlpha);`)}
} else {
if (fillAlphaFactor < ${le}) {
discard;
}
${O(!oe,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, samplePos, -0.5);
if (texColor.a < ${le}) {
discard;
}
${O(!oe,A`fragColor = texColor * premultiplyAlpha(vcolor);`)}
`}
${O(J&&!oe,A`
float zSample = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;
if (zSample < gl_FragCoord.z) {
fragColor *= occludedOpacity;
}
`)}
${O(!oe&&k,A`fragColor = mix(fragColor, vec4(1.0, 0.0, 1.0, 1.0), isBorder * 0.5);`)}
`;switch(W){case a.Color:case a.ColorEmission:i.outputs.add("fragColor","vec4",0),W===a.ColorEmission&&i.outputs.add("fragEmission","vec4",1),X===T.ColorAlpha&&i.outputs.add("fragAlpha","float",W===a.ColorEmission?2:1),ee.main.add(A`
${ae}
${O(X===T.FrontFace,A`fragColor.rgb /= fragColor.a;`)}
${O(W===a.ColorEmission,A`fragEmission = vec4(0.0);`)}
${O(X===T.ColorAlpha,A`fragAlpha = fragColor.a;`)}`);break;case a.ObjectAndLayerIdColor:ee.main.add(A`
${ae}
outputObjectAndLayerIdColor();`);break;case a.Highlight:i.include(p,e),ee.main.add(A`
${ae}
outputHighlight(${O(ie,A`voccluded == 1.0`,A`false`)});`)}return i}function U(e){return e.outlineColor[3]>0&&e.outlineSize>0}function M(o){return o.textureIsSignedDistanceField?H(o.anchorPosition,o.distanceFieldBoundingBox,R):e(R,o.anchorPosition),R}function H(e,i,r){o(r,e[0]*(i[2]-i[0])+i[0],e[1]*(i[3]-i[1])+i[1])}const R=i(),V=32e3,I=A.float(V),_=Object.freeze(Object.defineProperty({__proto__:null,build:B,calculateAnchorPosition:M,fullUV:V},Symbol.toStringTag,{value:"Module"}));export{_ as H,B as b,M as c,V as f};