{"version":3,"file":"SAOShader.cjs","sources":["../../src/shaders/SAOShader.ts"],"sourcesContent":["import { Matrix4, Vector2 } from 'three'\n\nimport type { IUniform, Texture } from 'three'\nimport type { IShader } from './types'\n\nexport type SAOShaderDefines = Record<\n  'DEPTH_PACKING' | 'DIFFUSE_TEXTURE' | 'NORMAL_TEXTURE' | 'NUM_RINGS' | 'NUM_SAMPLES' | 'PERSPECTIVE_CAMERA',\n  number\n>\n\nexport type SAOShaderUniforms = {\n  bias: IUniform<number>\n  cameraFar: IUniform<number>\n  cameraInverseProjectionMatrix: IUniform<Matrix4>\n  cameraNear: IUniform<number>\n  cameraProjectionMatrix: IUniform<Matrix4>\n  intensity: IUniform<number>\n  kernelRadius: IUniform<number>\n  minResolution: IUniform<number>\n  randomSeed: IUniform<number>\n  scale: IUniform<number>\n  size: IUniform<Vector2>\n  tDepth: IUniform<Texture | null>\n  tDiffuse: IUniform<Texture | null>\n  tNormal: IUniform<Texture | null>\n}\n\nexport interface ISAOShader extends IShader<SAOShaderUniforms, SAOShaderDefines> {\n  defines: SAOShaderDefines\n  needsUpdate?: boolean\n}\n\nexport const SAOShader: ISAOShader = {\n  defines: {\n    NUM_SAMPLES: 7,\n    NUM_RINGS: 4,\n    NORMAL_TEXTURE: 0,\n    DIFFUSE_TEXTURE: 0,\n    DEPTH_PACKING: 1,\n    PERSPECTIVE_CAMERA: 1,\n  },\n  uniforms: {\n    tDepth: { value: null },\n    tDiffuse: { value: null },\n    tNormal: { value: null },\n    size: { value: /* @__PURE__ */ new Vector2(512, 512) },\n\n    cameraNear: { value: 1 },\n    cameraFar: { value: 100 },\n    cameraProjectionMatrix: { value: /* @__PURE__ */ new Matrix4() },\n    cameraInverseProjectionMatrix: { value: /* @__PURE__ */ new Matrix4() },\n\n    scale: { value: 1.0 },\n    intensity: { value: 0.1 },\n    bias: { value: 0.5 },\n\n    minResolution: { value: 0.0 },\n    kernelRadius: { value: 100.0 },\n    randomSeed: { value: 0.0 },\n  },\n  vertexShader: /* glsl */ `\n    varying vec2 vUv;\n\n    void main() {\n    \tvUv = uv;\n    \tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n    }\n  `,\n  fragmentShader: /* glsl */ `\n    #include <common>\n\n    varying vec2 vUv;\n\n    #if DIFFUSE_TEXTURE == 1\n    uniform sampler2D tDiffuse;\n    #endif\n\n    uniform sampler2D tDepth;\n\n    #if NORMAL_TEXTURE == 1\n    uniform sampler2D tNormal;\n    #endif\n\n    uniform float cameraNear;\n    uniform float cameraFar;\n    uniform mat4 cameraProjectionMatrix;\n    uniform mat4 cameraInverseProjectionMatrix;\n\n    uniform float scale;\n    uniform float intensity;\n    uniform float bias;\n    uniform float kernelRadius;\n    uniform float minResolution;\n    uniform vec2 size;\n    uniform float randomSeed;\n\n    // RGBA depth\n\n    #include <packing>\n\n    vec4 getDefaultColor( const in vec2 screenPosition ) {\n    \t#if DIFFUSE_TEXTURE == 1\n    \treturn texture2D( tDiffuse, vUv );\n    \t#else\n    \treturn vec4( 1.0 );\n    \t#endif\n    }\n\n    float getDepth( const in vec2 screenPosition ) {\n    \t#if DEPTH_PACKING == 1\n    \treturn unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );\n    \t#else\n    \treturn texture2D( tDepth, screenPosition ).x;\n    \t#endif\n    }\n\n    float getViewZ( const in float depth ) {\n    \t#if PERSPECTIVE_CAMERA == 1\n    \treturn perspectiveDepthToViewZ( depth, cameraNear, cameraFar );\n    \t#else\n    \treturn orthographicDepthToViewZ( depth, cameraNear, cameraFar );\n    \t#endif\n    }\n\n    vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {\n    \tfloat clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];\n    \tvec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );\n    \tclipPosition *= clipW; // unprojection.\n\n    \treturn ( cameraInverseProjectionMatrix * clipPosition ).xyz;\n    }\n\n    vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {\n    \t#if NORMAL_TEXTURE == 1\n    \treturn unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );\n    \t#else\n    \treturn normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );\n    \t#endif\n    }\n\n    float scaleDividedByCameraFar;\n    float minResolutionMultipliedByCameraFar;\n\n    float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) {\n    \tvec3 viewDelta = sampleViewPosition - centerViewPosition;\n    \tfloat viewDistance = length( viewDelta );\n    \tfloat scaledScreenDistance = scaleDividedByCameraFar * viewDistance;\n\n    \treturn max(0.0, (dot(centerViewNormal, viewDelta) - minResolutionMultipliedByCameraFar) / scaledScreenDistance - bias) / (1.0 + pow2( scaledScreenDistance ) );\n    }\n\n    // moving costly divides into consts\n    const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );\n    const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );\n\n    float getAmbientOcclusion( const in vec3 centerViewPosition ) {\n    \t// precompute some variables require in getOcclusion.\n    \tscaleDividedByCameraFar = scale / cameraFar;\n    \tminResolutionMultipliedByCameraFar = minResolution * cameraFar;\n    \tvec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );\n\n    \t// jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/\n    \tfloat angle = rand( vUv + randomSeed ) * PI2;\n    \tvec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES ) / size;\n    \tvec2 radiusStep = radius;\n\n    \tfloat occlusionSum = 0.0;\n    \tfloat weightSum = 0.0;\n\n    \tfor( int i = 0; i < NUM_SAMPLES; i ++ ) {\n    \t\tvec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius;\n    \t\tradius += radiusStep;\n    \t\tangle += ANGLE_STEP;\n\n    \t\tfloat sampleDepth = getDepth( sampleUv );\n    \t\tif( sampleDepth >= ( 1.0 - EPSILON ) ) {\n    \t\t\tcontinue;\n    \t\t}\n\n    \t\tfloat sampleViewZ = getViewZ( sampleDepth );\n    \t\tvec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ );\n    \t\tocclusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition );\n    \t\tweightSum += 1.0;\n    \t}\n\n    \tif( weightSum == 0.0 ) discard;\n\n    \treturn occlusionSum * ( intensity / weightSum );\n    }\n\n    void main() {\n    \tfloat centerDepth = getDepth( vUv );\n    \tif( centerDepth >= ( 1.0 - EPSILON ) ) {\n    \t\tdiscard;\n    \t}\n\n    \tfloat centerViewZ = getViewZ( centerDepth );\n    \tvec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );\n\n    \tfloat ambientOcclusion = getAmbientOcclusion( viewPosition );\n\n    \tgl_FragColor = getDefaultColor( vUv );\n    \tgl_FragColor.xyz *=  1.0 - ambientOcclusion;\n    }\n  `,\n}\n"],"names":["Vector2","Matrix4"],"mappings":";;;AAgCO,MAAM,YAAwB;AAAA,EACnC,SAAS;AAAA,IACP,aAAa;AAAA,IACb,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,oBAAoB;AAAA,EACtB;AAAA,EACA,UAAU;AAAA,IACR,QAAQ,EAAE,OAAO,KAAK;AAAA,IACtB,UAAU,EAAE,OAAO,KAAK;AAAA,IACxB,SAAS,EAAE,OAAO,KAAK;AAAA,IACvB,MAAM,EAAE,2BAA2BA,MAAQ,QAAA,KAAK,GAAG,EAAE;AAAA,IAErD,YAAY,EAAE,OAAO,EAAE;AAAA,IACvB,WAAW,EAAE,OAAO,IAAI;AAAA,IACxB,wBAAwB,EAAE,OAAuB,oBAAIC,MAAAA,UAAU;AAAA,IAC/D,+BAA+B,EAAE,OAAuB,oBAAIA,MAAAA,UAAU;AAAA,IAEtE,OAAO,EAAE,OAAO,EAAI;AAAA,IACpB,WAAW,EAAE,OAAO,IAAI;AAAA,IACxB,MAAM,EAAE,OAAO,IAAI;AAAA,IAEnB,eAAe,EAAE,OAAO,EAAI;AAAA,IAC5B,cAAc,EAAE,OAAO,IAAM;AAAA,IAC7B,YAAY,EAAE,OAAO,EAAI;AAAA,EAC3B;AAAA,EACA;AAAA;AAAA,IAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzB;AAAA;AAAA,IAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyI7B;;"}