   Some quick XNA questions
Question 1: Can I get the output of a RenderTarget2D without calling device.SetRenderTarget(0, null)? For example, can I replace it with another rendertarget (such as a dummy target)? I tried, but cannot seem to get any contents? It's just that stupid purple color. Setting the rendertarget to null works, but setting it to a dummy fails.The reason I'm asking is because I'm sick of that purple color.Question 2: Can I combine two effects? I have a deferred renderer and I would like to add a more flexible material system. What I would like is something like a function pointer I suppose, which would preferably be able to call a function from another effect. Any ideas?Example: float3 (*GetNormalAtPixelFunc)(float2 texCoord, float3 normalFromVertexOrWhatever);Or something like that. Is this at all possible? Is there any other way to share functionality among effects without having to copy-paste all functionality or have one huge effect?   
Quote:Original post by DvDmanDTQuestion 1: Can I get the output of a RenderTarget2D without calling device.SetRenderTarget(0, null)? For example, can I replace it with another rendertarget (such as a dummy target)? I tried, but cannot seem to get any contents? It's just that stupid purple color. Setting the rendertarget to null works, but setting it to a dummy fails.The reason I'm asking is because I'm sick of that purple color.You can call GetTexture() as long as that RenderTarget is not currently set onto the device. Switching to another RenderTarget is fine, as is switching to the backbuffer (which is what happens when you set null). The default behavior for render targets is that they are cleared to purple every time you set it onto the device. So if you were to render something to a render target, switch to another render target, and then switch back, you'd lose its contents. This behavior is mainly for compatibility with the Xbox 360, where preserving render target contents requires a manual copy into eDRAM which is performed by the framework. If you want to change this behavior you can pass RenderTargetUsage.PreserveContents when creating the RenderTarget2D. However in most most cases you don't want to be setting a render target more than once...switching render targets is expensive, so if possible it's best to do all of your rendering to a render target before switching it out.Quote:Original post by DvDmanDTQuestion 2: Can I combine two effects? I have a deferred renderer and I would like to add a more flexible material system. What I would like is something like a function pointer I suppose, which would preferably be able to call a function from another effect. Any ideas?Example: float3 (*GetNormalAtPixelFunc)(float2 texCoord, float3 normalFromVertexOrWhatever);Or something like that. Is this at all possible? Is there any other way to share functionality among effects without having to copy-paste all functionality or have one huge effect?The easiest way to do this is to put the common functionality into some functions in a separate file. Then you can have both effect files #include the file with the common functions, so that they can both use them.;  Thanks alot. I think I understand the basic reason for the purple thingy. Clearing the entire backbuffer every time I switch rendertarget is annoying though. Not to mention slow (I do shadow mapping and deferred rendering, easily 10+ rendertarget switches per frame). I wish I could unset a rendertarget without setting it to the back buffer. I figured I'd set some tiny dummytarget instead which would at least have a smaller fill area, but calling shadowMapRenderTarget.GetTexture() seems to return an empty texture unless I set the active render target to null. I don't get any exceptions or anything, just a purple texture.Any ideas?;  Well if you're only targeting PC then I would just use PreserveContents and forget about it. If you're targeting 360 it's a little trickier...in your case it may still be worth it to use PreserveContents, so that you can keep re-using your shadow map render target.Which render target do you render your lighting to? You'll have to switch to that anyway before you can use your shadow map.   ;Quote:Original post by DvDmanDTThanks alot. I think I understand the basic reason for the purple thingy. Clearing the entire backbuffer every time I switch rendertarget is annoying though. Not to mention slow (I do shadow mapping and deferred rendering, easily 10+ rendertarget switches per frame). I wish I could unset a rendertarget without setting it to the back buffer. I figured I'd set some tiny dummytarget instead which would at least have a smaller fill area, but calling shadowMapRenderTarget.GetTexture() seems to return an empty texture unless I set the active render target to null. I don't get any exceptions or anything, just a purple texture.Any ideas?I'm not sure why you need a dummy rendertarget?  You're going to be rendering to something eventually, why not just set that one?  Once you've set the new render target, calling GetTexture() on the old one should work.  If it's purple, it means you didn't draw anything to it, so your code isn't doing what you think it's doing :-)   ;  I'm pretty sure I do draw things to it. If I SetRenderTarget(0,null) then do a prevTarget.GetTexture() it works fine. If I do SetRenderTarget(0, dummy) then do prevTarget.GetTexture() all I get is nothing at all. Now sure, I should set the next real rendertarget instead of the dummy, but I don't see why what I'm doing shouldn't work. What I'm trying to do is not to preserve the contents of my targets, I already know how to do that. I don't mind the clear. What I'm trying to reduce here is the fillrate. Say I'm doing 10 rendertarget switches per frame and have to switch to backbuff in between. With a resolution of 1024x768x4 and a framerate of 60 fps, that should equal to writing something like 1.8GB unecessary data per second which sucks.;  Can anyone verify they can do device.SetRenderTarget(0, someTarget); *draw stuff*device.SetRenderTarget(0,otherTarget);Texture2D = someTarget.GetTexture();and actually get the results of the stuff drawn? I can't seem to get it working. Also: how does xna recycle rendertarget textures? Or how does it work? Does each RenderTaget2D have a texture and a surface which it draws to, and then it copies the data from that surface to the texture when GetTexture() is called?   ;  Hi again.I think I figured most of this out. In case anyone gets a huge amount of headache over something releated to this, here's some things to note:When you call device.SetRenderTarget(idx, someTarget), XNA clears that target to some dark purple color. When you device.SetRenderTarget(idx, null), it clears the back buffer to that dark purple color AND clears the depth buffer. Notice how it does not clear the depth buffer for rendertarget2ds.So I got purple results because nothing could be drawn since the depth buffer wasn't cleared when using the dummy targets. Seems to me like unexpected inconsequent behavior by XNA. Setting rendertarget can change device state and/or renderstates. In particular, the viewport seems to get reset. For some reason, I only see problems with this when using my dummy targets, but that's probably something in my code. So, I'm sure there are great reasons for these behaviors, but I sure as hell wouldn't mind seeing it as a remark on the SetRenderTarget documentaion page.I seem to get 5-20% performance gain by using dummy targets on old hardware in case anyone is interested. My next plan is to stop using the z-buffer when it is not needed instead of clearing it, I guess that will have more of an effect.   ;  Yeah, things to behave a little strangely with the depth buffers.  Version 4.0 of the XNA framework is going to address some of the usability concerns with render targets though:http://blogs.msdn.com/shawnhar/archive/2010/03/26/rendertarget-changes-in-xna-game-studio-4-0.aspxAnd actually - I wonder if the difference you're seeing (depth buffer being cleared in one case, but not in the other) has to do with tiling.  What you're seeing, at least in some cases, is that the depth buffer has essentially been preserved across render target switches.  But if your RT + depth buffer is large enough to cause tiling, there is *no way* the depth buffer could be preserved across RT switches (at least not without PreserveContents causing the copying back into EDRAM).  But if tiling is not happening, then the depth buffer could just sit in EDRAM across RT switches.  Still an inconsistency in the API though.[Edited by - phil_t on May 12, 2010 9:01:08 PM];  Depth buffer clears are tried to the RenderTargetUsage of the render target being set. If it's PreserveContents it stays, if it's DiscardContents it goes. For switching to the backbuffer it depends on the RenderTargetUsage property of the PresentationParameters you used when creating the GraphicsDevice.So again on PC if you use PreserveContents for everything, everything pretty much works "like it should" (AKA how it does in native D3D9) with no performance penalty. If you do this on the 360, you'll pay the cost of render target and depth buffer contents being restored in eDRAM. Also on the 360, the contents of the stencil buffer are never preserved.   