/*
All material copyright Esri, All Rights Reserved, unless otherwise specified.
See https://js.arcgis.com/5.0/esri/copyright.txt for details.
*/
import{radiusModifier as e}from"../geometry/ellipsoidUtils.js";import{earth as o,mars as r,moon as a}from"../geometry/support/Ellipsoid.js";import{ComponentData as i}from"../views/3d/webgl-engine/collections/Component/Material/ComponentData.glsl.js";import{ForwardLinearDepthToWriteShadowMap as l}from"../views/3d/webgl-engine/core/shaderLibrary/ForwardLinearDepthToWriteShadowMap.glsl.js";import{isColor as t}from"../views/3d/webgl-engine/core/shaderLibrary/ShaderOutput.js";import{SlicePass as n}from"../views/3d/webgl-engine/core/shaderLibrary/Slice.glsl.js";import{TextureCoordinateAttribute as s}from"../views/3d/webgl-engine/core/shaderLibrary/attributes/TextureCoordinateAttribute.glsl.js";import{VertexColor as d}from"../views/3d/webgl-engine/core/shaderLibrary/attributes/VertexColor.glsl.js";import{VertexNormal as g}from"../views/3d/webgl-engine/core/shaderLibrary/attributes/VertexNormal.glsl.js";import{VertexPosition as c}from"../views/3d/webgl-engine/core/shaderLibrary/attributes/VertexPosition.glsl.js";import{OutputDepth as m}from"../views/3d/webgl-engine/core/shaderLibrary/output/OutputDepth.glsl.js";import{OutputHighlight as v}from"../views/3d/webgl-engine/core/shaderLibrary/output/OutputHighlight.glsl.js";import{OutputHighlightOverlay as u}from"../views/3d/webgl-engine/core/shaderLibrary/output/OutputHighlightOverlay.js";import{ReadDepth as h}from"../views/3d/webgl-engine/core/shaderLibrary/output/ReadDepth.glsl.js";import{computeFragmentNormals as w}from"../views/3d/webgl-engine/core/shaderLibrary/shading/ComputeFragmentNormals.glsl.js";import{ComputeMaterialColor as p}from"../views/3d/webgl-engine/core/shaderLibrary/shading/ComputeMaterialColor.glsl.js";import{ComputeNormalTexture as f}from"../views/3d/webgl-engine/core/shaderLibrary/shading/ComputeNormalTexture.glsl.js";import{EvaluateSceneLighting as b,addLightingGlobalFactor as y}from"../views/3d/webgl-engine/core/shaderLibrary/shading/EvaluateSceneLighting.glsl.js";import{addMainLightIntensity as C,addMainLightDirection as x}from"../views/3d/webgl-engine/core/shaderLibrary/shading/MainLighting.glsl.js";import{PhysicallyBasedRenderingParameters as L}from"../views/3d/webgl-engine/core/shaderLibrary/shading/PhysicallyBasedRenderingParameters.glsl.js";import{PiUtils as j}from"../views/3d/webgl-engine/core/shaderLibrary/shading/PiUtils.glsl.js";import{ReadBaseColorTexture as O}from"../views/3d/webgl-engine/core/shaderLibrary/shading/ReadBaseColorTexture.glsl.js";import{ReadShadowMapPass as S}from"../views/3d/webgl-engine/core/shaderLibrary/shading/ReadShadowMap.glsl.js";import{terrainDepthTest as $}from"../views/3d/webgl-engine/core/shaderLibrary/shading/TerrainDepthTest.glsl.js";import{OverlayIM as N}from"../views/3d/webgl-engine/core/shaderLibrary/terrain/Overlay.glsl.js";import{DiscardOrAdjustAlphaDraw as T}from"../views/3d/webgl-engine/core/shaderLibrary/util/DiscardOrAdjustAlpha.glsl.js";import{BooleanDrawUniform as D}from"../views/3d/webgl-engine/core/shaderModules/BooleanDrawUniform.js";import{If as M,glsl as R}from"../views/3d/webgl-engine/core/shaderModules/glsl.js";import{Texture2DBindUniform as P}from"../views/3d/webgl-engine/core/shaderModules/Texture2DBindUniform.js";import{SnowCover as W}from"../views/3d/webgl-engine/effects/weather/SnowCover.glsl.js";import{outputColorHighlightOLID as A}from"../views/3d/webgl-engine/shaders/OutputColorHighlightOLID.glsl.js";import{sphereDepthInterpolate as F}from"../views/3d/webgl-engine/shaders/SphereDepthInterpolate.glsl.js";import{ShaderBuilder as U}from"../views/webgl/ShaderBuilder.js";import{alphaCutoff as V}from"../webscene/support/AlphaCutoff.js";function z(z){const B=new U,{vertex:E,fragment:_}=B;B.include(c,z),B.include(g,z),B.include(d,z),B.include(s,z),B.include(i,z),B.include(T,z),_.include(n,z),B.include(O,z),B.include($,z);const{output:I,pbrMode:G,hasNormalTexture:H,snowCover:k,receiveShadows:q,shadeNormals:J,spherical:K,sphericalSR:Q,ellipsoidMode:X,overlayEnabled:Y,componentData:Z,vertexDiscardMode:ee,renderOccluded:oe,isGroundSlice:re}=z,ae=1===G||2===G;ae&&(B.include(L,z),H&&B.include(f,z));const ie=3===I||4===I||5===I,le=ie&&1===Z,te=1===X,ne=1===X?o.radius:te?r.radius:a.radius;Y&&(_.include(b,z),B.include(N,z),E.include(j),E.uniforms.add(new D("useENUForGlobalOverlayUV",e=>e.useENUForGlobalOverlayUV)),_.uniforms.add(new D("useENUForGlobalOverlayUV",e=>e.useENUForGlobalOverlayUV)),E.code.add(`\n      ${M(K,`const float invRadius = ${R.float(1/ne)};`)}\n      vec2 projectOverlay(vec3 pos) { return pos.xy ${M(K,"/ (1.0 + invRadius * pos.z);")}; }\n    `));const se=Y&&t(I)&&4===G;se&&(B.varyings.add("tbnTangent","vec3"),B.varyings.add("tbnBiTangent","vec3"),B.varyings.add("groundNormal","vec3"));const de=0===ee,ge=2===ee,ce=1-1/255;if(B.include(S,z),B.include(l,z),E.main.add(R`
    bool castShadows;
    vec4 externalColor = forwardExternalColor(castShadows);
    ${M(le,"if(!castShadows) { gl_Position = vec4(vec3(1e38), 1.0); return; }")}
    ${M(!de,`{ if (externalColor.a ${ge?">":"<="} ${R.float(ce)}) { gl_Position = vec4(vec3(1e38), 1.0); return; } }`)}
    ${M(9===I,"externalColor.a = 1.0;")}

    forwardPosition(readElevationOffset());
    forwardViewPosDepth(vPosition_view);
    forwardNormal();
    forwardTextureCoordinates();
    forwardVertexColor();
    forwardLinearDepthToReadShadowMap();
    forwardLinearDepthToWriteShadowMap();
    forwardEmissiveStrength();
    forwardObjectAndLayerIdColor();
    ${M(se,K?R`
            groundNormal = normalize(positionWorld());
            tbnTangent = normalize(cross(vec3(0.0, 0.0, 1.0), groundNormal));
            tbnBiTangent = normalize(cross(groundNormal, tbnTangent));`:R`
            groundNormal = vec3(0.0, 0.0, 1.0);
            tbnTangent = vec3(1.0, 0.0, 0.0);
            tbnBiTangent = vec3(0.0, 1.0, 0.0);`)}
    ${M(Y,M(K,"\n        if (useENUForGlobalOverlayUV) {\n          setOverlayVTC(projectOverlay(position));\n        } else {\n          vtcOverlay = vec4(0.0); // Definite assignment\n        }\n      ","setOverlayVTC(projectOverlay(position));"))}

    if (externalColor.a < ${R.float(V)}) {
      // Discard this vertex
      gl_Position = vec4(1e38, 1e38, 1e38, 1.0);
      return;
    }
  `),t(I))return B.include(p,z),B.include(w,z),_.include(b,z),B.include(A,z),_.include(W,z),_.code.add(R`
      float evaluateShadow() {
        return ${q?"readShadowMap(vPositionWorldCameraRelative, linearDepth)":"0.0"};
      }`),_.main.add(R`
      ${M(!re,"discardBySlice(vPositionWorldCameraRelative);")}
      discardByTerrainDepth();

      vec4 textureColor = readBaseColorTexture();
      discardOrAdjustAlpha(textureColor);

      // When rendering the occluded overlay, we still need to read the base color texture because we need to use the
      // same discard logic. However after that to render only the draped overlay, we simply set the base texture color
      // to zero.
      ${M(oe,R`textureColor = vec4(0);`)}

      ${M(Y,R`
        ${M(K,R`
            vec4 overlayUVs;
            if (useENUForGlobalOverlayUV) {
              overlayUVs = vtcOverlay;
            } else {
              const float pRadius = ${R.float(ne)};
              const float rad2deg1 = 180.0 / PI;

              vec3 wPos = positionWorld();

              float oRadius = length(wPos.xyz);
              float oLonRad = atan(wPos.y, wPos.x);
              float sinLat = wPos.z / oRadius;

              ${M(1===Q,R`
                  const float halfSemiMajorAxis = 0.5 * pRadius;
                  vec2 posWM = vec2(
                    oLonRad * pRadius,
                    halfSemiMajorAxis * log((1.0 + sinLat) / (1.0 - sinLat))
                  );

                  vec2 overlayUV = posWM;
              `,R`
                float oLatRad = asin(clamp(sinLat,-1.0,1.0));
                vec2 posWgs84 = vec2(rad2deg1 * oLonRad, rad2deg1 * oLatRad);
                vec2 overlayUV = posWgs84;
              `)}
              overlayUVs = vec4(overlayUV, overlayUV) * overlayTexScale + overlayTexOffset;
            }
          `,R`vec4 overlayUVs = vtcOverlay;`)}

        vec4 overlayColor = getOverlayColor(ovColorTex, overlayUVs);

        /* Early discard to only emit when we have overlay */
        ${M(oe,R`if (overlayColor.a < ${R.float(V)}) { discard; }`)}
        `)}

      vec4 externalColor;
      int externalColorMixMode;
      readExternalColor(externalColor, externalColorMixMode);

      vec4 materialColor = computeMaterialColor(textureColor, externalColor, externalColorMixMode);
    `),ae?(C(_),K&&y(_),_.main.add(R`
        applyPBRFactors();
        ${M(1===G,R`if (externalColorMixMode == 3) {
              mrr = vec3(0.0, 0.6, 0.2);
            }`)}
        float additionalIrradiance = 0.02 * mainLightIntensity[2];
        ${M(H,"mat3 tangentSpace = computeTangentSpace(fragmentFaceNormal, vPositionWorldCameraRelative, vuv0);")}
        vec3 shadingNormal = ${H?"computeTextureNormal(tangentSpace, vuv0)":"fragmentShadingNormal"};
        vec3 groundNormal = ${K?R`normalize(positionWorld())`:R`vec3(0.0, 0.0, 1.0)`};

        vec3 viewDir = normalize(vPositionWorldCameraRelative);
        float ssao = 1.0 - occlusion * evaluateAmbientOcclusionInverse();
        ${M(k,R`float snow = getSnow(fragmentFaceNormal, normalize(positionWorld()));
                 materialColor.rgb = mix(materialColor.rgb, vec3(1.1), snow);
                 ssao = mix(ssao, 0.5 * ssao, snow);
                 shadingNormal = mix(shadingNormal, fragmentFaceNormal, snow);`)}
        ${M(Y,"materialColor = materialColor * (1.0 - overlayColor.a) + overlayColor;")}

        vec3 additionalLight = evaluateAdditionalLighting(ssao, positionWorld());
        ${M(K,"float additionalAmbientScale = additionalDirectedAmbientLight(positionWorld());")}
        ${K?R`float shadow = max(lightingGlobalFactor * (1.0 - additionalAmbientScale), evaluateShadow());`:"float shadow = evaluateShadow();"}
        vec4 shadedColor = vec4(evaluateSceneLightingPBR(shadingNormal, materialColor.rgb, shadow, ssao, additionalLight, viewDir, groundNormal, mrr, additionalIrradiance), materialColor.a);
        `)):(x(_),K&&y(_),se&&_.uniforms.add(new P("ovNormalTex",e=>e.overlay?.getTexture(3))),_.main.add(R`
        ${M(K,"float additionalAmbientScale = additionalDirectedAmbientLight(positionWorld());")}
        float shadow = ${q?K?"max(lightingGlobalFactor * (1.0 - additionalAmbientScale), evaluateShadow())":"evaluateShadow()":K?"lightingGlobalFactor * (1.0 - additionalAmbientScale)":"0.0"};

        ${M(q&&!J,R`
            float dotFL = dot(fragmentFaceNormal, mainLightDirection);
            if( dotFL <= 0.0) shadow = 1.0;
        `)}
        ${M(k,R`float snow = getSnow(fragmentFaceNormal, normalize(positionWorld()));
               materialColor.rgb = mix(materialColor.rgb, vec3(1), snow);`)}

        // At global scale we create some additional ambient light based on the main light to simulate global illumination
        float ssao = evaluateAmbientOcclusion();
        vec3 additionalLight = evaluateAdditionalLighting(ssao, positionWorld());

        ${M(Y,"materialColor = materialColor * (1.0 - overlayColor.a) + overlayColor;")}

        vec4 shadedColor = vec4(evaluateSceneLighting(fragmentShadingNormal, materialColor.rgb, shadow, ssao, additionalLight), materialColor.a);
        ${M(se,R`vec4 overlayWaterMask = getOverlayColor(ovNormalTex, vtcOverlay);
                 float waterNormalLength = length(overlayWaterMask);
                 if (waterNormalLength > 0.95) {
                   mat3 tbnMatrix = mat3(tbnTangent, tbnBiTangent, groundNormal);
                   vec4 waterColorLinear = getOverlayWaterColor(overlayWaterMask, overlayColor, -normalize(vPositionWorldCameraRelative), shadow, groundNormal, tbnMatrix, vPosition_view, positionWorld());
                   vec4 waterColorNonLinear = delinearizeGamma(vec4(waterColorLinear.xyz, 1.0));
                   // un-gamma the ground color to mix in linear space
                   shadedColor = mix(shadedColor, waterColorNonLinear, waterColorLinear.w);
                 }`)}
      `)),_.main.add(`\n      ${M(re,"if(rejectBySlice(vPositionWorldCameraRelative)) shadedColor.a *= groundSliceOpacity;")}\n\n      outputColorHighlightOLID(shadedColor, vPositionWorldCameraRelative, materialColor.rgb ${M(k,", snow")});\n    `),z.sphereDepthInterpolate&&(B.include(F,{radius:ne*e}),B.fragment.include(h),_.main.add(R`if (sphereFade()>0.0) {
vec3 worldRay = normalize(vPositionWorldCameraRelative);
vec3 viewRay = normalize(vPosition_view);
gl_FragDepth = delinearizeDepth(sphereDepthInterpolate(worldRay, viewRay, linearizeDepth(gl_FragCoord.z)));
} else {
gl_FragDepth = gl_FragCoord.z;
}`)),B;const me=2===I,ve=9===I,ue=8===I,he=ie||6===I||7===I;return he&&B.include(m,z),me&&B.include(w,z),Y&&B.include(u,z),B.include(v,z),_.main.add(R`
    ${M(!re,"discardBySlice(vPositionWorldCameraRelative);")}

    vec4 textureColor = readBaseColorTexture();
    discardOrAdjustAlpha(textureColor);

    ${M(he,"outputDepth(linearDepth);")}
    ${M(me,R`fragColor = vec4(vec3(0.5) + 0.5 * fragmentFaceNormalView, 1.0);`)}
    ${M(ve,Y?"fragColor = getOverlayColorTexel();":"outputObjectAndLayerIdColor();")}
    ${M(ue,M(Y,R`calculateOcclusionAndOutputHighlight(getAllOverlayHighlightValuesEncoded());`,R`calculateOcclusionAndOutputHighlight();`))}`),B}const B=Object.freeze(Object.defineProperty({__proto__:null,build:z},Symbol.toStringTag,{value:"Module"}));export{B as C,z as b};
