Tuesday, January 31, 2006

One Texture Per Object 4-Evuh

I sometimes get requests for two features:
  1. The ability to use more than one texture per OBJ.
  2. The ability to not use a texture per OBJ.
My answer to both is the same: one texture per object forever!

The issue with the first request is simply framerate - see my previous post on the "crayon rule". X-Plane has to do a certain amount of setup work for each OBJ it draws. Therefore we have two ways to implement multiple textures per object.*

If we want to obey the crayon rule, we would draw the parts of the objects that use the first texture first for all objects, then change textures once and draw the second texture. But this isn't so good - if you are using polygon offset or translucency or any other feature that requires the object to be drawn in order, those features won't work. Also we do a certain amount of setup work per object - we now have to do that work twice! This is about the same as doubling the number of objects. Ouch!

Or we can disregard the crayon rule and change textures once per object. That would be performance death . No optimization has more impact on framerate than minimizing texture changes! This is why X-Plane keeps moving from multiple textures to one texture - in both airplanes and objects! We do it for speed!

So that's why we require one texture. But why not zero textures? Well, there are a few issues with allowing untextured objects:
  • The request for an untextured object almost always includes a request to use colors on the object instead. This would actually possibly be slower, not faster. Color information is twelve bytes per vertex, while texture is only eight. Each vertex per object is now 32 bytes, a wonderful power of 2 that happens to be very efficient on certain modern hardware. With color we hit 36 bytes. Ouch! Remove the color (not useful anyway) and we have 24 bytes. (Why not use 4-bytes instead of 12 per color? The hardware works better with color as floating points, not bytes - surprising but validated by performance testing.)
  • X-Plane would have to take time off from drawing to turn texturing off and then turn it on again. So unless we're going to stop texturing for MOST of the sim, this "state change" hurts us.
  • The actual process of drawing with a texture is basically free on modern hardware. Either the chip has dedicated hardware to do the texturing that would be idle otherwise or, if it's a pixel-shader chip, the ability of the card to texture is so far ahead of what X-Plane needs that the issue is moot.
So we don't allow color-instead-of-texture because it would be slower! Instead simply make a small "color palette" in your object texture and use that part of the texture stretched over your object to make your colors.

We do allow you to tint your object with ATTR_diffuse, but do not do this! The performance of the diffuse attribute is way worse than using a bit of your texture for color. ATTR_diffuse only has one legitimate use - paired with ATTR_emission to allow for the creation of objects that are self-lighting in low-light daytime conditions. I will post about this in a future entry.

* For OpenGL geeks: technically with pixel shaders you could bind multiple textures simultaneously and write a shader to select one, perhaps by mapping ST coordinates from a virtual texture space. So perhaps someday when we require pixel shaders for X-Plane and they are ubiquitous we can re-examine this.

No comments: