Spaces:
Running
Running
THREE.DepthLimitedBlurShader = { | |
defines: { | |
'KERNEL_RADIUS': 4, | |
'DEPTH_PACKING': 1, | |
'PERSPECTIVE_CAMERA': 1 | |
}, | |
uniforms: { | |
'tDiffuse': { type: 't', value: null }, | |
'size': { type: 'v2', value: new THREE.Vector2( 512, 512 ) }, | |
'sampleUvOffsets': { type: 'v2v', value: [ new THREE.Vector2( 0, 0 ) ] }, | |
'sampleWeights': { type: '1fv', value: [ 1.0 ] }, | |
'tDepth': { type: 't', value: null }, | |
'cameraNear': { type: 'f', value: 10 }, | |
'cameraFar': { type: 'f', value: 1000 }, | |
'depthCutoff': { type: 'f', value: 10 }, | |
}, | |
vertexShader: [ | |
"#include <common>", | |
"uniform vec2 size;", | |
"varying vec2 vUv;", | |
"varying vec2 vInvSize;", | |
"void main() {", | |
" vUv = uv;", | |
" vInvSize = 1.0 / size;", | |
" gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", | |
"}" | |
].join( "\n" ), | |
fragmentShader: [ | |
"#include <common>", | |
"#include <packing>", | |
"uniform sampler2D tDiffuse;", | |
"uniform sampler2D tDepth;", | |
"uniform float cameraNear;", | |
"uniform float cameraFar;", | |
"uniform float depthCutoff;", | |
"uniform vec2 sampleUvOffsets[ KERNEL_RADIUS + 1 ];", | |
"uniform float sampleWeights[ KERNEL_RADIUS + 1 ];", | |
"varying vec2 vUv;", | |
"varying vec2 vInvSize;", | |
"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", | |
"}", | |
"void main() {", | |
" float depth = getDepth( vUv );", | |
" if( depth >= ( 1.0 - EPSILON ) ) {", | |
" discard;", | |
" }", | |
" float centerViewZ = -getViewZ( depth );", | |
" bool rBreak = false, lBreak = false;", | |
" float weightSum = sampleWeights[0];", | |
" vec4 diffuseSum = texture2D( tDiffuse, vUv ) * weightSum;", | |
" for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {", | |
" float sampleWeight = sampleWeights[i];", | |
" vec2 sampleUvOffset = sampleUvOffsets[i] * vInvSize;", | |
" vec2 sampleUv = vUv + sampleUvOffset;", | |
" float viewZ = -getViewZ( getDepth( sampleUv ) );", | |
" if( abs( viewZ - centerViewZ ) > depthCutoff ) rBreak = true;", | |
" if( ! rBreak ) {", | |
" diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight;", | |
" weightSum += sampleWeight;", | |
" }", | |
" sampleUv = vUv - sampleUvOffset;", | |
" viewZ = -getViewZ( getDepth( sampleUv ) );", | |
" if( abs( viewZ - centerViewZ ) > depthCutoff ) lBreak = true;", | |
" if( ! lBreak ) {", | |
" diffuseSum += texture2D( tDiffuse, sampleUv ) * sampleWeight;", | |
" weightSum += sampleWeight;", | |
" }", | |
" }", | |
" gl_FragColor = diffuseSum / weightSum;", | |
"}" | |
].join( "\n" ) | |
}; | |
THREE.BlurShaderUtils = { | |
createSampleWeights: function ( kernelRadius, stdDev ) { | |
var gaussian = function ( x, stdDev ) { | |
return Math.exp( - ( x * x ) / ( 2.0 * ( stdDev * stdDev ) ) ) / ( Math.sqrt( 2.0 * Math.PI ) * stdDev ); | |
}; | |
var weights = []; | |
for ( var i = 0; i <= kernelRadius; i ++ ) { | |
weights.push( gaussian( i, stdDev ) ); | |
} | |
return weights; | |
}, | |
createSampleOffsets: function ( kernelRadius, uvIncrement ) { | |
var offsets = []; | |
for ( var i = 0; i <= kernelRadius; i ++ ) { | |
offsets.push( uvIncrement.clone().multiplyScalar( i ) ); | |
} | |
return offsets; | |
}, | |
configure: function ( material, kernelRadius, stdDev, uvIncrement ) { | |
material.defines[ 'KERNEL_RADIUS' ] = kernelRadius; | |
material.uniforms[ 'sampleUvOffsets' ].value = THREE.BlurShaderUtils.createSampleOffsets( kernelRadius, uvIncrement ); | |
material.uniforms[ 'sampleWeights' ].value = THREE.BlurShaderUtils.createSampleWeights( kernelRadius, stdDev ); | |
material.needsUpdate = true; | |
} | |
}; | |