Friday, March 6, 2009

The Big Move!

The response to the interviewing article went really well! I got a lot of great comments about it and am really glad I was able to give back a little by contributing a piece like that. Hopefully I'll find some time to write more articles like it in the future.

So the past few months have been pretty interesting for me. A few months ago I made the decision to leave Destineer to work for id Software. They're a great company and everyone there is absolutely awesome but I just could not pass up the chance of a life time to work at the company that got me excited about computers and games in the first place! They were all incredibly understanding and I truly wish them the very best. Trust me when I say they're working on something really amazing and I'm very excited to see the final result!

So outside of that I've been keeping pretty busy. While looking for some code to generate cubic noise maps (as part of a series of new experiments I've been working on to generate spherical terrains) I ran into my old starfield generator which generates random points and "blurs" them as they whiz by you. A very cool effect, especially when you consider how the points were generated.

When you generate random noise around a unit sphere you have to be incredibly careful to ensure that they are uniform, otherwise you'll see them gathering towards one of the poles as demonstrated here:

The problem lies in how spherical coordinates tend to congregate points towards the poles. To fix this problem you can use sphere picking to ensure any given area around the sphere contains the same number of points:
This may seem relatively trivial and unimportant for something like a starfield (which it is), but where it starts to really matter is when you need to generate random vectors for something like raytracing. I recently created an ambient occlusion generator for heightfields and ran into an issue where the sampled values where resulting in way to many false positives than they should have been. As I'm sure you can imagine, the issue is pretty obvious; most of the generated rays were going straight up, and heightfields by definition do not have overhangs for those rays to hit!!! The simplest solution is to scale the generated rays up value so they go more towards the sides (which helps quite a bit), but really the best way to do it is to properly generate the sampling rays around the unit hemisphere uniformly. By doing this I was able to get away with using a lot less rays for fantastic looking results!

I won't bother to provide the full algorithm here but if you're interested, check out this page: Sphere Point Picking.

So as I mentioned I've been doing quite a bit with terrains. Unfortunately I don't have much to show as far as screenshots as it's been mostly experimental type stuff to learn and get acquainted with new algorithms. After I finished the ambient occlusion generator I went ahead and wrote a lightmapper for fun (it wasn't that much of a departure) and started a survery of terrain shadowing techniques.

Shadow Mapping is a tried and true classic which can give some great results if you're willing to put a little blood and sweat into your implementation (ala CSM's, VSM's, TSM's, etc...). Lightmapping is nice but only works for static terrains and doesn't work so well for dynamic objects (though I know of some neat tricks to fix this). Ambient Occlusion works nice but only works for global indirect light (so is more complementary than comprehensive). Spherical Harmonics is an option but from my research doesn't always result in the best looking shadows.

One experimental shadowing technique I tried which resulted in some really nice soft-shadows is Ambient Aperture Mapping. The idea behind it is pretty novel and is similar to relief mapping but simpler. First, you generate your aperture values which consist of a bent normal; a vector pointing towards an un-occluded light source (i.e. the sky/sun/moon), and the aperture; essentially a circle at the end of the bent normal which defines how much light reaches that point (this value is similar to an ambient occlusion result and make the bent normal into a sort of cone). After you have these you can test any given terrain surface point's aperture against your global light source which has it's own aperture values. The intersection of these two apertures defines how much light reaches that surface point.

The results are surprisingly good! I may utilize this in full force the next time I need an efficient low to medium frequency shadowing solution with modest storage costs for terrain rendering. Here's a paper on it for your reading pleasure: Ambient Aperture Lighting, and a screenshot of their results:

That's enough for now. Until next time!

No comments: