three-stdlib
Version:
stand-alone library of threejs examples
116 lines (115 loc) • 3.95 kB
JavaScript
import { Vector2 } from "three";
const DepthLimitedBlurShader = {
defines: {
KERNEL_RADIUS: 4,
DEPTH_PACKING: 1,
PERSPECTIVE_CAMERA: 1
},
uniforms: {
tDiffuse: { value: null },
size: { value: new Vector2(512, 512) },
sampleUvOffsets: { value: [new Vector2(0, 0)] },
sampleWeights: { value: [1] },
tDepth: { value: null },
cameraNear: { value: 10 },
cameraFar: { value: 1e3 },
depthCutoff: { 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")
};
const BlurShaderUtils = {
createSampleWeights: (kernelRadius, stdDev) => {
const gaussian = (x, stdDev2) => {
return Math.exp(-(x * x) / (2 * (stdDev2 * stdDev2))) / (Math.sqrt(2 * Math.PI) * stdDev2);
};
const weights = [];
for (let i = 0; i <= kernelRadius; i++) {
weights.push(gaussian(i, stdDev));
}
return weights;
},
createSampleOffsets: (kernelRadius, uvIncrement) => {
const offsets = [];
for (let i = 0; i <= kernelRadius; i++) {
offsets.push(uvIncrement.clone().multiplyScalar(i));
}
return offsets;
},
configure: (shader, kernelRadius, stdDev, uvIncrement) => {
shader.defines["KERNEL_RADIUS"] = kernelRadius;
shader.uniforms["sampleUvOffsets"].value = BlurShaderUtils.createSampleOffsets(kernelRadius, uvIncrement);
shader.uniforms["sampleWeights"].value = BlurShaderUtils.createSampleWeights(kernelRadius, stdDev);
shader.needsUpdate = true;
}
};
export {
BlurShaderUtils,
DepthLimitedBlurShader
};
//# sourceMappingURL=DepthLimitedBlurShader.js.map