Friday, February 24, 2006

Faking depth in a cyc arena


Listening To : Prince, Raspberry Beret

A problem that came up during Flyboys was that we had a tiled arena floor that was 10kms square, but beyond that we had a matte painting 'cyc' aka cylindrically projected onto a bowl shaped geometry with vertical sides.
When rendering a Depth pass or secondary output, when a camera following the action got close to the bowl, then the colour information in the matte tells you there are things far away in the distance, but the depth (as in length(I) ) doesn't. The depth values decrease rapidly as you approach the sides of the cyc.

Not what we want at all.

So if its safe to assume the ground continues in a near-planar fashion in all directions out to the horizon, we can do a very simple, quite elegant cheat to work out what the depth would be, if the cyc wasn't there.


Breifly (see diagram also):

float S = 1;
point P = transform("world", P);
point E = transform("world", E);
vector I = vtransform("world", I);

if ( ycomp(I) < 0 ) // I.e. point being shaded is closer to ground than the camera
{
// S is some scale value we need to solve to scale I upto;
// I' = P'-E
// ycomp(P') we know is always zero
// therefore we can solve the scale for ycomp and use it to scale I (similar triangles)
// P' = E + I*S;
// so;
// ycomp(E) + ( ycomp(I) * S ) = 0;

S = ( -ycomp(E) / ycomp(I) );

I = vtransform("world", "current", I*S);

// Voila, our new fake (clamped) depth is;
depth = min( length(I), 65535 );
}
else
{
// E.g. plane is upside down, etc.
// Just Set depth to Max ( 65535, which is the largest value our EXR's can store )
depth = 65535;
}