123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- /**
- * @author alteredq / http://alteredqualia.com/
- *
- * Screen-space ambient occlusion shader
- * - ported from
- * SSAO GLSL shader v1.2
- * assembled by Martins Upitis (martinsh) (http://devlog-martinsh.blogspot.com)
- * original technique is made by ArKano22 (http://www.gamedev.net/topic/550699-ssao-no-halo-artifacts/)
- * - modifications
- * - modified to use RGBA packed depth texture (use clear color 1,1,1,1 for depth pass)
- * - refactoring and optimizations
- */
- THREE.SSAOShader = {
- uniforms: {
- "tDiffuse": { value: null },
- "tDepth": { value: null },
- "size": { value: new THREE.Vector2( 512, 512 ) },
- "cameraNear": { value: 1 },
- "cameraFar": { value: 100 },
- "onlyAO": { value: 0 },
- "aoClamp": { value: 0.5 },
- "lumInfluence": { value: 0.5 }
- },
- vertexShader: [
- "varying vec2 vUv;",
- "void main() {",
- "vUv = uv;",
- "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
- "}"
- ].join( "\n" ),
- fragmentShader: [
- "uniform float cameraNear;",
- "uniform float cameraFar;",
- "#ifdef USE_LOGDEPTHBUF",
- "uniform float logDepthBufFC;",
- "#endif",
- "uniform bool onlyAO;", // use only ambient occlusion pass?
- "uniform vec2 size;", // texture width, height
- "uniform float aoClamp;", // depth clamp - reduces haloing at screen edges
- "uniform float lumInfluence;", // how much luminance affects occlusion
- "uniform sampler2D tDiffuse;",
- "uniform sampler2D tDepth;",
- "varying vec2 vUv;",
- // "#define PI 3.14159265",
- "#define DL 2.399963229728653", // PI * ( 3.0 - sqrt( 5.0 ) )
- "#define EULER 2.718281828459045",
- // user variables
- "const int samples = 8;", // ao sample count
- "const float radius = 5.0;", // ao radius
- "const bool useNoise = false;", // use noise instead of pattern for sample dithering
- "const float noiseAmount = 0.0003;", // dithering amount
- "const float diffArea = 0.4;", // self-shadowing reduction
- "const float gDisplace = 0.4;", // gauss bell center
- // RGBA depth
- "#include <packing>",
- // generating noise / pattern texture for dithering
- "vec2 rand( const vec2 coord ) {",
- "vec2 noise;",
- "if ( useNoise ) {",
- "float nx = dot ( coord, vec2( 12.9898, 78.233 ) );",
- "float ny = dot ( coord, vec2( 12.9898, 78.233 ) * 2.0 );",
- "noise = clamp( fract ( 43758.5453 * sin( vec2( nx, ny ) ) ), 0.0, 1.0 );",
- "} else {",
- "float ff = fract( 1.0 - coord.s * ( size.x / 2.0 ) );",
- "float gg = fract( coord.t * ( size.y / 2.0 ) );",
- "noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;",
- "}",
- "return ( noise * 2.0 - 1.0 ) * noiseAmount;",
- "}",
- "float readDepth( const in vec2 coord ) {",
- "float cameraFarPlusNear = cameraFar + cameraNear;",
- "float cameraFarMinusNear = cameraFar - cameraNear;",
- "float cameraCoef = 2.0 * cameraNear;",
- "#ifdef USE_LOGDEPTHBUF",
- "float logz = unpackRGBAToDepth( texture2D( tDepth, coord ) );",
- "float w = pow(2.0, (logz / logDepthBufFC)) - 1.0;",
- "float z = (logz / w) + 1.0;",
- "#else",
- "float z = unpackRGBAToDepth( texture2D( tDepth, coord ) );",
- "#endif",
- "return cameraCoef / ( cameraFarPlusNear - z * cameraFarMinusNear );",
- "}",
- "float compareDepths( const in float depth1, const in float depth2, inout int far ) {",
- "float garea = 2.0;", // gauss bell width
- "float diff = ( depth1 - depth2 ) * 100.0;", // depth difference (0-100)
- // reduce left bell width to avoid self-shadowing
- "if ( diff < gDisplace ) {",
- "garea = diffArea;",
- "} else {",
- "far = 1;",
- "}",
- "float dd = diff - gDisplace;",
- "float gauss = pow( EULER, -2.0 * dd * dd / ( garea * garea ) );",
- "return gauss;",
- "}",
- "float calcAO( float depth, float dw, float dh ) {",
- "float dd = radius - depth * radius;",
- "vec2 vv = vec2( dw, dh );",
- "vec2 coord1 = vUv + dd * vv;",
- "vec2 coord2 = vUv - dd * vv;",
- "float temp1 = 0.0;",
- "float temp2 = 0.0;",
- "int far = 0;",
- "temp1 = compareDepths( depth, readDepth( coord1 ), far );",
- // DEPTH EXTRAPOLATION
- "if ( far > 0 ) {",
- "temp2 = compareDepths( readDepth( coord2 ), depth, far );",
- "temp1 += ( 1.0 - temp1 ) * temp2;",
- "}",
- "return temp1;",
- "}",
- "void main() {",
- "vec2 noise = rand( vUv );",
- "float depth = readDepth( vUv );",
- "float tt = clamp( depth, aoClamp, 1.0 );",
- "float w = ( 1.0 / size.x ) / tt + ( noise.x * ( 1.0 - noise.x ) );",
- "float h = ( 1.0 / size.y ) / tt + ( noise.y * ( 1.0 - noise.y ) );",
- "float ao = 0.0;",
- "float dz = 1.0 / float( samples );",
- "float z = 1.0 - dz / 2.0;",
- "float l = 0.0;",
- "for ( int i = 0; i <= samples; i ++ ) {",
- "float r = sqrt( 1.0 - z );",
- "float pw = cos( l ) * r;",
- "float ph = sin( l ) * r;",
- "ao += calcAO( depth, pw * w, ph * h );",
- "z = z - dz;",
- "l = l + DL;",
- "}",
- "ao /= float( samples );",
- "ao = 1.0 - ao;",
- "vec3 color = texture2D( tDiffuse, vUv ).rgb;",
- "vec3 lumcoeff = vec3( 0.299, 0.587, 0.114 );",
- "float lum = dot( color.rgb, lumcoeff );",
- "vec3 luminance = vec3( lum );",
- "vec3 final = vec3( color * mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // mix( color * ao, white, luminance )
- "if ( onlyAO ) {",
- "final = vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );", // ambient occlusion only
- "}",
- "gl_FragColor = vec4( final, 1.0 );",
- "}"
- ].join( "\n" )
- };
|