3D Game Resources & WebGL

onGameStart 2011 - Brandon Jones

A little bit about me

Warning! Technical Jargon Ahead!

This presentation assumes a basic knowledge of 3D rendering concepts. If you are new to graphics development and want to learn more about WebGL, check out LearningWebGL.org for some excellent beginners tutorials!

What we'll be covering today

So where do we start?

The same place we ALWAYS start with any new technology

Get id tech to run on it!

Rendering Quake 3

Launch Demo

Quake 3 - details

No geometry culling

Things that made life difficult

Looking for something more streamlined...

iOS RAGE Level

View Video

iOS RAGE Level - details

Megatexture "Lite"

RAGE is an awesome example of everything that WebGL games should strive to be

Reverse engineering the files

Musings on file formats

When talking about file formats for WebGL, you've got two semi-competing goals:

Downloading files fast

But if you need to parse the files really fast...

It's entirely possible that getting the appropriate buffers into your video memory would take nothing more than a couple of subarray calls.

var byteArray = new Uint8Array(binaryBuffer);
var vertBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, 
    byteArray.subarray(vertOffset, vertOffset + count), 
    gl.STATIC_DRAW);

var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, 
    byteArray.subarray(indexOffset, indexOffset + count), 
    gl.STATIC_DRAW);
            

For elements of your model that are not simple arrays of numbers, it's probably a lot faster to simply use JSON

{
    materials: [
        water: {
            baseTexture: "texture/waterbase.png",
            shader: "shaders/water.shader"
        },
    ],
    rootBone: {
        pos: [0, 0, 0],
        orient: [0, 0, 0, 1],
        children: [
            // and recurse!
        ]
    },
    // etc.
}
            

Downloading fast and Parsing fast

It may be that a best case scenario is to download a compressed version of your resources, expand them in script, and cache the expanded version with local storage options like the filesystem API.

Performance Tips

I am primarily talking about desktop browsers, mobile is still very early with it's WebGL support. That said, most of these concepts are pretty universal.

Use RequestAnimationFrame!

Every time you do a draw call with setTimeout, somewhere a kitten cries.

Do you hate kittens?

Rendering optimization: No big surprises here

But at the same time...

Change state as little as possible

Take advantage of spare GPU cycles!

In many scenarios, you won't be GPU limited.* That means that you can get a couple of features "for free".

Pre-compute, pre-compute, precompute!

If you can calculate something "offline", do it! The browser is going to be racing full tilt to keep up with your game logic, it really doesn't need to be calculating your normals for you too.

Many existing formats require lots of processing to get to a displayable point. This can help allow for things like LOD or hardware optimizations.

That stops making sense in a Web-centeric environment. Just send the client the right file type!

Cross platform format support

There will be cases where different platforms will perform best with different formats. Like Mobile vs. Desktop or various texture compression formats.

In these cases, store all the different file permutations on the server! Let the client tell you it's capabilities, and send it the appropriate types based on that.

1 Artist > 1,000 GPU Cores

It's worth considering that all the shader tricks in the world will never yield the results that you'll get from one good artist.

Yes, we all love our fancy water shaders and refractive glass, but a solid art direction can make even flat polygons look spectacular! (See: iOS RAGE)

Things to avoid

There are a couple of things that WebGL makes more painful than usual:

Thank you!

Q&A