(function (global, factory) {
  if (typeof define === "function" && define.amd) {
    define(["exports", "three"], factory);
  } else if (typeof exports !== "undefined") {
    factory(exports, require("three"));
  } else {
    var mod = {
      exports: {}
    };
    factory(mod.exports, global.three);
    global.SSRrShader = mod.exports;
  }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (_exports, _three) {
  "use strict";

  Object.defineProperty(_exports, "__esModule", {
    value: true
  });
  _exports.SSRrShader = _exports.SSRrDepthShader = void 0;
  var SSRrShader = {
    defines: {
      MAX_STEP: 0,
      PERSPECTIVE_CAMERA: true,
      SPECULAR: true,
      FILL_HOLE: true,
      INFINITE_THICK: false
    },
    uniforms: {
      'tDiffuse': {
        value: null
      },
      'tSpecular': {
        value: null
      },
      'tNormalSelects': {
        value: null
      },
      'tRefractive': {
        value: null
      },
      'tDepth': {
        value: null
      },
      'tDepthSelects': {
        value: null
      },
      'cameraNear': {
        value: null
      },
      'cameraFar': {
        value: null
      },
      'resolution': {
        value: new _three.Vector2()
      },
      'cameraProjectionMatrix': {
        value: new _three.Matrix4()
      },
      'cameraInverseProjectionMatrix': {
        value: new _three.Matrix4()
      },
      'ior': {
        value: 1.03
      },
      'cameraRange': {
        value: 0
      },
      'maxDistance': {
        value: 180
      },
      'surfDist': {
        value: .007
      }
    },
    vertexShader:
    /* glsl */
    "\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}\n\n\t",
    fragmentShader:
    /* glsl */
    "\n\t\t// precision highp float;\n\t\tprecision highp sampler2D;\n\t\tvarying vec2 vUv;\n\t\tuniform sampler2D tDepth;\n\t\tuniform sampler2D tDepthSelects;\n\t\tuniform sampler2D tNormalSelects;\n\t\tuniform sampler2D tRefractive;\n\t\tuniform sampler2D tDiffuse;\n\t\tuniform sampler2D tSpecular;\n\t\tuniform float cameraRange;\n\t\tuniform vec2 resolution;\n\t\tuniform float cameraNear;\n\t\tuniform float cameraFar;\n\t\tuniform float ior;\n\t\tuniform mat4 cameraProjectionMatrix;\n\t\tuniform mat4 cameraInverseProjectionMatrix;\n\t\tuniform float maxDistance;\n\t\tuniform float surfDist;\n\t\t#include <packing>\n\t\tfloat pointToLineDistance(vec3 x0, vec3 x1, vec3 x2) {\n\t\t\t//x0: point, x1: linePointA, x2: linePointB\n\t\t\t//https://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html\n\t\t\treturn length(cross(x0-x1,x0-x2))/length(x2-x1);\n\t\t}\n\t\tfloat pointPlaneDistance(vec3 point,vec3 planePoint,vec3 planeNormal){\n\t\t\t// https://mathworld.wolfram.com/Point-PlaneDistance.html\n\t\t\t//// https://en.wikipedia.org/wiki/Plane_(geometry)\n\t\t\t//// http://paulbourke.net/geometry/pointlineplane/\n\t\t\tfloat a=planeNormal.x,b=planeNormal.y,c=planeNormal.z;\n\t\t\tfloat x0=point.x,y0=point.y,z0=point.z;\n\t\t\tfloat x=planePoint.x,y=planePoint.y,z=planePoint.z;\n\t\t\tfloat d=-(a*x+b*y+c*z);\n\t\t\tfloat distance=(a*x0+b*y0+c*z0+d)/sqrt(a*a+b*b+c*c);\n\t\t\treturn distance;\n\t\t}\n\t\tfloat getDepth( const in vec2 uv ) {\n\t\t\treturn texture2D( tDepth, uv ).x;\n\t\t}\n\t\tfloat getDepthSelects( const in vec2 uv ) {\n\t\t\treturn texture2D( tDepthSelects, uv ).x;\n\t\t}\n\t\tfloat getViewZ( const in float depth ) {\n\t\t\t#ifdef PERSPECTIVE_CAMERA\n\t\t\t\treturn perspectiveDepthToViewZ( depth, cameraNear, cameraFar );\n\t\t\t#else\n\t\t\t\treturn orthographicDepthToViewZ( depth, cameraNear, cameraFar );\n\t\t\t#endif\n\t\t}\n\t\tvec3 getViewPosition( const in vec2 uv, const in float depth/*clip space*/, const in float clipW ) {\n\t\t\tvec4 clipPosition = vec4( ( vec3( uv, depth ) - 0.5 ) * 2.0, 1.0 );//ndc\n\t\t\tclipPosition *= clipW; //clip\n\t\t\treturn ( cameraInverseProjectionMatrix * clipPosition ).xyz;//view\n\t\t}\n\t\tvec3 getViewNormalSelects( const in vec2 uv ) {\n\t\t\treturn unpackRGBToNormal( texture2D( tNormalSelects, uv ).xyz );\n\t\t}\n\t\tvec2 viewPositionToXY(vec3 viewPosition){\n\t\t\tvec2 xy;\n\t\t\tvec4 clip=cameraProjectionMatrix*vec4(viewPosition,1);\n\t\t\txy=clip.xy;//clip\n\t\t\tfloat clipW=clip.w;\n\t\t\txy/=clipW;//NDC\n\t\t\txy=(xy+1.)/2.;//uv\n\t\t\txy*=resolution;//screen\n\t\t\treturn xy;\n\t\t}\n\t\tvoid setResultColor(vec2 uv){\n\t\t\tvec4 refractColor=texture2D(tDiffuse,uv);\n\t\t\t#ifdef SPECULAR\n\t\t\t\tvec4 specularColor=texture2D(tSpecular,vUv);\n\t\t\t\tgl_FragColor.xyz=mix(refractColor.xyz,vec3(1),specularColor.r);\n\t\t\t\t// gl_FragColor.xyz=refractColor.xyz*(1.+specularColor.r*3.);\n\t\t\t#else\n\t\t\t\tgl_FragColor.xyz=refractColor.xyz;\n\t\t\t#endif\n\t\t\tgl_FragColor.a=1.;\n\n\t\t}\n\t\tvoid main(){\n\t\t\tif(ior==1.) return; // Adding this line may have better performance, but more importantly, it can avoid display errors at the very edges of the model when IOR is equal to 1.\n\n\t\t\tfloat refractive=texture2D(tRefractive,vUv).r;\n\t\t\tif(refractive<=0.) return;\n\n\t\t\t// gl_FragColor=vec4(0,0,.5,1);return;\n\t\t\tvec3 viewNormalSelects=getViewNormalSelects( vUv );\n\t\t\t// gl_FragColor=vec4(viewNormalSelects,1);return;\n\n\t\t\t// if(viewNormalSelects.x<=0.&&viewNormalSelects.y<=0.&&viewNormalSelects.z<=0.) return;\n\n\t\t\tfloat depth = getDepthSelects( vUv );\n\t\t\tfloat viewZ = getViewZ( depth );\n\t\t\t// if(-viewZ>=cameraFar) return;\n\n\t\t\tfloat clipW = cameraProjectionMatrix[2][3] * viewZ+cameraProjectionMatrix[3][3];\n\t\t\tvec3 viewPosition=getViewPosition( vUv, depth, clipW );\n\n\t\t\tvec2 d0=gl_FragCoord.xy;\n\t\t\tvec2 d1;\n\n\t\t\t#ifdef PERSPECTIVE_CAMERA\n\t\t\t\tvec3 viewIncidentDir=normalize(viewPosition);\n\t\t\t#else\n\t\t\t\tvec3 viewIncidentDir=vec3(0,0,-1);\n\t\t\t#endif\n\n\t\t\tvec3 viewRefractDir=refract(viewIncidentDir,viewNormalSelects,1./ior);\n\t\t\t// https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/refract.xhtml\n\n\t\t\tvec3 d1viewPosition=viewPosition+viewRefractDir*maxDistance;\n\t\t\t#ifdef PERSPECTIVE_CAMERA\n\t\t\t\tif(d1viewPosition.z>-cameraNear){\n\t\t\t\t\t//https://tutorial.math.lamar.edu/Classes/CalcIII/EqnsOfLines.aspx\n\t\t\t\t\tfloat t=(-cameraNear-viewPosition.z)/viewRefractDir.z;\n\t\t\t\t\td1viewPosition=viewPosition+viewRefractDir*t;\n\t\t\t\t}\n\t\t\t#endif\n\t\t\td1=viewPositionToXY(d1viewPosition);\n\n\t\t\tfloat totalLen=length(d1-d0);\n\t\t\tfloat xLen=d1.x-d0.x;\n\t\t\tfloat yLen=d1.y-d0.y;\n\t\t\tfloat totalStep=max(abs(xLen),abs(yLen));\n\t\t\tfloat xSpan=xLen/totalStep;\n\t\t\tfloat ySpan=yLen/totalStep;\n\t\t\t#ifdef FILL_HOLE\n\t\t\t\tbool isRough=false;\n\t\t\t\tvec2 uvRough;\n\t\t\t#endif\n\t\t\tfor(float i=0.;i<float(MAX_STEP);i++){\n\t\t\t\tif(i>=totalStep) break;\n\t\t\t\tvec2 xy=vec2(d0.x+i*xSpan,d0.y+i*ySpan);\n\t\t\t\tif(xy.x<0.||xy.x>resolution.x||xy.y<0.||xy.y>resolution.y) break;\n\t\t\t\tfloat s=length(xy-d0)/totalLen;\n\t\t\t\tvec2 uv=xy/resolution;\n\n\t\t\t\tfloat d = getDepth(uv);\n\t\t\t\tfloat vZ = getViewZ( d );\n\t\t\t\tfloat cW = cameraProjectionMatrix[2][3] * vZ+cameraProjectionMatrix[3][3];\n\t\t\t\tvec3 vP=getViewPosition( uv, d, cW );\n\n\t\t\t\t#ifdef PERSPECTIVE_CAMERA\n\t\t\t\t\t// https://www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf\n\t\t\t\t\tfloat recipVPZ=1./viewPosition.z;\n\t\t\t\t\tfloat viewRefractRayZ=1./(recipVPZ+s*(1./d1viewPosition.z-recipVPZ));\n\t\t\t\t\tfloat sD=surfDist*cW;\n\t\t\t\t#else\n\t\t\t\t\tfloat viewRefractRayZ=viewPosition.z+s*(d1viewPosition.z-viewPosition.z);\n\t\t\t\t\tfloat sD=surfDist;\n\t\t\t\t#endif\n\n\t\t\t\t#ifdef FILL_HOLE // TODO: May can improve performance by check if INFINITE_THICK too.\n\t\t\t\t\tif(viewRefractRayZ<=vZ){\n\t\t\t\t\t\tif(!isRough){\n\t\t\t\t\t\t\tuvRough=uv;\n\t\t\t\t\t\t\tisRough=true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t#endif\n\n\t\t\t\tbool hit;\n\t\t\t\t#ifdef INFINITE_THICK\n\t\t\t\t\thit=viewRefractRayZ<=vZ;\n\t\t\t\t#else\n\t\t\t\t\tif(viewRefractRayZ-sD>vZ) continue;\n\t\t\t\t\tfloat away=pointToLineDistance(vP,viewPosition,d1viewPosition);\n\t\t\t\t\thit=away<=sD;\n\t\t\t\t#endif\n\t\t\t\tif(hit){\n\t\t\t\t\tsetResultColor(uv);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t#ifdef FILL_HOLE\n\t\t\t\tif(isRough){\n\t\t\t\t\tsetResultColor(uvRough);\n\t\t\t\t}\n\t\t\t\t// else{\n\t\t\t\t// \tgl_FragColor=texture2D(tDiffuse,vUv);//For afterward add color mix feature.\n\t\t\t\t// }\n\t\t\t#else\n\t\t\t\t// gl_FragColor=texture2D(tDiffuse,vUv);//For afterward add color mix feature.\n\t\t\t#endif\n\t\t}\n\t"
  };
  _exports.SSRrShader = SSRrShader;
  var SSRrDepthShader = {
    defines: {
      'PERSPECTIVE_CAMERA': 1
    },
    uniforms: {
      'tDepth': {
        value: null
      },
      'cameraNear': {
        value: null
      },
      'cameraFar': {
        value: null
      }
    },
    vertexShader:
    /* glsl */
    "\n\n\t\tvarying vec2 vUv;\n\n\t\tvoid main() {\n\n\t\t\tvUv = uv;\n\t\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n\t\t}\n\n\t",
    fragmentShader:
    /* glsl */
    "\n\n\t\tuniform sampler2D tDepth;\n\n\t\tuniform float cameraNear;\n\t\tuniform float cameraFar;\n\n\t\tvarying vec2 vUv;\n\n\t\t#include <packing>\n\n\t\tfloat getLinearDepth( const in vec2 uv ) {\n\n\t\t\t#if PERSPECTIVE_CAMERA == 1\n\n\t\t\t\tfloat fragCoordZ = texture2D( tDepth, uv ).x;\n\t\t\t\tfloat viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar );\n\t\t\t\treturn viewZToOrthographicDepth( viewZ, cameraNear, cameraFar );\n\n\t\t\t#else\n\n\t\t\t\treturn texture2D( tDepth, uv ).x;\n\n\t\t\t#endif\n\n\t\t}\n\n\t\tvoid main() {\n\n\t\t\tfloat depth = getLinearDepth( vUv );\n\t\t\tfloat d = 1.0 - depth;\n\t\t\t// d=(d-.999)*1000.;\n\t\t\tgl_FragColor = vec4( vec3( d ), 1.0 );\n\n\t\t}\n\n\t"
  };
  _exports.SSRrDepthShader = SSRrDepthShader;
});