/* COPYRIGHT Esri - https://js.arcgis.com/5.1.0/LICENSE.txt */
import{set as e}from"../core/libs/gl-matrix-2/math/vec2.js";import{create as a}from"../core/libs/gl-matrix-2/factories/vec2f64.js";import{create as i}from"../core/libs/gl-matrix-2/factories/vec3f64.js";import{RejectBySlicePass as n}from"../views/3d/webgl-engine/core/shaderLibrary/Slice.glsl.js";import{positionOutsideClipSpace as r}from"../views/3d/webgl-engine/core/shaderLibrary/shading/PositionOutsideClipSpace.js";import{GaussianSplatCovariance as o}from"../views/3d/webgl-engine/core/shaderLibrary/util/GaussianSplatCovariance.glsl.js";import{GaussianSplatEvaluation as c}from"../views/3d/webgl-engine/core/shaderLibrary/util/GaussianSplatEvaluation.glsl.js";import{GaussianSplatTextureFetch as s}from"../views/3d/webgl-engine/core/shaderLibrary/util/GaussianSplatTextureFetch.glsl.js";import{GaussianSplatUnpackingPassParameters as t,GaussianSplatUnpacking as l}from"../views/3d/webgl-engine/core/shaderLibrary/util/GaussianSplatUnpacking.glsl.js";import{QuaternionToRotationMatrix as v}from"../views/3d/webgl-engine/core/shaderLibrary/util/QuaternionToRotationMatrix.glsl.js";import{Float2BindUniform as d}from"../views/3d/webgl-engine/core/shaderModules/Float2BindUniform.js";import{Float3PassUniform as p}from"../views/3d/webgl-engine/core/shaderModules/Float3PassUniform.js";import{FloatPassUniform as u}from"../views/3d/webgl-engine/core/shaderModules/FloatPassUniform.js";import{glsl as m,If as f}from"../views/3d/webgl-engine/core/shaderModules/glsl.js";import{Matrix4BindUniform as x}from"../views/3d/webgl-engine/core/shaderModules/Matrix4BindUniform.js";import{Texture2DUintPassUniform as g}from"../views/3d/webgl-engine/core/shaderModules/Texture2DUintPassUniform.js";import{ShaderBuilder as h}from"../views/webgl/ShaderBuilder.js";class w extends t{constructor(){super(...arguments),this.clipMinCameraRelative=i(),this.clipMaxCameraRelative=i(),this.minSplatRadius=-1}}function S(a){const{clippingEnabled:i,hasSlicePlane:t}=a,w=new h,{fragment:S,varyings:j,vertex:y}=w;j.add("conic","vec3"),j.add("gaussianLogAlphaCutoff","float"),j.add("offsetFromCenter","vec2"),y.uniforms.add(new g("splatOrderTexture",e=>e.splatOrder),new g("splatAtlasTexture",e=>e.splatAtlas),new u("minSplatRadius",e=>e.minSplatRadius),new d("inverseScreenSize",({camera:a})=>e(P,1/a.fullWidth,1/a.fullHeight)),new x("proj",e=>e.camera.projectionMatrix),new x("view",e=>e.camera.viewMatrix),new d("nearFar",e=>e.camera.nearFar)),i&&y.uniforms.add(new p("clipMin",e=>e.clipMinCameraRelative),new p("clipMax",e=>e.clipMaxCameraRelative)),y.include(l),y.include(s),y.include(v),y.include(o),y.include(c),y.include(n,a),y.code.add(m`float safeClipW(float clipW) {
return abs(clipW) < 1e-7 ? (clipW < 0.0 ? -1e-7 : 1e-7) : clipW;
}`),y.code.add(m`vec3 computeProjectivePixelGradient(
vec3 clipGradient,
vec3 clipWGradient,
float clipValue,
float safeW,
float invWSquared,
float halfScreenSize
) {
return (clipGradient * safeW - clipValue * clipWGradient) * invWSquared * halfScreenSize;
}`),y.code.add(m`vec3 multiplyCovariance3D(float[6] covariance3D, vec3 value) {
return vec3(
covariance3D[0] * value.x + covariance3D[1] * value.y + covariance3D[2] * value.z,
covariance3D[1] * value.x + covariance3D[3] * value.y + covariance3D[4] * value.z,
covariance3D[2] * value.x + covariance3D[4] * value.y + covariance3D[5] * value.z
);
}`),y.code.add(m`vec3 computeProjectiveCovariance2D(vec3 pixelXGradient, vec3 pixelYGradient, float[6] covariance3D, mat4 view) {
mat3 worldToView = transpose(mat3(view));
vec3 axisX = worldToView * pixelXGradient;
vec3 axisY = worldToView * pixelYGradient;
vec3 covarianceAxisX = multiplyCovariance3D(covariance3D, axisX);
vec3 covarianceAxisY = multiplyCovariance3D(covariance3D, axisY);
const float regularization = 0.3;
float covarianceXX = dot(axisX, covarianceAxisX) + regularization;
float covarianceXY = dot(axisX, covarianceAxisY);
float covarianceYY = dot(axisY, covarianceAxisY) + regularization;
return vec3(covarianceXX, covarianceXY, covarianceYY);
}`),y.code.add(m`float biasDepth(float linearDepth) {
const float bias = 80.0 * .000015259;
return min(linearDepth + bias, 1.0);
}`);const G=.25,D=Math.log(G);return y.main.add(`\n    uint gaussianIndex = fetchOrderedGaussianIndex(uint(gl_InstanceID));\n    uvec4 packedGaussian = fetchPackedGaussian(gaussianIndex);\n\n    float opacity = unpackOpacity(packedGaussian);\n\n    gl_Position = ${r};\n\n    if (opacity < ${G}) {\n      return;\n    }\n\n    vec3 cameraRelativePosition = fetchGaussianCameraRelativePosition(gaussianIndex, packedGaussian);\n\n    ${f(i,m`if (cameraRelativePosition.x < clipMin.x || cameraRelativePosition.y < clipMin.y || cameraRelativePosition.z < clipMin.z ||
cameraRelativePosition.x > clipMax.x || cameraRelativePosition.y > clipMax.y || cameraRelativePosition.z > clipMax.z) {
return;
}`)}\n\n    ${f(t,m`if (rejectBySlice(cameraRelativePosition)) {
return;
}`)}\n\n    vec4 viewPos = vec4(mat3(view) * cameraRelativePosition, 1.0);\n\n    if (viewPos.z > -nearFar.x || viewPos.z < -nearFar.y) {\n      return;\n    }\n\n    vec3 covarianceA;\n    vec3 covarianceB;\n    computePackedGaussianCovariance3D(packedGaussian, covarianceA, covarianceB);\n\n    float covariance3D[6] = float[6](covarianceA.x, covarianceA.y, covarianceA.z, covarianceB.x, covarianceB.y, covarianceB.z);\n\n    vec4 projPos = proj * viewPos;\n    float safeW = safeClipW(projPos.w);\n    float invWSquared = 1.0 / (safeW * safeW);\n    vec2 halfScreenSize = 0.5 / inverseScreenSize;\n    float maxShadowSplatRadius = max(halfScreenSize.x, halfScreenSize.y);\n\n    // Projection matrix columns are the clip-space derivatives with respect to view-space xyz.\n    vec3 clipWGradient = vec3(proj[0][3], proj[1][3], proj[2][3]);\n    vec3 pixelXGradient = computeProjectivePixelGradient(\n      vec3(proj[0][0], proj[1][0], proj[2][0]),\n      clipWGradient,\n      projPos.x,\n      safeW,\n      invWSquared,\n      halfScreenSize.x\n    );\n    vec3 pixelYGradient = computeProjectivePixelGradient(\n      vec3(proj[0][1], proj[1][1], proj[2][1]),\n      clipWGradient,\n      projPos.y,\n      safeW,\n      invWSquared,\n      halfScreenSize.y\n    );\n    vec3 covariance2D = computeProjectiveCovariance2D(pixelXGradient, pixelYGradient, covariance3D, view);\n\n    float determinant = computeGaussianCovarianceDeterminant(covariance2D);\n    if (determinant <= 0.0) {\n      return;\n    }\n\n    vec2 eigenvalues = computeGaussianCovarianceEigenvalues(covariance2D);\n\n    gaussianLogAlphaCutoff = ${D} - log(opacity);\n    float gaussianEllipseThreshold = computeGaussianEllipseThreshold(gaussianLogAlphaCutoff);\n    vec2 axisLengths = computeGaussianAxisLengths(eigenvalues, gaussianEllipseThreshold);\n    float maxRadius = max(axisLengths.x, axisLengths.y);\n\n    // Avoid invalid/extremely large footprints.\n    if (maxRadius < 0.0 || maxRadius > maxShadowSplatRadius) {\n      return;\n    }\n\n    if (rejectGaussianByMinimumRadius(maxRadius, opacity, minSplatRadius)) {\n      return;\n    }\n\n    vec3 ndcPos = projPos.xyz / safeW;\n    vec2 clipSpacePixelScale = 2.0 * inverseScreenSize;\n\n    if (rejectGaussianByScreenBounds(ndcPos.xy, maxRadius, clipSpacePixelScale)) {\n      return;\n    }\n\n    offsetFromCenter = computeGaussianQuadOffset(covariance2D, eigenvalues, axisLengths, gl_VertexID);\n    conic = computeGaussianConic(covariance2D, determinant);\n    float linearDepth = (-viewPos.z - nearFar.x) / (nearFar.y - nearFar.x);\n    float biasedDepth = biasDepth(linearDepth);\n\n    vec2 clipPos = ndcPos.xy + offsetFromCenter * clipSpacePixelScale - inverseScreenSize;\n    gl_Position = vec4(clipPos, biasedDepth * 2.0 - 1.0, 1.0);\n  `),S.include(c),S.main.add(m`float gaussianExponent = evaluateGaussianExponent(conic, offsetFromCenter);
if (gaussianExponent > 0.0 || gaussianExponent < gaussianLogAlphaCutoff) {
discard;
}`),w}const P=a(),j=Object.freeze(Object.defineProperty({__proto__:null,GaussianSplatShadowPassParameters:w,build:S},Symbol.toStringTag,{value:"Module"}));export{w as G,j as a,S as b};
