Created
December 15, 2016 02:45
-
-
Save shshaw/f1d4713fb25ab531f74a2e83a7773fa9 to your computer and use it in GitHub Desktop.
Day & Night π
+π (#3December - Day 14)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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