| 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;} )();
 |