Brandon Bloom

I'm having some problems getting my shadow maps to work on the Xbox 360, but they work great under Windows. There seems to be some weird SetRenderTarget and ResolveRenderTarget behaviors I don't really understand on the Xbox 360.

IĄ¯ve got too much code to post here, so some pseudocode is at the bottom.

I realize it may be hard to help without seeing the actual code, so if more information is needed, IĄ¯d be happy to provide it. Any advice on what I might be doing wrong is greatly appreciated.

Thanks!

clear render target to ambient light color

for each light
{
set render target to light's depth map
clear render target
draw scene depth from light's perspective
resolve render target
}

for each light
{
set render target to some offscreen buffer
draw light's contribution to the scene
resolve render target

set render target to null
draw offscreen buffer as full screen quad with addative blending
}

set render target to offscreen buffer
clear offscreen buffer
draw scene, full bright
resolve render target

set render target to null
draw offscreen buffer as full screen quad with multiply blending

present



Re: XNA Framework My shadow maps work on Windows, not Xbox 360

gmcbay

Since there have been multiple posts by different people about their shadow maps not working on the 360, I ripped out some of my shadow mapping code (which works on both the PC with Nvidia and ATI cards and also the 360) and made a small demo of it. The code was hastily ripped out of my larger game so there is some oddness to it (the light and camera classes are barely classes, etc) and so it shouldn't be used as a good example of coding style, but its small and focused and hopefully looking at it you might get some idea as to what you're doing differently and thus why your shadow code is failing on the 360. Or you could just use this code as a starting point for your own implementation (consider what is in the demo as public domain).

It is a very simplistic shader-based shadow map implementation, the code in my actual game uses PSSM for much better looking shadows with smaller render target textures, but what is in the demo works and is relatively simple to follow:

http://www.georgemcbay.com/xna/ShadowMapDemo.zip






Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Brandon Bloom

Thanks for the sample code. For the record: My PC has an ATI Mobility 9700.

Your demo only supports a single light. The pseudocode I provided is a (highly unoptimized) multi-light solution.

I understand that the 360 only has a single render target and works with multiple targets through copies. I am using the frame buffer for intermediate composition, is that bad Should I be doing all composition in off screen buffers and then copy that to the frame buffer as my very last operation before presenting

I'm going to try to write a small reproduction case tomorrow.





Re: XNA Framework My shadow maps work on Windows, not Xbox 360

gmcbay

Yeah the demo is only for a single light, and only for a directional light.  My full game supports more features than that, but I wanted to keep it as simple as possible, though in doing that perhaps it doesn't address the problem you are having.  I think a lot of the issues other people are having with shadow maps have to do with trying to use the same depthstencilbuffer information for the frame buffer and their shadow map render target, which my demo addresses. 

It is true that the 360 doesn't support multiple _active_ render targets, but I don't think that should be an issue in your case unless you are trying to process multiple light render targets at once through your shaders.  I got the impression that you're looping the lights one at a time from the C# code, which should work fine.  Using the frame buffer for composition on the 360 shouldn't be a problem, though I guess it is possible that the default blend modes for shaders might be different on the PC vs the 360, which could be a problem if you're relying on any of the default modes, but that is pure speculation and I don't know if its true that the modes are different.. someone on the XNA team should know for sure, though.  In any case it should be really simple to modify the code to composite to a render target rather than the frame buffer and just present that as a screen aligned quad at the end.  It is probably worth doing that anyway to compare the performance of that vs the frame buffer on the 360 side.

If you post a small sample that exhibits the broken 360 behavior, I'll take a look and see if I find anything obviously amiss.

 

 

 






Re: XNA Framework My shadow maps work on Windows, not Xbox 360

DudleySoft

Hi George

The problem I'm having isn't to do with the DepthStencil buffer, but with the actual render target, for some reason it seems to be treating the render target as SurfaceFormat.Color instead of SurfaceFormat.Single, which explains why I get values back that make no sense wherever I've written to the surface, I've built a cutdown version of my current source without the audio files in which is a lot smaller than the original, you can download it from (it's 1.3MBytes):

http://www.dudleysoft.org/HDL_Test.zip

There's lots of odd code that's commented out that I was using to test various solutions in the code, I've moved the shadow target code out of GameMode and into Game1, I've tried rendering my models the same way you're doing it, and it still refuses to work, there's commented out code in the IntroPage, TitlePage and Mission classes that will draw the current shadow map to the screen. You can check out how it should appear on the PC and then see how it actually appears on the 360.




Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Jon Watte

A lot of people are reporting problems with various backbuffer or render target formats other than Color. As far as I can tell, the Xbox runtime currently just assumes everything is Color, and you can't use anything else. You'll have to file a bug on Connect about it.






Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Brandon Bloom

I've created a tiny project which nicely demos the differing behaviors from Windows to Xbox 360: http://www.pages.drexel.edu/~bb682/misc/RenderTarget360Test.zip (I used "#region Added" to indicate any code I added)

The expected behavior is to draw a "1", a blank space, and then a "3" on a cornflower blue background. This behavior works fine on Windows, but not on 360. On the 360, only the 3 is drawn. I suspect this has to do with the render target hardware differences mentioned above, but this behavior needs to be documented as the Windows behavior is much more logical.

I think this experiment has armed me with the knowledge I needed to fix my shadow maps, I will keep you all posted :-)

Thanks,

Brandon





Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Jon Watte

I think the right way to do it is to make the Windows version explicitly clear the color buffer when switching render targets, so it behaves the same. At least in debug mode (although clear is a really cheap operation these days, so it might not hurt too much in release mode, either).






Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Brandon Bloom

Quick update: I've fixed my shadows on the 360 and even reduced the number of SetRenderState calls by about 2*nLights on both platforms with some algorithmic changes.

Thanks for the help.

I'm going to file a bug highlighting the differing behaviors. Maybe some better documentation is all that is required to resolve this problem.





Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Mitch Walker - MSFT

Brandon, did you file a bug on this If so, can I get the Id




Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Brandon Bloom

I sure did: 249078





Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Ralph Egas

Hi,

Shadowmapping is working for me on 360 using all information from posts and my own experience. Still, I would like to render my scene to the depth buffer only (turn color output off) just once and then have multiple passes, one for each light using DepthFunction == Equal to kill overdraw.

So far I've got this only working if I do this preceding *every* lighting pass, because my shadowmap generation render I have to do for every light before I accumulate to the color target seems to overwrite my depthbuffer. This happens eventhough I've created an individual depthbuffer for my shadowmap, which I acquire when generating my shadowmap.

So currently in pseudocode my algorithm works like this:

for each light do
{
Render scene from light to shadow target using shadow depthbuffer, outputting depth info in x
Render scene from given camera to color target using default depthbuffer, outputting nothing to color target, just z-write
Render scene from given camera to color target using default depthbuffer, outputting lit color info, using z == equal
}

This already kills some overdraw (it prevents complex shaders from doing expensive lighting calculations for pixels that get overwritten). *But*, There's still the overhead of outputting z-info for every light.

I'd rather have it like this:

Render scene from given camera to color target using default depthbuffer, outputting nothing to color target, just z-write

for each light do
{
Render scene from light to shadow target using shadow depthbuffer, outputting depth info in x
Render scene from given camera to color target using default depthbuffer, outputting lit color info, using z == equal
}

I tried this approach, but somehow the shadow generation pass kills the values in the default depthbuffer I use to prepare z data which should remain invariant over multiple light passes. I vaguely remember that on the 360 all videomemory is managed, including depthbuffers and that upon a ResolveRenderTarget (which happens once the shadowmap is generated) the memory becomes invalid. As this holds for depthbuffers as well *and* the fact that you can't GetTexture a depthbuffer there doesn't seem to be a way to keep this memory persistent.

Of course this is pretty inconvinient in terms of performance as the example above shows. Any light on this shady topic would be highly appreciated.

Cheers,

Ralph





Re: XNA Framework My shadow maps work on Windows, not Xbox 360

Shawn Hargreaves - MSFT

There is no way to do this on Xbox. There is only a single piece of hardware depth buffer memory, so whenever you switch buffers, that destroys whatever was in the previous depth buffer.