/* COPYRIGHT Esri - https://js.arcgis.com/5.1.0/LICENSE.txt */
import{numberMaxFloat32 as e}from"../core/mathUtils.js";import{multiply as i,fromTranslation as o}from"../core/libs/gl-matrix-2/math/mat4.js";import{create as r}from"../core/libs/gl-matrix-2/factories/mat4f64.js";import{set as t}from"../core/libs/gl-matrix-2/math/vec2.js";import{create as s}from"../core/libs/gl-matrix-2/factories/vec2f64.js";import{set as a}from"../core/libs/gl-matrix-2/math/vec3.js";import{create as n}from"../core/libs/gl-matrix-2/factories/vec3f64.js";import{create as c,positiveInfinity as l}from"../geometry/support/aaBoundingBox.js";import{isColor as p}from"../views/3d/webgl-engine/core/shaderLibrary/ShaderOutput.js";import{SlicePlaneParameters as m,RejectBySliceDraw as d}from"../views/3d/webgl-engine/core/shaderLibrary/Slice.glsl.js";import{OutputHighlight as f}from"../views/3d/webgl-engine/core/shaderLibrary/output/OutputHighlight.glsl.js";import{positionOutsideClipSpace as g}from"../views/3d/webgl-engine/core/shaderLibrary/shading/PositionOutsideClipSpace.js";import{Float2DrawUniform as u}from"../views/3d/webgl-engine/core/shaderModules/Float2DrawUniform.js";import{Float2PassUniform as S}from"../views/3d/webgl-engine/core/shaderModules/Float2PassUniform.js";import{Float3DrawUniform as x}from"../views/3d/webgl-engine/core/shaderModules/Float3DrawUniform.js";import{glsl as h,If as v}from"../views/3d/webgl-engine/core/shaderModules/glsl.js";import{Matrix4BindUniform as w}from"../views/3d/webgl-engine/core/shaderModules/Matrix4BindUniform.js";import{Matrix4DrawUniform as z}from"../views/3d/webgl-engine/core/shaderModules/Matrix4DrawUniform.js";import{NoParameters as b}from"../views/webgl/NoParameters.js";import{ShaderBuilder as M}from"../views/webgl/ShaderBuilder.js";class j extends b{constructor(){super(...arguments),this.clipBox=c(l),this.useFixedSizes=!1,this.useRealWorldSymbolSizes=!1,this.scaleFactor=1,this.minSizePx=0,this.size=0,this.sizePx=0}get fixedSize(){return this.drawScreenSpace?this.sizePx:this.size}get screenMinSize(){return this.useFixedSizes?0:this.minSizePx}get drawScreenSpace(){return this.useFixedSizes&&!this.useRealWorldSymbolSizes}}class P extends m{constructor(e,i,o){super(e),this.origin=e,this.isLeaf=i,this.splatSize=o}}function y(r){const s=new M,n=p(r.output),{attributes:c,vertex:l,fragment:m}=s;return c.add("position","vec3"),c.add("color","vec3"),l.include(d,r),l.uniforms.add(new z("modelView",(e,r)=>i(B,r.camera.viewMatrix,o(B,e.origin))),new w("proj",e=>e.camera.projectionMatrix),new u("screenMinMaxSize",(e,i,o)=>t(_,o.useFixedSizes?0:o.minSizePx*i.camera.pixelRatio,O(e.isLeaf)*i.camera.pixelRatio)),r.useFixedSizes?new S("pointScale",(e,i)=>t(_,e.fixedSize*i.camera.pixelRatio,i.camera.fullHeight)):new u("pointScale",(e,i,o)=>t(_,e.splatSize*o.scaleFactor*i.camera.pixelRatio,i.camera.fullHeight/i.camera.pixelRatio))),r.clippingEnabled?l.uniforms.add(new x("clipMin",(e,i,o)=>a(R,o.clipBox[0]-e.origin[0],o.clipBox[1]-e.origin[1],o.clipBox[2]-e.origin[2])),new x("clipMax",(e,i,o)=>a(R,o.clipBox[3]-e.origin[0],o.clipBox[4]-e.origin[1],o.clipBox[5]-e.origin[2]))):(l.constants.add("clipMin","vec3",[-e,-e,-e]),l.constants.add("clipMax","vec3",[e,e,e])),n&&s.varyings.add("vColor","vec3"),l.main.add(h`
    // Move clipped points outside of clipspace
    if (position.x < clipMin.x || position.y < clipMin.y || position.z < clipMin.z ||
      position.x > clipMax.x || position.y > clipMax.y || position.z > clipMax.z) {
      gl_Position = ${g};
      gl_PointSize = 0.0;
      return;
    }

    if (rejectBySlice(position)) {
      gl_Position = ${g};
      gl_PointSize = 0.0;
      return;
    }

    // Position in camera space
    vec4 camera = modelView * vec4(position, 1.0);

    float pointSize = pointScale.x;
    vec4 position = proj * camera;
    ${r.drawScreenSize?h`float clampedScreenSize = pointSize;`:h`float pointRadius = 0.5 * pointSize;
           vec4 cameraOffset = camera + vec4(0.0, pointRadius, 0.0, 0.0);
           vec4 positionOffset = proj * cameraOffset;
           float radius = abs(positionOffset.y - position.y);
           float viewHeight = pointScale.y;
           // screen diameter = (2 * r / w) * (h / 2)
           float screenPointSize = (radius / position.w) * viewHeight;
           float clampedScreenSize = clamp(screenPointSize, screenMinMaxSize.x, screenMinMaxSize.y);
           // Shift towards camera, to move rendered point out of terrain i.e. to
           // the camera-facing end of the virtual point when considering it as a
           // 3D sphere.
           camera.xyz -= normalize(camera.xyz) * pointRadius * clampedScreenSize / screenPointSize;
           position = proj * camera;`}

    gl_PointSize = clampedScreenSize;
    gl_Position = position;
    ${n?h`vColor = color;`:""}`),s.include(f,r),n&&(s.outputs.add("fragColor","vec4",0),r.hasEmission&&s.outputs.add("fragEmission","vec4",1)),m.main.add(h`
    vec2 vOffset = gl_PointCoord - vec2(0.5, 0.5);
    float r2 = dot(vOffset, vOffset);

    if (r2 > 0.25) {
      discard;
    }
    calculateOcclusionAndOutputHighlight();
    ${v(n,`fragColor = vec4(vColor, 1.0);\n      ${v(r.hasEmission,"fragEmission = vec4(vec3(0.0), 1.0);")}`)}
  `),s}function O(e){return e?256:64}const B=r(),R=n(),_=s(),F=Object.freeze(Object.defineProperty({__proto__:null,PointRendererDrawParameters:P,PointRendererPassParameters:j,build:y,getMaxPointSizeScreenspace:O},Symbol.toStringTag,{value:"Module"}));export{j as P,P as a,F as b,y as c,O as g};
