Home » Community » Forums » Graphics Programming and Theory » Soft shadows - isn't there a better way?
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

Add Forum to Favorites |  Send Topic To a Friend | View Forum FAQ | Track this topic

Page:   1 2 »»

 Last Thread Next Thread 
 Soft shadows - isn't there a better way?
Post New Topic  Post Reply 
I have been doing a little reading up on real-time shadowing, and most peticularily, soft shadows. In some powerpoint presentation by Nvidia (GDC2002_RobustShadowVolumes.ppt - not sure where I found it, probably at www.nvidia.com somewhere) they were using the stencil buffer to tell where there should and shouldn't be a shadow. Now I will admit that I don't understand a lot of the math/technical stuff there.

Using just one light source would give sharp edged shadows. To get smooth edge shadows, they used 12 dim lights and the same technique to get soft looking shadows. The real interesting piece is right near the end of the presentation that they said that the Doom 3 engine uses this technique. They said that they (the people who wrote the presentation) where getting 8 frames per second on a Geforce 4 Ti 4600.

Now I realize that I don't understand a lot of this, but why isn't it possible to simply use 1 light and blur the contents of the stencil buffer to make things look soft? If the stencil buffer already has definite sharp edges, why can't each pixel of the stencil buffer be averaged with the 9 surrounding pixels to give a softer looking shadow while only using 1 light instead of 12? If the stencil buffer was 8 bits, why couldn't you do the original stencil testing into the last (lower) 4 bits, calculate the averaged/filtered stencil buffer into the upper 4 bits, then copy the upper 4 bits into the lower 4 bits and then clear the upper 4 bits, and rener?

Ascii diagram:
  
32 bit z/stencil bufer:
[24 bits for z buffer][8 bits for stencil buffer]
_ _ _ _ | _ _ _ _
upper bits | lower bits

averaging the 9 surrounding pixels, where 9 is the darkest possible value:
0|0|0
0|0|9
0|9|9
before averaging

0|1|1
1|3|9
1|9|9
after the surrounding 9 pixels aver averaged 
  

Why isn't this possible?

Moe's Site

 User Rating: 1622   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

This isnt possible because the stencil buffer does not work that way. Your making it sound like its a secondary framebuffer. Its not, its just a buffer which tells opengl which pixels to draw and which ones to not. When using the stencil buffer for shadow volumes, you are counting the number enters and exits for the volume at each pixel. Now in that new paper by nvidia, the places where there is no shadow will have a stencil of 0 and those pixels are the only pixels to be rendered to. If the stencil buffer contains any pixel that is non-zero it will not be rendered to. So you couldnt say if the pixels stencil value is 1 then render that pixel a little transparent and so on.

Also when they said that the new doom uses this technique, they meant stencil shadow volumes using a single light for every light source, not using a large cluster to get soft shadows. Soft shadows where present in the new doom are done another way. I heard someone say that Carmack may be using a texture shader as a filter to blur the shadows to make them soft but if thats possible im not sure how. But that isnt official so its not 100%.

You will probably want to read more about the stencil buffer.

Also keep in mind that these demos are getting a low framerate becuase they are not optimized engines and not made to run as fast as possible. They were made just to work and show off the new technique. Much much higher framerates are possible with that demo with enough optimizations.

-SirKnight

 User Rating: 1145   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Yeah, the soft shadows they are talking about have been around for a long time. All they did to achieve the effect was to take 12 jittered samples of the lightsource. They just created 12 different lights that made 12 different shadow volumes at different points on a light, thus simulating an area source. There is an old demo on their site that uses the technique with 8 samples if you want to check it out. Its not fast.

 User Rating: 1046   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

You can do such a 'faked' softshadow effect, if you use the alpha-buffer instead of the stencil buffer. This requires a bit of fiddeling with alpha-combiners + blending equation when rendering the shadow volumes (with masked R, G and B channels).

Then you can blur the alpha component of the frambuffer (RGB are still locked) in a separate pass, perhaps using the imaging subset.

In the last pass, you unlock RGB and draw a quad covering the whole screen with a blending equation taking into account the destination alpha (where your soft shadows are stored).

Result are nice realtime soft shadows.

/ Yann

 User Rating: 1996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by lunarss
There is an old demo on their site that uses the technique with 8 samples if you want to check it out. Its not fast.


I know, I have the demo and it does have some problems with banding in a decent sized window.

Yann L, that sounds like a rather interesting way of doing it. Has there ever been a demo thats done soft shadows in the way that you describe?

Moe's Site

 User Rating: 1622   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:

Yann L, that sounds like a rather interesting way of doing it. Has there ever been a demo thats done soft shadows in the way that you describe?


Hmm. I'm not aware of any demos/tutorials/open engines using that technique. I implemented it in my own engine some time ago, and it works great (and it isn't that different from the stencil buffer method either, from a code POV). It has some pitfalls though, eg. it doesn't work in 16bit mode (no alpha buffer). And the blurring pass is somewhat critical (performance-wise). If you have HW imaging subset support, then it's no problem at all. Otherwise, you can copy the alpha component to a texture and jitter multiple quads using it as an alpha texture. This is reasonably fast. But don't try to blur it with the CPU, this will require a framebuffer readback, and will certainly kill your framerate.

/ Yann

 User Rating: 1996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

were getting some nice soft shadow results on the ps2...but we're cheating. the artist builds the light, then builds a shadow map which then gets animated to match the light. it doesnt work in all cases, but for the ones that it does it looks sweet.

there are some really nice tech demos running on the gamecube doing soft shadows, but again this is using an approach similar to the stencil buffer technique used by pc cards. in a real game scenario, id rather spend my precious cpu and gpu time doing things that are pertainent to the game...like having more critters on screen.

 User Rating: 1015    Report this Post to a Moderator | Link

The problem with using cookies (I think thats what they are called - rendering the scene from the point of view of the light, and using that texture as a sort of lightmap for the objects) is that you don't really get self shadowing unless you do a combination of the two techniques.

You do make an interesting point AP, in that shadows shouldn't be the only focus for a game engine.

Moe's Site

 User Rating: 1622   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

From what I understand, the fastest current way to do a "soft shadow" is to use projective textures, and use a fairly lo-res texture, letting the texture filtering blur it to a soft shadow. I can't really comment too much on this, as I have never implemented the technique. Can anyone else shed some light on the effectiveness/suitability of this technique? (omg that was a shitty pun )

Also, an OT comment on whether shadows would add to gameplay.

While it certainly shouldn't be the main focus of an engine, I think that in certain genres/situations (such as the FPS) shadowing has the potential to enhance gameplay substantially... imagine how much more strategic a game could be if players couldn't camp just around a corner (or conversely, rush someone) because their shadow gives them away to their opponents... sweet

 User Rating: 1030   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:

The problem with using cookies (I think thats what they are called - rendering the scene from the point of view of the light, and using that texture as a sort of lightmap for the objects) is that you don't really get self shadowing unless you do a combination of the two techniques.


That's shadow-mapping. You get full self shadowing and it works by rendering the scene from the light POV, and saving the depth buffer as a texture (the shadowmap). It is fully hardware accelerated on GF3+, and semi-hardware on GF2. The quality *highly* depends on the resolution of the shadowmap. If the resolution is good (2048*2048 or more), then the quality is impressive. Performance is also not bad, but it burns one texture unit for the depth iterator / compare. But due to it's very high texture resolution requirements, shadow mapping are currently only useful on small scenes.

/ Yann

 User Rating: 1996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

we are using shadow maps for our entire world. however they are pre-generated, by our tool chain, from the given scenes lights and geometry and cannot animate. Yann is absolutely correct in that they can be quite expensive because your eating up texture space and the extra pass across a given poly. plus the results can vary depending on the resolution you choose for the shadowmap and how subdivided your world is.

the special cases i mentioned above are when the artist explicitly whats a certain look. he or she has the capability to get that look without eating up the graphics processing time, except to run that particular animation.


 User Rating: 1015    Report this Post to a Moderator | Link

Ah, so thats what shadow-mapping is. I knew that the Geforce 3/4 had some sort of hardware shadows, but I wasn't quite sure how it worked.

If I am not mistaken, that Abes Odworld for the Xbox used shadow mapping.

Moe's Site

 User Rating: 1622   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Just an idea, but wouldn't nice shadows be possible by having each "shadow" be a seperate polygon in the world? I mean, with a little bit of math it should be easy enough (and not too expensive) to calculate the edge vertices of each shadow, and just draw this poly to the screen as a black, semi-transparent surface.

 User Rating: 1024   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Q3's "fake" shadows do that I think ( there are two types remember? )

Death of one is a tragedy, death of a million is just a statistic.

 User Rating: 1552   |  Rate This User  Send Private MessageView ProfileView Journal Report this Post to a Moderator | Link

Note that shadows can't just be softened, there's another problem with shadows.

Imagine a high wall with a sun shining. The shadow is quite sharp at the point where the wall is stuck in the ground. But the greater the distance you get from the object casting the shadow to the object 'getting' the shadow, the softer the edges of the shadows become. Gee...

I haven't noticed this effect in a game yet, I'd like to hear if anybody has made some demo on this.

 User Rating: 1077   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

yeah coelurus, I have thought of that. The people who are making No One Lives Forever 2 found some way of simulating that. But whats worse, having soft shadows or having hard edged shadows?

Moe's Site

 User Rating: 1622   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:

But whats worse, having soft shadows or having hard edged shadows?


You should have both. In reality, direct sunlight creates almost 100% hard shadows, since it can be viewed as directional light at a small scale. So simulating sunlight using a stencil-type method is very accurate.

The other type of diffuse light you have in reality is indirect light. This is created by the general skylight, interreflection of light on surfaces and interreflected sunlight. It produces soft shadows, and the degree of 'softness' is variable. The best way to simulate this kind of lighting is radiosity, and (highres) lightmaps at rendertime.

Combining both methods in an engine can be very easy or extremely difficult, depending on the exact result you are expecting. If you want really realistic lighting, then you'd have to take things like wavelength, atmospheric multiple scattering, absorbtion, etc.. into account. Bye bye realtime...

/ Yann

 User Rating: 1996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
Original post by Brobanx
Just an idea, but wouldn't nice shadows be possible by having each "shadow" be a seperate polygon in the world? I mean, with a little bit of math it should be easy enough (and not too expensive) to calculate the edge vertices of each shadow, and just draw this poly to the screen as a black, semi-transparent surface.


thats what a shadowmap is. you have a tool, off-line, that takes in all the worlds geometry and lights and it either 1)builds a shadowmap texture (greyscale and/or additive) that gets mapped onto the existing world geometry as a second pass texture or 2) you have it "bake in" the colors and shadowing figured out by your lighting process directly into the vertices of the world. the second option can yeild very nice results when your world is highly subdivided..you dont want to color vertices when youve got huge ground polygons that stretch for hundreds of feet, else youll get bad blending across the diagonal.

the problem with building extra geometry for shadows and not using the existing geometry is that on most hardware youll get z-buffering problems with the created geometry due to floating point (or in some cases fixed point) errors..unless of course youve got a sweet render order/priority system that can handle these z-buffering and drawing order problems.



 User Rating: 1015    Report this Post to a Moderator | Link

quote:

thats what a shadowmap is


Nope, that's not shadow mapping. That's simply precalculated lightmapping. The lighting values are prestored on a map, which gets applied at rendertime by multiplying (or adding) the lighting values to the textured polygons.

Shadow mapping is different. A shadowmap is a *depth* texture, it contains depth (z) values, that represent the zbuffer from the light's POV. Then later, while rendering your normal camera view, this depth map is applied to all faces in a secondary unit, using a special kind of projective texgen. You also interpolate a z-value at each vertex. Now at every fragment, the interpolated z-value is compared to the light's zbuffer (the applied shadowmap), to determine if that particular pixel would be 'visible' to the lightsource (it is lit in that case).

More information about real shadowmapping at nVidia's site here.

/ Yann

 User Rating: 1996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

coelurus:
You can create soft shadows fairly easily using shadow maps. You need to access the shadow surface and apply a gradual blur from bottom to top. The amount of blur should be based on how many rows of pixels you're processing. Thus, short shadows would end up receiving less blur than tall ones.

Optimization is critical here. If your image processing code isn't very fast, then you might as well use multiple light sources, because both techniques will be slow.

 User Rating: 1168   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link


yann l, yes, you are correct..i described the pre-calculated lightmapping. when most of your game world does not animate, why waste gpu time figuring stuff out that could be done off-line, especially when maintaining a good and constant framerate is of utmost importance?




 User Rating: 1015    Report this Post to a Moderator | Link

AP:
sure, most of the games out there use lightmapping, and it is definitely a good method (esp. since you can use ultra-realistic, but totally non-realtime, lighting models such as radiosity to calculate them). Lightmapping is without doubt the system that achieves the most realistic lighting of all the ways that were proposed on this thread. But it takes up lots of memory, esp. if you have very large game worlds (as in RPGs). And precalculated lightmap animations do look awesome, but they lack interactivity.

And sometimes it is better to waste some GPU cycles on a full-realtime shadow, than having non-stop cache thrashing and swapping because of your 1GB of precalc lightmap data...

But my point was more about the term 'shadowmapping'. It is often 'abused' even by professionals. "Shadowmapping" refers to a well defined technique (the depthmap/light-zbuffer one), preculated intensity maps are lightmapping (whether they actually store light or shadow values, ie. they are added or multiplied). This ambiguity often creates confusion for newcomers in the domain: they heard of shadowmapping, ask for a tutorial/example, and you give them a *real* shadowmap example, when they actually were looking for lightmapping.

Oh well, let's not fight about terminology

/ Yann


 User Rating: 1996   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

quote:
It is often 'abused' even by professionals.


no doubt about that!

yeah and they do take up some space, thats where the second method comes into play. the artist is able to select on a per object basis, within maya, what method to use, be it lightmaps or vertex coloring. we have still yet to implement our realtime shadow solution, weve currently got the standard poly mapped with a circle of "shadow" that gets cast down onto the floor beneath the player..for the ps2 i think we are going to go with a projected volume method (ala jax-daxter), but for gamecube and xbox the true shadowmap method you described will be, hopefully, implemented before we ship...

 User Rating: 1015    Report this Post to a Moderator | Link

First off I'd like to correct whoever said that stencil shadows are very realistic for shadows from the sun. Although the sun is, for all practical purposes, infinately far away, it is still 3 degrees across (or in other words, very big). Most lights are no-where near 3 degrees across from any normal viewpoint. That means the shadows are very soft. Look at the shadow of a tree some sunny day, you will see very large penumbra's where the light goes between the leaves.

I did invent a way of using the stencil shadow method for soft shadows, but I need a floating point buffer of some sort instead of a stencil buffer. What you do is render the scene in ambient lighting, read off the depth buffer (ouch) and pass it to a shader you use for rendering the shadow volumes. The shadow volumes are the same as normal. The shader first works out how big the penumbra (soft bit) should be using the distance to the start of the shadow volume and the distance to the light. Then it compares the depth of the pixel it is curently rendering with the one in the depth buffer it has been passed as a texture. It then adds to a buffer which probably doesn't exist a number between 0 and 1. If the pixel being rendered is more than half the penumbra size in front of the stored depth 0 is added. If it is more than half the penumbra size behind, 1 is added. Anything inbetween is something inbetween. Then you do it all again for the back facing polygons only subtracting. Then when the lighting is rendered you just multiply it by 1-non existant buffer before you clamp it to 0-1. You could at least compress it into the alpha buffer (that is floating point before rendering and a byte after right?).

Man, I don't sound my age.

[edited by - RAZORUNREAL on May 12, 2004 1:49:28 AM]

 User Rating: 1257   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I started reading this thread and thought Yann L came back

This thread is 2 years old.

 User Rating: 1015    Report this Post to a Moderator | Link
Page:   1 2 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: