Tuesday, September 15, 2009

Virtual Texturing part 4; importing madness

So after rewriting the code to load the pages in the background on a secondary thread, i started to write some code to import a Quake 4 level (.proc files) and modify the geometry so it could be displayed using a virtual texture, which would be automatically created from the textures in the level.
The red in the screenshot above are textures that i couldn't automatically discover without hacking. The black areas are supposed to be transparent, but i'm not handling that at the moment.

Here's a screenshot where every color is a different page, which shows that i have way too many different pages on screen at the same time:
There are a couple of things that I've learned about converting existing (Quake 4, but the same will apply to other sources as well) geometry to take advantage of virtual textures:
  • Quake 4 uses a z prepass to take care of occlusion, so it's geometry is optimized for number of triangles and not so much for using as little geometry area as possible, which means a lot of wasted texel space.
  • Quake 4 has a lot of transparent textures that are placed upon other textures, which again leads to wasted texel space, as you can see in my screenshots i'm actually not handling transparency.
  • Since Quake 4 has separate geometry for each type of shader, you might end up with lots of patches of geometry that each have completely different pages. If this was build with virtual textures in mind, it would've been continuous. This is bad because it means more pages need to be loaded into memory.
  • Sometimes large textures are assigned to a relatively small area. If you don't take that into account you'll be assigning large areas of texture space to something which is tiny.
  • Without parsing materials (which i'm not doing), discovering the right textures is sometimes impossible.
These problems are causing me some headaches with my test-scene because i'm loading waaaay more pages than i would need to in a scene that would've been build with virtual textures in mind.
I could solve this by building my own quake4 map CSG code, which i might do eventually as i already have some experience with CSG.

However, if you would be building geometry from scratch this would all be easier, as long as you try to keep texel density at a sane level and keep surface area to a minimum. (aka don't assign texel space to something which is never visible)
Sounds rather straightforward, i know, but if you don't think about this up front you might end up with some nasty surprises later on.

Also, allocated texture space should be aligned to page boundaries, if you don't you might end up loading 4 pages when 1 would've been sufficient.

One mistake i made trough this whole process was thinking about a virtual texture as a giant texture, and processing it as such.
The problem with this is that you cannot handle unused pages easily.

Update: scratch that, fixing existing geometry (automatically), to be able to be used with virtual texturing -efficiently-, is hard enough to be considered a dead-end.
I'm going to rebuild the geometry with my own CSG process instead.