Skip to content

Instantly share code, notes, and snippets.

@daoshengmu
Created April 26, 2015 16:30
Show Gist options
  • Save daoshengmu/da66727d5f7124cfd172 to your computer and use it in GitHub Desktop.
Save daoshengmu/da66727d5f7124cfd172 to your computer and use it in GitHub Desktop.
SAO shader on Three.js
precision highp float;
precision highp int;
uniform mat4 viewMatrix;
uniform vec3 cameraPosition;
#extension GL_OES_standard_derivatives : enable
uniform float cameraNear;
uniform float cameraFar;
uniform bool onlyAO;
uniform vec2 size;
uniform float aoClamp;
uniform float lumInfluence;
uniform float aoIntensity;
uniform sampler2D tDiffuse;
uniform sampler2D tDepth;
uniform float intensityDivR6;
uniform mat4 matProjInverse123;
uniform float projScale;
uniform vec4 projInfo;
float radius = 1.0;
uniform float bias;
uniform vec2 resolution;
varying vec2 vUv;
varying vec2 vView;
float width = size.x;
float height = size.y;
const int NUM_SAMPLES = 11;
const int NUM_SPIRAL_TURNS = 7;
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;
}
vec3 getViewSpaceNormalByView( const in vec3 viewPos ) {
return normalize( cross( vec3( dFdx(viewPos.x), dFdx(viewPos.y), dFdx(viewPos.z) )
, vec3( dFdy(viewPos.x), dFdy(viewPos.y), dFdy(viewPos.z) ) ) );
}
float getCameraSpaceZByClipZ( const in float depth ) {
return (cameraNear*cameraFar) / (cameraNear-cameraFar) * depth + cameraFar;
}
vec3 getCameraPositionByClip( const in vec2 coord ) {
float clipDepth = unpackDepth( texture2D( tDepth, coord ) );
float cameraDepth = getCameraSpaceZByClipZ( clipDepth );
vec2 clipPos;
clipPos = (coord - 0.5) * 2.0;
return vec3( (clipPos * projInfo.xy + projInfo.zw) * cameraDepth, cameraDepth );
}
vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){
float alpha = float(float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES));
float angle = alpha * float(float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle;
ssR = alpha;
return vec2(cos(angle), sin(angle));
}
vec3 getOffsetPosition(vec2 ssC, vec2 unitOffset, float ssR) {
vec2 ssP = ssR * unitOffset * (1.0/resolution) + ssC;
return getCameraPositionByClip(ssP);
}
float radius2 = radius * radius;
float sampleAO(in vec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in int tapIndex, in float randomPatternRotationAngle) {
float ssR;
vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR);
ssR *= ssDiskRadius;
vec3 Q = getOffsetPosition(ssC, unitOffset, ssR);
vec3 v = Q - C;
float vv = dot(v, v);
float vn = dot(v, n_C);
const float epsilon = 0.01;
float f = max(radius2 - vv, 0.0);
return f * f * f * max((vn - bias) / (epsilon + vv), 0.0);
}
float xor(float a, float b) {
float result = 0.0;
bool toggleA = (a==1.0);
bool toggleB = (b==1.0);
if (toggleA) result = 1.0;
if (toggleB) result = 1.0;
if (toggleA && toggleB) result = 0.0;
return result;
}
float and(float a, float b) {
float result = 0.0;
bool toggleA = (a==1.0);
bool toggleB = (b==1.0);
if (toggleA && toggleB) result = 1.0;
return result;
}
void main() {
ivec2 screenPos = ivec2(gl_FragCoord.xy);
vec3 cameraPos = getCameraPositionByClip( vUv );
float randomPatternRotationAngle = (3.0 * xor(float(screenPos.x), float(screenPos.y)) + float(screenPos.x * screenPos.y)) * 10.0;
vec3 normalCameraSpace = getViewSpaceNormalByView(cameraPos);
float screenSpaceDiskRadius = -projScale * radius / cameraPos.z;
float sum = 0.0;
for ( int i = 0; i < NUM_SAMPLES; ++i ) {
sum += sampleAO(vUv, cameraPos, normalCameraSpace, screenSpaceDiskRadius, i, randomPatternRotationAngle);
}
float MIN_AMBIENT_LIGHT = 0.1;
float ao = (1.0 - sum) / float(NUM_SAMPLES);
ao = 1.0-clamp(pow(ao, 1.0 + 100.0), 0.0, 1.0);
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 * ao );
gl_FragColor = vec4( final.x, final.y,final.z, 1.0 );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment