Skip to content


Technical Notes on O3D

Google released O3D, a web plugin for 3d rendering, today. It’s a pretty sweet piece of work. Definitely check it out if you have any interest in 3d rendering, the web, or JavaScript.

There are a couple of cool pieces to this puzzle, and I wanted to call them out to other people who might be reviewing this technology. The two sentence review: I am blown away. They got this right.

(FYI: This post isn’t meant to be a full walkthrough, just a quick indication of the cool jumping off points in the codebase.)

Stop number one is the graphics API abstraction. This is rooted in o3d/core/cross/renderer.h, which provides an abstract interface for performing render operations. This is sensibly designed, oriented for SM2.0 through SM4.0 level hardware. It will also deal with DX11 class hardware, although it won’t expose all of the niceties DX11 gets you. It wraps GL (o3d/core/cross/gl/) and D3D9 (o3d/core/win/d3d9). The purpose of all this is to provide a common ground for all the higher level code to issue draw commands from. It is not directly accessible from JavaScript (although some of the related classes like Sampler and State are.)

As an aside, writing a Pixomatic or Larrabee backend would not be hard. At GarageGames, we had a rendering API similar to this (unimaginatively called GFX), and it was fantastically useful. Last time I checked, there were DX8, DX9, DX10/11, GL, and Pixomatic backends for it in varying states of usefulness. We even had one guy write a backend that would stream draw commands over a socket, which was pretty cool. In the context of O3D, they have an implementation of Renderer that queues everything into command_buffer, then streams it to a command buffer server running in a separate thread, which issues the actual draw commands. It’s unclear whether this is used in the current version of the plugin based on casual inspection, but it’s a great example of what good design can get you.

The next piece is the DrawList, which is where most of the heavy lifting for drawing happens. JavaScript, of course, is not really desirable to have in your inner rendering loops, so you queue everything you want to draw (DrawElements) into a DrawList. This is wrapped by higher levels, of course, but it represents the lowest level API that’s available to JS code. All the sorting and state management to get stuff on screen happens in this area.

Alongside the DrawList stuff, you find the material system, which is pretty slick. You write your shaders in their shading language, and it converts to HLSL SM2.0 and Cg (arbvp1/arbfp1). This is enough to do almost anything you might want to (as fantastic as SM3.0+ is it’s not really necessary for most rendering). There’s a full SAS system so you can interface programmatically with your shaders.

Above this, you get into the scenegraph. Now, I subscribe to Tom Foryth’s views on scenegraphs, which is that they are basically a bad idea, but I think the Google guys were smart and set up their API so intelligent developers can avoid being screwed by the scenegraph. The scenegraph-esque stuff they do have (they call it a rendergraph) is powerful enough you can do most rendering without going nuts, and lets a lot of the heavy lifting stay in native code, where it will be fast. You end up doing retained mode-ish things, but since JS is slow, and most JS developers come from a DOM background, it works better than you might expect.

There are a lot of cool miscellaneous features, too. They embed the fast V8 JS engine right in the plugin so you can have consistently fast JS execution. They support falling back to an error texture (via Client.SetErrorTexture) when you fail to bind a sampler. You can group objects via Pack objects for easier management and stream things from archives, too. There are debugging aids and libraries for math and quaternions.

You should check out the samples. There’s a lot of impressive stuff. There’s the beach demo in the video at the top of this post, but they also do some cool stuff with animation, HUDs, text rendering, picking, and stenciled teapots. And everything is done in JavaScript right in the web page. Even the shaders are embedded in <script> tags!

O3D is a great piece of technology, and I hope it thrives. I’m excited to see what people build on this (and I’ve got a few ideas myself ;) .

Posted in Code, Cool Stuff, Opinion.

  • Very cool Ben!
  • elenzil
    it seems like O3D + google native would be an awesome combo.
    the computation you can do on the GPU is pretty impressive these days (eg calculating julia sets, simple waves etc), but for really crunching data like in say a large gravity or fluid simulation i think you need a general-purpose CPU and i'm not sure that V8 or tamarin will really satisfy.

    on another topic, what's the coolest O3D demo peeps have seen so far ?
    has anyone used render targets + environment mapping do do dynamic reflections yet ? all the pieces are sorta just sitting there.
  • elenzil
    now *this* feels like the web-based graphics environment i've been looking for !
    i'll try to port my "400 rotating squares" demo, which imo exposes Flash10 as a dog, to it tonight.
  • 400 squares made Flash10 break? What resolution were you running at?
  • elenzil
    well it doesn't behave incorrectly, but it chews up nearly all the CPU of my pretty zippy machine at say 1000 x 1000 pixels.
    it's clearly the rasterization which is the issue. http://elenzil.com/flash/flash_5/oxeFlash5_norm...
  • zwetan
    I ran demo under OSX and no problem

    but looking at the code, there is room for optimization

    use Vector, not Array, this is a real boost in FP10

    try also to use cacheAsBitmap, it speed up the rendering

    other things to explore:
    don't draw the 400 vector graphics on screen, keep them out of the display list,
    copy them to a bitmapdata and just display that
    (see for ex: http://www.bigspaceship.com/blog/labs/improving... )
  • elenzil
    thanks for taking the time to look at that .as code, zwetan.
    i tried cacheAsBitmap as you suggested, but not much change (presuming i used it correctly - just shape.cacheAsBitmap = true ?)

    i guess my fundamental take here is that rasterizing 400 rectangles should not be anywhere close to a bottleneck. i've got way more interesting things to do with my programming time than fight that.

    compare, for example, to this demo which renders 1000 rotating bump-and-environment-mapped utah teapots (3783 triangles each) at 30 to 40+ FPS on the same exact machine, and barely bumps the CPU at all. and it uses javascript instead of actionscript, and there's no compilation step.
  • Thomas
    Keep in mind that Flash ain't GPU accelerated and O3D clearly is.
  • Are you running under OS X with these tests?
  • elenzil
    vista
  • I just ran it on my XP box at home and it ran very smoothly. My OS X laptop at work had trouble, though.
  • I checked out the demo. You're right, not running super smooth. I was getting some errors, maybe something internally is going wrong and causing problems?
  • elenzil
    huh. many thanks for looking at the demo. other folks have mentioned it gives errors. where to these errors show up ? do i need a debugger installed ? but in any event i doubt it's the errors which are giving it trouble; at small window sizes it uses just a tiny portion of the CPU.
  • sul
    funny there is no linux support, but i don't blame them. linux 3d is like a mud hut compared to a mansion.
  • I wish Linux had good 3d support. But the infrastructure just isn't there. A shame. But really, if you want a desktop linux experience, why not use OSX?
  • equex
    O3D doesnt work on non-3d accellerated cards, so most corporate workstations cant deal with it :(
    So this is pretty much a hobby level trinket.
  • JeramieH
    "... so most corporate workstations cant deal with it. So this is pretty much a hobby level trinket."

    Blizzard, Sony, EA, etc seem to have tapped a hidden market full of computers with 3D cards not in a corporate environment. Maybe they're onto something.
  • equex
    uh, for gaming i use my crossfire setup at home, no browser needed.
  • Yeah, I guess it will really hurt the sales of your game to people who play during work hours.

    Seriously, though, what market are you targeting? Every cheap computer sold in the past few years has some sort of minimal 3d capable graphics chip on board. X300s are plenty to run O3D on, and even the Intel parts are capable enough to do it. Heck, even really terrible cards like S3s have SM2 support nowadays.

    Certainly there are situations where you will want to go with something like Flash that requires no special hardware, but claiming that O3D is a "hobby level trinket" is like saying that Half Life 2 or Left 4 Dead was a "small success." The set of people that can run O3D, HL2, and L4D are basically identical.
  • Well, according to the our stats - http://unity3d.com/webplayer/hwstats/pages/web-... - there's still almost 30% of the machines that have fixed function hardware. That number is dropping, but it's still quite significant. O3D currently does not support Intel GMA 950 (aka 945), which is also very popular - but that's probably just some bugs or missing workarounds; technically GMA 950 can run SM2.0.
  • Good to see you here, Aras. :)

    Yeah - a lot of people have crappy 3d capable hardware (like the intel chips) but they DO have 3d capable hardware. O3D needs to get a path for those chips.
  • Ooh very cool, looking forward to seeing it used!
  • zwetan
    thanks for the review, very good stuff indeed

    and technically it should be possible to make another branch of the code base and use tamarin as the running engine instead of v8 (agreed it's a lot of work, but definitively possible =))
  • Yeah definitely - then the issue is mainly penetration rate. But as an alternative to something like Unity where you're already pushing a player plugin...
blog comments powered by Disqus