Three.js Time Tunnel
Dr Who style time tunnel with a cylinder and ShaderMaterial
HTML
<script src="https://rawgit.com/mrdoob/three.js/r76/build/three.min.js"></script>
<script src="https://cdn.rawgit.com/dataarts/dat.gui/v0.5.1/build/dat.gui.min.js"></script>
<script id="tunnelVertexShader" type="x-shader/x-vertex">
varying vec3 vPosition;
void main( void ) {
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
</script>
<script id="tunnelFragmentShader" type="x-shader/x-fragment">
varying vec3 vPosition;
uniform vec3 color;
uniform vec3 noiseScale;
uniform float speed;
uniform float time;
uniform float intensity;
//
// Description : Array and textureless GLSL 2D/3D/4D simplex
// noise functions.
// Author : Ian McEwan, Ashima Arts.
// Maintainer : ijm
// Lastmod : 20110822 (ijm)
// License : Copyright (C) 2011 Ashima Arts. All rights reserved.
// Distributed under the MIT License. See LICENSE file.
// https://github.com/ashima/webgl-noise
//
vec4 mod289(vec4 x) {
return x - floor(x * (1.0 / 289.0)) * 289.0; }
float mod289(float x) {
return x - floor(x * (1.0 / 289.0)) * 289.0; }
vec4 permute(vec4 x) {
return mod289(((x*34.0)+1.0)*x);
}
float permute(float x) {
return mod289(((x*34.0)+1.0)*x);
}
vec4 taylorInvSqrt(vec4 r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
float taylorInvSqrt(float r)
{
return 1.79284291400159 - 0.85373472095314 * r;
}
vec4 grad4(float j, vec4 ip)
{
const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0);
vec4 p,s;
p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0;
p.w = 1.5 - dot(abs(p.xyz), ones.xyz);
s = vec4(lessThan(p, vec4(0.0)));
p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www;
return p;
}
// (sqrt(5) - 1)/4 = F4, used once below
#define F4 0.309016994374947451
...
CSS
body {
margin: 0px;
background-color: #000000;
}
canvas {
display: block;
}
JavaScript
var camera, scene, renderer, mesh, material;
var clock = new THREE.Clock();
init();
animate();
function init(){
// Renderer.
renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
//renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
// Add renderer to page
document.body.appendChild(renderer.domElement);
// Create camera.
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100000);
camera.position.z = 1500;
// Create scene.
scene = new THREE.Scene();
// Create material
var uniforms = {
color: { type: "c", value: new THREE.Color(0xffffff) },
noiseScale: { type: "v3", value: new THREE.Vector3(3000.0, 3000.0, 2000.0)},
speed: { type: "f", value: 1000.0},
time: { type:"f", value: 0.0},
intensity: { type:"f", value: 3.0}
};
var vertexShader = document.getElementById('tunnelVertexShader').text;
var fragmentShader = document.getElementById('tunnelFragmentShader').text;
material = new THREE.ShaderMaterial(
{
uniforms : uniforms,
vertexShader : vertexShader,
fragmentShader : fragmentShader,
side: THREE.BackSide
});
// Create cylinder and add to scene.
// CylinderBufferGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded, thetaStart, thetaLength)
var geometry = new THREE.CylinderBufferGeometry( 200, 100, 3000, 32, 16, true );
mesh = new THREE.Mesh(geometry, material);
// rotate 90 degrees
mesh.rotation.x = (90 * Math.PI)/180;
scene.add(mesh);
// Add listener for window resize.
window.addEventListener('resize', onWindowResize, false);
// set up controls
gui(uniforms);
}
function animate() {
requestAnimationFrame(animate);
//mesh.rotation.x += 0.01;
material.uniforms.time.value = clock.getElapsedTime();
...