Made a Sky| Code Fun| HTML, CSS, JS
Made a Sky using HTML, CSS and JavaScript
The sky |
Hey Guys, I was experimenting with these languages to make something special and i ended up making this.After 3 hours of dedicated time on codepen, i've achevied what i would call a self challenge.Just check it out and have fun with it.
DEMO:
Ok guys,Let's Jump right into the code.
HTML:
<div id="container"></div>
CSS:
html { overflow: hidden; } body { margin: 0; padding: 0; overflow: hidden; color: #fff; background: #4831ab; }
JAVASCRIPT:
var container = document.getElementById( 'container' ); var renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement ); var camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, .1, 1000 ); camera.position.set( 0, 0, 4 ); var scene = new THREE.Scene(); scene.background = new THREE.Color( 0x4831ab ); // lights var aLight = new THREE.AmbientLight( 0x7f46ab ); scene.add( aLight ); // --------------------------------------------------------------- // --------------------------------------------------------------- // clouds var cloudsSize = new THREE.Vector3( 15, 4, 6 ); var cloudsBox = new THREE.Box3(); cloudsBox.setFromCenterAndSize( new THREE.Vector3(), cloudsSize ); // ----------------------------------------------------------------- var sphereGeo = new THREE.SphereBufferGeometry( 0.2, 32, 16 ); var cloudMat = new THREE.MeshPhongMaterial({ color: 0xffffff, shininess: 0 }); var Cloud = function() { THREE.Group.call( this ); this.spheres = []; // fill in 3 boxes with a random number of // randomly positioned and randomly scaled spheres // large base var center1 = new THREE.Vector3(); var size1 = new THREE.Vector3( 1, 0.25, 0.6 ); var number1 = THREE.Math.randInt( 10, 25 ); var scaleRange1 = new THREE.Vector2( 0.2, 1 ); this.fillBox( center1, size1, number1, scaleRange1 ); // top of cloud var center2 = new THREE.Vector3( 0, size1.y, 0 ); var size2 = new THREE.Vector3( 0.5, 0.25, 0.5 ); var number2 = THREE.Math.randInt( 5, 15 ); var scaleRange2 = new THREE.Vector2( 0.2, 1 ); this.fillBox( center2, size2, number2, scaleRange2 ); // small tail var center3 = new THREE.Vector3( -0.7, 0, 0 ); var size3 = new THREE.Vector3( 0.4, 0.2, 0.25 ); var number3 = THREE.Math.randInt( 3, 7 ); var scaleRange3 = new THREE.Vector2( 0.1, 0.5 ); this.fillBox( center3, size3, number3, scaleRange3 ); this.userData.velocity = THREE.Math.randFloat( 0.003, 0.007 ); }; Cloud.prototype = Object.create( THREE.Group.prototype ); Cloud.prototype.constructor = Cloud; Cloud.prototype.fillBox = function( center, size, number, scale ){ var box = new THREE.Box3(); box.setFromCenterAndSize( center, size ); var boxGroup = new THREE.Group(); boxGroup.position.copy( center ); this.add( boxGroup ); for ( var i = 0; i < number; i++ ) { var sphere = new THREE.Mesh( sphereGeo, cloudMat ); sphere.position.set( THREE.Math.randFloatSpread( size.x ), THREE.Math.randFloatSpread( size.y ), THREE.Math.randFloatSpread( size.z ) ); sphere.userData.scale = THREE.Math.randFloat( scale.x, scale.y ); sphere.scale.setScalar( sphere.userData.scale ); sphere.userData.velocity = THREE.Math.randFloat( 0.001, 0.002 ); boxGroup.add( sphere ); this.spheres.push( sphere ); } return boxGroup; }; Cloud.prototype.update = function( t ){ // scale individual spheres for ( var i = 0; i < this.spheres.length; i++ ) { var sphere = this.spheres[i]; var scaleOffset = Math.sin( t + ( i + 1 ) ) * 0.4 + 1; sphere.scale.setScalar( sphere.userData.scale * scaleOffset ); } // move entire cloud forward this.position.x += this.userData.velocity; // reset cloud position if ( this.position.x > cloudsBox.max.x ) { this.position.x = cloudsBox.min.x; } }; // ----------------------------------------------------------------- // fill clouds box with clouds var clouds = []; for ( var i = 0; i < 40; i++ ) { var cloud = new Cloud(); cloud.position.set( THREE.Math.randFloatSpread( cloudsSize.x ), THREE.Math.randFloatSpread( cloudsSize.y ), THREE.Math.randFloatSpread( cloudsSize.z ) ); scene.add( cloud ); clouds.push( cloud ); } // ----------------------------------------------------------------- // ----------------------------------------------------------------- // moon var MoonShader = { uniforms: { colorA: { type: 'v3', value: scene.background }, colorB: { type: 'v3', value: new THREE.Color('#fff') }, }, vertexShader: [ "varying vec2 vUv;", "void main() {", " vUv = uv;", " gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}" ].join('\n'), fragmentShader: [ "varying vec2 vUv;", "uniform vec3 colorA;", "uniform vec3 colorB;", "void main() {", " float pct = smoothstep( 0.39, 0.44, vUv.y );", " vec3 col = mix( colorA, colorB, pct );", " gl_FragColor = vec4( col, 1.0 );", "}" ].join('\n') }; var moonGeo = new THREE.SphereBufferGeometry( 2, 32, 32 ); var moonMat = new THREE.ShaderMaterial({ uniforms: THREE.UniformsUtils.clone( MoonShader.uniforms ), vertexShader: MoonShader.vertexShader, fragmentShader: MoonShader.fragmentShader, }); var moon = new THREE.Mesh( moonGeo, moonMat ); moon.position.set( -3, 4, -20 ); moon.rotation.set( - Math.PI / 2, - Math.PI / 6, Math.PI / 4, ); scene.add( moon ); var moonLight = new THREE.DirectionalLight( 0xffffff, 0.8 ); moonLight.position.copy( moon.position ); scene.add( moonLight ); // // key light var dLight = new THREE.DirectionalLight( 0xffffff, 0.2 ); dLight.position.set( 1, 1, 1 ); scene.add( dLight ); // --------------------------------------------------------------- // --------------------------------------------------------------- // stars StarShader = { uniforms: { color: { type: 'v3', value: new THREE.Color( 0xffffff ) }, texture: { type: 't', value: null }, time: { type: 'f', value: 0 }, size: { type: 'f', value: 500.0 } }, vertexShader: [ 'uniform float time;', 'uniform float size;', 'attribute float alphaOffset;', 'varying float vAlpha;', 'uniform vec4 origin;', 'void main() {', 'vAlpha = 0.5 * ( 1.0 + sin( alphaOffset + time ) );', 'vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );', 'float cameraDist = distance( mvPosition, origin );', 'gl_PointSize = size / cameraDist;', 'gl_Position = projectionMatrix * mvPosition;', '}' ].join('\n'), fragmentShader: [ 'uniform float time;', 'uniform vec3 color;', 'uniform sampler2D texture;', 'varying float vAlpha;', 'void main() {', ' gl_FragColor = vec4( color, vAlpha );', ' gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );', '}' ].join('\n') }; var Stars = function( options ) { var color = this.color = options.color || 0x333333; var size = this.size = options.size || 0.4; var pointCount = this.pointCount = options.pointCount || 40; var range = this.range = options.range || new THREE.Vector3( 2, 2, 2 ); THREE.Group.call( this ); // circle texture var canvas = document.createElement('canvas'); canvas.width = canvas.height = 128; var ctx = canvas.getContext( '2d' ); var centerX = canvas.width / 2; var centerY = canvas.height / 2; var radius = canvas.width / 3; ctx.beginPath(); ctx.arc( centerX, centerY, radius, 0, 2 * Math.PI, false ); ctx.fillStyle = '#fff'; ctx.fill(); var texture = new THREE.Texture( canvas ); texture.premultiplyAlpha = true; texture.needsUpdate = true; // StarShader.uniforms.texture.value = texture; StarShader.uniforms.size.value = size; var pointsMat = new THREE.ShaderMaterial( { uniforms: StarShader.uniforms, vertexShader: StarShader.vertexShader, fragmentShader: StarShader.fragmentShader, blending: THREE.AdditiveBlending, depthWrite: false, transparent: true }); var pointsGeo = new THREE.BufferGeometry(); var positions = new Float32Array( pointCount * 3 ); var alphas = new Float32Array( pointCount ); for ( var i = 0; i < pointCount; i++ ) { positions[ i*3 + 0 ] = THREE.Math.randFloatSpread( range.x ); positions[ i*3 + 1 ] = THREE.Math.randFloatSpread( range.y ); positions[ i*3 + 2 ] = THREE.Math.randFloatSpread( range.z ); alphas[ i ] = i; } pointsGeo.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); pointsGeo.addAttribute( 'alphaOffset', new THREE.BufferAttribute( alphas, 1 ) ); var points = this.points = new THREE.Points( pointsGeo, pointsMat ); points.sortParticles = true; points.renderOrder = 1; this.add( points ); } Stars.prototype = Object.create( THREE.Group.prototype ); Stars.prototype.constructor = Stars; // --------------------------------------------------------------- var stars = new Stars({ color: 0xffffff, range: new THREE.Vector3( 110, 60, 30 ), pointCount: 400, size: 400, speed: 0.1 }); scene.add( stars ); stars.position.z = -50; // --------------------------------------------------------------- // --------------------------------------------------------------- window.addEventListener( 'resize', resize, false ); function resize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); renderer.setSize( window.innerWidth, window.innerHeight ); } var clock = new THREE.Clock(); renderer.setAnimationLoop( loop ); function loop() { var time = clock.getElapsedTime(); for ( var i = 0; i < clouds.length; i++ ) { clouds[i].update( time ); } stars.points.material.uniforms.time.value = time; renderer.render( scene, camera ); }
Enjoyed it?
Feel free to post the feedback /edit this and post it on the comments.
Happy Coding.
Interesting.
ReplyDeleteI love this. Nice work!
ReplyDeleteGreat job! I need to hone my skills!
ReplyDeleteNice Job!!!
ReplyDelete