Permalink
Browse files

First commit.

Signed-off-by: Grant Skinner <info@gskinner.com>
  • Loading branch information...
gskinner committed Aug 19, 2012
0 parents commit 4d203e6db12c28f17c02adf3f6a46c7f8403860d
@@ -0,0 +1,36 @@
+##EASELJS DYNAMIC RENDERERS:
+
+This is an experiment that aims to provide runtime pluggable renderers for a subset EaselJS content. They allow you to create your content for EaselJS, then render it to a variety of surfaces (ex. Canvas, WebGL, HTML DOM) dynamically at runtime. It is really only intended as a proof of concept, and as a starting point for more complete renderers.
+
+If you are not familiar with EaselJS already, this is not the best place to start.
+
+Currently, most renderers support displaying Bitmap, BitmapAnimation, Container, and content that has had .cache() applied (ex. Shape, Text).
+
+Currently, these renderers have only been developed for and tested in Webkit browsers, as proofs of concept. There is a lot of room for improvement and optimization. For example, it should be possible to extend these renderers to support Text directly, as well as providing mouse & possibly touch interaction for all surfaces. Most renderers (WebGL in particular) would also benefit from sprite sheet generation to reduce texture count, most likely via SpriteSheetBuilder.
+
+Current supported surfaces include:
+
+**Null renderer:**
+RendererNullMtx - no rendering. Useful for isolating calculation vs display costs.
+
+**Canvas 2D:**
+Renderer2DMtx - uses the EaselJS matrix class avoiding save & restore.
+Renderer2D - transformation based renderer using save & restore.
+
+**HTML DOM:**
+RendererDOMMtx - uses the EaselJS matrix, persistent DOM elements & document fragments.
+RendererDOMMtxStr - generates innerHTML on the surface div using matrix values.
+RendererDOMStr - generates innerHTML on the surface div using transforms.
+
+**SVG:**
+RendererSVGMtx - uses the EaselJS matrix, persistent SVG elements & document fragments.
+RendererSVGMtxStr - generates SVG strings using matrix values.
+RendererSVGStr - generates SVG strings using transforms.
+
+**WebGL:**
+RendererWebGL - sample WebGL renderer. Lots of room for optimizations.
+
+**Flash:**
+RendererSWF - very rough, outdated Flash renderer. Included for reference only.
+
+The renderers that are most stable, and would make the most sense to extend moving forward are: Renderer2DMtx, RendererDOMMtx, and RendererWebGL.
@@ -0,0 +1,189 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title>Pluggable Renderers</title>
+
+<style>
+ body {
+ background: #111;
+ color: #FFF;
+ font-family: Arial, sans-serif;
+ font-size: 14px;
+ }
+
+ .description {
+ background: #222;
+ padding: 5px;
+ }
+</style>
+
+<script>
+ // currently, the renderers don't work with the createjs namespace, so we'll bypass it.
+ var createjs = this;
+</script>
+<script src="../lib/easeljs-NEXT.min.js"></script>
+
+
+<script src="../src/renderers/Renderer.js"></script>
+<script src="../src/renderers/RendererNullMtx.js"></script>
+<script src="../src/renderers/Renderer2D.js"></script>
+<script src="../src/renderers/Renderer2DMtx.js"></script>
+<script src="../src/renderers/RendererDOMStr.js"></script>
+<script src="../src/renderers/RendererDOMMtxStr.js"></script>
+<script src="../src/renderers/RendererDOMMtx.js"></script>
+<script src="../src/renderers/RendererSVGMtxStr.js"></script>
+<script src="../src/renderers/RendererSVGStr.js"></script>
+<script src="../src/renderers/RendererSVGMtx.js"></script>
+<script src="../src/geom/glMatrix-0.9.5.min.js"></script>
+<script src="../src/renderers/RendererWebGL.js"></script>
+
+<script>
+var rendererName;
+var rendererClass;
+var rotate = true;
+var scale = true;
+var useAlpha = true;
+var numParticles = 1000;
+
+var renderer;
+var root;
+
+var img = new Image();
+var particleTemplate;
+var w=1000;
+var h=600;
+var fpsDiv;
+
+function init() {
+ rendererName = document.getElementById("renderer").value;
+ rendererClass = window[rendererName];
+
+ numParticles = parseInt(document.getElementById("numParticles").value);
+ rotate = !!document.getElementById("rotate").checked;
+ scale = !!document.getElementById("scale").checked;
+ useAlpha = !!document.getElementById("useAlpha").checked;
+
+ var target = document.getElementById("target");
+ fpsDiv = document.getElementById("fps");
+ fpsDiv.style.pixelWidth = w+"px";
+
+ root = new Container();
+ renderer = new rendererClass(root);
+ target.parentNode.replaceChild(renderer.getSurface(w,h),target);
+
+ img.onload = handleImageLoad;
+ img.src = "img/daisy.png";
+}
+
+function handleImageLoad() {
+
+ // this instance will be cloned as needed to create new particles.
+ particleTemplate = new Bitmap(img);
+ particleTemplate.regX = img.width>>1;
+ particleTemplate.regY = img.height>>1;
+
+ // start the tick and point it at the window so we can do some work before updating the stage:
+ Ticker.setFPS(100);
+ Ticker.addListener(window);
+}
+
+
+function tick() {
+ // loop through all of the active particles on stage:
+ var l = root.getNumChildren();
+ for (var i=l-1; i>=0; i--) {
+ var particle = root.getChildAt(i);
+
+ // apply gravity and friction
+ particle.vY += 2;
+ particle.vX *= 0.98;
+
+ // update position, scale, and alpha:
+ particle.x += particle.vX;
+ particle.y += particle.vY;
+
+ //remove particles that are off screen or not invisble
+ if (particle.alpha <= 0 || particle.y > h) {
+ root.removeChildAt(i);
+ l--;
+ }
+ }
+
+ if (l<numParticles) { addParticles(numParticles-l,w>>1,h, 60); }
+
+ document.getElementById("fps").innerText = rendererName + ": "+Math.round(Ticker.getMeasuredFPS())+" fps";
+
+ // draw the updates to stage
+ renderer.update();
+}
+
+function addParticles(count, x, y, speed) {
+ //create the specified number of particles
+ for (var i=0; i<count; i++) {
+ // clone the original particle, so we don't need to set shared properties:
+ var particle = particleTemplate.clone();
+
+ // set display properties:
+ particle.x = x;
+ particle.y = y;
+
+ if (rotate) { particle.rotation = Math.random()*360; }
+ if (scale) { particle.scaleX = particle.scaleY = Math.random()+0.5; }
+ if (useAlpha) { particle.alpha = Math.random()*0.8+0.2; }
+
+ // set up velocities:
+ var a = Math.PI/2*Math.random()-Math.PI*0.75;
+ var v = Math.random()*speed;
+ particle.vX = Math.cos(a)*v;
+ particle.vY = Math.sin(a)*v;
+
+ // add to the display list:
+ root.addChild(particle);
+ }
+}
+
+</script>
+</head>
+
+<body>
+ <div class="description">
+ <input type="button" value="reload" onclick="window.location.reload()"/>
+ |
+ <span id="fps">
+ <select id="renderer">
+ <option label="null renderer">RendererNullMtx</option>
+ <optgroup label="Context2D">
+ <option label="transforms">Renderer2D</option>
+ <option label="matrix">Renderer2DMtx</option>
+ </optgroup>
+ <optgroup label="HTML DOM">
+ <option label="string transforms">RendererDOMStr</option>
+ <option label="string matrix">RendererDOMMtxStr</option>
+ <option label="element matrix">RendererDOMMtx</option>
+ </optgroup>
+ <optgroup label="SVG">
+ <option label="string transforms">RendererSVGStr</option>
+ <option label="string matrix">RendererSVGMtxStr</option>
+ <option label="element matrix">RendererSVGMtx</option>
+ </optgroup>
+ <option label="WebGL">RendererWebGL</option>
+ </select>
+ Particles:
+ <input type="text" id="numParticles" value="1000" maxlength="5" size="4"/>
+ <input type="checkbox" id="useAlpha" checked="checked"/>
+ <label for="useAlpha">alpha</label>
+ <input type="checkbox" id="rotate"/>
+ <label for="rotate">rotate</label>
+ <input type="checkbox" id="scale"/>
+ <label for="scale">scale</label>
+
+
+ <input type="button" value="run" onclick="init()">
+ </span>
+ </div>
+ <div id="target">
+
+ </div>
+</body>
+</html>
Oops, something went wrong.

0 comments on commit 4d203e6

Please sign in to comment.