Shadows

Going through a loop with shadows at the moment. I wonder if theres some method I’ve missed:

Planar Projection Shadows - not worth the time since it makes it extemely intensive to shadow a many faced object (like say an MD2 model).

Shadow Volumes - great if you can caculate the silloutte geometry and hence shadow volume quickly enough. However, this seems pretty heavyweight and I don’t think it will be quick enough on the systems I’m aiming at.

Shadow Mapping - brilliant method, unfortunately requires the GL_ARB_depth_texture extension which low end cards don’t support.

So… I’m a bit scuppered for realistic shadows?

I’ve been thinking about a method where I generate a shadow volume based on the bounding box of the object then draw slices through the volume textured with a render of the shadow caster from the lights perspective. Render these slices with depth test = equal and blended onto the surround geometry.

Any thoughts on this rambling?

Kev

Well if shadow volumes and shadow mapping are out you’ll pretty much out of options for a general case stuff, so I guess it’s back to the old-school methods of cheating. :slight_smile: Projected textures (even just with generated greyscale textures) can still look pretty nice, so that might be an option. And Realtime Rendering has a good section on shadows and includes lots of the more simpler methods.

What kind of environment are we talking about here?

Isometric rendered in OpenGL. Simple rooms with dynamic boxes and models in all modelled as axis oriented bounding boxes. Fixed viewport (might help?). Fixed Lighting (probably).

At the moment shadowing boxes seems pretty damn easy :slight_smile: However, the non-animating ornaments (think vases, statues, chests) are slightly more worrying. More so the actual characters wandering arond seems really difficult to achieve in any nice looking way. My central character is an MD2 with ~600 polys. He can face and direction and may have up to 100 frames of animation.

I was wondering if I could maybe use two shadow methods (say planar projection for the MD2 and shadow volumes for the non-animating stuff)? Anyone tried anything like that before?

Kev

If your target doesn’t support the shadow mapping extensions then shadow volumes are probably not going to be practical. Even if you simplified the geometry so generating the volumes was quick, the real killer on older cards is the fillrate it needs. Even GF2 can do simple shadow mapping, but they don’t have nearly enough fillrate for anything other than the crudest shadow volumes.

I think your best bet is probably projective shadow textures - should mean objects shadow their environment correctly without too much fuss. If you really want self shadowing and shadows between objects then one of the Game Programming Gems books has a nice article on shadow textures with per-object ids. Can’t remember the details at the moment though. :-[

Edit: “Practical Priority Buffer Shadows” is in GPG2 if you can lay your hands on it.

Mehhh, Kev you’re always making life difficult for yourself. The solution is simple! Disable shadows if your fancy extension isn’t present! Who’s going to be any the wiser?

Cas :slight_smile:

Disable shadows if your fancy extension isn’t present!

Well, its sorta difficult to write stuff which your own card doesnt support :slight_smile:

My card (ati 9100 [8500 basically]) also doesnt support it, but you can play doom3 with it.

Unfortunately my card doesn’t support the required extension for shadows, so I can’t even test against it. Not to mention I was intending to use shadowing as part of some of the puzzles (maybe).

Fraid I don’t own Gems and I’m not in a position to buying books at the moment (given I’m leaving for the states in 3 weeks). I’ll try googling for the term see if I can get the idea. Thanks.

Kev

Those are mostly like shadow mapping, but give an ID to the object when rendered, this gives an inifinite precision, but because two pixels share the same id (same object), self shadowing doesn’t occur because of the ID’s.

If you really really want to do shadow mapping, then a view-dependant, progressive refinment of the shadow map using a heirarchial grid (i think thats called adaptive shadow mapping) should help as that minimises the area on which you need to read back from the frame buffer if you keep the memory bound of the textures quite low (glReadPixel is necessary in your case kevglass). You wont get as nice shadows as shadow volumes, or a high-res shadow mapping technique, but it works on old cards and has self-shadowing.

DP

Seems like OT is right really. Projective shadows should be fine for me I think.

Kev

So I implemented some shadows last night. Not sure what the right term is (projective shadow textures?) but I render the shadow caster from the light source using black on white. Copy that image into a texture then use project texture coordinate generation to map this over everything that is further away from the light source that the shadow caster. It does look nice and is pretty much what I was looking for.

However…

  1. The black on white texture when blending across the scene causes all the colours to get washed out where the white blends onto the scene. I tried alpha masking and blending on alpha but with no success. I wondered if multitexturing might help this morning but I’m pretty sure I’ll get the same effect. What I really need to do is fill the background of the shadow texture with a non-colour, i.e. not specified so that the blending ignores the white but I can’t seem to figure this out? I assumed it’ll be alpha=0 but that doesn’t want to work out.

  2. This method seems to need me to generate one shadow map per shadow caster or inversely one shadow map per shadow reciever. One map per caster is fine accept it means rerendering some part of the scene lots of times to place lots of shadows over it. One map per reciever seems fine accept that means tracking changes in things that might cast shadows on the reciever to work out when to recalculate the shadow map. I assume, I’m missing something?

Even so, the results were very nice (though I haven’t screenshoted yet - soon). Thanks for the initial points guys.

Kev

Im supposing your just using gluLookAt, modifying the frustum a bit and rendering the scene, copy to texture and use that as the texture ?

If your doing that, you can use glClearColor to specify the alpha value of the colour. Although from my experience, that never works for the display, maybe it works for textures…If that doesn’t work, maybe you can try rendering a full screen quad before doing the black and white rendering to specify the alpha (worked for me in VEpi). Its a hack, but it might be worth trying it out…

And now I shall just sit here, on this exact chair until I get that screenie! :stuck_out_tongue:

DP

Ok, this is where I’m at right now:

http://www.cokeandcode.com/mm2/mm2-shadows.png

Kev

Wow - Looking good Kev!

Got a little bit further along, the screenshot above has been updated. I’m now using 512x512 shadow maps (one per shadow caster). With a bunch of clip planes defined to get some of the performance back and getting around 100 fps for a reasonbly simple scene (see screenshot) on my terrible hardware (ATI Mobility 7000 IGP).

Still tweening out performance a bit but its starting to come together.

Kev

If you have ~50% alpha, the shadows will be more realistic.

If you can’t find a way to do that without shaders, you can render a quad with glColor(1,1,1, 0.5) on top of your texture.

The only side-effect would be that when 2 shadows overlap, the overlap will be darker (even for 1 light-source) which is unrealistic.

That is very almost impossible to correct, unless you write all shadows to a seperate texture and render that on top of the entire scene. But well, that would be just wasting gpu-cycles by blocking the pipelines several times per frame.

Funny you should say that…

Currently I render the shadow textures to the back buffer (one texture per shadow caster). The shadows are rendered pure black on a white background. Since I have no alpha channel on my display I have to mask the shadows onto the scene using GL_DST_COLOR,GL_ZERO blending and hence can’t get a 50% alpha (at least I don’t think so).

At the moment, I can’t see anyway of using a single texture for all casters without using the ARB_depth_texture extension (which I don’t have). I can’t see any way of using any other blending since I don’t have alpha support on my display (16 bit mode).

I’m aiming at rubbish cards like mine so I guess the restrictions are what they are.

As a side note, I kinda prefer the black shadows since the whole thing is meant to look cartoony… but I’d appreciate any pointers where I might get peformance increase (it drops a fair bit with additional alien models) or where I might get smoother graphical effects.

Kev

Perhaps you didn’t understand me correctly: I meant rendering all shadow-textures to YetAnotherTexture and alpha-fading that one.
Anyway, that doesn’t really help you much, as it’s even slower than your current approach.

In my current project I render very simple shadows that are only projected on the ground, using only 1 texture. I agree that it’s not as fancy as projecting shadows at other objects, but you might wonder whether that’s realistisch for the hardware you aim for.

The basic idea is to render all objects to the ground-plane texture (black on white) - I did that with a custom projection matrix - and render the texture as a quad to the floor, with a certain faded alpha. Add some jittering over some passes and you’ll have truly high-res soft-shadows. It requires only 1 additional pass, so you can let many objects cast the shadow.

It might not be what you need at all, but if shadows on the floor are enough for you, it does the job.

Hmm… if you want to get really fancy, do your own ray-tracing in a 64^3 grid, put the data in a 3d-texture and project it in world-coordinates at your scene… hehe. That only really works for static scenes :slight_smile:

When I find something more usefull, I’ll tell you ::slight_smile:

Currently my thinking is I’ll either

a) Just remove shadows, too costly.
b) Replace proper shadows with simple faded circlular shadows beneath every object projected onto the surface below them (though this could quite costly since I still end up with needing a depth factor.
c) Leave it with what I’ve got, try to get the speed up a little bit and stick to about two enemies in a room (which is probably enough anyway)

Thanks. :slight_smile:

If it would be option B, then just layer 1 quad per object on top of the surface. Nothing fancy, no depth-factor required. The algorithm described in my previous post would be much nicer and only a bit heavier.

Now you’re using a isometric-projection, shouldn’t you search for algorithms for isometric shadows? It’s fairly easy to create a isometric-shadow-projection-to-a-plane projection-matrix thingy.