/*
All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/5.0/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{RejectBySlice as a}from"../views/3d/webgl-engine/core/shaderLibrary/Slice.glsl.js";import{ObjectAndLayerIdColor as s}from"../views/3d/webgl-engine/core/shaderLibrary/attributes/ObjectAndLayerIdColor.glsl.js";import{AlignPixel as n}from"../views/3d/webgl-engine/core/shaderLibrary/hud/AlignPixel.glsl.js";import{HUD as c}from"../views/3d/webgl-engine/core/shaderLibrary/hud/HUD.glsl.js";import{HUDOcclusionPass as d}from"../views/3d/webgl-engine/core/shaderLibrary/hud/HUDOcclusionPass.glsl.js";import{HUDVisibility as u}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 p}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{ScreenSizePerspective as v,addScreenSizePerspective as g,addScreenSizePerspectiveAlignment as b}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 h}from"../views/3d/webgl-engine/core/shaderModules/Float2PassUniform.js";import{Float4BindUniform as w}from"../views/3d/webgl-engine/core/shaderModules/Float4BindUniform.js";import{Float4DrawUniform as C}from"../views/3d/webgl-engine/core/shaderModules/Float4DrawUniform.js";import{Float4PassUniform as z}from"../views/3d/webgl-engine/core/shaderModules/Float4PassUniform.js";import{FloatBindUniform as P}from"../views/3d/webgl-engine/core/shaderModules/FloatBindUniform.js";import{FloatPassUniform as S}from"../views/3d/webgl-engine/core/shaderModules/FloatPassUniform.js";import{glsl as j,If as y}from"../views/3d/webgl-engine/core/shaderModules/glsl.js";import{Texture2DBindUniform as A}from"../views/3d/webgl-engine/core/shaderModules/Texture2DBindUniform.js";import{Texture2DPassUniform as $}from"../views/3d/webgl-engine/core/shaderModules/Texture2DPassUniform.js";import{ShaderBuilder as O}from"../views/webgl/ShaderBuilder.js";import{alphaCutoff as D}from"../webscene/support/AlphaCutoff.js";function F(e){const i=new O;if(i.include(c,e),i.vertex.include(a,e),e.occlusionPass)return i.include(d,e),i;const{output:F,oitPass:M,signedDistanceFieldEnabled:U,visibilityPixelEnabled:E,horizonCullingEnabled:H,pixelSnappingEnabled:_,hasEmission:q,hasScreenSizePerspective:R,debugDrawLabelBorder:k,hasVVSize:I,hasVVColor:G,hasRotation:J,occludedFragmentFade:K,sampleSignedDistanceFieldTexelCenter:N}=e;i.include(v),i.include(p,e),i.include(s,e),E&&i.include(u);const{vertex:Q,fragment:W}=i;W.include(m),i.varyings.add("vcolor","vec4"),i.varyings.add("vtc","vec2"),i.varyings.add("vsize","vec2");const X=8===F,Y=X&&E;Y&&i.varyings.add("voccluded","float"),Q.uniforms.add(new w("viewport",e=>e.camera.fullViewport),new h("screenOffset",(e,i)=>o(L,2*e.screenOffset[0]*i.camera.pixelRatio,2*e.screenOffset[1]*i.camera.pixelRatio)),new h("anchorPosition",e=>B(e)),new z("materialColor",e=>e.color),new S("materialRotation",e=>e.rotation),new $("tex",e=>e.texture)),x(Q),U&&(Q.uniforms.add(new z("outlineColor",e=>e.outlineColor)),W.uniforms.add(new z("outlineColor",e=>T(e)?e.outlineColor:r),new S("outlineSize",e=>T(e)?e.outlineSize:0))),H&&Q.uniforms.add(new C("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)})),_&&Q.include(n),R&&(g(Q),b(Q)),k&&i.varyings.add("debugBorderCoords","vec4"),i.attributes.add("uv0","vec2"),i.attributes.add("uvi","vec4"),i.attributes.add("color","vec4"),i.attributes.add("size","vec2"),i.attributes.add("rotation","float"),(I||G)&&i.attributes.add("featureAttribute","vec4"),Q.code.add(H?j`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;
}`:j`bool behindHorizon(vec3 posModel) { return false; }`),Q.main.add(j`
    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;
    ${y(R,j`
        inputSize = screenSizePerspectiveScaleVec2(size, projectAux.absCosAngle, projectAux.distanceToCamera, screenSizePerspective);
        vec2 screenOffsetScaled = screenSizePerspectiveScaleVec2(screenOffset, projectAux.absCosAngle, projectAux.distanceToCamera, screenSizePerspectiveAlignment);`,j`
        inputSize = size;
        vec2 screenOffsetScaled = screenOffset;`)}
    ${y(I,j`inputSize *= vvScale(featureAttribute).xx;`)}

    vec2 combinedSize = inputSize * pixelRatio;
    vec4 quadOffset = vec4(0.0);

    ${y(E,j`
    bool visible = testHUDVisibility(posProj);
    if (!visible) {
      vtc = vec2(0.0);
      ${y(k,"debugBorderCoords = vec4(0.5, 0.5, 1.5 / combinedSize);")}
      return;
    }`)}
    ${y(Y,j`voccluded = visible ? 0.0 : 1.0;`)}
  `);const Z=j`
      vec2 uv = mix(uvi.xy, uvi.zw, bvec2(uv0));
      vec2 texSize = vec2(textureSize(tex, 0));
      uv = mix(vec2(1.0), uv / texSize, lessThan(uv, vec2(${V})));
      quadOffset.xy = (uv0 - anchorPosition) * 2.0 * combinedSize;

      ${y(J,j`
          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;
  `,ee=_?U?j`posProj = alignToPixelOrigin(posProj, viewport.zw) + quadOffset;`:j`posProj += quadOffset;
if (inputSize.x == size.x) {
posProj = alignToPixelOrigin(posProj, viewport.zw);
}`:j`posProj += quadOffset;`;Q.main.add(j`
    ${Z}
    ${G?"vcolor = interpolateVVColor(featureAttribute.y) * materialColor;":"vcolor = color / 255.0 * materialColor;"}

    ${y(9===F,j`vcolor.a = 1.0;`)}

    bool alphaDiscard = vcolor.a < ${j.float(D)};
    ${y(U,`alphaDiscard = alphaDiscard && outlineColor.a < ${j.float(D)};`)}
    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 {
      ${ee}
      gl_Position = posProj;
    }

    vtc = uv;

    ${y(k,j`debugBorderCoords = vec4(uv01, 1.5 / combinedSize);`)}
    vsize = inputSize;
  `),W.uniforms.add(new $("tex",e=>e.texture)),K&&!X&&W.uniforms.add(new A("depthMap",e=>e.mainDepth),new P("occludedOpacity",e=>e.hudOccludedFragmentOpacity));const oe=k?j`(isBorder > 0.0 ? 0.0 : ${j.float(D)})`:j.float(D),ie=j`
    ${y(k,j`float isBorder = float(any(lessThan(debugBorderCoords.xy, debugBorderCoords.zw)) || any(greaterThan(debugBorderCoords.xy, 1.0 - debugBorderCoords.zw)));`)}

    vec2 samplePos = vtc;

    ${y(N,j`
      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;`)}

    ${U?j`
      vec4 fillPixelColor = vcolor;

      // Get distance in output units (i.e. pixels)

      float sdf = texture(tex, samplePos).r;
      float pixelDistance = sdf * vsize.x;

      // Create smooth transition from the icon into its outline
      float fillAlphaFactor = clamp(0.5 - pixelDistance, 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(pixelDistance) - 0.5*clampedOutlineSize), 0.0, 1.0);
        outlinePixelColor.a *= outlineAlphaFactor;

        if (
          outlineAlphaFactor + fillAlphaFactor < ${oe} ||
          fillPixelColor.a + outlinePixelColor.a < ${j.float(D)}
        ) {
          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);

        ${y(!X,j`fragColor = vec4(compositeColor, compositeAlpha);`)}
      } else {
        if (fillAlphaFactor < ${oe}) {
          discard;
        }

        ${y(!X,j`fragColor = premultiplyAlpha(fillPixelColor);`)}
      }

      // visualize SDF:
      // fragColor = vec4(clamp(-pixelDistance/vsize.x*2.0, 0.0, 1.0), clamp(pixelDistance/vsize.x*2.0, 0.0, 1.0), 0.0, 1.0);
      `:j`
          vec4 texColor = texture(tex, samplePos, -0.5);
          if (texColor.a < ${oe}) {
            discard;
          }
          ${y(!X,j`fragColor = texColor * premultiplyAlpha(vcolor);`)}
          `}

    ${y(K&&!X,j`
        float zSample = texelFetch(depthMap, ivec2(gl_FragCoord.xy), 0).x;
        if (zSample < gl_FragCoord.z) {
          fragColor *= occludedOpacity;
        }
        `)}

    ${y(!X&&k,j`fragColor = mix(fragColor, vec4(1.0, 0.0, 1.0, 1.0), isBorder * 0.5);`)}
  `;switch(F){case 0:i.outputs.add("fragColor","vec4",0),q&&i.outputs.add("fragEmission","vec4",1),1===M&&i.outputs.add("fragAlpha","float",q?2:1),W.main.add(j`
        ${ie}
        ${y(2===M,j`fragColor.rgb /= fragColor.a;`)}
        ${y(q,j`fragEmission = vec4(0.0);`)}
        ${y(1===M,j`fragAlpha = fragColor.a;`)}`);break;case 9:W.main.add(j`
        ${ie}
        outputObjectAndLayerIdColor();`);break;case 8:i.include(f,e),W.main.add(j`
        ${ie}
        outputHighlight(${y(Y,j`voccluded == 1.0`,j`false`)});`)}return i}function T(e){return e.outlineColor[3]>0&&e.outlineSize>0}function B(o){return o.textureIsSignedDistanceField?M(o.anchorPosition,o.distanceFieldBoundingBox,L):e(L,o.anchorPosition),L}function M(e,i,r){o(r,e[0]*(i[2]-i[0])+i[0],e[1]*(i[3]-i[1])+i[1])}const L=i(),U=32e3,V=j.float(U),E=Object.freeze(Object.defineProperty({__proto__:null,build:F,calculateAnchorPosition:B,fullUV:U},Symbol.toStringTag,{value:"Module"}));export{E as H,F as b,B as c,U as f};
