@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
123 lines (97 loc) • 8.64 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{set as e}from"../core/libs/gl-matrix-2/math/vec2.js";import{create as i}from"../core/libs/gl-matrix-2/factories/vec2f64.js";import{SliceDraw as o}from"../views/3d/webgl-engine/core/shaderLibrary/Slice.glsl.js";import{terrainDepthTest as n}from"../views/3d/webgl-engine/core/shaderLibrary/shading/TerrainDepthTest.glsl.js";import{Float2BindUniform as s}from"../views/3d/webgl-engine/core/shaderModules/Float2BindUniform.js";import{Float4BindUniform as t}from"../views/3d/webgl-engine/core/shaderModules/Float4BindUniform.js";import{FloatBindUniform as d}from"../views/3d/webgl-engine/core/shaderModules/FloatBindUniform.js";import{glsl as l,If as r}from"../views/3d/webgl-engine/core/shaderModules/glsl.js";import{VertexAttribute as a}from"../views/3d/webgl-engine/lib/VertexAttribute.js";import{AdjustProjectedPosition as c}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/AdjustProjectedPosition.glsl.js";import{DiscardNonSilhouetteEdges as p}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/DiscardNonSilhouetteEdges.glsl.js";import{DistanceFalloff as P}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/DistanceFalloff.glsl.js";import{EdgeUtil as u,EdgeType as f}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/EdgeUtil.glsl.js";import{LineAmplitude as g}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/LineAmplitude.glsl.js";import{LineOffset as m}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/LineOffset.glsl.js";import{UnpackAttributes as v}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/UnpackAttributes.glsl.js";import{ShaderBuilder as x}from"../views/webgl/ShaderBuilder.js";import{Uniform as w}from"../views/webgl/Uniform.js";function h(i){const w=new x,{vertex:h,fragment:b,varyings:V,attributes:j}=w;i.legacy&&h.uniforms.add(new A("model"),new A("localView")),w.include(c,i),w.include(u,i),w.include(g,i),w.include(v,i),w.include(m,i),b.include(o,i),w.include(p,i),w.include(n,i),w.include(P,i),V.add("vColor","vec4"),V.add("vRadius","float"),V.add("vPosition","vec3",{invariant:!0}),V.add("vWorldPosition","vec3",{invariant:!0}),V.add("vLineLengthPixels","float"),V.add("vSizeFalloffFactor","float"),h.uniforms.add(new s("pixelToNDC",(({camera:i})=>e(L,2/i.fullViewport[2],2/i.fullViewport[3]))),new t("viewport",(e=>e.camera.fullViewport)),new d("pixelRatio",(e=>e.camera.pixelRatio))),j.add(a.POSITION0,"vec3"),j.add(a.POSITION1,"vec3"),j.add(a.VARIANTOFFSET,"float"),j.add(a.VARIANTSTROKE,"float"),j.add(a.VARIANTEXTENSION,"float");const S=i.type===f.Sketch,C=i.type===f.Mixed,y=1/255,N=1;return h.code.add(l`
void calculateGeometricOutputs(vec3 viewPosV0, vec3 viewPosV1, vec3 worldPosV0, vec3 worldPosV1, vec3 worldNormal, UnpackedAttributes unpackedAttributes) {
vec2 sideness = unpackedAttributes.sideness;
vec2 sidenessNorm = unpackedAttributes.sidenessNorm;
vWorldPosition = mix(worldPosV0, worldPosV1, sidenessNorm.y).xyz;
vec3 viewPos = mix(viewPosV0, viewPosV1, sidenessNorm.y);
forwardViewPosDepth(viewPos);
vec4 projPosV0 = projFromViewPosition(viewPosV0);
vec4 projPosV1 = projFromViewPosition(viewPosV1);
vec4 projPos = projFromViewPosition(viewPos);
vec3 screenSpaceLineNDC = (projPosV1.xyz / projPosV1.w - projPosV0.xyz / projPosV0.w);
vec2 ndcToPixel = viewport.zw * 0.5;
vec2 screenSpaceLinePixels = screenSpaceLineNDC.xy * ndcToPixel;
float lineLengthPixels = length(screenSpaceLinePixels);
float dzPerPixel = screenSpaceLineNDC.z / lineLengthPixels;
vec2 screenSpaceDirection = screenSpaceLinePixels / lineLengthPixels;
vec2 perpendicularScreenSpaceDirection = vec2(screenSpaceDirection.y, -screenSpaceDirection.x) * sideness.x;
float falloffFactor = distanceBasedPerspectiveFactor(-viewPos.z) * pixelRatio;
float lineWidthPixels = unpackedAttributes.lineWidthPixels * falloffFactor;
float extensionLengthPixels = calculateExtensionLength(unpackedAttributes.extensionLengthPixels, lineLengthPixels) * falloffFactor;
float lineAmplitudePixels = calculateLineAmplitude(unpackedAttributes) * pixelRatio;
vSizeFalloffFactor = falloffFactor;
float lineWidthAndAmplitudePixels = lineWidthPixels + lineAmplitudePixels + lineAmplitudePixels;
float extendedLineLengthPixels = lineLengthPixels + extensionLengthPixels + extensionLengthPixels;
// Line size with padding
float halfAAPaddedLineWidthAndAmplitudePixels = lineWidthAndAmplitudePixels * 0.5 + ${l.float(N)};
float aaPaddedRoundedCapSizePixels = lineWidthPixels * 0.5 + ${l.float(N)};
// Half line width in NDC including padding for anti aliasing
vec2 halfAAPaddedLineWidthAndAmplitudeNDC = halfAAPaddedLineWidthAndAmplitudePixels * pixelToNDC;
vec2 aaPaddedRoundedCapSizeNDC = aaPaddedRoundedCapSizePixels * pixelToNDC;
vec2 extensionLengthNDC = extensionLengthPixels * pixelToNDC;
// Compute screen space position of vertex, offsetting for line size and end caps
vec2 ndcOffset = (
screenSpaceDirection * sideness.y * (aaPaddedRoundedCapSizeNDC + extensionLengthNDC)
+ perpendicularScreenSpaceDirection * halfAAPaddedLineWidthAndAmplitudeNDC
);
projPos.xy += ndcOffset * projPos.w;
projPos.z += (dzPerPixel * (aaPaddedRoundedCapSizePixels + extensionLengthPixels)) * sideness.y * projPos.w;
projPos = adjustProjectedPosition(projPos, worldNormal, 1.0 + max((lineWidthAndAmplitudePixels - 1.0) * 0.5, 0.0));
// Line length with end caps
float aaPaddedLineWithCapsLengthPixels = extendedLineLengthPixels + aaPaddedRoundedCapSizePixels + aaPaddedRoundedCapSizePixels;
float pixelPositionAlongLine = aaPaddedLineWithCapsLengthPixels * sidenessNorm.y - aaPaddedRoundedCapSizePixels;
// Position in pixels with origin at first vertex of line segment
vPosition = vec3(
halfAAPaddedLineWidthAndAmplitudePixels * sideness.x,
pixelPositionAlongLine,
pixelPositionAlongLine / extendedLineLengthPixels
);
// The line width radius in pixels
vRadius = lineWidthPixels * 0.5;
vLineLengthPixels = extendedLineLengthPixels;
// discard short edges below a certain length threshold
${r(S||C,l`if (lineLengthPixels <= 3.0 ${r(C," && unpackedAttributes.type <= 0.0")}) {
gl_Position = vec4(10.0, 10.0, 10.0, 1.0);
return;
}`)}
gl_Position = projPos;
}`),h.main.add(l`
ComponentData component = readComponentData();
UnpackedAttributes unpackedAttributes = unpackAttributes(component);
vec3 worldPosV0, worldPosV1, viewPosV0, viewPosV1;
worldAndViewFromModelPosition(position0, component.verticalOffset, worldPosV0, viewPosV0);
worldAndViewFromModelPosition(position1, component.verticalOffset, worldPosV1, viewPosV1);
// Component color
vColor = component.color;
// Discard fully transparent edges
if (vColor.a < ${l.float(y)}) {
gl_Position = vec4(10.0, 10.0, 10.0, 1.0);
return;
}
if (discardNonSilhouetteEdges(viewPosV0, worldPosV0, component)) {
return;
}
// General geometric computation for all types of edges
calculateGeometricOutputs(viewPosV0, viewPosV1, worldPosV0, worldPosV1, worldNormal(component), unpackedAttributes);
// Specific computation for different edge styles
calculateStyleOutputs(unpackedAttributes);`),b.code.add(l`float lineWithCapsDistance(float radius, vec2 position, float lineLength) {
float positionX = position.x - calculateLineOffset();
if (radius < 1.0) {
float coverageX = clamp(min(radius, positionX + 0.5) - max(-radius, positionX - 0.5), 0.0, 1.0);
float coverageY = clamp(min(lineLength, position.y + 0.5) - max(0.0, position.y - 0.5), 0.0, 1.0);
return 0.5 - min(coverageX, coverageY);
}
else {
float positionOnCap = position.y - clamp(position.y, 0.0, lineLength);
return length(vec2(positionX, positionOnCap)) - radius;
}
}`),b.main.add(l`discardByTerrainDepth();
float radius = vRadius * calculateLinePressure();
float distance = lineWithCapsDistance(radius, vPosition.xy, vLineLengthPixels);
float coverage = clamp(0.5 - distance, 0.0, 1.0);
discardBySlice(vWorldPosition);
fragColor = vec4(vColor.rgb, vColor.a * coverage);`),w}const L=i();class A extends w{constructor(e){super(e,"mat4")}}const b=Object.freeze(Object.defineProperty({__proto__:null,build:h},Symbol.toStringTag,{value:"Module"}));export{b as E,h as b};