Quake 2 BSP WebGL Demo
(Linkified because trying to scrunch the viewport into the blog would make it difficult to use.)
It's certainly not perfect, but hopefully you guys like it. I would be thrilled to see someone expand on what I've done here... oh wait.
So, let's talk about why I've decided to move on from this project. This bit is gonna get rather long and technical so feel free to ignore it if subjects like binary parsing and lightmap calculations make your eyes glaze over.
I was hoping to get several more features in there like visibility culling and collision detection in there but after a lot of reflection I just don't think it's worth it. Actually, a better place to start may be to look at why I chose to try this particular format in the first place.
So having decided to do a binary file I toyed with the idea of doing Quake 3 maps but shied away from that because I wasn't too keen on the idea of doing Bezier curve math at the time and it would require more in the way of effect shaders to get the right look. Quake 2 maps were (I thought) simpler and rendering would take nothing more than a simple lightmap pass, not to mention they were smaller. There was also an educational motivation to the choice: I've done Quake 3 loaders before (In C++), but I'd never worked with Quake 2 maps before so I wanted a chance to familiarize myself with them.
Well, in retrospect I'm still glad for the chance to get to know the format but I don't think I would work with them ever again. I'm sure that many of the design decisions that drove the format made sense back in '97 when hardware rendering was a novel idea, but in todays graphics scene there are some choices on display here that seem pretty ludicrous:
- Texture coordinates aren't stored directly but are instead derived from the dot product of the vertex position and a texture "axis" plus some offset. I'm certain this is a byproduct of the software renderer, but that doesn't stop it from being a royal pain to work with.
- Once calculated the Texture coordinates are give in terms of pixels, not the 0..1 scale that the hardware expects. This means that in order to correctly calculate the vertex data you must first pre-load every texture the map uses. That's fine for a local client, but is murder for a web browser that's trying to be nice and asynchronous.
- To make things more interesting, the texture format is a proprietary one (.wal) It's a simple enough format, basic 8-bit indexed color, but not many tools are available to convert them to something more friendly like .png, so that just means more binary parsing for your script.
- Oh, and the lightmaps are all stored separately. One for each. And. Every. Face. So your options are to pack them all into a single texture or render one face per draw call and store several thousand teeny tiny textures. Guess which option I picked?
That's not even looking at things like visibility determination or collision detection. Plus there's several bits that I'm still not sure how to determine. For example: how do you figure out which texture to show for the skybox?
Now, all of these things are annoyances to be sure, but can be worked around. After all, one of the most successful games of all time was built around this format, it can't be THAT bad, right? The real problem here is that these issues make the format almost antagonistic towards a web environment. Yes, Google got it working, but even they mentioned how painful some aspects of the loading were.
So while I had fun putting together this demo I also don't plan to take it any further, simply because if I'm going to put any real effort into a format I want it to be one that can play to WebGL's strengths and not highlight it's weaknesses.
So now a question for the readers: What formats have you seen that WOULD work well in a browser environment and why? I have a few that I want to look at anyway but I'd be delighted to take some suggestions! In the meantime, I'm working on getting glMatrix to 1.0 (which for me means improving things like documentation and unit testing), so expect to see some updates in that area soon!