<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:posterous="http://posterous.com/help/rss/1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
  <channel>
    <title>XeoLabs</title>
    <link>http://blog.xeolabs.com</link>
    <description>3D software skunkworks </description>
    <generator>posterous.com</generator>
    <link xmlns="http://www.w3.org/2005/Atom" href="http://posterous.com/api/sup_update#650ff91fc" type="application/json" rel="http://api.friendfeed.com/2008/03#sup" />
    
    
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/XeolabsBlog" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="xeolabsblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://posterous.superfeedr.com/" /><item>
      <pubDate>Sat, 03 Dec 2011 12:59:00 -0800</pubDate>
      <title>Texture Atlases in SceneJS</title>
      <link>http://blog.xeolabs.com/83828150</link>
      <guid>http://blog.xeolabs.com/83828150</guid>
      <description>
        <![CDATA[<p>
	<p>A texture atlas is a large image that contains many sub-images, each of&nbsp;which is used as a <a href="https://github.com/xeolabs/scenejs/wiki/texture" target="_blank">texture</a> for a different <a href="https://github.com/xeolabs/scenejs/wiki/geometry" target="_blank">geometry</a>, or different parts of&nbsp;the same geometry. The sub-textures are applied by mapping the geometries&rsquo; texture coordinates (UV) to different regions of the atlas.</p>
<p>In a scene where there are many small textures, this has the benefit of reducing state changes on the graphics hardware by binding once, instead of for each individual texture. It also reduces the number of HTTP requests for texture image files.</p>
<p>SceneJS state-sorts its draw list by shader (which is normally auto-generated by SceneJS), then by texture, so as long as&nbsp;each of the geometry nodes within the texture's subtree inherit the same configuration of parent node&nbsp;states, and can therefore share the same shader, the draw list will bind&nbsp;the texture once for all the geometries.</p>
<ul>
<li>Read the <a href="http://en.wikipedia.org/wiki/Texture_atlas" target="_blank">Wikipedia page</a> on texture atlases</li>
<li>Learn more about texture atlases in this&nbsp;<a href="http://http.download.nvidia.com/developer/NVTextureSuite/Atlas_Tools/Texture_Atlas_Whitepaper.pdf|Texture Atlas Whitepaper" target="_blank">white paper</a>&nbsp;from nVIDIA.</li>
</ul>
<p><span style="font-size: large;">Example</span></p>
<p>To show how texture atlases are done in SceneJS, we'll define a texture containing two sub-textures that will be applied to two separate quads, as shown below. You can run the <a href="http://scenejs.org/dist/v2.0.0/extr/examples/texture-atlas/index.html" target="_blank">live example here</a>.</p>
<p><div class='p_embed p_image_embed'>
<img alt="Texture-atlas" height="385" src="http://getfile4.posterous.com/getfile/files.posterous.com/temp-2011-12-03/kvtaIslachoakhjufbjBpxlGjitBfzbwAEbfjGCoEabxtlahDzFlCfebzIrr/texture-atlas.jpg.scaled780.jpg" width="541" />
</div>
</p>
<p>Shown below is our atlas texture, texture-atlas.jpg. The guy on the left is <a href="http://en.wikipedia.org/wiki/General_Zod" target="_blank">General Zod</a>, from Superman:</p>
<p><div class='p_embed p_image_embed'>
<img alt="Texture-atlas-img" height="200" src="http://getfile8.posterous.com/getfile/files.posterous.com/temp-2011-12-03/bDogGAowdHqqAzFdHBfrjFJGJIBtArCEpsEwhFsnqwlCppxJgqFnvdaqquvv/texture-atlas-img.jpg.scaled780.jpg" width="392" />
</div>
</p>
<p>Now we'll define a fragment of scene graph. To start with, we have a <a href="https://github.com/xeolabs/scenejs/wiki/material" target="_blank">material</a> node, which wraps a <a href="https://github.com/xeolabs/scenejs/wiki/material" target="_blank">texture</a>, which is our atlas:</p>
<div class="CodeRay">
  <div class="code"><pre>{
    type: &quot;material&quot;,
    baseColor:      { r: 1.0, g: 1.0, b: 1.0 },
    specularColor:  { r: 1.0, g: 1.0, b: 1.0 },
    specular:       0.9,
    shine:          6.0,

    nodes: [


        /*------------------------------------------------------------------
         * Our texture atlas
         *
         * The atlas is the General Zod portrait and the brickwall pattern,
         * arranged side-by-side within the same image file.
         *-----------------------------------------------------------------*/

        {
            type: &quot;texture&quot;,

            layers: [
                {
                    uri:&quot;texture-atlas.jpg&quot;,
                    applyTo:&quot;baseColor&quot;,
                    blendMode: &quot;multiply&quot;
                }
            ],</pre></div>
</div>

<p>Next, we have a couple of <a href="https://github.com/xeolabs/scenejs/wiki/rotate" target="_blank">rotate</a> nodes, just to tilt our quads a little bit:</p>
<div class="CodeRay">
  <div class="code"><pre>nodes: [

                /*------------------------------------------------------------------
                 * Rotate our geometry a little bit to make it more interesting
                 *-----------------------------------------------------------------*/

                {
                    type: &quot;rotate&quot;,
                    angle: -30.0,
                    x : 1.0,

                    nodes: [
                        {
                            type: &quot;rotate&quot;,
                            angle: -30.0,
                            y : 1.0,</pre></div>
</div>

<p>Next, we have the quads themselves, arranged along the X-axis with a couple of <a href="https://github.com/xeolabs/scenejs/wiki/translate" target="_blank">translate</a> nodes. Although SceneJS has a special quad node, we'll manually define our quads in order to demonstrate how UV coordinates map to the textures. The first quad's UV coordinates map to the left half of the texture, to texture it with General Zod's image:</p>
<div class="CodeRay">
  <div class="code"><pre>nodes: [

                                /* General Zod
                                 */
                                {
                                    type: &quot;translate&quot;,

                                    x: 1.5,

                                    nodes: [
                                        {
                                            type: &quot;geometry&quot;,
                                            positions : [ 1, 1, 0, - 1, 1, 0, -1, -1, 0, 1, -1, 0],
                                            normals : [ 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 ],

                                            /* UV coords map to left half of texture image
                                             */
                                            uv : [ 1, 1, .5, 1, .5, 0, 1, 0 ],
                                            indices : [ 0, 1, 2,0, 2, 3]
                                        }
                                    ]
                                },</pre></div>
</div>

<p>The second quad's UV coordinates map to the right half of the texture, to texture it with the brick pattern:</p>
<div class="CodeRay">
  <div class="code"><pre>/* Brick wall
                                 */
                                {
                                    type: &quot;translate&quot;,

                                    x: -1.5,

                                    nodes: [
                                        {
                                            type: &quot;geometry&quot;,
                                            positions : [1, 1, 0, - 1, 1, 0, -1, -1, 0, 1, -1, 0 ],
                                            normals : [ 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1 ],

                                            /* UV coords map to right half of texture image
                                             */
                                            uv : [ .5, 1, 0, 1, 0, 0, .5, 0 ],
                                            indices : [ 0, 1, 2,0, 2, 3]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
}</pre></div>
</div>

<p>So there we have it - a useful technique to improve rendering speed by reducing WebGL state changes, while also reducing loading time by reducing the number of HTTP requests.</p>
<p>Note that we can have textures of various sizes in an atlas and use UV coordinates to scale them to fit the geometry vertices.&nbsp;</p>
<p><span style="font-size: medium;">Limitations</span></p>
<p>Take care if using mipmaps to arrange the textures so as to avoid sub-images being affected by their neighbours.</p>
<p>Note how SceneJS texture layers configure what geometry/material aspects their texture applies to (eg. "baseColor", "normals" etc). Therefore we can't currently have mixtures of those configurations within the same atlas, so we must have separate atlases for color-mapping, emission-mapping, normal mapping and so on.&nbsp;</p>
<p><span style="font-size: large;">Future Work</span></p>
<ul>
<li>It would be very cool to make a server-side utility in Python or Node.js to optimise a SceneJS JSON scene by by aggregating it's textures into atlases.&nbsp;</li>
</ul>
<ul>
</ul>
	
</p>

<p><a href="http://blog.xeolabs.com/83828150">Permalink</a> 

	| <a href="http://blog.xeolabs.com/83828150#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1733525/lk-bio-portrait-300x300.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/hgAOeTO2KzktI</posterous:profileUrl>
        <posterous:firstName>Lindsay</posterous:firstName>
        <posterous:lastName>Kay</posterous:lastName>
        <posterous:nickName>xeolabs</posterous:nickName>
        <posterous:displayName>Lindsay Kay</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Sun, 20 Nov 2011 08:23:00 -0800</pubDate>
      <title>Fast Ray Picking in SceneJS</title>
      <link>http://blog.xeolabs.com/ray-picking-in-scenejs</link>
      <guid>http://blog.xeolabs.com/ray-picking-in-scenejs</guid>
      <description>
        <![CDATA[<p>
	<p>SceneJS <strong>ray picking</strong> finds the logical&nbsp;<a href="https://github.com/xeolabs/scenejs/wiki/name" target="_blank">pick name</a> of the picked object, plus the point in world-space at which a ray cast from the eye position intersects with object's surface.&nbsp;It's ridiculously fast because the Z-coordinate is found with the help of the GPU, while the X and Y are found by unprojecting the canvas mouse coordinates.</p>
<p>Ray-pick can therefore be done almost as fast as a normal frame render and scales up to huge amounts of detail, with no ray intersection testing against millions of triangles using JavaScript math.</p>
<p>In the screenshot below, we're doing an instantaneous pick on a scene containing a very large number of triangles, fast enough for mouse-over picking. <a href="http://scenejs.org/dist/v2.0.0/extr/examples/ray-picking/index.html" target="_blank">Try the example live here</a>.</p>
<p><div class='p_embed p_image_embed'>
<img alt="Raypickhit" height="454" src="http://getfile9.posterous.com/getfile/files.posterous.com/temp-2011-11-20/mamAIdqqcmcCcusnBAckymEfamrxxGabfevCBlotqjnsuwzwuAFsrxlpkgdA/rayPickHit.jpg.scaled780.jpg" width="639" />
</div>
</p>
<p>&nbsp;</p>
<p><span style="font-size: x-large;">The Technique</span></p>
<p><a href="https://github.com/xeolabs/scenejs/wiki/name" target="_blank">As shown in the wiki</a>, a pickable scene contains <strong>name</strong> nodes that assign logical pick names collectively to the geometries within their subgraphs. Each name node has a "name" value, which multiple name nodes can share. In other words, we could have a house model with a name node around each window geometry, with each name having the value "window". Clicking on any window then picks "window".</p>
<p>The steps:</p>
<ol>
<li>User clicks canvas at coordinates (X, Y).&nbsp;</li>
<li>Do a render pass to a hidden frame buffer, in which the objects within each name node are are rendered in a colour that uniquely maps to node's "name" value (eg "window").</li>
<li>Read the colour from the framebuffer at the canvas coordinates, map the colour back to a name. Now we have the pick name.</li>
<li>Do a second render pass to another hidden frame buffer, this time rendering objects with each pixel colour being the clip-space Z-value packed into an RGBA value.</li>
<li>Read the colour from the framebuffer at the canvas coordinates and unpack it to the clip-space Z value. Now we have the clip-space Z, which will be in the range of [0..1], with near clip plane at 0 and far clip plane at 1.</li>
<li>Transform the canvas coordinates to clip-space. Make a ray from clip space (X,Y,0) to (X,Y,1) and transform that ray into world-space by the inverse view and projection matrices.</li>
<li>Linearly interpolate along ray by the value of our clip-space Z, to find the world-space coordinate (X,Y,Z).</li>
<li>Voila, we have the picked name, canvas (X,Y) and world-space (X,Y,Z) for the pick hit.</li>
</ol>
<p><strong>Packing clip-space Z in GLSL:</strong></p>
<div class="CodeRay">
  <div class="code"><pre>vec4 packDepth(const in float depth) {
     const vec4 bitShift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);
     const vec4 bitMask  = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);
     vec4 res = fract(depth * bitShift);
     res -= res.xxyz * bitMask;
     return res;
}</pre></div>
</div>

<p><strong>Unpacking clip-space Z in JavaScript:</strong></p>
<div class="CodeRay">
  <div class="code"><pre>function unpackDepth(depthZ) {
        var vec = [depthZ[0] / 256.0, depthZ[1] / 256.0, depthZ[2] / 256.0, depthZ[3] / 256.0];
        var bitShift = [1.0 / (256.0 * 256.0 * 256.0), 1.0 / (256.0 * 256.0), 1.0 / 256.0, 1.0];
        return SceneJS_math_dotVector4(vec, bitShift);
    };</pre></div>
</div>

<p><strong>Calculating clip-space Z in the fragment shader:</strong></p>
<p>Step (4) requires that we have the view-space position in the fragment shader, which we pass through from the vertex shader. It also requires us to feed the locations of the near and far clipping planes into the fragment shader (which we take from the scene's <a href="https://github.com/xeolabs/scenejs/wiki/camera" target="_blank">camera</a> node). Using these, we calculate the clip-space depth like so:</p>
<div class="CodeRay">
  <div class="code"><pre>float depth = (uZNear - vViewVertex.z) / (uZFar - uZNear);
gl_FragColor = packDepth(depth);</pre></div>
</div>

<p>&nbsp;</p>
<p><span style="font-size: x-large;">API</span></p>
<p>Through the API, the pick operation looks like this:</p>
<div class="CodeRay">
  <div class="code"><pre>var hit = scene.pick(45, 150, { rayPick: true });  // Picking at canvas coordinates

if (hit) {
    alert(&quot;Picked 'name' node(s) with name '&quot; + hit.name + 
             &quot;' at canvas coords &quot; + hit.canvasPos[0] + &quot;, &quot; + hit.canvasPos[1]
             &quot;' and world coords &quot; + hit.worldPos[0] + &quot;, &quot; + hit.worldPos[1] + &quot;, &quot; + hit.worldPos[2]);
} else {
    alert(&quot;Nothing picked&quot;);
}</pre></div>
</div>

<p>SceneJS internally caches the hidden frame buffers to avoid re-rendering them. This means that when we do a subsequent pick, as long as a re-render is not neccessary after objects have moved or changed appearance, we just re-read the buffers without repeating any rendering passes.</p>
<p>For picking, many WebGL frameworks will save time by doing a picking render of only a 1x1 viewport at the canvas coordinates. SceneJS renders the entire view for picking so that it can cache the pick framebuffers as just mentioned. This is an optimisation geared towards fast mouse-over picking effects in model viewing apps, such as highlighting and tooltips.</p>
<p>&nbsp;</p>
<p><span style="font-size: x-large;">Caveats</span></p>
<p>The technique described here trades accuracy for speed. Packing and unpacking the clip-space Z to and from a colour value is lossy. Hopefully in future it will be possible to instead read the WebGL depth buffer, which will preserve much more precision.</p>
<p>Another limitation is that this technique does not find any topological information on the pick hit: it only finds the name and a world-space coordinate. When picking a mesh for example, it does not report the actual face that was picked.</p>
	
</p>

<p><a href="http://blog.xeolabs.com/ray-picking-in-scenejs">Permalink</a> 

	| <a href="http://blog.xeolabs.com/ray-picking-in-scenejs#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1733525/lk-bio-portrait-300x300.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/hgAOeTO2KzktI</posterous:profileUrl>
        <posterous:firstName>Lindsay</posterous:firstName>
        <posterous:lastName>Kay</posterous:lastName>
        <posterous:nickName>xeolabs</posterous:nickName>
        <posterous:displayName>Lindsay Kay</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Sat, 19 Nov 2011 05:54:00 -0800</pubDate>
      <title>SceneJS in the Wild: BIMSurfer</title>
      <link>http://blog.xeolabs.com/scenejs-in-the-wild-bimsurfer-44057</link>
      <guid>http://blog.xeolabs.com/scenejs-in-the-wild-bimsurfer-44057</guid>
      <description>
        <![CDATA[<p>
	<div style="margin: 8px;">
<p>Last week saw the public beta release of <a href="http://bimsurfer.org" target="_blank">BIMSurfer</a>, an open-source &nbsp;Web-based <a href="http://bimserver.org" target="_blank">BIMServer</a>&nbsp;front-end&nbsp;which was created by <a href="https://github.com/rehno-lindeque" target="_blank">Rehno Lindeque</a>&nbsp;and uses&nbsp;<a href="http://scenejs.org" target="_blank">SceneJS</a> as the rendering engine.&nbsp;</p>
<p><a href="http://en.wikipedia.org/wiki/Building_information_modeling" target="_blank">Building Information Modelling</a> (BIM) is the process of generating and managing building data during its lifecycle; BIMServer is the server that manages and queries that data, while BIMSurfer is a viewer that displays and interacts with it.</p>
<p><div class='p_embed p_image_embed'>
<img alt="Bimsurfer" height="181" src="http://getfile1.posterous.com/getfile/files.posterous.com/temp-2011-11-19/EfrcdjdmtkFHeJwhnqbmcAyviekDAhFjqvHFwimJbzzbtBwaqjlEgrufcpJE/BIMSurfer.png.scaled780.png" width="300" />
</div>
</p>
<p>BIMServer is an open source project that tracks data on every part of a building under development:&nbsp;<span style="font-family: sans-serif; line-height: 19px;">geometry, spatial relationships, light analysis, geographic information</span>&nbsp;- whatever is useful, while supporting queries on the data. It also functions as a sort of version control system, allowing multiple users to collaborate on the model, while continually updating the overall data, sending notifications, preventing modification conflicts and so on.</p>
<p>One interesting feature is that, along with&nbsp;<a href="http://en.wikipedia.org/wiki/Industry_Foundation_Classes" target="_blank">IFC</a>&nbsp;models,&nbsp;BIMSurfer is able to import and export them as SceneJS JSON, which means they could be rendered using straight SceneJS. Another cool feature is the ability to author fly-throughs by creating a sequence of snapshots.</p>
<div class='p_embed p_image_embed'>
<img alt="Bimsurfer2" height="529" src="http://getfile0.posterous.com/getfile/files.posterous.com/temp-2011-11-19/nkFxgjJllwlgcqBkcqgEwfuHqqmErIDjkutetlqDbnJgmtvkcfhiHjeFsicf/bimsurfer2.jpg.scaled780.jpg" width="700" />
</div>
</div>
<div>
<p>As mentioned, BIMSurfer is an open-source project which welcomes developer contributions and funding. All source code is <a href="https://github.com/bimserver/BIMsurfer" target="_blank">forkable at GitHub</a> - more info may be found on the <a href="http://bimsurfer.org" target="_blank">project website</a>.</p>
<p>SceneJS seems to fit BIMSurfer requirements well: large numbers of objects kept in the scene core, individually isolatable, pickable and highlightable. As the scale of building models increases, we look forward seeing SceneJS performance scale up accordingly to maintain an acceptable FPS. The transparent windows are also rendering in correct order for alpha blending, so the SceneJS render layer feature appears to be working well there.</p>
<p>Keep your eye on this project - BIM is hot stuff right now, valuable technology both economically and ecologically since it focuses on the efficient use of energy and materials, with minimal waste.</p>
</div>
<p>&nbsp;</p>
	
</p>

<p><a href="http://blog.xeolabs.com/scenejs-in-the-wild-bimsurfer-44057">Permalink</a> 

	| <a href="http://blog.xeolabs.com/scenejs-in-the-wild-bimsurfer-44057#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1733525/lk-bio-portrait-300x300.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/hgAOeTO2KzktI</posterous:profileUrl>
        <posterous:firstName>Lindsay</posterous:firstName>
        <posterous:lastName>Kay</posterous:lastName>
        <posterous:nickName>xeolabs</posterous:nickName>
        <posterous:displayName>Lindsay Kay</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Fri, 18 Nov 2011 14:49:00 -0800</pubDate>
      <title>Loading and Unloading SceneJS Content</title>
      <link>http://blog.xeolabs.com/80736697</link>
      <guid>http://blog.xeolabs.com/80736697</guid>
      <description>
        <![CDATA[<p>
	<p>Today a SceneJS user asked the mailing list how content can be pulled into a scene graph on-demand, for an application in which the user browses a map view that loads and displays geometry, material and texture assets as they fall into view.&nbsp;</p>
<p><span style="font-size: large;">Early SceneJS: The "instance" Node</span></p>
<p>Old versions of SceneJS had the <a href="http://scenejs.wikispaces.com/instance" target="_blank">instance node</a>, which instantiated a target subgraph as a child. Really early versions of that were even able to pull the JSON for the target from disk and into the scene graph, on demand. The instance node was however removed in V2.0 because its implementation was so complicated, with the multiple parent paths it would create making engine optimisations impractical. It was replaced by <a href="https://github.com/xeolabs/scenejs/wiki/Node-Cores" target="_blank">shareable node cores</a>&nbsp;in V2.0.</p>
<p><span style="font-size: large;">Latest SceneJS: Staging In-Core</span></p>
<p>On-demand loading of geometries can be done with a <a href="https://github.com/xeolabs/scenejs/wiki/GeoLoader-Service" target="_blank">GeoLoaderService</a>&nbsp;(the SceneJS plugin interface for custom mesh loading strategies), but there's nothing in V2.0 that loads whole subgraphs&nbsp;on demand, the way the instance node did.</p>
<p>Aside from implimentation simplicity, the reason is that SceneJS encourages staging content in-core. This means staging content in the scene graph, setting "enabled" flags false to cull it from the view until you want to render it,</p>
<p>For example:</p>
<div class="CodeRay">
  <div class="code"><pre>{     
    type: &quot;flags&quot;,     
    id: &quot;my-teapot-content&quot;,     
    flags: { enabled: false },     
    nodes: [         
        { type: &quot;teapot&quot; }     
    ]
}

myScene.findNode(&quot;my-teapot-content&quot;).set(&quot;flags&quot;, { enabled: true });</pre></div>
</div>

<p>Geometries, textures and shaders will be allocated on the GPU as the nodes are created in the scene graph. They will be bound on the GPU for rendering only when the geometries that use them are enabled.</p>
<p>You can stage as much content in your scene graph as your GPU has memory for, which these days is often as much as 1-2GB.</p>
<p>Internally, SceneJS optimises for in-core staging by maintaining a "visible list" that caches enabled (ie. visible) objects. Enabling an object causes the main draw list to be iterated on the next frame while saving the enabled objects into the visible list, which will then be the list that's iterated for each subsequent frame as long as more objects are not enabled. Then as objects are disabled, they are just plucked out of the visible list.</p>
<p><span style="font-size: large;">Creating and destroying Nodes</span></p>
<p>If your scene is too big to stage everything in the scene graph, then out-of-core content needs to swapped in and out by creating and destroying nodes:</p>
<div class="CodeRay">
  <div class="code"><pre>myScene.findNode(&quot;some-node&quot;).add(&quot;node&quot;, { type: &quot;teapot&quot;, id: &quot;my-teapot&quot; });
myScene.findNode(&quot;my-teapot&quot;).destroy();</pre></div>
</div>

<p>Bear in mind that adding and destroying nodes cause scene-to-draw list recompilation (an internal optimisation) each time, so these add/destroys are best done in batches, and will cause a moment's delay when they happen.</p>
<p>If you're adding large numbers of nodes, you may want to pause the render loop on the scene graph while loading, just to ensure that the render interval doesn't keep kicking in and recompiling the draw list while you're still in the process of adding them:</p>
<div class="CodeRay">
  <div class="code"><pre>myScene.stop();

// ..add many nodes..

myScene.start({
    // ...
});</pre></div>
</div>

<p>So you can see how it's up to your application code to do this swapping, possibly under the direction of some sort of bounding volume visibility system.&nbsp;</p>
<p>How to do this? In BioDigital Human we have our own application logic for swapping nodes and out of the scene, but that's driven by the user explicitly selecting what anatomy and conditions they want to view (Eg. switching gender, loading a beating heart etc).</p>
<p>A view-driven solution is a different kettle of fish. Way back in early SceneJS versions (around V0.7) I had "spheres of locality" centered about the viewpoint: a large outer sphere of say, 100000 units containing an inner sphere of 10000 units. The scene graph could have bounding volumes nodes which enclosed subgraphs: these nodes would load their subgraph when they intersected the inner boundary, then unload it as soon as they fell outside the outer boundary. SceneJS also performed frustum culling with the bounding volumes, enabling (making visible) the subgraphs whenever they intersected the view frustum.</p>
<p>All this was chopped out of V0.8 onwards to keep the engine lean and fast. As long as you are able to track the boundaries of things in application code, you should be able to implement this in third-party code using libraries like <a href="https://github.com/imbcmdth/jsBVH" target="_blank">jsBVH</a>.&nbsp;</p>
<p>To be continued..</p>
<p>&nbsp;</p>
<p><div class='p_embed p_image_embed'>
<img alt="Objectswap" height="179" src="http://getfile4.posterous.com/getfile/files.posterous.com/temp-2011-11-18/arBHCtlDJrIanikAtzbgjzyamvdwnnrghqozCHFChJEwFAGDdqyerDfrFmoh/objectswap.jpg.scaled780.jpg" width="250" />
</div>
</p>
<p />
<p>&nbsp;</p>
<p>&nbsp;</p>
	
</p>

<p><a href="http://blog.xeolabs.com/80736697">Permalink</a> 

	| <a href="http://blog.xeolabs.com/80736697#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1733525/lk-bio-portrait-300x300.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/hgAOeTO2KzktI</posterous:profileUrl>
        <posterous:firstName>Lindsay</posterous:firstName>
        <posterous:lastName>Kay</posterous:lastName>
        <posterous:nickName>xeolabs</posterous:nickName>
        <posterous:displayName>Lindsay Kay</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Wed, 16 Nov 2011 05:45:00 -0800</pubDate>
      <title>SceneJS 2.0 in OpenGL Insights 2012</title>
      <link>http://blog.xeolabs.com/scenejs-20-in-opengl-insights-2012</link>
      <guid>http://blog.xeolabs.com/scenejs-20-in-opengl-insights-2012</guid>
      <description>
        <![CDATA[<p>
	<p>I've written a <a href="http://scenejs.org/media/OpenGLInsightsSceneJSArticleProposal.pdf" target="_blank">chapter on SceneJS</a> for <a href="http://www.openglinsights.com/" target="_blank">OpenGL Insights</a>, a book on OpenGL and WebGL techniques which will be published in time for <a href="http://www.siggraph.org/" target="_blank">SIGGRAPH</a> 2012. My focus is on the caching strategies and optimisations used to reduce JavaScript re-execution per frame, which may be relevant to others considering writing their own WebGL frameworks.</p>
<p>The book is shaping up to be seriously awesome, with quality chapters ranging from <a href="http://spidergl.org" target="_blank">SpiderGL</a> to efficient text in WebGL, plus many chapters on OpenGL ES techniques.</p>
<p>&nbsp;</p>
<p><div class='p_embed p_image_embed'>
<img alt="Books" height="113" src="http://getfile7.posterous.com/getfile/files.posterous.com/temp-2011-11-16/itiFfywikImpnHDvrnuqrHlgymkbbAuDzhAzioIfyCaagjAJDeyEupFxoqzj/books.jpeg.scaled780.jpg" width="220" />
</div>
</p>
	
</p>

<p><a href="http://blog.xeolabs.com/scenejs-20-in-opengl-insights-2012">Permalink</a> 

	| <a href="http://blog.xeolabs.com/scenejs-20-in-opengl-insights-2012#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1733525/lk-bio-portrait-300x300.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/hgAOeTO2KzktI</posterous:profileUrl>
        <posterous:firstName>Lindsay</posterous:firstName>
        <posterous:lastName>Kay</posterous:lastName>
        <posterous:nickName>xeolabs</posterous:nickName>
        <posterous:displayName>Lindsay Kay</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Sun, 13 Nov 2011 18:25:00 -0800</pubDate>
      <title>SceneJS 2.0 Release</title>
      <link>http://blog.xeolabs.com/scenejs-20-release</link>
      <guid>http://blog.xeolabs.com/scenejs-20-release</guid>
      <description>
        <![CDATA[<p>
	<p>The <a href="http://scenejs.org/releases.html" target="_blank">SceneJS 2.0 release</a> is finally out the door, focusing on high rendering speed for complex scenes containing many individually articulated and pickable objects, which is characteristic of model viewing applications for engineering, architecture and medical visualisation.</p>
<p>While most WebGL frameworks support multi-pass effects such as shadows and reflections, SceneJS 2.0 has evolved to specialise in optimised single-pass rendering of large amounts of detail.&nbsp;That's not to say, however, that we can't create some catchy effects using some of its new features, as shown in the <a href="http://scenejs.org/dist/v2.0.0/extr/examples/index.html">live examples</a>.</p>
<p><div class='p_embed p_image_embed'>
<a href="http://getfile6.posterous.com/getfile/files.posterous.com/temp-2011-11-13/pDacpnktbowqspmCzbsGDIaDonAovsuqbhqohGrleefrHAdfFprJtvcpnrii/human-xray.jpg.scaled1000.jpg"><img alt="Human-xray" height="556" src="http://getfile0.posterous.com/getfile/files.posterous.com/temp-2011-11-13/pDacpnktbowqspmCzbsGDIaDonAovsuqbhqohGrleefrHAdfFprJtvcpnrii/human-xray.jpg.scaled780.jpg" width="780" /></a>
</div>
</p>
<p style="text-align: center;"><em><span style="font-size: small;">BioDigital Human (in development), with 1886&nbsp;meshes and 126 textures visible,&nbsp;rendering at around 13-15 FPS in Chrome 14.0.835.202 on an i7 CPU and an NVIDIAGeForce GTX 260M GPU</span></em></p>
<p>&nbsp;</p>
<p><span style="font-size: x-large;">What's New</span></p>
<p><span style="font-size: medium;">New Wiki at GitHub</span></p>
<p>V2.0 has a <a href="https://github.com/xeolabs/scenejs/wiki" target="_blank">new wiki over at GitHub</a>, which I'm still in the process of building up. We'll keep the <a href="http://scenejs.wikispaces.com/Wiki+Home" target="_blank">old V0.9 wiki</a> around for a few more months to help people port to the new SceneJS release, then we'll archive it and make it available for download.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">Custom Shaders</span></p>
<p>SceneJS normally generates shaders for us, but when special effects are required we can now inject custom functions into them to intercept and modify colours, matrices, coordinates etc, all parameterised via the JSON API.&nbsp;</p>
<p>With custom shaders, we can intercept coordinate positions to do things like displace them for <a href="http://scenejs.org/dist/v2.0.0/extr/examples/custom-shaders-vertex-displacement/index.html" target="_blank">wobbling effects</a>, or discard fragments for <a href="http://scenejs.org/dist/v2.0.0/extr/examples/custom-shaders-clipping/index.html" target="_blank">clipping effects</a>.</p>
<p>In the <a href="http://scenejs.org/dist/v2.0.0/extr/examples/custom-shaders-fog/index.html" target="_blank">fog shader</a>&nbsp;example, we intercept the view-space position and fragment colour in the fragment shader, then fog the colour in proportion to the coordinate Z-depth.</p>
<p>The <a href="http://scenejs.org/dist/v2.0.0/extr/examples/custom-shaders-transparency/index.html" target="_blank">fancy transparency</a>&nbsp;example creates the glass effect shown in the snapshot above by intercepting the view-space normal and fragment colour, then setting the colour's alpha to a value that is proportional to how directly the normal faces the view point.</p>
<p>We can also modify matrices, like in the <a href="http://scenejs.org/dist/v2.0.0/extr/examples/custom-shaders-sky-sphere/index.html" target="_blank">sky sphere shader</a> example, in which we zero out the translation elements to keep the sky sphere centered at the viewpoint.</p>
<p>The <a href="http://scenejs.org/dist/v2.0.0/extr/examples/tron-tank/index.html" target="_blank">Tron Tank program</a> even got a custom shader - note the blurred horizon line.</p>
<p>The colorTrans node from SceneJS V0.9 has been deprecated, since we can now do the same effect with something like this <a href="http://scenejs.org/dist/v2.0.0/extr/examples/custom-shaders-clipping/index.html" target="_blank">pixel colour shader</a>.</p>
<p>Read more in the&nbsp;<a href="https://github.com/xeolabs/scenejs/wiki/shader" target="_blank">wiki page on shaders</a>.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">More Scene Graph Compilation&nbsp;</span></p>
<p>SceneJS dynamically (re)compiles the scene graph to a draw list of optimised WebGL state changes, which in V2.0 is now further (re)compiled to a list of fast WebGL calls. SceneJS caches these lists to minimise JavaScript re-execution per frame, rebuilding only the affected portions of them whenever scene state updates occur.</p>
<p>The WebGL calls are higher order functions which memoize things like shader variable locations in closures. After adding this, I observed a ~30-40% speedup for some applications - expect the next version of BioDigital Human to be noticeable faster.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">Shared Node Cores</span></p>
<ul>
</ul>
<p>Traditionally, re-use within a scene graph is done by attaching nodes to&nbsp;multiple parents. For dynamically updated scenes this can have a performance impact when the engine must traverse multiple parent paths in the&nbsp;scene graph, so SceneJS now takes an alternative approach with &rdquo;node cores&rdquo;,&nbsp;<a href="http://www.opensg.org/htdocs/doc-1.8/PageSystemNodesNCores.html" target="_blank">a concept borrowed from OpenSG</a>.</p>
<p>Shared node cores replace the&nbsp;<em>instance</em>&nbsp;nodes found in earlier versions of SceneJS.</p>
<p>A node core is the scene node&rsquo;s state. Having multiple nodes share a core&nbsp;means that they share the same state. This can have two significant performance&nbsp;benefits: an update to a shared node core can write through to multiple draw list elements simultaneously, and there is increased chance of runs of same state objects in the draw list after state sorting, which SceneJS capitalises on by avoiding repeated execution of them.</p>
<p>Many of the examples (such as the custom shaders) demonstrate shared node cores. Read more on the&nbsp;<a href="https://github.com/xeolabs/scenejs/wiki/Node-Cores" target="_blank">wiki page on node cores</a>&nbsp;or check out this rather <a href="http://scenejs.org/dist/v2.0.0/extr/examples/node-cores/index.html" target="_blank">plain example</a>.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">Video Textures</span></p>
<p>Movie files can be applied as textures - useful for complex animated textures, animated bump maps, moving backgrounds etc. Read the <a href="https://github.com/xeolabs/scenejs/wiki/Video" target="_blank">wiki page on video textures</a>&nbsp;or try this&nbsp;<a href="http://www.scenejs.org/dist/v2.0.0/extr/examples/video-texture/index.html" target="_blank">this example.</a></p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">Multiple Scenes</span></p>
<p><strong>&nbsp;</strong>Multiple scene graphs can now be created within the same JavaScript runtime environment, allowing us to update them concurrently and share JSON content between them. Here's a&nbsp;<a href="http://www.scenejs.org/dist/v2.0.0/extr/examples/multi-scene/index.html" target="_blank">multi-scene example</a>.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">Mutable Geometry</span></p>
<p>Geometry VBOs and IBOs can now be dynamically updated.&nbsp;Try this&nbsp;<a href="http://www.scenejs.org/dist/v2.0.0/extr/examples/mutable-geometry/index.html">very plain example</a>.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">Ray Picking</span></p>
<p>SceneJS&nbsp;ray picking&nbsp;finds the logical&nbsp;<a href="https://github.com/xeolabs/scenejs/wiki/name" target="_blank">pick name</a>&nbsp;of the picked object, plus the point in world-space at which a ray cast from the eye position intersects with object's surface.&nbsp;It's ridiculously fast because the Z-coordinate is found with the help of the GPU, while the X &amp; Y are found by unprojecting the canvas mouse coordinates.</p>
<p>Ray-pick can therefore be done almost as fast as a normal frame render and scales up to large amounts of detail, with no ray intersection testing against millions of triangles using JavaScript math. Read the <a href="http://blog.xeolabs.com/ray-picking-in-scenejs" target="_blank">blog post</a> or try out the ray <a href="http://scenejs.org/dist/v2.0.0/extr/examples/ray-picking/index.html" target="_blank">pick example</a>.</p>
<p>&nbsp;</p>
<p><span style="font-size: medium;">Picking Changes&nbsp;</span></p>
<p>Subgraphs are now wrapped in <em>name</em> nodes which assign geometries to logical pick names. Pick listeners are no longer bound to nodes. Instead a pick operation is made on the scene, which returns a name if a hit occurs.&nbsp;Read more in the&nbsp;<a href="https://github.com/xeolabs/scenejs/wiki/name" target="_blank">wiki page on name nodes</a>&nbsp;or check out the <a href="http://www.scenejs.org/dist/v2.0.0/extr/examples/basic-picking/index.html" target="_blank">basic picking example</a>.</p>
<p>&nbsp;</p>
<ul>
</ul>
<p><span style="font-size: medium;">Simpler Node State Inheritance&nbsp;</span></p>
<p>Many scene nodes (such as <em>material</em>, <em>flags</em>&nbsp;and <em>texture</em>) now completely override state defined by parents instead of augmenting it. This simplifies reprocessing of the scene graph after updates, giving a huge speed increase. I'll highlight this more in the wiki.</p>
<ul>
</ul>
<ul>
</ul>
<ul>
</ul>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p />
<p>&nbsp;</p>
	
</p>

<p><a href="http://blog.xeolabs.com/scenejs-20-release">Permalink</a> 

	| <a href="http://blog.xeolabs.com/scenejs-20-release#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1733525/lk-bio-portrait-300x300.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/hgAOeTO2KzktI</posterous:profileUrl>
        <posterous:firstName>Lindsay</posterous:firstName>
        <posterous:lastName>Kay</posterous:lastName>
        <posterous:nickName>xeolabs</posterous:nickName>
        <posterous:displayName>Lindsay Kay</posterous:displayName>
      </posterous:author>
    </item>
    <item>
      <pubDate>Sun, 13 Nov 2011 12:15:00 -0800</pubDate>
      <title>Caching WebGL Calls in SceneJS 2.0</title>
      <link>http://blog.xeolabs.com/caching-webgl-calls-in-scenejs-20</link>
      <guid>http://blog.xeolabs.com/caching-webgl-calls-in-scenejs-20</guid>
      <description>
        <![CDATA[<p>
	<p><span style="font-family: lucida grande, tahoma, verdana, arial, sans-serif; line-height: 14px; text-align: left; font-size: small;"><a href="http://blog.xeolabs.com/scenejs-20-release">SceneJS 2.0</a> does a ton of caching to efficiently adapt its abstract JSON-based scene graph API to WebGL.&nbsp;</span></p>
<p><span style="font-family: lucida grande, tahoma, verdana, arial, sans-serif; line-height: 14px; text-align: left; font-size: small;">I just added another layer of caching, which turned out to give a major performance boost - anyone who's not getting high enough FPS should try the <a href="http://scenejs.org/dist/v2.0.0/scenejs-2.0.0.0.zip">latest build</a> and see if it improves things.</span></p>
<p><span style="font-size: small;"><span style="font-family: lucida grande, tahoma, verdana, arial, sans-serif; line-height: 14px; text-align: left;">The engine now compiles its internal draw list to a cached list of WebGL function calls, which execute very quickly. The calls are generated by higher-order functions, which cache parameters for the calls in their closures, such as variable locations in programs etc. A classic JavaScript optimisation strategy.</span><span style="font-family: lucida grande, tahoma, verdana, arial, sans-serif; line-height: 14px; text-align: left;">&nbsp;</span></span></p>
<ol>
<li><span style="font-size: small;"><span style="font-family: Helvetica, Arial, sans-serif;"><span style="line-height: 16px;"><strong>Scene definition</strong> - a JSON definition is parsed&nbsp;</span></span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">to create a scene graph with resources buffered for its&nbsp;</span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">nodes on the GPU (VBOs, textures etc).&nbsp;</span></span></li>
<li><span style="font-size: small;"><span style="font-family: Helvetica, Arial, sans-serif;"><span style="line-height: 16px;"><strong>Draw list compilation</strong> - the scene graph is traversed to compile a&nbsp;</span></span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">sequence of WebGL state changes.</span></span></li>
<li><span style="font-size: small;"><span style="font-family: Helvetica, Arial, sans-serif;"><span style="line-height: 16px;"><strong>Call list compilation</strong> - the draw list is compiled into a fast list of W</span></span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">ebGL calls with arguments prepared from the draw list states. C</span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">all list nodes are functions that wrap WebGL&nbsp;</span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">calls, and are created by higher-order functions which prepare and&nbsp;</span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">memoize their arguments in closures.</span></span></li>
<li><span style="font-size: small;"><span style="font-family: Helvetica, Arial, sans-serif;"><span style="line-height: 16px;"><strong>State sorting</strong> - the call list nodes are sorted on their corresponding&nbsp;</span></span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">draw list states to minimize the number of state changes that will&nbsp;</span><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif;">go down the OpenGL pipeline.</span></span></li>
<li><span style="line-height: 16px; font-family: Helvetica, Arial, sans-serif; font-size: small;">The call list is executed to render the frame.</span></li>
</ol>
<p>&nbsp;</p>
<p><span style="font-size: x-small;"><span style="font-family: Helvetica, Arial, sans-serif; line-height: 16px;"> </span></span></p>
<p><div class='p_embed p_image_embed'>
<img alt="House-smaller" height="263" src="http://getfile5.posterous.com/getfile/files.posterous.com/temp-2011-11-16/loywoHxBhapGsEIseHnzjksAkohCqAvtjifHrpoaiFffFerllymAsqBnnIhf/house-smaller.jpg.scaled780.jpg" width="400" />
</div>
</p>

	
</p>

<p><a href="http://blog.xeolabs.com/caching-webgl-calls-in-scenejs-20">Permalink</a> 

	| <a href="http://blog.xeolabs.com/caching-webgl-calls-in-scenejs-20#comment">Leave a comment&nbsp;&nbsp;&raquo;</a>

</p>]]>
      </description>
      <posterous:author>
        <posterous:userImage>http://files.posterous.com/user_profile_pics/1733525/lk-bio-portrait-300x300.JPG</posterous:userImage>
        <posterous:profileUrl>http://posterous.com/users/hgAOeTO2KzktI</posterous:profileUrl>
        <posterous:firstName>Lindsay</posterous:firstName>
        <posterous:lastName>Kay</posterous:lastName>
        <posterous:nickName>xeolabs</posterous:nickName>
        <posterous:displayName>Lindsay Kay</posterous:displayName>
      </posterous:author>
    </item>
  </channel>
</rss>

