Skip to content

Instantly share code, notes, and snippets.

@fatlinesofcode
Created June 17, 2017 04:30
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fatlinesofcode/3a02af88ac44a9adea0ca9021536095d to your computer and use it in GitHub Desktop.
Save fatlinesofcode/3a02af88ac44a9adea0ca9021536095d to your computer and use it in GitHub Desktop.
Zoom blur shader for Three.js with Effect composer
<!-- https://codepen.io/fatlinesofcode/pen/yXVGPp -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/84/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://threejs.org/examples/js/postprocessing/ShaderPass.js"></script>
<script src="https://threejs.org/examples/js/shaders/CopyShader.js"></script>
<script type="x-shader/x-vertex" id="vertexShaderZoom">
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script type="x-shader/x-fragment" id="fragmentShaderZoom">
uniform sampler2D tDiffuse;
uniform vec2 center;
uniform float strength;
uniform vec2 resolution;
varying vec2 vUv;
float random(vec3 scale,float seed){return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);}
void main(){
vec4 color=vec4(0.0);
float total=0.0;
vec2 toCenter=center-vUv*resolution;
float offset=random(vec3(12.9898,78.233,151.7182),0.0);
for(float t=0.0;t<=40.0;t++){
float percent=(t+offset)/40.0;
float weight=4.0*(percent-percent*percent);
vec4 sample=texture2D(tDiffuse,vUv+toCenter*percent*strength/resolution);
sample.rgb*=sample.a;
color+=sample*weight;
total+=weight;
}
gl_FragColor=color/total;
gl_FragColor.rgb/=gl_FragColor.a+0.00001;
}
</script>
<script>
var camera, scene, renderer, composer;
var controls;
var zBlurPass;
var mesh;
init();
initControls();
initGui();
animate();
function init() {
camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.z = 400;
scene = new THREE.Scene();
scene.background = new THREE.Color( 0x000000 );
THREE.ImageUtils.crossOrigin = '';
var texture = THREE.ImageUtils.loadTexture('https://threejs.org/examples/textures/crate.gif');
var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
var material = new THREE.MeshBasicMaterial( { map:texture } );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
composer = new THREE.EffectComposer(renderer);
var pass1 = new THREE.RenderPass(scene, camera);
var shader = new THREE.ShaderMaterial({
uniforms: {
tDiffuse: {value: null},
strength: { type: 'f', value: .5 },
center: { type: 'v2', value: new THREE.Vector2( window.innerWidth *0.5, window.innerHeight*0.5 ) },
resolution: { type: 'v2', value: new THREE.Vector2( window.innerWidth, window.innerHeight ) },
},
vertexShader: document.getElementById('vertexShaderZoom').textContent,
fragmentShader: document.getElementById('fragmentShaderZoom').textContent
});
zBlurPass = new THREE.ShaderPass(shader);
composer.addPass(pass1);
composer.addPass(zBlurPass);
zBlurPass.renderToScreen = true;
//
window.addEventListener( 'resize', onWindowResize, false );
}
function initGui() {
var params = {
strength: zBlurPass.uniforms.strength.value
}
var gui = new dat.GUI();
gui.add(params, 'strength', .01, 2 ).onChange(function(val){
zBlurPass.uniforms.strength.value=val;
})
}
function initControls() {
controls = new THREE.OrbitControls(camera);
controls.damping = 0.2;
controls.keyPanSpeed = 700;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
mesh.rotation.x += 0.005;
mesh.rotation.y += 0.01;
// renderer.render( scene, camera );
composer.render();
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment