Browse Source

Merge pull request #4900 from drakh/dev

DigitalGlitch postprocessing effect
Mr.doob 11 years ago
parent
commit
4c41ca09b8

+ 1 - 0
examples/index.html

@@ -250,6 +250,7 @@
 				"webgl_postprocessing_dof2",
 				"webgl_postprocessing_godrays",
 				"webgl_postprocessing_crossfade",
+				"webgl_postprocessing_glitch",
 				"webgl_rtt",
 				"webgl_sandbox",
 				"webgl_shader",

+ 114 - 0
examples/js/postprocessing/GlitchPass.js

@@ -0,0 +1,114 @@
+/**
+ 
+ */
+
+THREE.GlitchPass = function ( dt_size ) {
+
+	if ( THREE.DigitalGlitch === undefined ) console.error( "THREE.GlitchPass relies on THREE.DigitalGlitch" );
+	
+	var shader = THREE.DigitalGlitch;
+	this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
+
+	if(dt_size==undefined) dt_size=64;
+	
+	
+	this.uniforms[ "tDisp"].value=this.generateHeightmap(dt_size);
+	
+
+	this.material = new THREE.ShaderMaterial({
+		uniforms: this.uniforms,
+		vertexShader: shader.vertexShader,
+		fragmentShader: shader.fragmentShader
+	});
+
+	console.log(this.material);
+	
+	this.enabled = true;
+	this.renderToScreen = false;
+	this.needsSwap = true;
+
+
+	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
+	this.scene  = new THREE.Scene();
+
+	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.scene.add( this.quad );
+	
+	this.goWild=false;
+	this.curF=0;
+	this.generateTrigger();
+	
+};
+
+THREE.GlitchPass.prototype = {
+
+	render: function ( renderer, writeBuffer, readBuffer, delta ) 
+	{
+		this.uniforms[ "tDiffuse" ].value = readBuffer;
+		this.uniforms[ 'seed' ].value=Math.random();//default seeding
+		this.uniforms[ 'byp' ].value=0;
+		
+		if(this.curF % this.randX ==0 || this.goWild==true)
+		{
+			this.uniforms[ 'amount' ].value=Math.random()/30;
+			this.uniforms[ 'angle' ].value=THREE.Math.randFloat(-Math.PI,Math.PI);
+			this.uniforms[ 'seed_x' ].value=THREE.Math.randFloat(-1,1);
+			this.uniforms[ 'seed_y' ].value=THREE.Math.randFloat(-1,1);
+			this.uniforms[ 'distortion_x' ].value=THREE.Math.randFloat(0,1);
+			this.uniforms[ 'distortion_y' ].value=THREE.Math.randFloat(0,1);
+			this.curF=0;
+			this.generateTrigger();
+		}
+		else if(this.curF % this.randX <this.randX/5)
+		{
+			this.uniforms[ 'amount' ].value=Math.random()/90;
+			this.uniforms[ 'angle' ].value=THREE.Math.randFloat(-Math.PI,Math.PI);
+			this.uniforms[ 'distortion_x' ].value=THREE.Math.randFloat(0,1);
+			this.uniforms[ 'distortion_y' ].value=THREE.Math.randFloat(0,1);
+			this.uniforms[ 'seed_x' ].value=THREE.Math.randFloat(-0.3,0.3);
+			this.uniforms[ 'seed_y' ].value=THREE.Math.randFloat(-0.3,0.3);
+		}
+		else if(this.goWild==false)
+		{
+			this.uniforms[ 'byp' ].value=1;
+		}
+		this.curF++;
+		
+		this.quad.material = this.material;
+		if ( this.renderToScreen ) 
+		{
+			renderer.render( this.scene, this.camera );
+		} 
+		else 
+		{
+			renderer.render( this.scene, this.camera, writeBuffer, false );
+		}
+	},
+	generateTrigger:function()
+	{
+		this.randX=THREE.Math.randInt(120,240);
+	},
+	generateHeightmap:function(dt_size)
+	{
+		var data_arr = new Float32Array( dt_size*dt_size * 3 );
+		console.log(dt_size);
+		var length=dt_size*dt_size;
+		
+		for ( var i = 0; i < length; i++) 
+		{
+			var val=THREE.Math.randFloat(0,1);
+			data_arr[ i*3 + 0 ] = val;
+			data_arr[ i*3 + 1 ] = val;
+			data_arr[ i*3 + 2 ] = val;
+		}
+		
+		var texture = new THREE.DataTexture( data_arr, dt_size, dt_size, THREE.RGBFormat, THREE.FloatType );
+		console.log(texture);
+		console.log(dt_size);
+		texture.minFilter = THREE.NearestFilter;
+		texture.magFilter = THREE.NearestFilter;
+		texture.needsUpdate = true;
+		texture.flipY = false;
+		return texture;
+	}
+};

+ 103 - 0
examples/js/shaders/DigitalGlitch.js

@@ -0,0 +1,103 @@
+/**
+ * @author felixturner / http://airtight.cc/
+ *
+ * RGB Shift Shader
+ * Shifts red and blue channels from center in opposite directions
+ * Ported from http://kriss.cx/tom/2009/05/rgb-shift/
+ * by Tom Butterworth / http://kriss.cx/tom/
+ *
+ * amount: shift distance (1 is width of input)
+ * angle: shift angle in radians
+ */
+
+THREE.DigitalGlitch = {
+
+	uniforms: {
+
+		"tDiffuse":		{ type: "t", value: null },//diffuse texture
+		"tDisp":		{ type: "t", value: null },//displacement texture for digital glitch squares
+		"byp":			{ type: "i", value: 0 },//apply the glitch ?
+		"amount":		{ type: "f", value: 0.08 },
+		"angle":		{ type: "f", value: 0.02 },
+		"seed":			{ type: "f", value: 0.02 },
+		"seed_x":		{ type: "f", value: 0.02 },//-1,1
+		"seed_y":		{ type: "f", value: 0.02 },//-1,1
+		"distortion_x":	{ type: "f", value: 0.5 },
+		"distortion_y":	{ type: "f", value: 0.6 },
+		"col_s":		{ type: "f", value: 0.05 }
+	},
+
+	vertexShader: [
+
+		"varying vec2 vUv;",
+		"void main() {",
+			"vUv = uv;",
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+		"}"
+	].join("\n"),
+
+	fragmentShader: [
+		"uniform int byp;",//should we apply the glitch ?
+		
+		"uniform sampler2D tDiffuse;",
+		"uniform sampler2D tDisp;",
+		
+		"uniform float amount;",
+		"uniform float angle;",
+		"uniform float seed;",
+		"uniform float seed_x;",
+		"uniform float seed_y;",
+		"uniform float distortion_x;",
+		"uniform float distortion_y;",
+		"uniform float col_s;",
+			
+		"varying vec2 vUv;",
+		
+		
+		"float rand(vec2 co){",
+			"return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);",
+		"}",
+				
+		"void main() {",
+			"if(byp<1) {",
+				"vec2 p = vUv;",
+				"float xs = floor(gl_FragCoord.x / 0.5);",
+				"float ys = floor(gl_FragCoord.y / 0.5);",
+				//based on staffantans glitch shader for unity https://github.com/staffantan/unityglitch
+				"vec4 normal = texture2D (tDisp, p*seed*seed);",
+				"if(p.y<distortion_x+col_s && p.y>distortion_x-col_s*seed) {",
+					"if(seed_x>0.){",
+						"p.y = 1. - (p.y + distortion_y);",
+					"}",
+					"else {",
+						"p.y = distortion_y;",
+					"}",
+				"}",
+				"if(p.x<distortion_y+col_s && p.x>distortion_y-col_s*seed) {",
+					"if(seed_y>0.){",
+						"p.x=distortion_x;",
+					"}",
+					"else {",
+						"p.x = 1. - (p.x + distortion_x);",
+					"}",
+				"}",
+				"p.x+=normal.x*seed_x*(seed/5.);",
+				"p.y+=normal.y*seed_y*(seed/5.);",
+				//base from RGB shift shader
+				"vec2 offset = amount * vec2( cos(angle), sin(angle));",
+				"vec4 cr = texture2D(tDiffuse, p + offset);",
+				"vec4 cga = texture2D(tDiffuse, p);",
+				"vec4 cb = texture2D(tDiffuse, p - offset);",
+				"gl_FragColor = vec4(cr.r, cga.g, cb.b, cga.a);",
+				//add noise
+				"vec4 snow = 200.*amount*vec4(rand(vec2(xs * seed,ys * seed*50.))*0.2);",
+				"gl_FragColor = gl_FragColor+ snow;",
+			"}",
+			"else {",
+				"gl_FragColor=texture2D (tDiffuse, vUv);",
+			"}",
+		"}"
+
+	].join("\n")
+
+};

+ 142 - 0
examples/webgl_postprocessing_glitch.html

@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - postprocessing - digital glitch</title>
+		<meta charset="utf-8">
+		<style>
+			body {
+				margin: 0px;
+				background-color: #000000;
+				overflow: hidden;
+			}
+
+			div {
+				position: absolute;
+				z-index: 10;
+				color: #fff;
+				font-family: monospace;
+				text-align: center;
+				margin: 10px;
+				width: 100%;
+			}
+
+			label, input {
+				cursor: pointer;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/shaders/CopyShader.js"></script>
+		<script src="js/shaders/DigitalGlitch.js"></script>
+
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/MaskPass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+		<script src="js/postprocessing/GlitchPass.js"></script>
+
+		<div>
+			<label for="dotScreen">Glitch me wild:</label><input id="wildGlitch" type="checkbox" onchange="updateOptions()"/><br />
+		</div>
+
+		<script>
+
+			var camera, scene, renderer, composer;
+			var object, light;
+
+			var glitchPass;
+
+			init();
+			animate();
+
+			function updateOptions() {
+				var wildGlitch = document.getElementById('wildGlitch');
+				glitchPass.goWild=wildGlitch.checked;
+			}
+
+			function init() {
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( renderer.domElement );
+
+				//
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.z = 400;
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0x000000, 1, 1000 );
+
+				object = new THREE.Object3D();
+				scene.add( object );
+
+				var geometry = new THREE.SphereGeometry( 1, 4, 4 );
+				var material = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading } );
+
+				for ( var i = 0; i < 100; i ++ ) {
+					material = new THREE.MeshPhongMaterial( { color: 0xffffff * Math.random(), shading: THREE.FlatShading } );
+
+					var mesh = new THREE.Mesh( geometry, material );
+					mesh.position.set( Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 ).normalize();
+					mesh.position.multiplyScalar( Math.random() * 400 );
+					mesh.rotation.set( Math.random() * 2, Math.random() * 2, Math.random() * 2 );
+					mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * 50;
+					object.add( mesh );
+
+				}
+
+				scene.add( new THREE.AmbientLight( 0x222222 ) );
+
+				light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( 1, 1, 1 );
+				scene.add( light );
+
+				// postprocessing
+
+				composer = new THREE.EffectComposer( renderer );
+				composer.addPass( new THREE.RenderPass( scene, camera ) );
+
+				glitchPass = new THREE.GlitchPass();
+				glitchPass.renderToScreen = true;
+				composer.addPass( glitchPass );
+
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+				updateOptions();
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				var time = Date.now();
+
+				object.rotation.x += 0.005;
+				object.rotation.y += 0.01;
+
+				composer.render();
+				//renderer.render(scene, camera);
+
+			}
+
+		</script>
+	</body>
+</html>