/*
All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/4.24/esri/copyright.txt for details.
*/
define(["exports","../util/RgbaFloatEncoding.glsl","../util/View.glsl","../../shaderModules/Float4PassUniform","../../shaderModules/FloatPassUniform","../../shaderModules/FloatUniform","../../shaderModules/interfaces","../../shaderModules/Texture2DUniform","../../../shaders/ensureColor4"],(function(e,t,l,i,o,a,r,s,n){"use strict";function p(e,t){e.constants.add("stippleAlphaColorDiscard","float",.001),e.constants.add("stippleAlphaHighlightDiscard","float",.5),t.stippleEnabled?d(e,t):c(e)}function d(e,p){const d=!(p.draped&&p.stipplePreferContinuous),{vertex:c,fragment:u}=e;u.include(t.RgbaFloatEncoding),c.uniforms.add(new a.FloatUniform("stipplePatternPixelSize")),p.draped||(l.addCameraPosition(c,p),c.uniforms.add(new o.FloatPassUniform("worldToScreenPerDistanceRatio",((e,t)=>1/t.camera.perScreenPixelRatio))),c.code.add(r.glsl`float computeWorldToScreenRatio(vec3 segmentCenter) {
float segmentDistanceToCamera = length(segmentCenter - cameraPosition);
return worldToScreenPerDistanceRatio / segmentDistanceToCamera;
}`)),e.varyings.add("vStippleDistance","float"),p.stippleRequiresClamp&&e.varyings.add("vStippleDistanceLimits","vec2"),p.stippleRequiresStretchMeasure&&e.varyings.add("vStipplePatternStretch","float"),c.code.add(r.glsl`
    float discretizeWorldToScreenRatio(float worldToScreenRatio) {
      float step = ${f};

      float discreteWorldToScreenRatio = log(worldToScreenRatio);
      discreteWorldToScreenRatio = ceil(discreteWorldToScreenRatio / step) * step;
      discreteWorldToScreenRatio = exp(discreteWorldToScreenRatio);
      return discreteWorldToScreenRatio;
    }
  `),c.code.add(r.glsl`vec2 computeStippleDistanceLimits(float startPseudoScreen, float segmentLengthPseudoScreen, float segmentLengthScreen, float patternLength) {`),c.code.add(r.glsl`
    if (segmentLengthPseudoScreen >= ${d?"patternLength":"1e4"}) {
  `),c.uniforms.add(new o.FloatPassUniform("pixelRatio",((e,t)=>t.camera.pixelRatio))),c.code.add(r.glsl`
        // Round the screen length to get an integer number of pattern repetitions (minimum 1).
        float repetitions = segmentLengthScreen / (patternLength * pixelRatio);
        float flooredRepetitions = max(1.0, floor(repetitions + 0.5));
        float segmentLengthScreenRounded = flooredRepetitions * patternLength;

        ${p.stippleRequiresStretchMeasure?r.glsl`
              float stretch = repetitions / flooredRepetitions;

              // We need to impose a lower bound on the stretch factor to prevent the dots from merging together when there is only 1 repetition.
              // 0.75 is the lowest possible stretch value for flooredRepetitions > 1, so it makes sense as lower bound.
              vStipplePatternStretch = max(0.75, stretch);`:""}

        return vec2(0.0, segmentLengthScreenRounded);
      }
      return vec2(startPseudoScreen, startPseudoScreen + segmentLengthPseudoScreen);
    }
  `),u.uniforms.add(new s.Texture2DUniform("stipplePatternTexture")),u.uniforms.add(new a.FloatUniform("stipplePatternSDFNormalizer")),u.uniforms.add(new a.FloatUniform("stipplePatternTextureSize")),u.uniforms.add(new a.FloatUniform("stipplePatternPixelSizeInv")),u.code.add(r.glsl`float padTexture(float u) {
return (u * stipplePatternTextureSize + 1.0)/(stipplePatternTextureSize + 2.0);
}`),u.code.add(r.glsl`
    float getStippleSDF(out bool isClamped) {
      ${p.stippleRequiresClamp?r.glsl`
          float stippleDistanceClamped = clamp(vStippleDistance, vStippleDistanceLimits.x, vStippleDistanceLimits.y);
          vec2 aaCorrectedLimits = vStippleDistanceLimits + vec2(1.0, -1.0) / gl_FragCoord.w;
          isClamped = vStippleDistance < aaCorrectedLimits.x || vStippleDistance > aaCorrectedLimits.y;`:r.glsl`
          float stippleDistanceClamped = vStippleDistance;
          isClamped = false;`}

      float u = stippleDistanceClamped * gl_FragCoord.w * stipplePatternPixelSizeInv;
      ${p.stippleScaleWithLineWidth?r.glsl`u *= vLineSizeInv;`:""}
      u = padTexture(fract(u));

      float encodedSDF = rgba2float(texture2D(stipplePatternTexture, vec2(u, 0.5)));
      float sdf = (encodedSDF * 2.0 - 1.0) * stipplePatternSDFNormalizer;

      ${p.stippleRequiresStretchMeasure?r.glsl`return (sdf - 0.5) * vStipplePatternStretch + 0.5;`:r.glsl`return sdf;`}
    }

    float getStippleSDF() {
      bool ignored;
      return getStippleSDF(ignored);
    }

    float getStippleAlpha() {
      bool isClamped;
      float stippleSDF = getStippleSDF(isClamped);

      float antiAliasedResult = ${p.stippleScaleWithLineWidth?r.glsl`clamp(stippleSDF * vLineWidth + 0.5, 0.0, 1.0);`:r.glsl`clamp(stippleSDF + 0.5, 0.0, 1.0);`}

      return isClamped ? floor(antiAliasedResult + 0.5) : antiAliasedResult;
    }
  `),p.stippleOffColorEnabled?(u.uniforms.add(new i.Float4PassUniform("stippleOffColor",(e=>n.ensureColor4(e.stippleOffColor)))),u.code.add(r.glsl`#define discardByStippleAlpha(stippleAlpha, threshold) {}
#define blendStipple(color, stippleAlpha) mix(color, stippleOffColor, stippleAlpha)`)):u.code.add(r.glsl`#define discardByStippleAlpha(stippleAlpha, threshold) if (stippleAlpha < threshold) { discard; }
#define blendStipple(color, stippleAlpha) vec4(color.rgb, color.a * stippleAlpha)`)}function c(e){e.fragment.code.add(r.glsl`float getStippleAlpha() { return 1.0; }
#define discardByStippleAlpha(_stippleAlpha_, _threshold_) {}
#define blendStipple(color, _stippleAlpha_) color`)}const f=r.glsl.float(.4);e.LineStipple=p,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}));
