123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- ( function () {
- /**
- * TODO
- */
- const 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 THREE.Vector2( 512, 512 )
- },
- 'cameraNear': {
- value: 1
- },
- 'cameraFar': {
- value: 100
- },
- 'cameraProjectionMatrix': {
- value: new THREE.Matrix4()
- },
- 'cameraInverseProjectionMatrix': {
- value: new THREE.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:
- /* glsl */
- `
- varying vec2 vUv;
- void main() {
- vUv = uv;
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
- }`,
- fragmentShader:
- /* glsl */
- `
- #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;
- }`
- };
- THREE.SAOShader = SAOShader;
- } )();
|