You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
5.5 KiB
178 lines
5.5 KiB
THREE.SAOShader = {
|
|
defines: {
|
|
'NUM_SAMPLES': 7,
|
|
'NUM_RINGS': 4,
|
|
'NORMAL_TEXTURE': 0,
|
|
'DIFFUSE_TEXTURE': 0,
|
|
'DEPTH_PACKING': 1,
|
|
'PERSPECTIVE_CAMERA': 1
|
|
},
|
|
uniforms: {
|
|
|
|
'tDepth': { type: 't', value: null },
|
|
'tDiffuse': { type: 't', value: null },
|
|
'tNormal': { type: 't', value: null },
|
|
'size': { type: 'v2', value: new THREE.Vector2( 512, 512 ) },
|
|
|
|
'cameraNear': { type: 'f', value: 1 },
|
|
'cameraFar': { type: 'f', value: 100 },
|
|
'cameraProjectionMatrix': { type: 'm4', value: new THREE.Matrix4() },
|
|
'cameraInverseProjectionMatrix': { type: 'm4', value: new THREE.Matrix4() },
|
|
|
|
'scale': { type: 'f', value: 1.0 },
|
|
'intensity': { type: 'f', value: 0.1 },
|
|
'bias': { type: 'f', value: 0.5 },
|
|
|
|
'minResolution': { type: 'f', value: 0.0 },
|
|
'kernelRadius': { type: 'f', value: 100.0 },
|
|
'randomSeed': { type: 'f', value: 0.0 }
|
|
},
|
|
vertexShader: [
|
|
"varying vec2 vUv;",
|
|
|
|
"void main() {",
|
|
" vUv = uv;",
|
|
" gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
|
|
"}"
|
|
|
|
].join( "\n" ),
|
|
fragmentShader: [
|
|
"#include <common>",
|
|
|
|
"varying vec2 vUv;",
|
|
|
|
"#if DIFFUSE_TEXTURE == 1",
|
|
"uniform sampler2D tDiffuse;",
|
|
"#endif",
|
|
|
|
"uniform sampler2D tDepth;",
|
|
|
|
"#if NORMAL_TEXTURE == 1",
|
|
"uniform sampler2D tNormal;",
|
|
"#endif",
|
|
|
|
"uniform float cameraNear;",
|
|
"uniform float cameraFar;",
|
|
"uniform mat4 cameraProjectionMatrix;",
|
|
"uniform mat4 cameraInverseProjectionMatrix;",
|
|
|
|
"uniform float scale;",
|
|
"uniform float intensity;",
|
|
"uniform float bias;",
|
|
"uniform float kernelRadius;",
|
|
"uniform float minResolution;",
|
|
"uniform vec2 size;",
|
|
"uniform float randomSeed;",
|
|
|
|
"// RGBA depth",
|
|
|
|
"#include <packing>",
|
|
|
|
"vec4 getDefaultColor( const in vec2 screenPosition ) {",
|
|
" #if DIFFUSE_TEXTURE == 1",
|
|
" return texture2D( tDiffuse, vUv );",
|
|
" #else",
|
|
" return vec4( 1.0 );",
|
|
" #endif",
|
|
"}",
|
|
|
|
"float getDepth( const in vec2 screenPosition ) {",
|
|
" #if DEPTH_PACKING == 1",
|
|
" return unpackRGBAToDepth( texture2D( tDepth, screenPosition ) );",
|
|
" #else",
|
|
" return texture2D( tDepth, screenPosition ).x;",
|
|
" #endif",
|
|
"}",
|
|
|
|
"float getViewZ( const in float depth ) {",
|
|
" #if PERSPECTIVE_CAMERA == 1",
|
|
" return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );",
|
|
" #else",
|
|
" return orthographicDepthToViewZ( depth, cameraNear, cameraFar );",
|
|
" #endif",
|
|
"}",
|
|
|
|
"vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {",
|
|
" float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];",
|
|
" vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );",
|
|
" clipPosition *= clipW; // unprojection.",
|
|
|
|
" return ( cameraInverseProjectionMatrix * clipPosition ).xyz;",
|
|
"}",
|
|
|
|
"vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {",
|
|
" #if NORMAL_TEXTURE == 1",
|
|
" return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz );",
|
|
" #else",
|
|
" return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );",
|
|
" #endif",
|
|
"}",
|
|
|
|
"float scaleDividedByCameraFar;",
|
|
"float minResolutionMultipliedByCameraFar;",
|
|
|
|
"float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) {",
|
|
" vec3 viewDelta = sampleViewPosition - centerViewPosition;",
|
|
" float viewDistance = length( viewDelta );",
|
|
" float scaledScreenDistance = scaleDividedByCameraFar * viewDistance;",
|
|
|
|
" return max(0.0, (dot(centerViewNormal, viewDelta) - minResolutionMultipliedByCameraFar) / scaledScreenDistance - bias) / (1.0 + pow2( scaledScreenDistance ) );",
|
|
"}",
|
|
|
|
"// moving costly divides into consts",
|
|
"const float ANGLE_STEP = PI2 * float( NUM_RINGS ) / float( NUM_SAMPLES );",
|
|
"const float INV_NUM_SAMPLES = 1.0 / float( NUM_SAMPLES );",
|
|
|
|
"float getAmbientOcclusion( const in vec3 centerViewPosition ) {",
|
|
" // precompute some variables require in getOcclusion.",
|
|
" scaleDividedByCameraFar = scale / cameraFar;",
|
|
" minResolutionMultipliedByCameraFar = minResolution * cameraFar;",
|
|
" vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );",
|
|
|
|
" // jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/",
|
|
" float angle = rand( vUv + randomSeed ) * PI2;",
|
|
" vec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES ) / size;",
|
|
" vec2 radiusStep = radius;",
|
|
|
|
" float occlusionSum = 0.0;",
|
|
" float weightSum = 0.0;",
|
|
|
|
" for( int i = 0; i < NUM_SAMPLES; i ++ ) {",
|
|
" vec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius;",
|
|
" radius += radiusStep;",
|
|
" angle += ANGLE_STEP;",
|
|
|
|
" float sampleDepth = getDepth( sampleUv );",
|
|
" if( sampleDepth >= ( 1.0 - EPSILON ) ) {",
|
|
" continue;",
|
|
" }",
|
|
|
|
" float sampleViewZ = getViewZ( sampleDepth );",
|
|
" vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ );",
|
|
" occlusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition );",
|
|
" weightSum += 1.0;",
|
|
" }",
|
|
|
|
" if( weightSum == 0.0 ) discard;",
|
|
|
|
" return occlusionSum * ( intensity / weightSum );",
|
|
"}",
|
|
|
|
|
|
"void main() {",
|
|
" float centerDepth = getDepth( vUv );",
|
|
" if( centerDepth >= ( 1.0 - EPSILON ) ) {",
|
|
" discard;",
|
|
" }",
|
|
|
|
" float centerViewZ = getViewZ( centerDepth );",
|
|
" vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );",
|
|
|
|
" float ambientOcclusion = getAmbientOcclusion( viewPosition );",
|
|
|
|
" gl_FragColor = getDefaultColor( vUv );",
|
|
" gl_FragColor.xyz *= 1.0 - ambientOcclusion;",
|
|
"}"
|
|
].join( "\n" )
|
|
};
|