First of all let me mention you will not be able to run this demo unless your browser is WebGL ready. So that means if you want to see this then you have to download a nightly build of FireFox, Chrome, or Safari. You can read how to do this here.
My first impressions of WebGL is it is awesome and easy to do. I believe WebGL will make it easy for any developer to rapidly create a game on the web. It is fast appears to have decent support meaning that it works awesome on my Apple computers and on one of my Windows7 computers but then fails for me on one of my workstations that has a souped up ATI graphics card humm.. go figure. It is hard to say how well the graphics rendering will perform on the majority of computers out their but it probably won’t be that bad and after all these are nightly builds that are pre-alpha for the most part. It also makes me wonder if the next iPhones will have this feature built into their webkit. Hard to say. It is known that out of all the new browsers coming out that ie9 will not support graphics rendering shocking (Not really). It might be because Microsoft believes that WebGL will be an epic failure or maybe they simply don’t have the resources to devote to it at this time.
I believe graphic card support in these new browsers will speed up canvas rendering a little but I when looking at the flash benchmarks that are currently out their it definitely shows you how fast the flash player is in comparison. In short canvas tag is not even remotely as fast. In the news their has been lots of discussion about flash being dead but this simply isn’t true. Here is why forthcoming HDTV/3DTV will support flash, google phones will support flash, blackberry, and windows phones will all support flash. So as a mobile platform it will be the easiest way to build and deploy to all platforms. It is too bad Apple doesn’t see it but oh well. I guess I will just have to get better at Objective-C to be on that platform.
This is the first part of a two part example. I created a simple mashup. To create this example I used C3DL and jQuery. C3DL is an awesome opensouce library put together by the wonderful people at Seneca College. This example pulls a search results from twitter with the search query subject being fishing. Yes, I know that twitter is all about birds and tweets but after scouring the Google 3D warehouse, I decided that most of the models for birds that are freely available suck. So I made a virtual fish tank instead. The tank has bubbles rendered with the C3DL particle library and it also has a school of fish that swim slowly though the tank. It’s not really ground shaking stuff pretty simple. I will work on a future version where it pulls results with ajax. I noticed the C3DL library attaches an event listener in the init.js that listens for the document to be loaded
. This of course makes my search function of twitter fail. I have looked at overriding this feature a number of ways not limited to jQuery getScript, etc.. I could also put the query on the query string for the window location and then re-load the page but I think that would be kind of wonky so whatever I will do this in the next version of the experiment. So whatever I will save it for next time.
Check out the experiment here but before you do download a nightly build of Firefox.
Here is the code for the experiment:
var CANVAS_WIDTH = $(window).width(); var CANVAS_HEIGHT = $(window).height()*2; $('#tweetTank').width(CANVAS_WIDTH); $('#tweetTank').height(CANVAS_HEIGHT); $('#tweetTank').css('display','block'); var arrayTwit; var schooloffish; var fishArray = []; var bubblesArray = []; var bubbles; var objectsHit = ""; var objectSelected; function mRandom(r) { var randomInt = Math.floor(Math.random() * r + 1); return randomInt; } c3dl.addModel("fish.dae"); c3dl.addModel("OceanSphere.dae"); // The program main function canvasMain(canvasName) { // Create new c3dl.Scene object scn = new c3dl.Scene(); scn.setCanvasTag(canvasName); // Create GL context renderer = new c3dl.WebGL(); renderer.addTexture("bubble.jpg"); renderer.createRenderer(this); // Attach renderer to the scene scn.setRenderer(renderer); scn.init(canvasName); //the isReady() function tests whether or not a renderer //is attached to a scene. If the renderer failed to //initialize this will return false but only after you //try to attach it to a scene. if (renderer.isReady()) { // Create a Collado object that // will contain a imported // model of something to put // in the scene. //fish.setAngularVel(new Array(0.0, 0.0001, 0.0)); var schooloffish = mRandom(100); var ocean = new c3dl.Collada(); ocean.init("OceanSphere.dae"); ocean.setAngularVel(new Array(0, .00005, 0)); ocean.scale([20.0, 20.0, 20.0]); ocean.setPickable(false); scn.addObjectToScene(ocean); //console.log(arrayTwit.length); for (var i = 0; i < arrayTwit.length; i++) { //console.log(arrayTwit[i]); fishArray[i] = new c3dl.Collada(); fishArray[i].init("fish.dae"); fishArray[i].yaw(45.0); fishArray[i].ID = "Fish" + i; //fish.roll(25.0); fishArray[i].pitch(-86.4); fishArray[i].setLinearVel([0,0,-2]); fishArray[i].url = "http://twitter.com/" + arrayTwit[i].from_user; //fish.setPosition([1200, 100, 700]); fishArray[i].setPosition([mRandom(1200), mRandom(900), mRandom(1500)]); scn.addObjectToScene(fishArray[i]); } for (var i = 0; i < 7; i++) { bubblesArray[i] = new c3dl.ParticleSystem(); bubblesArray[i].setMinVelocity([-2, 0, -2]); bubblesArray[i].setMaxVelocity([2, 25, 2]); bubblesArray[i].setMinLifetime(5.3); bubblesArray[i].setMaxLifetime(10.7); bubblesArray[i].setMinColor([0, 0, 0.3, 0]); bubblesArray[i].setMaxColor([0, 0.3, 0.5, 1]); bubblesArray[i].setSrcBlend(c3dl.ONE); bubblesArray[i].setDstBlend(c3dl.ONE); bubblesArray[i].setMinSize(0.5); bubblesArray[i].setMaxSize(5.0); bubblesArray[i].setTexture("bubble.gif"); bubblesArray[i].setAcceleration([0, 9, 0]); bubblesArray[i].setEmitRate(40); bubblesArray[i].init(150); bubblesArray[i].setPosition([mRandom(1200), mRandom(100), mRandom(700)]); scn.addObjectToScene(bubblesArray[i]); } // Create a camera //var cam = new c3dl.FreeCamera(); // scn.setCamera(cam); cam = new c3dl.OrbitCamera(); cam.setFarthestDistance(2000); //cam.pitch(90); cam.setPosition(new Array(3000.0, 300.0, 200.0)); //cam.setLookAtPoint(new Array(0.0, 0.0, 0.0)); cam.setOrbitPoint(new Array(800.0, 100.0, 200.0)); cam.setClosestDistance(200); cam.setDistance(900); //cam.pitch(1); scn.setCamera(cam); // Start the scene scn.startScene(); scn.setPickingCallback(goLink); scn.setKeyboardCallback(onKeyUp, onKeyDown); scn.setMouseCallback(mouseMove, mouseWheel); } } function goLink(pickingObj) { var objectsHit = pickingObj.getObjects(); if( objectsHit.length > 0 ) { var sepiaEffect = new c3dl.Effect(); sepiaEffect.init(c3dl.effects.SEPIA); window.open(objectsHit[0].url, '_blank'); objectsHit[0].setEffect(sepiaEffect); for(var i = 0; i < arrayTwit.length; i++){ if(objectsHit[0].url == scn.getObj(i).url) scn.getObject(i).setEffect(sepiaEffect); } } } function onKeyUp(event) { if (event.keyCode == 89) { keyD = false; } } function mouseWheel(event) { var delta = 0; // Chromium if (event.wheelDelta) { delta = -event.wheelDelta / 20; } // Minefield else if (event.detail) { delta = event.detail * 4; } else { if (keyD) { cam.yaw(delta * ZOOM_SENSITIVITY / 100); } else { // towards user if (-delta * ZOOM_SENSITIVITY < 0) { cam.goFarther(-1 * -delta * ZOOM_SENSITIVITY); } // towards screen else { cam.goCloser(-delta * ZOOM_SENSITIVITY); } } } } function onKeyDown(event) { if (event.keyCode == 65) { cam.setOrbitPoint([0, 0, 0]); } if (event.keyCode == 89) { keyD = true; } } function mouseMove(event) { // get mouse coords relative to window var mmx = event.pageX - 1; var mmy = event.pageY - 1; if (mmx != null && mmy != null) { // NDC var normalizedDeviceCoords = [ (2 * mmx / CANVAS_WIDTH) - 1, -((2 * mmy / CANVAS_HEIGHT) - 1), 1, 1]; // Sometimes this is called before the perspective transform // is setup which causes warnings. This check prevents that. if (c3dl.isValidMatrix(scn.getProjectionMatrix())) { var iproj = c3dl.inverseMatrix(scn.getProjectionMatrix()); // To get the clip coords, we multiply the viewspace coordinates by // the projection matrix. // Working backwards across the pipeline, we have to take the normalized // device coordinates and multiply by the inverse projection matrix to get // the clip coordinates. var clipCoords = c3dl.multiplyMatrixByVector(iproj, normalizedDeviceCoords); // perspective divide clipCoords[0] /= clipCoords[3]; clipCoords[1] /= clipCoords[3]; clipCoords[2] /= clipCoords[3]; clipCoords[2] = -clipCoords[2]; var rayInitialPoint = cam.getPosition(); var x = clipCoords[0]; var y = clipCoords[1]; var z = clipCoords[2]; var kludge = c3dl.multiplyVector(cam.getLeft(), -1); var viewMatrix = c3dl.makePoseMatrix(kludge, cam.getUp(), cam.getDir(), cam.getPosition()); var rayTerminalPoint = c3dl.multiplyMatrixByVector(viewMatrix, [x, y, z, 0]); var rayDir = c3dl.normalizeVector(rayTerminalPoint); // get angle var angle = Math.acos(-1 * rayDir[1]); var camHeight = rayInitialPoint[1]; var hyp = camHeight / Math.cos(angle); mx = hyp * rayDir[0] + rayInitialPoint[0]; my = hyp * rayDir[1]; mz = hyp * rayDir[2] + rayInitialPoint[2]; } } } function twitterSearch(searchTag) { //console.log(searchTag); arrayTwit = ""; arrayTwit = new Array(); $.getJSON("http://search.twitter.com/search.json?q=" + searchTag + "&callback=?", function(data) { $.each(data.results, function(i, item) { twitSeach = item; arrayTwit.push(twitSeach); }); //c3dl.init(); c3dl.addMainCallBack(canvasMain, "tweetTank"); }); } $(document).ready(function() { twitterSearch("fishing"); });
Launch Experiment / Download Code
I mentioned possibly creating a spider with silverlight. I still would like to do that in the near future. I found this cool silverlight examples and would like to study it! I have installed Visual Studio 2010 on my Windows boxes and it is awesome!
I have also been eying a new tutorial on the Hype Framework in ComputerArts latest issue(174). Has a really cool example that teaches you how to use Hype to make music drawings created by Stewart Hamilton-Arrandale. I will learn from this code. I could add this type of functionality into my KulerSplash.
I also found this resource recently on Objective-C really cool web site it was nice of them to share so much Fabien also has some cool JAVA examples as well.
WebGL libraries:
C3DL
CopperLicht
SceneJS
Related posts:













