Google Code offered in: English - Español - 日本語 - 한국어 - Português - Pусский - 中文(简体) - 中文(繁體)
The O3D Technical Overview describes the basic components of the transform graph, the render graph, and the shaders. This chapter goes into more detail on how a typical render graph is created, what happens when a view is rendered, and some of the varied ways you could use this flexible system.
One of the many ways you can use the O3D transform graph and render graph is to specify one transform graph, which contains the 3D scene, and then specify multiple sub-trees within the render graph that display this same scene in different ways using different viewport settings. The Viewport object specifies which portion of the screen to affect. The Creating Multiple Views sample sets up three sub-trees within the render graph that display the same transform graph from different viewpoints and with a different background color. Each part of the render graph draws the scene with a different viewport setting using a different DrawContext:

See Example: Multiple Views for more details on creating multiple views of the same scene.
You can also build multiple transform graphs that are rendered into the same viewport. The Creating a Heads-Up Display example demonstrates using a render graph with two sub-trees, each specifying a different view, to display different branches of the transform graph. One ViewInfo object is used to display the branch of the transform graph that contains the 3D view, and a second ViewInfo object is used to display the branch of the transform graph with the heads-up display (HUD). The view for the HUD has a higher priority than the view for the 3D objects, so the HUD view is drawn after (that is, on top of) the 3D view. The HUD view also has a ClearBuffer node that specifies to clear only the depth and stencil buffers—but not the color buffer—before rendering the HUD.

See Example: Multiple Scenes for more details.
The o3djs.renderGraph utility contains code for the createBasicView() function, which creates a general-purpose render graph sub-tree that contains the nodes commonly required to render a scene into a viewport. This section explains the arguments to this utility function, which is used in many of the sample programs. Once you understand how it works, you can customize it to suit your needs.
The following table describes the arguments to createBasicView():
| Function Arguments | Type | Description |
|---|---|---|
| pack | Pack |
Pack to manage the objects that are created |
| treeRoot | Transform |
Root transform of the transform graph to be rendered |
| opt_parent | RenderNode |
Parent node for the render graph that is being created |
| opt_clearColor | Float4 or Array of 4 numbers |
Color to clear the view |
| opt_priority | number | Optional base priority for drawing this set of objects |
| opt_viewport | Float4 or Array of 4 numbers |
Area of the viewport where this scene is to be rendered (see Viewport) |
The createBasicView() function returns a ViewInfo object that contains references to a group of O3D objects used to render a single 3D view. Here is what this render graph looks like:

The following paragraphs describe the nodes in the render graph in more detail. The render graph, like the transform graph, is traversed from top to bottom, and then by priority of the render nodes. The system walks the nodes in the render graph each time the screen is refreshed.
Many of the examples have an onRender() function that performs certain operations on the transform graph and render graph. In this case, the onRender() function is called each time before the render graph is traversed.
A Viewport sets the rectangular area on the screen where the scene is rendered. The viewport coordinates range from (0,0) in the top left corner of the screen to (1,1) in the bottom right corner. To render a scene into a smaller portion of the screen, pass in the coordinates to the opt_viewport argumentof createBasicView(). If you're creating the render graph manually, create a Viewport object with the desired coordinates.

The ClearBuffer node is a RenderNode that clears the color buffer, z buffer and/or stencil buffer of the current render target. The default specifies to clear all three buffers before rendering.
The TreeTraversal node causes a complete traversal of the transform graph, beginning with the specified root transform. This node has multiple DrawList objects registered with it. Each DrawList, in turn, has a DrawContext registered with it (see diagram of render graph and next section). As the TreeTraversal node walks the transform tree, whenever it finds a draw element with a material that matches one of its registered DrawLists, the TreeTraversal node adds that draw element to the DrawList. For example, the render graph created by createBasicView() has two draw lists: a performance draw list (draws opaque objects) and a z-ordered draw list (draws transparent objects). Draw elements with materials that are assigned to the performance draw list are added to the performance draw list at traversal time. Similarly, draw elements with materials that are assigned to the z-ordered draw list are added to the z-ordered draw list at traversal time.
While the TreeTraversal walks the transform graph, it can optionally cull transforms, primitives, draw elements, and even whole sub-trees of the transform graph. In order to be culled (that is, trimmed), an object must have its culling attribute set to TRUE (default is FALSE) and its boundBox must be set to something that matches how you want it culled.
Each view references a DrawContext object. The createBasicView() function creates a DrawContext object automatically for its view. Each DrawPass object contains a pointer to a DrawContext. The DrawContext uses two matrices to specify how the objects in the scene are viewed:
After walking the transform graph, O3D returns to the next node in the render graph, the StateSet element for the performance DrawPass. The StateSet node for the performance draw pass sets no states by default but could be used to set some nondefault behavior—for example to make objects render double-sided. The next node in the traversal is the DrawPass node, which references the DrawContext that sets up the viewing parameters. After that, O3D draws each of the draw elements in the performance draw list.
After rendering the draw elements in the performance draw list, the system traverses the second StateSet element, which specifies state for the z-ordered (transparency) DrawPass. The 2D view in the Creating a Heads-Up Display sample uses the StateSet node to turn off culling, so that objects flipped horizontally or vertically will still be drawn. It also turns off z-buffering, so that objects further back will be drawn on top of objects in front, even if the objects in front are drawn first. After traversing the StateSet node, O3D traverses the DrawPass node, which references the DrawContext that sets up the viewing parameters. Finally, O3D draws each of the draw elements in the z-ordered draw list.
In the Creating Multiple Views sample, the left viewport takes up the left half of the screen and is specified with the array [0, 0, 0.5, 1], where 0,0 are the screen coordinates for the top left corner of this viewport, .5 is the portion of the screen width used by this viewport and 1 is the portion of the screen height used by this viewport. The draw context in this render graph specifies a perspective projection.
This example uses the o3djs.renderGraph.createExtraView() utility to specify the size, background color, and priority for the two views on the right side of the screen:
for (var yy = 0; yy < 2; yy++) {
// Set the view extents to the right half, top or bottom.
var viewExtents = [0.5, yy * 0.5, 0.5, 0.5];
// Give each view a different background color.
var viewBackgroundColor = [0.5, 0.2 + 0.5 * yy, 0.7 - 0.5 * yy, 1.0];
// Make this view get processes after the first view.
var viewPriority = yy + 1;
var viewInfo = o3djs.renderGraph.createExtraView(
g_viewInfos[0],
viewExtents,
viewBackgroundColor,
viewPriority);
The second and third views are considered "extra" because they re-use the draw lists created for the first view. The code iterates through the second and third views and creates a perspective projection for the top right draw context and an orthographic projection for the bottom right draw context. The view matrices are also different for the two views.
The Creating a Heads-Up Display sample keeps things clear and simple by creating two transform graphs, one for the 3D objects (its root is g_3dRoot) and one for the 2D objects (its root is g_hudRoot). It calls createBasicView() twice, once to create the sub-tree of the render graph for the 3D view (g_viewInfo) and a second time to create the sub-tree of the render graph for the 2D view (g_hudViewInfo).
g_3dRoot = g_pack.createObject('Transform');
g_hudRoot = g_pack.createObject('Transform');
g_viewInfo = o3djs.renderGraph.createBasicView(
g_pack,
g_3dRoot,
g_client.renderGraphRoot);
g_hudViewInfo = o3djs.renderGraph.createBasicView(
g_pack,
g_hudRoot,
g_client.renderGraphRoot);
// Make sure the HUD view gets drawn after the 3D view
g_hudViewInfo.root.priority = g_viewInfo.root.priority + 1;
This example uses an orthographic projection for the 2D view and a perspective projection for the 3D view:
g_hudViewInfo.drawContext.projection = g_math.matrix4.orthographic(
0 + 0.5,
800 + 0.5,
600 + 0.5,
0 + 0.5,
0.001,
1000);
g_hudViewInfo.drawContext.view = g_math.matrix4.lookAt(
[0, 0, 1], // eye
[0, 0, 0], // target
[0, 1, 0]); // up
_viewInfo.drawContext.projection = g_math.matrix4.perspective(
g_math.degToRad(30), // 30 degree fov.
g_client.width / g_client.height,
0.1, // Near plane.
5000); // Far plane.
The view matrix for the 2D view (g_hudViewInfo.drawContext.view) has the virtual camera (the eye point) positioned at (0, 0, 1), aimed at the origin (0, 0, 0) with the y axis as the up vector (see previous code snippet). The view matrix for the 3D view (g_viewInfo.drawContext.view) has the virtual camera rotating around the "city," but is still aimed at the origin (0, 0, 0) and with y as the up vector.
// Fly the camera around the city.
var eye = [
Math.sin(g_clock * g_cameraSpeed) * g_cameraRadius,
10,
Math.cos(g_clock * g_cameraSpeed) * g_cameraRadius];
g_viewInfo.drawContext.view = g_math.matrix4.lookAt(
eye,
[0, 0, 0], // target
[0, 1, 0]); // up
The examples discussed so far in this chapter build the render graph under a RenderNode. The Render Targets example creates two views, one for the teapot scene and one for the 3D scene (the cube). The teapot scene is parented by a RenderSurfaceSet node. The cube scene is parented by a RenderNode. After the teapot is rendered into the RenderSurfaceSet node, this render target is drawn into a texture. The texture is then applied to the surface of the cube in the same manner as any other texture.
The Creating a Heads-Up Display example discussed in this chapter modifies the position of the virtual camera and the transformation matrices of the 2D objects to animate the view and the 2D objects. The next chapter (to be provided), Animation and Skinning, shows you how to animate objects using the O3D animation and skinning system.