Welcome to Minetown!
To join our community, please login or register!
Internet Explorer
Internet Explorer is not supported. Please upgrade to a more modern browser.

[Enjin Archive] WebGL: The future of the internet
Started by [E] sawine

Hey,

I felt like sharing this nice webgl minecraft script and to make a quick post about webgl because it is so awesome and will revolutionize the web in the next years.



Here is the minecraft script in question: http://mrdoob.github.com/three.js/examples/webgl_geometry_minecraft_ao.html

So right now I know you're probably thinking , "Why is it so awesome ?, it's already possible to play minecraft in your brower."

Well, everything you see on this page is generated only by your internet browser. Only using javascript. No java, no flash.

Code:
<!doctype html> <html lang="en"> <head> <title>three.js webgl - geometry - minecraft - ao</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> <style> body { color: #61443e; font-family:Monospace; font-size:13px; text-align:center; /* background-color: #bfd1e5; */ background-color: #ffffff; margin: 0px; overflow: hidden; } a { color: #a06851; } #info { position: absolute; top: 0px; width: 100%; padding: 5px; } #oldie { background:rgb(100,0,0) !important; color:#fff !important; margin-top:10em !important; } #oldie a { color:#fff } button { border:0; background:rgba(0,0,0,0.5); color:orange; cursor:pointer } button:hover { color:gold } </style> </head> <body> <div id="container"><br /><br /><br /><br /><br />Generating world...</div> <div id="info"> <a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - <a href="http://www.minecraft.net/" target="_blank">minecraft</a> demo . featuring <a href="http://painterlypack.net/" target="_blank">painterly pack</a><br />(left click: forward, right click: backward) <br/><br/> <button id="bt">texture</button> <button id="bao">ao</button> <button id="baot">texture + ao</button> </div> <script src="../build/Three.js"></script> <script src="js/ImprovedNoise.js"></script> <script src="js/Detector.js"></script> <script src="js/RequestAnimationFrame.js"></script> <script src="js/Stats.js"></script> <script> if ( ! Detector.webgl ) { Detector.addGetWebGLMessage(); document.getElementById( 'container' ).innerHTML = ""; } var fogExp2 = true; var container, stats; var camera, controls, scene, renderer; var mesh, mat; var worldWidth = 200, worldDepth = 200, worldHalfWidth = worldWidth / 2, worldHalfDepth = worldDepth / 2, data = generateHeight( worldWidth, worldDepth ); var clock = new THREE.Clock(); init(); animate(); function init() { container = document.getElementById( 'container' ); camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 ); camera.position.y = getY( worldHalfWidth, worldHalfDepth ) * 100 + 100; controls = new THREE.FirstPersonControls( camera ); controls.movementSpeed = 1000; controls.lookSpeed = 0.125; controls.lookVertical = true; controls.constrainVertical = true; controls.verticalMin = 1.1; controls.verticalMax = 2.2; scene = new THREE.Scene(); scene.fog = new THREE.FogExp2( 0xffffff, 0.00015 ); var debug_texture = false, debug_numbers = false, debug_corner_colors = false, strength = 2, textures = { side: 'textures/minecraft/grass_dirt.png', top: 'textures/minecraft/grass.png', bottom: 'textures/minecraft/dirt.png' }, m_aot = generateMegamaterialAO( textures, strength, debug_texture, debug_numbers, debug_corner_colors ), m_ao = generateMegamaterialAO( textures, strength, true, debug_numbers, debug_corner_colors ), m_t = generateMegamaterialPlain( textures ), //m_d = generateMegamaterialDebug(), mat = generateMegamaterialAO( textures, strength, debug_texture, debug_numbers, debug_corner_colors ), materials = ; var i, j, x, z, h, h2, uv, px, nx, pz, nz, sides, right, left, bottom, top, nright, nleft, nback, nfront, nleftup, nrightup, nbackup, nfrontup, nrb, nrf, nlb, nlf, nrbup, nrfup, face_px, face_nx, face_py, face_ny, face_pz, face_nz, ti, ri, li, bi, fi, ci, mi, mm, column, row, cube, unit = 1/16 * 0.95, padding = 1/16 * 0.025, p, s, t, hash, N = -1, // map of UV indices for faces of partially defined cubes uv_index_map = { 0: { nx: N, px: N, py: 0, ny: N, pz: N, nz: N }, 1: { nx: N, px: N, py: 0, ny: N, pz: N, nz: 1 }, 2: { nx: N, px: N, py: 0, ny: N, pz: 1, nz: N }, 3: { nx: N, px: N, py: 0, ny: N, pz: 1, nz: 2 }, 4: { nx: N, px: 0, py: 1, ny: N, pz: N, nz: N }, 5: { nx: N, px: 0, py: 1, ny: N, pz: N, nz: 2 }, 6: { nx: N, px: 0, py: 1, ny: N, pz: 2, nz: N }, 7: { nx: N, px: 0, py: 1, ny: N, pz: 2, nz: 3 }, 8: { nx: 0, px: N, py: 1, ny: N, pz: N, nz: N }, 9: { nx: 0, px: N, py: 1, ny: N, pz: N, nz: 2 }, 10: { nx: 0, px: N, py: 1, ny: N, pz: 2, nz: N }, 11: { nx: 0, px: N, py: 1, ny: N, pz: 2, nz: 3 }, 12: { nx: 0, px: 1, py: 2, ny: N, pz: N, nz: N }, 13: { nx: 0, px: 1, py: 2, ny: N, pz: N, nz: 3 }, 14: { nx: 0, px: 1, py: 2, ny: N, pz: 3, nz: N }, 15: { nx: 0, px: 1, py: 2, ny: N, pz: 3, nz: 4 } }, // all possible combinations of corners and sides // mapped to mixed tiles // (including corners overlapping sides) // (excluding corner alone and sides alone) // looks ugly, but allows to squeeze all // combinations for one texture into just 3 rows // instead of 16 mixmap = { "1_1": 0, "1_3": 0, "1_9": 0, "1_11": 0, "1_4": 1, "1_6": 1, "1_12": 1, "1_14": 1, "2_2": 2, "2_3": 2, "2_6": 2, "2_7": 2, "2_8": 3, "2_9": 3, "2_12": 3, "2_13": 3, "4_1": 4, "4_5": 4, "4_9": 4, "4_13": 4, "4_2": 5, "4_6": 5, "4_10": 5, "4_14": 5, "8_4": 6, "8_5": 6, "8_6": 6, "8_7": 6, "8_8": 7, "8_9": 7, "8_10": 7, "8_11": 7, "1_5": 8, "1_7": 8, "1_13": 8, "1_15": 8, "2_10": 9, "2_11": 9, "2_14": 9, "2_15": 9, "4_3": 10, "4_7": 10, "4_11": 10, "4_15": 10, "8_12": 11, "8_13": 11, "8_14": 11, "8_15": 11, "5_1": 12, "5_3": 12, "5_7": 12, "5_9": 12, "5_11": 12, "5_13": 12, "5_15": 12, "6_2": 13, "6_3": 13, "6_6": 13, "6_7": 13, "6_10": 13, "6_11": 13, "6_14": 13, "6_15": 13, "9_4": 14, "9_5": 14, "9_6": 14, "9_7": 14, "9_12": 14, "9_13": 14, "9_14": 14, "9_15": 14, "10_8": 15, "10_9": 15, "10_10": 15, "10_11": 15, "10_12": 15, "10_13": 15, "10_14": 15, "10_15": 15 }, tilemap = {}, top_row_corners = 0, top_row_mixed = 1, top_row_sides = 2, sides_row = 3, bottom_row = 4, geometry = new THREE.Geometry(); // mapping from 256 possible corners + sides combinations // into 3 x 16 tiles for ( i = 0; i < 16; i++ ) { for ( j = 0; j < 16; j++ ) { mm = i + "_" + j; if ( i == 0 ) row = top_row_corners; else if ( mixmap != undefined ) row = top_row_mixed; else row = top_row_sides; tilemap = row; } } function setUVTile( face, s, t ) { var j, uv = cube.faceVertexUvs; for ( j = 0; j < uv.length; j++ ) { uv.u += s * (unit+2*padding); uv.v += t * (unit+2*padding); } } for ( z = 0; z < worldDepth; z ++ ) { for ( x = 0; x < worldWidth; x ++ ) { h = getY( x, z ); // direct neighbors h2 = getY( x - 1, z ); nleft = h2 == h || h2 == h + 1; h2 = getY( x + 1, z ); nright = h2 == h || h2 == h + 1; h2 = getY( x, z + 1 ); nback = h2 == h || h2 == h + 1; h2 = getY( x, z - 1 ); nfront = h2 == h || h2 == h + 1; // corner neighbors nrb = getY( x - 1, z + 1 ) == h && x > 0 && z < worldDepth - 1 ? 1 : 0; nrf = getY( x - 1, z - 1 ) == h && x > 0 && z > 0 ? 1 : 0; nlb = getY( x + 1, z + 1 ) == h && x < worldWidth - 1 && z < worldDepth - 1 ? 1 : 0; nlf = getY( x + 1, z - 1 ) == h && x < worldWidth - 1 && z > 0 ? 1 : 0; // up neighbors nleftup = getY( x - 1, z ) > h && x > 0 ? 1 : 0; nrightup = getY( x + 1, z ) > h && x < worldWidth - 1 ? 1 : 0; nbackup = getY( x, z + 1 ) > h && z < worldDepth - 1 ? 1 : 0; nfrontup = getY( x, z - 1 ) > h && z > 0 ? 1 : 0; // up corner neighbors nrbup = getY( x - 1, z + 1 ) > h && x > 0 && z < worldDepth - 1 ? 1 : 0; nrfup = getY( x - 1, z - 1 ) > h && x > 0 && z > 0 ? 1 : 0; nlbup = getY( x + 1, z + 1 ) > h && x < worldWidth - 1 && z < worldDepth - 1 ? 1 : 0; nlfup = getY( x + 1, z - 1 ) > h && x < worldWidth - 1 && z > 0 ? 1 : 0; // textures ti = nleftup * 8 + nrightup * 4 + nfrontup * 2 + nbackup * 1; ri = nrf * 8 + nrb * 4 + 1; li = nlb * 8 + nlf * 4 + 1; bi = nrb * 8 + nlb * 4 + 1; fi = nlf * 8 + nrf * 4 + 1; ci = nlbup * 8 + nlfup * 4 + nrbup * 2 + nrfup * 1; // cube sides px = nx = pz = nz = 0; px = !nright || x == 0 ? 1 : 0; nx = !nleft || x == worldWidth - 1 ? 1 : 0; pz = !nback || z == worldDepth - 1 ? 1 : 0; nz = !nfront || z == 0 ? 1 : 0; sides = { px: px, nx: nx, py: true, ny: false, pz: pz, nz: nz }; cube = new THREE.CubeGeometry( 100, 100, 100, 1, 1, 1, materials, sides ); // set UV tiles for ( i = 0; i < cube.faceVertexUvs.length; i ++ ) { uv = cube.faceVertexUvs; for ( j = 0; j < uv.length; j++ ) { p = uv.u == 0 ? padding : -padding; uv.u = uv.u * unit + p; p = uv.v == 0 ? padding : -padding; uv.v = uv.v * unit + p; } } hash = px * 8 + nx * 4 + pz * 2 + nz; face_px = uv_index_map.px; face_nx = uv_index_map.nx; face_py = uv_index_map.py; face_ny = uv_index_map.ny; face_pz = uv_index_map.pz; face_nz = uv_index_map.nz; if( face_px != N ) setUVTile( face_px, ri, sides_row ); if( face_nx != N ) setUVTile( face_nx, li, sides_row ); if( face_py != N ) { mm = ti + "_" + ci; switch ( tilemap ) { case top_row_sides: column = ti; break; case top_row_corners: column = ci; break; case top_row_mixed: column = mixmap; break; } setUVTile( face_py, column, tilemap ); } if( face_ny != N ) setUVTile( face_ny, 0, bottom_row ); if( face_pz != N ) setUVTile( face_pz, bi, sides_row ); if( face_nz != N ) setUVTile( face_nz, fi, sides_row ); mesh = new THREE.Mesh( cube ); mesh.position.x = x * 100 - worldHalfWidth * 100; mesh.position.y = h * 100; mesh.position.z = z * 100 - worldHalfDepth * 100; THREE.GeometryUtils.merge( geometry, mesh ); } } mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() ); scene.add( mesh ); var ambientLight = new THREE.AmbientLight( 0xcccccc ); scene.add( ambientLight ); var directionalLight = new THREE.DirectionalLight( 0xffffff, 2 ); directionalLight.position.set( 1, 1, 0.5 ).normalize(); scene.add( directionalLight ); renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); container.innerHTML = ""; container.appendChild( renderer.domElement ); stats = new Stats(); stats.domElement.style.position = 'absolute'; stats.domElement.style.top = '0px'; container.appendChild( stats.domElement ); document.getElementById( "bao" ).addEventListener( "click", function() { mat.map = m_ao.map; }, false ); document.getElementById( "baot" ).addEventListener( "click", function() { mat.map = m_aot.map; }, false ); document.getElementById( "bt" ).addEventListener( "click", function() { mat.map = m_t.map; }, false ); } function generateMegamaterialAO( textures, strength, debug_texture, debug_numbers, debug_corner_colors ) { var count = 0, tex_side = loadTexture( textures.side, function() { count++; generateTexture() } ), tex_top = loadTexture( textures.top, function() { count++; generateTexture() } ), tex_bottom = loadTexture( textures.bottom, function() { count++; generateTexture() } ), canvas = document.createElement( 'canvas' ), ctx = canvas.getContext( '2d' ), size = 256, tile = 16; canvas.width = canvas.height = size; var texture = new THREE.Texture( canvas, new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, THREE.NearestFilter, THREE.LinearMipMapLinearFilter ); function generateTexture() { if( count == 3 ) { for( var i = 0; i < 16; i++ ) { drawAOCorners( ctx, tex_top, 0, i, i, tile, strength, debug_texture, debug_numbers, debug_corner_colors ); drawAOMixed ( ctx, tex_top, 1, i, i, tile, strength, debug_texture, debug_numbers, debug_corner_colors ); drawAOSides ( ctx, tex_top, 2, i, i, tile, strength, debug_texture, debug_numbers ); drawAOSides ( ctx, tex_side, 3, i, i, tile, strength, debug_texture, debug_numbers ); drawAOSides ( ctx, tex_bottom, 4, i, i, tile, strength, debug_texture, debug_numbers ); } texture.needsUpdate = true; } } return new THREE.MeshLambertMaterial( { map: texture, ambient: 0xbbbbbb } ); } function generateMegamaterialPlain( textures ) { var count = 0, tex_side = loadTexture( textures.side, function() { count++; generateTexture() } ), tex_top = loadTexture( textures.top, function() { count++; generateTexture() } ), tex_bottom = loadTexture( textures.bottom, function() { count++; generateTexture() } ), canvas = document.createElement( 'canvas' ), ctx = canvas.getContext( '2d' ), size = 256, tile = 16; canvas.width = canvas.height = size; var texture = new THREE.Texture( canvas, new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, THREE.NearestFilter, THREE.LinearMipMapLinearFilter ); function generateTexture() { if( count == 3 ) { var i, sx; for( i = 0; i < 16; i++ ) { sx = i * tile; drawBase( ctx, tex_top, sx, 0 * tile, tile, false ); drawBase( ctx, tex_top, sx, 1 * tile, tile, false ); drawBase( ctx, tex_top, sx, 2 * tile, tile, false ); drawBase( ctx, tex_side, sx, 3 * tile, tile, false ); drawBase( ctx, tex_bottom, sx, 4 * tile, tile, false ); } texture.needsUpdate = true; } } return new THREE.MeshLambertMaterial( { map: texture } ); } function generateMegamaterialDebug() { var canvas = document.createElement( 'canvas' ), ctx = canvas.getContext( "2d" ), size = 256, tile = 16, i, j, h, s; canvas.width = size; canvas.height = size; ctx.textBaseline = "top"; ctx.font = "8pt arial"; for ( i = 0; i < tile; i++ ) { for ( j = 0; j < tile; j++ ) { h = i * tile + j; ctx.fillStyle = "hsl(" + h + ",90%, 50%)"; ctx.fillRect( i * tile, j * tile, tile, tile ); drawHex( ctx, h, i * tile + 2, j * tile + 2 ); } } var texture = new THREE.Texture( canvas, new THREE.UVMapping(), THREE.ClampToEdgeWrapping, THREE.ClampToEdgeWrapping, THREE.NearestFilter, THREE.LinearMipMapLinearFilter ); texture.needsUpdate = true; return new THREE.MeshLambertMaterial( { map: texture } ); } function drawHex( ctx, n, x, y ) { ctx.fillStyle = "black"; ctx.font = "8pt arial"; ctx.textBaseline = "top"; var s = n.toString( 16 ); s = n < 16 ? "0" + s : s; ctx.fillText( s, x, y ); } function drawBase( ctx, image, sx, sy, tile, debug_texture ) { if ( debug_texture ) { ctx.fillStyle = "#888"; ctx.fillRect( sx, sy, tile, tile ); } else { ctx.drawImage( image, sx, sy, tile, tile ); } } function drawCorner( ctx, sx, sy, sa, ea, color, step, n ) { for( var i = 0; i < n; i++ ) { ctx.strokeStyle = color + step * ( n - i ) + ")"; ctx.beginPath(); ctx.arc( sx, sy, i, sa, ea, 0 ) ; ctx.stroke(); } } function drawSide( ctx, sx, sy, a, b, n, width, height, color, step ) { for( var i = 0; i < n; i++ ) { ctx.fillStyle = color + step * ( n - i ) + ")"; ctx.fillRect( sx + a * i, sy + b * i, width, height ); } } function drawAOSides( ctx, image, row, column, sides, tile, strength, debug_texture, debug_numbers ) { var sx = column * tile, sy = row * tile; drawBase( ctx, image, sx, sy, tile, debug_texture ); drawAOSidesImp( ctx, image, row, column, sides, tile, strength ); if ( debug_numbers ) drawHex( ctx, row * tile + sides, sx + 2, sy + 2 ); } function drawAOCorners( ctx, image, row, column, corners, tile, strength, debug_texture, debug_numbers, debug_corner_colors ) { var sx = column * tile, sy = row * tile; drawBase( ctx, image, sx, sy, tile, debug_texture ); drawAOCornersImp( ctx, image, row, column, corners, tile, strength, debug_corner_colors ); if ( debug_numbers ) drawHex( ctx, row * tile + corners, sx + 2, sy + 2 ); } function drawAOMixed( ctx, image, row, column, elements, tile, strength, debug_texture, debug_numbers, debug_corner_colors ) { var sx = column * tile, sy = row * tile, mmap = { 0: , 1: , 2: , 3: , 4: , 5: , 6: , 7: , 8: , 9: , 10: , 11: , 12: , 13: , 14: , 15: }; drawBase( ctx, image, sx, sy, tile, debug_texture ); drawAOCornersImp( ctx, image, row, column, mmap, tile, strength, debug_corner_colors ); drawAOSidesImp( ctx, image, row, column, mmap, tile, strength ); if ( debug_numbers ) drawHex( ctx, row * tile + elements, sx + 2, sy + 2 ); } function drawAOSidesImp( ctx, image, row, column, sides, tile, strength ) { var sx = column * tile, sy = row * tile, full = tile, step = 1 / full, half = full / 2 + strength, color = "rgba(0, 0, 0, ", left = (sides & 8) == 8, right = (sides & 4) == 4, bottom = (sides & 2) == 2, top = (sides & 1) == 1; if ( bottom ) drawSide( ctx, sx, sy, 0, 1, half, tile, 1, color, step ); if ( top ) drawSide( ctx, sx, sy + full - 1, 0, -1, half, tile, 1, color, step ); if ( left ) drawSide( ctx, sx, sy, 1, 0, half, 1, tile, color, step ); if ( right ) drawSide( ctx, sx + full - 1, sy, -1, 0, half, 1, tile, color, step ); } function drawAOCornersImp( ctx, image, row, column, corners, tile, strength, debug_corner_colors ) { var sx = column * tile, sy = row * tile, full = tile, step = 1 / full, half = full / 2 + strength, color = "rgba(0, 0, 0, ", bottomright = (corners & 8) == 8, topright = (corners & 4) == 4, bottomleft = (corners & 2) == 2, topleft = (corners & 1) == 1; if ( topleft ) { if ( debug_corner_colors ) color = "rgba(200, 0, 0, "; drawCorner( ctx, sx, sy, 0, Math.PI / 2 , color, step, half ); } if ( bottomleft ) { if ( debug_corner_colors ) color = "rgba(0, 200, 0, "; drawCorner( ctx, sx, sy + full, 1.5 * Math.PI, 2 * Math.PI, color, step, half ); } if ( bottomright ) { if ( debug_corner_colors ) color = "rgba(0, 0, 200, "; drawCorner( ctx, sx + full, sy + full, Math.PI, 1.5 * Math.PI, color, step, half ); } if ( topright ) { if ( debug_corner_colors ) color = "rgba(200, 0, 200, "; drawCorner( ctx, sx + full, sy, Math.PI / 2, Math.PI, color, step, half ); } } function loadTexture( path, callback ) { var image = new Image(); image.onload = function () { callback(); }; image.src = path; return image; } function generateHeight( width, height ) { var data = , perlin = new ImprovedNoise(), size = width * height, quality = 2, z = Math.random() * 100; for ( var j = 0; j < 4; j ++ ) { if ( j == 0 ) for ( var i = 0; i < size; i ++ ) data = 0; for ( var i = 0; i < size; i ++ ) { var x = i % width, y = ~~ ( i / width ); data += perlin.noise( x / quality, y / quality, z ) * quality; } quality *= 4 } return data; } function getY( x, z ) { return ~~( data * 0.2 ); } // function animate() { requestAnimationFrame( animate ); render(); stats.update(); } function render() { controls.update( clock.getDelta() ); renderer.render( scene, camera ); } </script> </body> </html>


And with the usage of a revolutionary lightweight javascript 3D engine: three.js

Few months ago, google(those crazy bastards) even ported Quake2 to it. http://code.google.com/p/quake2-gwt-port/

Here are a bunch of awesome and crazy examples:

http://labs.dinahmoe.com/plink/ (you can make songs in multiplayer thats awesome, atleast for 5min)

http://www.ro.me/

http://lights.elliegoulding.com/

http://oos.moxiecode.com/js_webgl/xwing/

http://alteredqualia.com/three/examples/webgl_cars.html

http://madebyevan.com/webgl-path-tracing/

http://madebyevan.com/webgl-water/

http://balldroppings.com/js

For more examples: http://www.chromeexperiments.com/

WebGL is still in emergence, but is coming mature pretty fast. How long until the first webgl mmo ?

Cya
Counter strike on ?

Browser?
This is some pretty old news...
OkiFool66 has been banned.

Reason unnecessary.
i still don't get it...
OkiFool66 wrote:
This is some pretty old news...

yes and no... I just felt to post about it while sharing the minecraft animation...

Yes WebGL is not new... but it's coming more and more widely used and we didn't see yet it's full potential.