Skip to content

Instantly share code, notes, and snippets.

@rhulha
Created June 7, 2014 11:26
Show Gist options
  • Save rhulha/f53b916b4032303822b6 to your computer and use it in GitHub Desktop.
Save rhulha/f53b916b4032303822b6 to your computer and use it in GitHub Desktop.
SSAO
// From Three.js
uniform float cameraNear;
uniform float cameraFar;
uniform float fogNear;
uniform float fogFar;
uniform bool fogEnabled;
uniform bool onlyAO;
uniform vec2 size;
uniform float aoClamp;
uniform float lumInfluence;
uniform sampler2D tDiffuse;
uniform sampler2D tDepth;
varying vec2 vUv;
#define DL 2.399963229728653
#define EULER 2.718281828459045
float width = size.x;
float height = size.y;
float cameraFarPlusNear = cameraFar + cameraNear;
float cameraFarMinusNear = cameraFar - cameraNear;
float cameraCoef = 2.0 * cameraNear;
const int samples = 8;
const float radius = 5.0;
const bool useNoise = false;
const float noiseAmount = 0.0003;
const float diffArea = 0.4;
const float gDisplace = 0.4;
const vec3 onlyAOColor = vec3( 1.0, 0.7, 0.5 );
float unpackDepth( const in vec4 rgba_depth ) {
const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );
float depth = dot( rgba_depth, bit_shift );
return depth;
}
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 * ( width / 2.0 ) );
float gg = fract( coord.t * ( height / 2.0 ) );
noise = vec2( 0.25, 0.75 ) * vec2( ff ) + vec2( 0.75, 0.25 ) * gg;
}
return ( noise * 2.0 - 1.0 ) * noiseAmount;
}
float doFog() {
float zdepth = unpackDepth( texture2D( tDepth, vUv ) );
float depth = -cameraFar * cameraNear / ( zdepth * cameraFarMinusNear - cameraFar );
return smoothstep( fogNear, fogFar, depth );
}
float readDepth( const in vec2 coord ) {
return cameraCoef / ( cameraFarPlusNear - unpackDepth( texture2D( tDepth, coord ) ) * cameraFarMinusNear );
}
float compareDepths( const in float depth1, const in float depth2, inout int far ) {
float garea = 2.0;
float diff = ( depth1 - depth2 ) * 100.0;
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 );
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 / width ) / tt + ( noise.x * ( 1.0 - noise.x ) );
float h = ( 1.0 / height ) / tt + ( noise.y * ( 1.0 - noise.y ) );
float pw;
float ph;
float ao;
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 );
pw = cos( l ) * r;
ph = sin( l ) * r;
ao += calcAO( depth, pw * w, ph * h );
z = z - dz;
l = l + DL;
}
ao /= float( samples );
ao = 1.0 - ao;
if ( fogEnabled ) {
ao = mix( ao, 1.0, doFog() );
}
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 ) );
if ( onlyAO ) {
final = onlyAOColor * vec3( mix( vec3( ao ), vec3( 1.0 ), luminance * lumInfluence ) );
}
gl_FragColor = vec4( final, 1.0 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment