Monday, February 18, 2008

Even more occlusion testing...

I've decided to drop the software Z buffer - it's proved too slow when it comes to writing polygons into it. Instead, I'm going back to an old idea which is fundamentally the same as hardware occlusion tests but run in software instead.

Thursday, February 14, 2008

More Software Occlusion

I have a software Z Buffer!

It's not completed yet - so far I've written the code to project a surface to virtual screen coords, and write the surface verts into the Z buffer. I still need to fill each surface polygon (although I've been reading up on scan lines, which seem the most straightforward way of doing it, so this bit shouldn't be too bad). Once I have that done, I will already have 99% of the code I need for occlusion testing, so linking the rest together will be extremely trivial.

The really really nice thing about this is that it's actually pretty damn fast. Certainly faster than using Hull Checks, Traces, or Clips, and also it will give me full reliability.

Tuesday, February 12, 2008

Software Occlusion Testing

I've written a basic software occlusion test that works with brush models as well as with the world. Initial impressions are that while it certainly works, in places it works too well, as it can remove models that are only partially occluded. Also, it gives a very nice speed up on account of having to render fewer alias models (I intend to run it on all of them).

I'm probably going to investigate the possibility of maintaining a software Z buffer though - the simplistic Hull Check approach has enough failings to prevent it from being properly viable. I'll probably look to the Mesa source code for ideas here, as it's got a compatible license (the Abrash code is enough of a grey area to rule it out - so far as I can tell, it has no license at all!) and will already work nicely with the OpenGL primitives I'll be sending to it.

At least I'm now satisfied that in terms of speed the likely worst case is an even trade, with FPS increases actually being more likely.

Fun with Sprites

I've been spending the evening deciphering the Sprite format (first time ever I'd really looked at this code), and unfortunately it's pretty ghastly. There seems to be a lot in there (animating frame groups) that's a hangover from the old days when Quake was intended to have more sprites in it (primarily to speed up alias model rendering - see Mike Abrash's papers for more info on this), but the unfortunate thing is that I just know that some mod out there will use it (I'd be surprised if Hipnotic didn't - it's pretty notorious for hacks like this), so I can't remove it to clean things up.

Frame interpolation doesn't seem to be so straightforward as I had hoped. I have an idea to count the frames in the original, then potentially fill in the gaps with the replacement and possibly blend between textures, but I have no guarantee of what the animation rate will be. I still haven't looked at the QC or Sprgen yet, so maybe some ideas will come from those.

I'm scrapping the plan of doubling size for external Sprite textures. It looks fine with some (explosions, lights) but bad with others (bubbles), so in the absence of consistency I'm just going with the basic size and leaving it as the responsibility of content creators (HA!) to ensure that replacements are correct.

Getting stuck into this is also bringing another issue to a head - proper BSP clipping for sprites. I was always going to hit this when I got round to torch flares anyway, but I might as well direct some thought to it now.

Sprites basically need to be drawn without depth testing to prevent them from poking into walls. The problem is that while there are some straightforward methods I can use - Hull checks or Traces - that will do the job, they only work with the World Model. Inline Brush Models also need to be checked. Turn off depth testing in an engine that does coronas, and have a look through the floor of the episode selection room in Start - you will see the coronas through the floor. They also only do the midpoint, whereas the whole bounding box really needs to be checked. Occlusion queries would be better, but they are slow (owing to having to do a read back), and I'm aiming my minimum specs for slightly lower than cards that can support them.

I have Mike Abrash's "z-sorted spans" code, so another idea would be to build a copy of the Z buffer in software (at a 320 x 240 resolution), and test against that, but I wonder how fast that would be. It doesn't seem to make sense to cut engine speed in half for the sake of a handful of lousy sprites.

I'll probably end up accepting Hull checks and Traces against the midpoint as the best of a bad lot, and extending the code to also support brush models.

A quiet day...

Didn't get much done today, just played around with explosion particles (nothing satisfactory came out of it), and made a splash screen (the same as the banner on this site).

I think I'm going to keep the standard explosion sprite, but introduce a special mode with external texture support whereby it can interpolate texture frames so that you're not restricted to the puny 6 or so frames in the original. This should allow you to use a custom sprite replacement with as many frames as you like. I've been thinking about this for a few days now, and - kinda - see a way to make it work. I might also add an option to use either a "strip texture" (like in Doom 3 and a lot of other modern games) or multiple individual frame textures. Of course, it would have to be able to detect the texture type and adjust the engine to support it automatically.

I might also double the size of the explosion sprite in-game. It's a little small as it stands, and could well use it. I suppose gl_doubleeyes serves as some kind of precedent that this kind of thing is allowable, but I'll need to wait and see how it looks before making a final decision. At least doing it if an external texture is detected should be OK.

Finally, I want to add a cloud of smoke around the explosion. I'm not happy with my current smoke texture, but I'm having a hard time finding a good-looking replacement. The trouble is that the one I have looks great for some things but not-so-great for others, and getting one that's at least acceptable for everything is proving difficult.

Sunday, February 10, 2008

Particles

Well that wasn't so bad...





All done aside from explosions. I managed to get some recent salvageable code from some experimental word I had done late last year.

Particle System

So I've bitten the bullet and have started work on the particle system. This part of an engine always gives me the horrors, as traditionally it's been a weak spot for me - make no mistake, anything good I may have written in the past has been totally by accident, and I've never been able to reproduce it.

I'd just port in the QMB system (a lot of people seem to like it), but I'm not really a fan of it - the effects are too flashy and overboard, whereas what I'm looking for is something with more of a "Quake"-ey look - not trad-Quake with just dots, but something that looks like it would have been included in Quake if the technology was available at the time.

So far I have my particle texture created and loading successfully (hard-coded in the engine, because this is Quake, after all), selection of individual texture components working, and variable scale and alpha. The really neat thing I'm just after doing is an R_NewParticle function that replaces the free_particles check, and takes particles that are just about to die if there are none free. This has enabled me to reduce the number of particles allocated, as it gives me a fairly good predictive reuse. It's pointfile-aware, of course, but that's the only time MHQuake should ever run out of particles these days.

The real horror comes when I go to tweak the various particle effects to make them look good.

Saturday, February 9, 2008

Celestia

If you're fascinated by the universe and want a really good space sim that just lets you fly around and look (in awe, naturally) at stuff, then Celestia comes highly recommended.

It runs on Windows, OS X and Linux, uses OpenGL, and is entensible via plug-ins. It's also free (as in "GPL-Free"), so you get the source code to play with. Just be prepared to wave goodbye to a large chunk of your time!

Friday, February 8, 2008

I forgot about this...


Nice, eh?

It also works with "playdemo", "game" and "loadsky".

Break time

Took a short break to avoid burning myself out on this, but will be resuming tomorrow with picking up and finishing off some stuff I'd half done - I won't announce yet, but a question on QuakeDev helped to clarify a few thoughts on the method.

Glad to see that my suggestion for handling translucent water detection is becoming adopted. It's only with hindsight that these things become obvious "no-brainer"s, but this one was so simple and sweet it's still amazing it took this long for anyone to think of it.

Oh yeah - I also wrote the .mdl/.spr texture fallback, which is nice to have for flexibility and compatibility.

I'm also pondering on how to handle player skins with external texture loading. In theory, the Quake architecture allows for custom skins that don't work well with colour changing, and using external textures will only make things worse. I'll probably end up disabling the whole colour changing system if a non-standard texture is used.

Did I mention that the player model animates in the colour selection screen?

Wednesday, February 6, 2008

Phew!

Quite a few new bits and pieces.

  • Been having some fun with frustum culling. There's room for optimization here, as there are quite a lot of unnecessary R_CullBox calls in the world (in theory child nodes should only need to be tested if a node intersects the frustum), but somehow this doesn't translate into extra FPS when implemented in the engine. I'm going to be leaving the code in, but commented out.
  • Did FitzQuake-style water warp updating, but using the texture matrix to update the warps, rather than doing it in software (based on a Mark Kilgard idea). Obvious advantages are that I can do a warp update with a 6 or 9 vertex trifan rather than having to use a lot of really tiny strips. I only update a texture if it's been visible the previous frame - to be correct I should use current frame, but this way doesn't seem to have any negative side effects (so far). The mess I had made of GL_SubdivideSurface has now been totally removed, which was a nice bonus. I don't actually need to subdivide any more, but I still do (but with a 65536 subdivide size) just to keep the changes coming one at a time.
  • In terms of raw speed, I'm currently getting over 260 FPS at 1280 x 1024 x 32 bit fullscreen on a GeForce 6600 GT/Athlon 64 2800/1 GB RAM system. This is in a debug build. Quite happy with that.
  • The really nice thing about my new vertex array wrapper, which I'm only just realising now, is that I can play around with just slamming triangles on screen to see what happens in the exact same way as with immediate mode.
  • Still 2 major things missing that are holding up a release - a particle system and support for less than 4 TMUs. I hate writing particle systems - they never seem to work out well for me, and the 4 TMU render is just so clean and elegant that it seems a shame to write an alternative path.
I've loads of other ideas, but I do want to get the core stuff finished and released in some form (I'm particularly keen in making my texture loader public, as it can do some really cool stuff) before I start into them.

Sunday, February 3, 2008

Back for more

I'm currently looking for a way to reliably get the amount of installed Video RAM in a system. Other information would be great, such as whether it's dedicated or shared, does it support hardware T & L, and so on, but the critical info is the amount. I had some Direct 3D code which gave an approximation, and currently have some Direct Draw code which does likewise, but both methods tend to be off by a few megabytes.

This is for adaptive external texture loading. The rest of the code is done, but this bit is missing. In summary, what I'm doing is reducing the size of external textures to a multiple of the original, based on the amount of video RAM, so that low end support is improved somewhat.

_________


Update: I've got the video RAM amount using the Direct X Diag COM interface. It's horrible stuff, and stands as one good reason not to use Direct 3D (although in fairness, the main API is nowhere near as bad as this).

I've also written a simple vertex arrays wrapper that uses equivalents of the immediate mode functions for easier porting. It's nice.