Buckets:
ktongue/docker_container / simsite /frontend /node_modules /three /examples /jsm /shaders /SAOShader.js
| import { | |
| Matrix4, | |
| Vector2 | |
| } from 'three'; | |
| /** | |
| * TODO | |
| */ | |
| const SAOShader = { | |
| name: 'SAOShader', | |
| defines: { | |
| 'NUM_SAMPLES': 7, | |
| 'NUM_RINGS': 4, | |
| 'DIFFUSE_TEXTURE': 0, | |
| '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: /* 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 highp sampler2D tDepth; | |
| uniform highp sampler2D tNormal; | |
| 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 ) { | |
| return texture2D( tDepth, screenPosition ).x; | |
| } | |
| 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 ) { | |
| return unpackRGBToNormal( texture2D( tNormal, screenPosition ).xyz ); | |
| } | |
| 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; | |
| }` | |
| }; | |
| export { SAOShader }; | |
Xet Storage Details
- Size:
- 4.88 kB
- Xet hash:
- 3981619629cf30ff828a442aa079f9a10999c4b061c63ea63caaee62da044667
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.