Angus Dorbie (angus++at++division.demon.co.uk)
Wed, 25 Jan 1995 20:35:42 +0000
o The technique involves generating a 2D shape in the stencil buffer
which corresponds to the intersection of the shadow with the ground
geometry then writing some shadow colour exclusively to this region.
Similar but more complex multi-pass techniques exist but they are
probably to costly for most vis sim.
o Firstly you require some stencil planes as part of your framebuffer
configuration. This is only possible with some graphics options.
The third argument in mssize() will give you stencil planes on REs and
the call stensize() with other options. I think performer configures
with stencil planes in pfInitGfx().
If your shadow shape is convex you will need a single stencil plane
if it's concave you will need more than one. How many depends on how
many overlaps the plane extrusion will generate when drawn but 2
bitplanes should do for a single aircraft.
o The generation of the 2D intersection shape is performed after the
rendering of the entire scene to the framebuffer. This leaves the
depth in the zbuffer.
You can draw the aircrafts shadow geometry to the stencil buffer
while performing a zbuffer check against the scene geometry. This
works because you can draw the planes shadow geometry backfacing
(culling frontfacing polys) with a stencil increment operation, then
draw the planes shadow geometry frontfacing (culling backfacing polys)
with a stencil decrement operation. The net effect is that you are
left with non-zero values in the stencil buffer where there are
shadows.
The shadow geometry can be a vertical extrusion of the aircraft
positioned through the ground, make sure that it extends through the
entire geometry you want to intersect with. You can keep this geometry
quite short to limit the number of pixels you have to write but you
then have to place a top on the extrusion.
Better results can be obtained by extruding the shadow through the
light vector for the sun, and/or calculating the correct aircraft
outline (not always that simple).
In your pre draw for the backface shadow you should call:
stencil(TRUE, 0, SF_ALWAYS, 0x00, ST_KEEP, ST_KEEP, ST_INCR);
zwritemask(0x00000000);
RGBwritemask(0x00, 0x00, 0x00);
and in your post draw call:
stencil(FALSE, 0, SF_ALWAYS, 0x00, ST_KEEP, ST_KEEP, ST_INCR);
zwritemask(0xFFFFFFFF);
RGBwritemask(0xFF, 0xFF, 0xFF);
For your front face pre draw you need to call:
stencil(TRUE, 0, SF_ALWAYS, 0x00, ST_KEEP, ST_KEEP, ST_DECR);
zwritemask(0x00000000);
RGBwritemask(0x00, 0x00, 0x00);
and in your post draw call:
stencil(FALSE, 0, SF_ALWAYS, 0x00, ST_KEEP, ST_KEEP, ST_DECR);
zwritemask(0xFFFFFFFF);
RGBwritemask(0xFF, 0xFF, 0xFF);
These mode changes may conflict with some performer voo-doo but
hopefully not under most circumstances.
o You then need to draw a shadow to the stencil area you've just created.
A simple way is to draw the frontfacing shadow geometry again but keep
it transparent and don't disable writes to the colourbuffer. This will
work with screendoor transparency but may cause problems when blending
with concave outlines. When blending, only convex geometry which
covers the entire shadow should be used for this stage.
The shadow geometry should be suitably coloured and requires pre draw:
stencil(TRUE, 0, SF_GREATER, 0xFF, ST_KEEP, ST_KEEP, ST_ZERO);
zwritemask(0x00000000);
and post draw:
stencil(FALSE, 0, SF_GREATER, 0xFF, ST_KEEP, ST_KEEP, ST_ZERO);
zwritemask(0xFFFFFFFF);
o The ST_ZERO argument above should save you having to perform an sclear(0)
every frame but I've never tried this. You should still clear the stencil
planes first time in.
Have fun and good luck. Sorry if there are any mistakes in the stencil calls.
-- Angus Dorbie Division Ltd, Software Engineer 19 Apex Court, Tel: (01454)615554 Woodlands, Fax: (01454)615532 Bristol BS12 4JT, angus++at++division.demon.co.uk UK
This archive was generated by hypermail 2.0b2 on Mon Aug 10 1998 - 17:50:53 PDT