EdgeShader.glsl.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. See https://js.arcgis.com/4.25/esri/copyright.txt for details.
  4. */
  5. import{s as e}from"./vec2.js";import{a as i}from"./vec2f64.js";import{SliceDraw as o}from"../views/3d/webgl-engine/core/shaderLibrary/Slice.glsl.js";import{multipassTerrainTest as s}from"../views/3d/webgl-engine/core/shaderLibrary/shading/MultipassTerrainTest.glsl.js";import{Float2PassUniform as n}from"../views/3d/webgl-engine/core/shaderModules/Float2PassUniform.js";import{Float4PassUniform as t}from"../views/3d/webgl-engine/core/shaderModules/Float4PassUniform.js";import{FloatPassUniform as d}from"../views/3d/webgl-engine/core/shaderModules/FloatPassUniform.js";import{glsl as a}from"../views/3d/webgl-engine/core/shaderModules/interfaces.js";import{ShaderBuilder as l}from"../views/3d/webgl-engine/core/shaderModules/ShaderBuilder.js";import{Uniform as r}from"../views/3d/webgl-engine/core/shaderModules/Uniform.js";import{VertexAttribute as c}from"../views/3d/webgl-engine/lib/VertexAttribute.js";import{AdjustProjectedPosition as p}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/AdjustProjectedPosition.glsl.js";import{DiscardByCoverage as P}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/DiscardByCoverage.glsl.js";import{DiscardNonSilhouetteEdges as u}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/DiscardNonSilhouetteEdges.glsl.js";import{DiscardShortEdges as g}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/DiscardShortEdges.glsl.js";import{EdgeUtil as v}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/EdgeUtil.glsl.js";import{LineAmplitude as f}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 x}from"../views/3d/webgl-engine/shaders/sources/edgeRenderer/UnpackAttributes.glsl.js";function w(i){const r=new l,{vertex:w,fragment:L}=r;return i.antialiasing&&(w.code.add(a`#define ANTIALIASING 1`),L.code.add(a`#define ANTIALIASING 1`)),i.legacy&&w.uniforms.add([new A("model"),new A("localView")]),r.include(p,i),r.include(v,i),r.include(f,i),r.include(x,i),r.include(m,i),r.include(o,i),r.include(u,i),r.include(P,i),r.include(g,i),r.include(s,i),r.varyings.add("vColor","vec4"),r.varyings.add("vRadius","float"),r.varyings.add("vPosition","vec3"),r.varyings.add("vWorldPosition","vec3"),r.varyings.add("vViewPos","vec3"),r.varyings.add("vLineLengthPixels","float"),r.varyings.add("vSizeFalloffFactor","float"),w.uniforms.add([new n("pixelToNDC",((i,o)=>e(h,2/o.camera.fullViewport[2],2/o.camera.fullViewport[3]))),new t("viewport",((e,i)=>i.camera.fullViewport)),new d("pixelRatio",((e,i)=>i.camera.pixelRatio))]),r.attributes.add(c.POSITION0,"vec3"),r.attributes.add(c.POSITION1,"vec3"),r.attributes.add(c.VARIANTOFFSET,"float"),r.attributes.add(c.VARIANTSTROKE,"float"),r.attributes.add(c.VARIANTEXTENSION,"float"),w.code.add(a`const float opaqueCutoff = 1.0 / 255.0;
  6. void calculateGeometricOutputs(vec3 viewPosV0, vec3 viewPosV1, vec3 worldPosV0, vec3 worldPosV1, vec3 worldNormal, UnpackedAttributes unpackedAttributes) {
  7. vec2 sideness = unpackedAttributes.sideness;
  8. vec2 sidenessNorm = unpackedAttributes.sidenessNorm;
  9. vWorldPosition = mix(worldPosV0, worldPosV1, sidenessNorm.y).xyz;
  10. vec3 viewPos = mix(viewPosV0, viewPosV1, sidenessNorm.y);
  11. vViewPos = viewPos;
  12. vec4 projPosV0 = projFromViewPosition(viewPosV0);
  13. vec4 projPosV1 = projFromViewPosition(viewPosV1);
  14. vec4 projPos = projFromViewPosition(viewPos);
  15. vec3 screenSpaceLineNDC = (projPosV1.xyz / projPosV1.w - projPosV0.xyz / projPosV0.w);
  16. vec2 ndcToPixel = viewport.zw * 0.5;
  17. vec2 screenSpaceLinePixels = screenSpaceLineNDC.xy * ndcToPixel;
  18. float lineLengthPixels = length(screenSpaceLinePixels);
  19. float dzPerPixel = screenSpaceLineNDC.z / lineLengthPixels;
  20. vec2 screenSpaceDirection = screenSpaceLinePixels / lineLengthPixels;
  21. vec2 perpendicularScreenSpaceDirection = vec2(screenSpaceDirection.y, -screenSpaceDirection.x) * sideness.x;
  22. float falloffFactor = distanceBasedPerspectiveFactor(-viewPos.z) * pixelRatio;
  23. float lineWidthPixels = unpackedAttributes.lineWidthPixels * falloffFactor;
  24. float extensionLengthPixels = calculateExtensionLength(unpackedAttributes.extensionLengthPixels, lineLengthPixels) * falloffFactor;
  25. float lineAmplitudePixels = calculateLineAmplitude(unpackedAttributes) * pixelRatio;
  26. vSizeFalloffFactor = falloffFactor;
  27. float lineWidthAndAmplitudePixels = lineWidthPixels + lineAmplitudePixels + lineAmplitudePixels;
  28. float extendedLineLengthPixels = lineLengthPixels + extensionLengthPixels + extensionLengthPixels;
  29. #ifdef ANTIALIASING
  30. const float aaPaddingPixels = 1.0;
  31. float halfAAPaddedLineWidthAndAmplitudePixels = lineWidthAndAmplitudePixels * 0.5 + aaPaddingPixels;
  32. float aaPaddedRoundedCapSizePixels = lineWidthPixels * 0.5 + aaPaddingPixels;
  33. #else
  34. float halfAAPaddedLineWidthAndAmplitudePixels = max(lineWidthAndAmplitudePixels, 1.0) * 0.5;
  35. float aaPaddedRoundedCapSizePixels = max(lineWidthPixels, 1.0) * 0.5;
  36. #endif
  37. vec2 halfAAPaddedLineWidthAndAmplitudeNDC = halfAAPaddedLineWidthAndAmplitudePixels * pixelToNDC;
  38. vec2 aaPaddedRoundedCapSizeNDC = aaPaddedRoundedCapSizePixels * pixelToNDC;
  39. vec2 extensionLengthNDC = extensionLengthPixels * pixelToNDC;
  40. vec2 ndcOffset = (
  41. screenSpaceDirection * sideness.y * (aaPaddedRoundedCapSizeNDC + extensionLengthNDC)
  42. + perpendicularScreenSpaceDirection * halfAAPaddedLineWidthAndAmplitudeNDC
  43. );
  44. projPos.xy += ndcOffset * projPos.w;
  45. projPos.z += (dzPerPixel * (aaPaddedRoundedCapSizePixels + extensionLengthPixels)) * sideness.y * projPos.w;
  46. projPos = adjustProjectedPosition(projPos, worldNormal, 1.0 + max((lineWidthAndAmplitudePixels - 1.0) * 0.5, 0.0));
  47. float aaPaddedLineWithCapsLengthPixels = extendedLineLengthPixels + aaPaddedRoundedCapSizePixels + aaPaddedRoundedCapSizePixels;
  48. float pixelPositionAlongLine = aaPaddedLineWithCapsLengthPixels * sidenessNorm.y - aaPaddedRoundedCapSizePixels;
  49. vPosition = vec3(
  50. halfAAPaddedLineWidthAndAmplitudePixels * sideness.x,
  51. pixelPositionAlongLine,
  52. pixelPositionAlongLine / extendedLineLengthPixels
  53. );
  54. vRadius = lineWidthPixels * 0.5;
  55. vLineLengthPixels = extendedLineLengthPixels;
  56. discardShortEdges(unpackedAttributes, lineLengthPixels);
  57. gl_Position = projPos;
  58. }
  59. void main() {
  60. ComponentData component = readComponentData();
  61. UnpackedAttributes unpackedAttributes = unpackAttributes(component);
  62. vec3 worldPosV0, worldPosV1, viewPosV0, viewPosV1;
  63. worldAndViewFromModelPosition(position0, component.verticalOffset, worldPosV0, viewPosV0);
  64. worldAndViewFromModelPosition(position1, component.verticalOffset, worldPosV1, viewPosV1);
  65. vColor = component.color;
  66. if (vColor.a < opaqueCutoff) {
  67. gl_Position = vec4(10.0, 10.0, 10.0, 1.0);
  68. return;
  69. }
  70. if (discardNonSilhouetteEdges(viewPosV0, worldPosV0)) {
  71. return;
  72. }
  73. calculateGeometricOutputs(viewPosV0, viewPosV1, worldPosV0, worldPosV1, worldNormal(), unpackedAttributes);
  74. calculateStyleOutputs(unpackedAttributes);
  75. }`),r.fragment.code.add(a`
  76. vec2 lineWithCapsDistance(float radius, vec2 position, float lineLength) {
  77. float lineOffset = calculateLineOffset();
  78. float positionX = position.x - lineOffset;
  79. if (radius < 1.0) {
  80. // Handle this specifically for subpixel sizes:
  81. // 1. Compute correct coverage (note coverage is computed by
  82. // 0.5 - dist, so we make sure that that will lead to correct
  83. // subpixel coverage
  84. // 2. Ignore rounded caps
  85. float coverageX = clamp(min(radius, positionX + 0.5) - max(-radius, positionX - 0.5), 0.0, 1.0);
  86. float coverageY = clamp(min(lineLength, position.y + 0.5) - max(0.0, position.y - 0.5), 0.0, 1.0);
  87. float coverage = min(coverageX, coverageY);
  88. return vec2(0.5 - coverage, 0.0);
  89. }
  90. else {
  91. // Between -radius -> 0 for start cap, 0 for line, 0 -> radius
  92. float positionOnCap = position.y - clamp(position.y, 0.0, lineLength);
  93. vec2 lineToPosition = vec2(positionX, positionOnCap);
  94. return vec2(length(lineToPosition) - radius, positionOnCap / radius);
  95. }
  96. }
  97. void main() {
  98. ${i.hasMultipassTerrain?"terrainDepthTest(gl_FragCoord, vViewPos.z);":""}
  99. float radius = vRadius * calculateLinePressure();
  100. vec2 distance = lineWithCapsDistance(radius, vPosition.xy, vLineLengthPixels);
  101. float coverage = clamp(0.5 - distance.x, 0.0, 1.0);
  102. discardByCoverage(radius, coverage);
  103. discardBySlice(vWorldPosition);
  104. float alpha = vColor.a * coverage;
  105. gl_FragColor = vec4(vColor.rgb, alpha);
  106. }
  107. `),r}const h=i();class A extends r{constructor(e){super(e,"mat4")}}const L=Object.freeze(Object.defineProperty({__proto__:null,build:w},Symbol.toStringTag,{value:"Module"}));export{L as E,w as b};