Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » 3D Shadows

This thread is locked; no one can reply to it. rss feed Print
3D Shadows
DanielH
Member #934
January 2001
avatar

I was playing SpongeBob's Battle for Bikini Bottom. Make fun of me, it's ok.

I noticed something I didn't think about before.

They figure where SpongeBob is and they place the shadow on the first polygon's that are straight down from a position above him. So If there is nothing above him then the shadows are under him as it should be. But when he walks under an umbrella, the shadows are on top of the umbrella.

Is this normal in games?
Do they do this for speed?

Thoughts please. Not just 'Yes'. ;)

I'm curious because My 3D game I'm working on could use shadows.

Kitty Cat
Member #2,815
October 2002
avatar

Quote:

Is this normal in games?
Do they do this for speed?

No. Yes.
;)

I don't know what kind of game that is, so I can't really guess at the technique they're using (it's not one I've played with, at least).

Today, shadows are mostly done using shadow mapping. That's where you take a snapshot of the scene from the light's POV, getting the depth information, then using that when drawing the scene from the camera's POV, and any pixel that's farther from the light source than what's in the previously rendered depth texture, is in shadow. I personally don't like this method since it has a lot of aliasing, and it's not trivial to remove that aliasing, as well as having trouble with point lights (lights that shine out in every direction; which is pretty much every one). It is, however, fairly quick depending on the size of the depth texture.

Another technique used is shadow volumes (as seen Doom3, Quake4, etc). Those basically take the shadow casters, find the polygon edges between what's facing a light and what's facing away, and build a closed volume from the object to infinity. Using a stencil buffer, you can determine which opaque pixels are inside the volume, and shade accordingly. I prefer this method, even though it's a bit harder on the processor/card, because it works perfectly with point lights, and doesn't suffer from the same aliasing issues. It is, however, much harder to remove the hard edges.

--
"Do not meddle in the affairs of cats, for they are subtle and will pee on your computer." -- Bruce Graham

kikabo
Member #3,679
July 2003
avatar

In Spongebob because not all objects cast a shadow and because of these glitches it's likely that the game is using planar shadows. Each object that casts a shadow probably is projected into a texture and then that texture is alpha blended onto the object in shadow. Each vertices x,z coords in the shadowed object would correspond to the light occluder's shadow texture coords (plus the difference in object position).

The glitches are because it is working on an object by object basis and not polygon by polygon. When there are two shadow casters there has to be some logic to work out which object is shadowing which, it could be comparing centers, min y values etc but obviously in this case it is doing something wrong.

This method is limited pretty much to shadows formed by parallel light projecting directly down but it's advantage is that the shadows can be drawn in one pass with no special hardware requirements.

I use this technique and it work pretty well, the other down side is you don't have time to find Patric's last damn 20 socks for those last two spatulas! ;D

DanielH
Member #934
January 2001
avatar

I've given up on the socks. It's just too damn hard.

Arthur Kalliokoski
Second in Command
February 2005
avatar

I'm starting to fiddle with shadows in a car racing game, due to 4e6 vertices in the heightfield I don't want to do the two pass stencil thing. Complex objects such as cars will have a simple shape (like a close fitting collision box) to cast a shadow volume, and there's a vector opposite the light direction. If all three vectors from a shadow volume polygon hit the same ground polygon, it just draws a dark alpha polygon slightly above the ground (0.0001 height), else it has to check ground vertices being within the shadow volume and draw dark triangles accordingly.

Simply drawing a shadow directly underneath a car wouldn't look right with the texture already having shadows drawn on it that clearly indicate a low sun angle. Oh, yeah, the car shadow thing has to check if it's in a hillside shadow as well. It's getting complicated. I really should see if I can do a texture that has "feathering" at the edges for penumbra too.

They all watch too much MSNBC... they get ideas.

kikabo
Member #3,679
July 2003
avatar

Quote:

it just draws a dark alpha polygon slightly above the ground (0.0001 height)

If your worried about z-fighting (I think that's the term), you can do it this way (although the results are pretty much the same).

      glEnable( GL_POLYGON_OFFSET_FILL );
      glPolygonOffset( -0.5f, -0.5f );

      DrawShadow();

      glPolygonOffset( 0.0f, 0.0f );
      glDisable( GL_POLYGON_OFFSET_FILL );

Arthur Kalliokoski
Second in Command
February 2005
avatar

I tried the polygon offset thing and it didn't seem to make any difference for polygons, I got the impression it was only to make sure GL_LINES and GL_POINTS didn't get buried beneath polygons since the line code & polygon rasterizer worked differently...

They all watch too much MSNBC... they get ideas.

kikabo
Member #3,679
July 2003
avatar

Here's an example where two polygons are drawn at the same depth, press spacebar to change the pollygon offsets.

1#include <allegro.h>
2#include <alleggl.h>
3 
4void InitGL()
5{
6 allegro_init();
7 install_allegro_gl();
8 install_keyboard();
9 
10 set_color_depth (32);
11 allegro_gl_clear_settings();
12 allegro_gl_set(AGL_COLOR_DEPTH, 32);
13 allegro_gl_set(AGL_Z_DEPTH, 8);
14 allegro_gl_set(AGL_WINDOWED, TRUE);
15 allegro_gl_set(AGL_SUGGEST, AGL_COLOR_DEPTH | AGL_Z_DEPTH | AGL_WINDOWED);
16 if (set_gfx_mode(GFX_OPENGL, 640, 480, 0, 0) < 0)
17 {
18 allegro_message ("Error setting OpenGL graphics mode:\n%s\nAllegro GL error : %s\n", allegro_error, allegro_gl_error);
19 remove_allegro_gl();
20 exit(0);
21 }
22 glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
23 glClearDepth(1.0f);
24 glEnable(GL_DEPTH_TEST);
25 glDepthFunc(GL_LEQUAL);
26}
27 
28void Draw(GLvoid)
29{
30 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
31 glLoadIdentity();
32 
33 glEnable( GL_POLYGON_OFFSET_FILL );
34 
35 if(key[KEY_SPACE])
36 glPolygonOffset( 0.0f, 0.0f );
37 else
38 glPolygonOffset( 1.0f, 1.0f );
39 
40 glBegin(GL_TRIANGLES);
41 glColor3f(1.0f,0.0f,0.0f); glVertex3f( 0.0f, 1.0f, 0.0f);
42 glColor3f(0.0f,1.0f,0.0f); glVertex3f(-1.0f,-1.0f, 0.0f);
43 glColor3f(0.0f,0.0f,1.0f); glVertex3f( 1.0f,-1.0f, 0.0f);
44 glEnd();
45 
46 glColor3f(0.5f,0.5f,1.0f);
47 
48 if(key[KEY_SPACE])
49 glPolygonOffset( 1.0f, 1.0f );
50 else
51 glPolygonOffset( 0.0f, 0.0f );
52 
53 glBegin(GL_QUADS);
54 glVertex3f(-0.8f, 0.8f, 0.0f);
55 glVertex3f( 0.8f, 0.8f, 0.0f);
56 glVertex3f( 0.8f,-0.8f, 0.0f);
57 glVertex3f(-0.8f,-0.8f, 0.0f);
58 glEnd();
59 
60 glDisable( GL_POLYGON_OFFSET_FILL );
61}
62 
63int main()
64{
65 InitGL();
66 
67 while (!key[KEY_ESC])
68 {
69 Draw();
70 allegro_gl_flip();
71 }
72 return 0;
73}
74END_OF_MAIN();

Arthur Kalliokoski
Second in Command
February 2005
avatar

Well, that takes care of "learn something new every day" today! Thanks Kikabo!

They all watch too much MSNBC... they get ideas.

Go to: