Created
April 26, 2015 16:30
-
-
Save daoshengmu/da66727d5f7124cfd172 to your computer and use it in GitHub Desktop.
SAO shader on Three.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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