• Advertisement
Sign in to follow this  

Virtual Shadow Depth Cube Shadow Maps

This topic is 3942 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 ! :)

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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


Share this post


Link to post
Share on other sites
Hi zoret,

the virtual cube shadow mapping is almost working now. But not quite.
Here is a list of problems/questions which you maybe could help me with.

The lightvector I use to lookup the cube texture has to be in worldspace or rotation won't be handled correctly. Why is modelspace not working (when a rotation is applied to the shadow reciever)?

It looks like the depthshadowmap is projected onto everything. I have no idea how to solve this.
Here is a shader code snippet.

//vertex shader
output.lightVec = mul(pos, g_world) - g_lightPos_world;

//pixel shader
float4 shadowIndirectCoord = texCUBE(indirectionCubeMap, input.lightVec);
shadowIndirectCoord.z = 1.0f; //I'm pretty sure this is the problem!!!!
shadowIndirectCoord.w = 1.0f;
float shadow = tex2Dproj(shadowMap, shadowIndirectCoord).r;






Another thing I am interested in is the indirection texture. It gets filled with 16bit integers. Where does the mapping to texture coords take place (0.0f..1.0f)?

Thanks for all the input so far!

[Edited by - B_old on March 28, 2007 12:17:53 PM]

Share this post


Link to post
Share on other sites
there's a big error in your pixel shader because you destroy the y of your shadowIndirectCoord


float4 shadowIndirectCoord = texCUBE(indirectionCubeMap, input.lightVec);
shadowIndirectCoord.y = 1.0f; //I'm pretty sure this is the problem!!!!
shadowIndirectCoord.z = 1.0f;
float shadow = tex2Dproj(shadowMap, shadowIndirectCoord).r;





if your depth map is projected on everything it's just because you don't recompute a correct Z for your pixel depending the rendering API you use

the pixel shader should be something like that


float3 p = pixelPos - lightPos; // in same space (world or local, as you want)

float3 pAbs = abs(positionInLight.xyz);
float MA = max(max(pAbs.r, pAbs.g), pAbs.b);

float2 redirectedUV = texCUBE( indirectionMap, p ).xy;
float4 shadowUV;
shadowUV.x = redirectedUV.x;
shadowUV.y = redirectedUV.z;

// correct Z
shadowUV.z = (-1.f / MA) * LightProjParams.x + LightProjParams.y;
shadowUV.w = 1.0;

float shadow = tex2Dproj(shadowMap, shadowUV).r;





with these projection parameters :


LightProj.SetPerspectiveFov(FOV, AspectRatio(1), Near, Far)
LightProjParams.y = Far / (Far - Near)
LightProjParams.x = Near * LightProjParams.y


Share this post


Link to post
Share on other sites
Quote:
Original post by zoret
there's a big error in your pixel shader because you destroy the y of your shadowIndirectCoord

Heh, that was just a typo while I posted...

I will try the thing with the LightProjParams. Does this mean that I cannot render the shadowmap with different near/far values for each (virtual) cube face?

float3 p = pixelPos - lightPos;
float3 pAbs = abs(positionInLight.xyz); //is positionInLight the same as p?



I just wanted to mention again, that if I use texCUBE() with a model space vector, rotation will not be reflected properly by the shadowmap. Any idea?



[Edited by - B_old on March 28, 2007 12:06:05 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by B_old
Quote:
Original post by zoret
there's a big error in your pixel shader because you destroy the y of your shadowIndirectCoord

Heh, that was just a typo while I posted...

I will try the thing with the LightProjParams. Does this mean that I cannot render the shadowmap with different near/far values for each (virtual) cube face?
*** Source Snippet Removed ***


indeed you can't have different projection values for each face

Quote:
Original post by B_old
I just wanted to mention again, that if I use texCUBE() with a model space vector, rotation will not be reflected properly by the shadowmap. Any idea?


why not ? that should work in model space as in world space or light space
you just have to take care of space you use.

Share this post


Link to post
Share on other sites
So, it seems to work now. (I made a silly mistake before)
Thanks a lot for the help!

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement