Virtual Shadow Depth Cube Shadow Maps

Started by
13 comments, last by B_old 17 years ago
Hi, I took a look at this demo from nvdia and would like to know if someone can help me to understand some of the concepts. Particularly how the indirection cube map is used. With normal shadow mapping, I render the depth to a texture and then pass this and lightView * lightProj * shadowBias to the shader (D3D). One thing I understand is, how they solve lightView part, as there would be 6, one for every face in the cube? It is also not quite clear to me which size the indirection cube map should have relative to the size of one "virtual depth cube" face. Thanks for any hints.
Advertisement
The basic ideas of cube shadow mapping are described in GPU Gems and the more advanced ideas are described in ShaderX3.
What I would be interested in is, if the virtual cube idea still has advantages on the 8x00 series of cards.
Quote:Original post by wolf
The basic ideas of cube shadow mapping are described in GPU Gems and the more advanced ideas are described in ShaderX3.
What I would be interested in is, if the virtual cube idea still has advantages on the 8x00 series of cards.


I suppose those resources are not online?
Does the 8x00 series support depth cube maps?
Quote:Original post by B_old
Does the 8x00 series support depth cube maps?

In D3D10 you can probably create a 32-bit float resource, and a DepthStencil view, as well as a ShaderResource (cube map) view. That said even if you can't, you can certainly render to a standard cube map in a single pass (if desired).
Quote:Original post by AndyTX
In D3D10 you can probably create a 32-bit float resource, and a DepthStencil view, as well as a ShaderResource (cube map) view. That said even if you can't, you can certainly render to a standard cube map in a single pass (if desired).


Hm, how can I render to a cube map in one pass? I was always under the impression that you needed one pass for every face.

Also, what do you mean by standard cube map? The whole point is to render to a depth stencil format.
Quote:Original post by B_old
Hm, how can I render to a cube map in one pass? I was always under the impression that you needed one pass for every face.

In D3D10 a cube map is just a texture array, and you can render to multiple levels of that at once.

Quote:Original post by B_old
Also, what do you mean by standard cube map? The whole point is to render to a depth stencil format.

That's probably possible in D3D10, but even if it isn't, there's not much of a hit for rendering to a standard surface instead, unless you're rendering a huge shadow map which is unlikely if it's going to be used for cube mapping.
Well, actually there is quite a hit on performance, at least on my hardware.

But we somehow we left the original topic.

So if anyone is still interested in helping me out with this, feel free.
I've a working implementation of this technique on Direct3D9
If you want some help don't hesitate to ask me.

The indirection cube map is used to transform a cube map space UV (3D vector) in depth map space UV (2D vector)

For example your depth map could be like that

|----------|
|+X|+Y|+Z|
|----------|
|-X|-Y|-Z|
|----------|

and your X face of your indirection cube map will just give you UV coordinates corresponding to the X face in the depth map
repeat that for each face.

for each view of your point light, instead render the scene in a cube render target, you just render it in the depth map (size of depth map = width*height*6) using viewport and scale to write in the good face of your depth map

the indirection cube map doesn't necessarly need to have the same size than your depth map, you just need to take care of face border (just render with a FOV greater than 90°, and deal with that when you create your indirection cube map)

Is it clear enough ?

point light shadows will ber really simpler with D3D10 ! :)
zoret:

Ok, I render each view of the point light (== 6) to the depth map. That is no problem.
I think I understand the concept of the indirection cube map. But how big should it be? Why is not 1x6 enough? That would return an offset so that I know where to start reading the shadowmap.

And now the thing I don't understand at all.
With a spotlight, the light only has one view/proj. This is passed to the shader and used to apply the shadow.

How are the 6 views of the point light handled?
Hi B_old,

first, do you have a point shadow implementation using a classic cube render target (float rendertarget of course, just store the distance from each vertex to the light / light radius) ? because this concept is very simple to implement when you have already all the basics of point shadows
you just have to add this famous indirection cube map in order to use a classic depth map (and so you will be able to have very nice soft shadows with PCF...)

the indirection cube map could have exactly the size of your cube render target
for example if your cube render target is 512*512 for each face (so 512*512*6) you can have an indirection cube map equals to 512*512 (for each face)
as you need to store the uv in order to map in the depth map, you will have to use a format with 2 float channels (16b is enough)
if your card support bilinear interpolation on float texture you can use a smaller texture (16*16 for each face)

here is the fragment shader for the final lighting phase (checking shadow map)

float3 vModelSpaceVertex2LightVector = vModelSpaceVertex - vModelSpaceLightPos;
float2 vRedirectedUV = texCUBE( indirectionCubeMap, vModelSpaceVertex2LightVector).xy;
float KShadow = tex2D(virtualshadowDepthMap, vRedirectedUV);

with a classic implementation you will have something like that
float3 vModelSpaceVertex2LightVector = vModelSpaceVertex - vModelSpaceLightPos;
float DistToLightInShadowMap = tex2D(shadowDistanceToLightMap, vModelSpaceVertex2LightVector);
if (DistToLightInShadowMap < currentDistanceToLight) KShadow = 1
else KShadow = 0

of course no bilinear filtering in this last implementation (shadow is 0 or 1 !)

the matrix to use is the view matrix computed and used to update positive Z face
in fact it depend which space you choose

again you should first try to have a classic implementation

R32 cube render target
for each face, you use classic pass and correct view matrix for each face to store distance from vertex to light
just use always the same zbuffer (don't forget to clear it at the beginning of each face)

then for you lighting/shadowing pass
use the PositiveZ view matrix and compare each z with values computed in the cube render target

after that you could try to optimize your implementation

hope it helps


This topic is closed to new replies.

Advertisement