123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- import {
- Matrix4,
- Vector2
- } from '../../../build/three.module.js';
- /**
- * TODO
- */
- var SAOShader = {
- defines: {
- 'NUM_SAMPLES': 7,
- 'NUM_RINGS': 4,
- 'NORMAL_TEXTURE': 0,
- 'DIFFUSE_TEXTURE': 0,
- 'DEPTH_PACKING': 1,
- 'PERSPECTIVE_CAMERA': 1
- },
- uniforms: {
- 'tDepth': { value: null },
- 'tDiffuse': { value: null },
- 'tNormal': { value: null },
- 'size': { value: new Vector2( 512, 512 ) },
- 'cameraNear': { value: 1 },
- 'cameraFar': { value: 100 },
- 'cameraProjectionMatrix': { value: new Matrix4() },
- 'cameraInverseProjectionMatrix': { value: new Matrix4() },
- 'scale': { value: 1.0 },
- 'intensity': { value: 0.1 },
- 'bias': { value: 0.5 },
- 'minResolution': { value: 0.0 },
- 'kernelRadius': { value: 100.0 },
- 'randomSeed': { 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' )
- };
- export { SAOShader };
|