Skip to content

Instantly share code, notes, and snippets.

@shshaw
Created December 15, 2016 02:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shshaw/f1d4713fb25ab531f74a2e83a7773fa9 to your computer and use it in GitHub Desktop.
Save shshaw/f1d4713fb25ab531f74a2e83a7773fa9 to your computer and use it in GitHub Desktop.
Day & Night πŸŒ… +πŸŒƒ (#3December - Day 14)
<div class="controls">Click to toggle day & night</div>
<script id="vertexShader" type="x-shader/x-vertex">
varying vec3 vNormal;
void main()
{
vNormal = normalize( normalMatrix * normal );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-vertex">
varying vec3 vNormal;
void main()
{
float intensity = pow( 0.3 - dot( vNormal, vec3( 0.0, 0.0, 1.0 ) ), 6.0 );
gl_FragColor = vec4( 1.0, 1.0, 0.5, 0.9 ) * intensity;
}
</script>
console.clear();
var renderCalls = [];
function render () {
requestAnimationFrame( render );
renderCalls.forEach((callback)=>{ callback(); });
}
render();
/*////////////////////////////////////////*/
var keys = [];
document.body.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
e.preventDefault();
});
document.body.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
e.preventDefault();
});
/*////////////////////////////////////////*/
var pointer = {
down: false,
x: 0,
y: 0,
onDown: function(e){
pointer.down = true;
pointerMove(e);
},
onUp: function(e){
pointer.down = false;
pointerMove(e);
}
};
document.addEventListener('mousedown', pointer.onDown);
document.addEventListener('touchstart', pointer.onDown);
document.addEventListener('mouseup', pointer.onUp);
document.addEventListener('touchend', pointer.onUp);
document.addEventListener('mousemove', pointerMove);
document.addEventListener('touchmove', pointerMove);
function pointerMove(e){
let pos = e.touches ? e.touches[0] : e;
pointer.x = pos.clientX / window.innerWidth;
pointer.y = pos.clientY / window.innerWidth;
};
/*////////////////////////////////////////*/
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 10, 5000 );
camera.position.z = 600;
let mousePos = { x: 0.5, y: 0.5, _x: 0.5, _y: 0.5 };
function trackMouse(e){
let pointer = e.touches ? e.touches[0] : e;
mousePos.x = ( pointer.clientX / window.innerWidth );
mousePos.y = ( pointer.clientY / window.innerHeight );
};
function ease(current,target,ease){ return current + (target - current) * ( ease || 0.2 ); }
function updateCamera(){
mousePos._x = ease(mousePos._x || 0.5, mousePos.x, 0.1);
mousePos._y = ease(mousePos._y || 0.5, mousePos.y, 0.1);
camera.position.x = (50 * (mousePos._x - 0.5) * 2);
camera.position.y = (-50 * (mousePos._y - 0.5) * 2);
}
updateCamera();
window.addEventListener('mousemove', trackMouse);
renderCalls.push(updateCamera);
/*////////////////////////////////////////*/
var scene = new THREE.Scene();
//scene.fog = new THREE.FogExp2( 0x000000, 0.0005);//new THREE.Fog(0xEEEEEE, 20, 600);
var renderer = new THREE.WebGLRenderer( { antialias: true, alpha: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0x000000, 0 );//0x );
renderer.toneMapping = THREE.LinearToneMapping;
renderer.toneMappingExposure = Math.pow( 0.91, 5.0 );
if ( window.innerWidth > 500 ) {
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
}
window.addEventListener( 'resize', function () {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}, false );
document.body.appendChild( renderer.domElement);
renderCalls.push(function(){ renderer.render( scene, camera ); });
/*////////////////////////////////////////*/
//var orbit = new THREE.OrbitControls( camera, renderer.domElement );
/*////////////////////////////////////////*/
var ambientLight = new THREE.AmbientLight(0x222222);
scene.add(ambientLight);
var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 0.5 );
hemiLight.color.setHSL( 0.6, 1, 0.6 );
hemiLight.groundColor.setHSL( 0.095, 1, 0.75 );
hemiLight.position.set( 0, 500, 0 );
scene.add( hemiLight );
var light = new THREE.PointLight( 0xffffaa, 1 );
light.power = 10;
light.position.z = 450;
light.position.y = 60;
scene.add( light );
/*////////////////////////////////////////*/
function makeSun(){
var geometry = new THREE.SphereGeometry( 100, 24, 8 );
var customMaterial = new THREE.ShaderMaterial({
uniforms: { },
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
side: THREE.BackSide,
blending: THREE.AdditiveBlending,
transparent: true
});
let sun = new THREE.Mesh( geometry, customMaterial );
let light = new THREE.PointLight( 0xffffaa, 1 );
light.power = 15;
sun.light = light;
sun.add( light );
return sun;
}
var sun = makeSun();
sun.position.y = 300;
sun.position.z = -500;
scene.add( sun );
/*////////////////////////////////////////*/
function makeMoon(){
function bezier(p0, p1, p2, p3){
var cX = 3 * (p1.x - p0.x),
bX = 3 * (p2.x - p1.x) - cX,
aX = p3.x - p0.x - cX - bX;
var cY = 3 * (p1.y - p0.y),
bY = 3 * (p2.y - p1.y) - cY,
aY = p3.y - p0.y - cY - bY;
return function(t){
var x = (aX * Math.pow(t, 3)) + (bX * Math.pow(t, 2)) + (cX * t) + p0.x;
var y = (aY * Math.pow(t, 3)) + (bY * Math.pow(t, 2)) + (cY * t) + p0.y;
return {x: x, y: y};
}
};
function getCurve(points, accuracy){
accuracy = accuracy || 0.1;
var b = bezier(points[0], points[1], points[2], points[3]), curve = [];
for (var i = 0; i < 1; i += accuracy ){ curve.push(b(i)); }
curve.push(b(1));
return curve;
}
let curve = getCurve([
{ x: 0, y: 0 },
{ x: 60, y: -20 },
{ x: 60, y: 80 },
{ x: 0, y: 60 }
]);
let curve2 = getCurve([
{ x: 0, y: 60 },
{ x: 90, y: 100 },
{ x: 90, y: -40 },
{ x: 0, y: 0 },
]);
var moonShape = new THREE.Shape(); // From http://blog.burlock.org/html5/130-paths
moonShape.moveTo(0, 0);
curve.forEach((point)=>{
moonShape.lineTo(point.x, point.y);
});
curve2.forEach((point)=>{
moonShape.lineTo(point.x, point.y);
});
var geometry = new THREE.ExtrudeGeometry( moonShape, {
amount: 7,
bevelEnabled: true,
bevelSegments: 4,
steps: 2,
bevelSize: 2,
bevelThickness: 10
});
var material = new THREE.MeshPhongMaterial({
color: 0xFFFFEE,
emissive: 0xFFFFEE,
emissiveIntensity: 0.5,
blending: THREE.AdditiveBlending
})
var moon = new THREE.Mesh( geometry, material);
let light = new THREE.PointLight( 0xffffaa, 1 );
light.power = 15;
moon.add( light );
return moon;
}
let moon = makeMoon();
moon.scale.set(1.5,1.5,1.5)
moon.position.x = -50;
moon.position.z = -600;
scene.add(moon);
/*////////////////////////////////////////*/
const TWOPI = Math.PI * 2;
const rad2deg = Math.PI * 180;
function noiseMap(size,intensity){
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
width = canvas.width = size || 512,
height = canvas.height = size || 512;
intensity = intensity || 120;
var imageData = ctx.getImageData(0, 0, width, height),
pixels = imageData.data,
n = pixels.length,
i = 0;
while (i < n) {
pixels[i++] = pixels[i++] = pixels[i++] = Math.sin( i * i * i + (i/n) * Math.PI) * intensity;
pixels[i++] = 255;
}
ctx.putImageData(imageData, 0, 0);
let sprite = new THREE.Texture(canvas);
sprite.needsUpdate = true;
return sprite;
}
function makeGround(){
let geometry = new THREE.SphereGeometry(300, 20, 20, 0, Math.PI, TWOPI, Math.PI / 1.5);
for (let i = 0, len = geometry.vertices.length; i < len; i++ ){
geometry.vertices[i].y += Math.cos(i / 1.5) * 10 + Math.random();
geometry.vertices[i].x -= 1.5 * Math.random(); //Math.cos(i / len) * 30;
geometry.vertices[i].z += 2.5 * Math.random();
}
geometry.verticesNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.computeFaceNormals();
let material = new THREE.MeshPhongMaterial({
color: 0x9ED763,
bumpMap: noiseMap(512,128),
bumpScale: 0.3,
//emissive: 0xAAAAFF,
//emissiveIntensity: 0.8,
shininess: 0,
side: THREE.DoubleSide,
shading: THREE.SmoothShading
});
return new THREE.Mesh(geometry, material);
}
let ground = makeGround();
ground.position.y = -300;
ground.scale.x = 3;
ground.scale.y = 0.5;
scene.add(ground);
/*////////////////////////////////////////*/
let starMaterial = new THREE.PointsMaterial({
size: 6,
color: 0xFFFFFF,
transparent: true,
opacity: 0.1,
blending: THREE.AdditiveBlending
});
function makeStars() {
let starQty = 1000;
let geometry = new THREE.Geometry();//;
for (var i = 0; i < starQty; i++) {
var starVertex = new THREE.Vector3();
starVertex.x = Math.random() * 3000 - 1500; //500 - 250;
starVertex.y = Math.random() * 2000 - 500; //500 - 250;
starVertex.z = -700 + Math.random() * -300; //500 - 250;
geometry.vertices.push(starVertex);
}
geometry.verticesNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.computeFaceNormals();
return new THREE.Points(geometry, starMaterial);
}
let stars = makeStars()
scene.add(stars);
/*////////////////////////////////////////*/
let cloudMaterial = new THREE.MeshPhongMaterial({
color: 0xEEEEEE,
emissive: 0xFFFFFF,
emissiveIntensity: 0.4,
shininess: 10,
transparent: true,
opacity: 0.8,
side: THREE.DoubleSide,
shading: THREE.SmoothShading
});
function randomGlob(rand, pos, size){
size = size || 10 + Math.sin(rand + Math.PI) * 20;
let geometry = new THREE.SphereGeometry( size, 15, 15 );
let mesh = new THREE.Mesh(geometry, cloudMaterial);
mesh.scale.x = Math.max(1, Math.random() + 0.4);
mesh.scale.y = Math.min(0.8, Math.random() + 0.3);
// mesh.scale.z = 0.5; //Math.max(1, Math.random() + 0.3);
if ( pos ) {
mesh.position.y = ( Math.sin(rand + Math.PI ) * size/2 );
mesh.position.x = ( Math.cos(rand + Math.PI ) * size/2 ) + ( rand * 8 * mesh.scale.x );
mesh.position.z = size/2; //( Math.random() < 0.4 ? size/2 : -size/2 ) * 0.2;
}
return mesh;
}
function Cloud(){
THREE.Object3D.call(this);
let size = 40 + Math.random() * 30;
let vert = 10 + (Math.random() * 5);
let horiz = 10 + (Math.random() * 5);
let geometry = new THREE.SphereGeometry( size, horiz, vert );
let offset = (vert+1) * horiz/3;//((horiz/2)+3);
for (let i = 0, len = geometry.vertices.length; i < len; i++ ){
//geometry.vertices[i].y += 10 * Math.cos( ((i % 66)/66) * TWOPI );
geometry.vertices[i].x += 10 * Math.cos( ((i % offset)/offset) * (i / len) * TWOPI );
geometry.vertices[i].z += 6 * Math.sin((i/len) * Math.PI);
geometry.vertices[i].y += 6 * Math.cos((i/len) * TWOPI);
}
geometry.verticesNeedUpdate = true;
geometry.normalsNeedUpdate = true;
geometry.computeFaceNormals();
let mesh = new THREE.Mesh(geometry, cloudMaterial);
mesh.scale.x = ( Math.random() < 0.5 ? -1.9 : 1.9 ); //Math.max(1, Math.random() + 0.8);
mesh.scale.y = 0.6 * ( Math.random() < 0.5 ? -1 : 1 );
mesh.scale.z = ( Math.random() < 0.5 ? -1 : 1 );
this.add(mesh);
this.speed = 0.2 + (Math.random() * 0.1)
renderCalls.push(()=>{
this.position.x -= this.speed;
if ( this.position.x < -1200 ) { this.position.x = 1200; }
});
}
Cloud.prototype = Object.assign(THREE.Object3D.prototype, {
constructor: Cloud,
speed: 0.2,
// onclick: function(){
// console.log('clicked a cloud!');
// let clone = this.clone();
// this.position.x -= 100;
// clone.position.y += 100;
// this.parent.add(clone);
// }
});
let clouds = 7;
for (var i = 0; i < clouds; i++){
let cloud = new Cloud();
cloud.position.x = 1000 * Math.sin((i / clouds) * TWOPI + ( Math.random() * 0.3) );
cloud.position.y = 200 + 300 * Math.cos((i / clouds) * TWOPI+ Math.random() + ( Math.random() * 0.3));
cloud.position.z = -200 + (-400 * Math.random());
scene.add(cloud);
}
/*////////////////////////////////////////*
let mouse = new THREE.Vector2();
let raycaster = new THREE.Raycaster();
document.body.addEventListener('mousedown',click);
document.body.addEventListener('touchstart',click);
function click(e){
let pointer = e.touches ? e.touches : [e];
for (let i = 0, len = pointer.length; i < len; i++){
let event = pointer[i];
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
//alert(mouse.x +' '+ mouse.y );
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( scene.children );
console.log(intersects);
if ( intersects.length > 0 ) {
let obj = intersects[ 0 ].object;
if ( obj.onclick ) { obj.onclick(); }
else {
obj.traverseAncestors((obj)=>{
if ( obj.onclick ) { obj.onclick(); return false; }
});
}
}
}
}
/*////////////////////////////////////////*/
var nightTl = new TimelineMax({ paused: true }); //repeat: 1, yoyo: true, repeatDelay: 2,
var colorTl = new TimelineLite({ paused: true });
colorTl.to(document.body, 1, { backgroundColor: '#FF895D', ease: Linear.easeNone });
colorTl.to(document.body, 1, { backgroundColor: '#A64942', ease: Linear.easeNone });
colorTl.to(document.body, 1, { backgroundColor: '#53354A', ease: Linear.easeNone });
colorTl.to(document.body, 1, { backgroundColor: '#1B1F3A', ease: Linear.easeNone });
nightTl.to(colorTl, 1.2, { progress: 1, ease: Linear.easeNone, delay: 0.6 },0);
nightTl.fromTo(sun.position, 1.2, { y: 300 },{
y: -600,
ease: Back.easeIn.config(2),
},0);
nightTl.to(sun.scale, 0.8, {
y: 2,
delay: 0.4,
ease: Power2.easeIn
},0);
nightTl.to(light, 1.8, { power: 4, ease: Back.easeIn.config(1.8) }, 0);
nightTl.to(starMaterial, 1.2, { opacity: 1 }, 0);
nightTl.to(sun.light, 1.2, {
power: 0,
ease: Back.easeOut.config(1.8),
},0.9);
nightTl.fromTo(moon.position, 1.2, { y: -600 },{
y: 300,
ease: Back.easeOut.config(1.8),
},0.9);
nightTl.from(moon.scale, 0.8, {
y: 1.7,
delay: 0.35,
ease: Power2.easeOut
},0.9);
nightTl.timeScale(1.6);
function transitionSky(){
nightTl[ nightTl.reversed() ? 'play' : 'reverse']();
}
document.body.addEventListener('mouseup', transitionSky);
document.body.addEventListener('touchend', transitionSky);
//sun.onclick = nightTl.play.bind(nightTl);
//moon.onclick = nightTl.reverse.bind(nightTl);
setTimeout(function(){
nightTl.play();
setTimeout(function(){
nightTl.reverse();
},nightTl.duration() * 1000);
},500);
<script src="http://codepen.io/shshaw/pen/epmrgO"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r82/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="//s3-us-west-2.amazonaws.com/s.cdpn.io/16327/CustomEase.min.js?r=2"></script>
canvas { display: block; }
body { background-color: #D2F6FC; cursor: pointer; }
.controls { position: absolute; bottom: 0; left: 0; right: 0; padding: 2em; z-index: 10; font-size: 10px; color: #FFF; opacity: 0.6; pointer-events: none; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment