<div class="world"></div>

<div id="credits">
  <p> <a href="https://codepen.io/Yakudoo/"  target="blank">my other codepens</a> | <a href="https://www.epic.net" target="blank">epic.net</a></p>
</div>

<script type="x-shader/x-fragment" id="fragmentShader">
	precision highp float;

	varying vec2 vUv;
	uniform sampler2D textureImage;
  uniform sampler2D textureDepth;
	uniform sampler2D textureNormal;
	uniform sampler2D textureNoise;
	
	uniform vec2 mousePosition;
	uniform float time;
	float PI = 3.141592;

	void main () {	
		vec4 texDepth = texture2D(textureDepth, vUv);
		vec4 texNoise = texture2D(textureNoise, vUv + time*.05);
		vec4 texNoise2 = texture2D(textureNoise, vUv*.1 + time*.1);
		
		float depthVal = texDepth.r - .7;		
		float noiseVal = texNoise.r - .5;
		float noiseVal2 = texNoise2.r - .5;
	
		float distToCenter = pow( distance(vUv, vec2(.5,.5)), 4.0 );
		float distToMouse = 1.0 - smoothstep(0.0, 0.25, distance(mousePosition + vec2(.5, .5), vUv));
		
		vec2 dispDepth = vUv + mousePosition * depthVal * .1; 
		vec2 dispWaves = vec2(noiseVal * distToCenter);
		vec2 dispMouse = vec2(noiseVal2 * .10 * distToMouse);
		
		vec4 texImage = texture2D(textureImage, dispDepth + dispWaves + dispMouse );
		vec4 texNormal = texture2D(textureNormal, dispDepth + dispWaves + dispMouse);
		
		// PARTICLES
		
		vec4 particles = texture2D(textureNoise, dispWaves + vec2( vUv.x - sin(time * .5), vUv.y - sin(time) ));
		float thr1 = .05 + sin(time*4.0)*.05;
		texImage.rgb *= smoothstep(thr1,thr1+.03, particles.r);
		
		
		// FOG RED
		vec4 displacedDepth = texture2D(textureDepth, dispDepth + dispWaves + dispMouse );
		vec4 smokeNoise1 = texture2D(textureNoise, dispDepth - vec2(time * .3));
		texImage.r *= 1. + (displacedDepth.b * (40.0 + smokeNoise1.r ) * pow(1.0 - vUv.y, 6.0) * (1.0 + sin(time*1.0)) *.1 ) ;
		
		
		// FOG BLUE
		vec4 smokeNoise2 = texture2D(textureNoise, dispDepth - vec2(time * .1, time * .5) );
		texImage.b *= 1. + (displacedDepth.g * (6.0 + sin(time * 5.0) ) * (.5 + smokeNoise2.r * ( 1.0 + sin(time) * .5 ) ) * vUv.y) ;
	 
		// LIGHTENING
		float lighteningValue = texture2D(textureNoise, vec2(time*.1)).r;
		lighteningValue = 1. - smoothstep(.6,.65, lighteningValue) * .3;
		texImage.rg *= lighteningValue;
		
		// MOUSE LIGHT
		
		vec3 lightDirection = normalize(vec3(mousePosition.x, mousePosition.y, .3));
		vec3 pixDirection = normalize(vec3(texNormal.r * 2.0 - 1.0, texNormal.b * 2.0 - 1.0, -texNormal.g * 2.0 + 1.0));
		float lightVal = dot(pixDirection, lightDirection);
		texImage.rgb *= .9 + ( distToMouse *  lightVal * (1.0 - displacedDepth.g)) * (2.0 + sin(time)*.5);
		
		
		
		gl_FragColor = vec4(texImage);
	}
</script>  

<script type="x-shader/x-vertex" id="vertexShader">  
  attribute vec3 position;
	attribute vec2 uv;
	uniform mat4 projectionMatrix;
	uniform mat4 modelViewMatrix;
	uniform mat3 normalMatrix;
	varying vec2 vUv;	
	
	void main() {
		vUv = uv;	
		gl_Position = projectionMatrix * modelViewMatrix * vec4 ( position, 1.0);
	}
</script>
@import url('https://fonts.googleapis.com/css?family=Voltaire');


body{
	overflow: hidden;
	user-select: none;
	cursor: default;
}
canvas { 
	display: block; 
}
.world{
	position: absolute;
  width:100%;
  height:100%;
  background: #000;
}
#credits{
  position:absolute;
  width:100%;
  margin: auto;
  bottom:0;
  margin-bottom:20px;
  font-family:"Voltaire", sans-serif;
  color:#d45e59;
  font-size:1.0em;
  text-transform: uppercase;
  text-align : center;
}
#credits a {
  color:#b92721;
	text-decoration: none;
}
View Compiled
class World {
  constructor(width, height) {

    this.renderer = new THREE.WebGLRenderer({
      alpha: true,
      antialias: true
    });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.setSize(width, height);
    this.container = document.getElementsByClassName("world")[0];
    this.scene = new THREE.Scene();
    this.width = width;
    this.height = height;
    this.aspectRatio = width / height;
    this.fieldOfView = 50;
		this.nLoadedImages = 0;
		this.targetX = 0;
		this.targetY = 0;

    var nearPlane = .1;
    var farPlane = 20000;
		
		
    this.camera = new THREE.PerspectiveCamera(this.fieldOfView, this.aspectRatio, nearPlane, farPlane);
		this.camera.position.z = 260;
		this.container.appendChild(this.renderer.domElement);
    this.timer = 0;
		this.loadTextures();
  }
	
	loadTextures() {
    const loader = new THREE.TextureLoader();
    loader.crossOrigin = '';
		
		this.textureImage = loader.load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/halloween.jpg', this.imageLoaded.bind(this));
		this.textureImage.minFilter = THREE.LinearFilter;
    
    this.textureDepth = loader.load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/halloween-depth.jpg', this.imageLoaded.bind(this));
    this.textureDepth.magFilter = this.textureDepth.minFilter = THREE.LinearFilter;
		
		this.textureNormal = loader.load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/halloween-normal.jpg', this.imageLoaded.bind(this));
    this.textureNormal.magFilter = this.textureNormal.minFilter = THREE.LinearFilter;
		
		this.textureNoise = loader.load('https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/noiseTexture.jpg', this.imageLoaded.bind(this));
		this.textureNoise.magFilter = this.textureDepth.minFilter = THREE.LinearFilter;
		this.textureNoise.wrapT = this.textureNoise.wrapS = THREE.RepeatWrapping;
  }
	
	imageLoaded(){
		this.nLoadedImages++;
		if ( this.nLoadedImages > 3 ) {
			this.createPlane();
			this.loop();
		}
	}

  createPlane(){
    this.material = new THREE.RawShaderMaterial({
      vertexShader: document.getElementById( 'vertexShader' ).textContent,
      fragmentShader: document.getElementById('fragmentShader').textContent,
			uniforms: { 
				time: { type: 'f', value: 5 },
				textureImage: { type: 't', value: this.textureImage },
        textureDepth: { type: 't', value: this.textureDepth },
				textureNormal: { type: 't', value: this.textureNormal },
				textureNoise: { type: 't', value: this.textureNoise },
				mousePosition: {type: 'v2', value: new THREE.Vector2( 0.5, 0.5 ) }
    	}
    });
		
		
    this.shapeGeometry = new  THREE.PlaneGeometry(200, 200, 256, 256);
    this.shape = new THREE.Mesh(this.shapeGeometry, this.material);		
		this.scene.add(this.shape);
  }
	
  render() {
    this.timer+=.01;
		this.shape.material.uniforms.time.value = this.timer;
		
		this.targetX += (mousePos.px - this.targetX) * .07;
		this.targetY += (mousePos.py - this.targetY) * .07;
		this.shape.material.uniforms.mousePosition.value = new THREE.Vector2(this.targetX, -this.targetY);
    this.renderer.render(this.scene, this.camera);
  }

  loop() {
    this.render();
		requestAnimationFrame(this.loop.bind(this));
  }

  updateSize(w, h) {
    this.renderer.setSize(w, h);
    this.camera.aspect = w / h;
    this.camera.updateProjectionMatrix();
  }
	
  mouseMove(mousePos) {
		
  }
};

document.addEventListener("DOMContentLoaded", domIsReady);
let mousePos = {x:0, y:0, px:0, py:0};
let PI = Math.PI;
let world;

function domIsReady() {
    world = new World(this.container, this.renderer, window.innerWidth, window.innerHeight);
    window.addEventListener('resize', handleWindowResize, false);
    document.addEventListener("mousemove", handleMouseMove, false);
	  document.addEventListener("touchmove", handleMouseMove, false);
    handleWindowResize();
}

function handleWindowResize() {
    world.updateSize(window.innerWidth, window.innerHeight);
}

function handleMouseMove(e) {
  if ((e.clientX)&&(e.clientY)) {  
		mousePos.x = e.clientX;
    mousePos.y = e.clientY;
		mousePos.px = mousePos.x / window.innerWidth * 2 - 1;
  	mousePos.py = mousePos.y / window.innerHeight * 2 - 1;
	}else if (e.targetTouches) {
		mousePos.x = e.targetTouches[0].clientX;
		mousePos.y = e.targetTouches[0].clientY;
		mousePos.px = mousePos.x / window.innerWidth * 2 - 1;
  	mousePos.py = mousePos.y / window.innerHeight * 2 - 1;
		mousePos.px *= 1.5;
  	mousePos.py *= 1.5;
		e.preventDefault();
	}
	
  world.mouseMove(mousePos);
}

Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/three.js/98/three.min.js