RenderTargets draw order in XNA
I think I am fundamentally misunderstanding the way render targets work. In my understanding RenderTargets are just Textures that the spritebatch draw calls draw to.
So I tried this code to render GUI windows in order to make sure they can only draw in their client area and its cropped outside that.
for (int i = Controls.Count - 1; i >= 0; i--)
{
RenderTarget2D oldTarget;
if (graphics.GetRenderTargets().Count() == 0) oldTarget = null;
else oldTarget = (RenderTarget2D)graphics.GetRenderTargets()[0].RenderTarget; // Get the old target being used.
graphics.SetRenderTarget(canvas); //set the target to a temporary RT
graphics.Clear(Color.Black); // Clear it
Control c = Controls[i]; // Get the current control (a form in this case)
c.Draw(spriteBatch, gameTime); // Draw it to the temp RT
graphics.SetRenderTarget(oldTarget); // Set the RT back to the main RT
Vector2 dest = c.DrawCoOrds(); // Gets the draw coordinates of the control
spriteBatch.Begin();
spriteBatch.Draw(canvas, new Rectangle((int)dest.X, (int)dest.Y, c.Bounds.Width, c.Bounds.Height), new Rectangle((int)dest.X, (int)开发者_C百科dest.Y, c.Bounds.Width, c.Bounds.Height), Color.White);
// take the rect from the temp RT and draw it to the main RT.
spriteBatch.End();
}
However this code only draws the last form in the list which means it must be clearing the main RT somehow but i dont understand why. I only call clear when the RT is set to the temp canvas.
i think the best method to draw gui controls is with ScissorRectangle, because lets draw only inside that rectangle, that can be the client area of the gui control.
MSDN: GraphicsDevice.ScissorRectangle
You need to enable this funcionality through a RasterizerState.
RasterizerState ScissorState = new RasterizerState()
{
ScissorTestEnabled = true;
}
Before you draw, call SpriteBatch.Begin with this state.
A video of my own gui running in a xbox360 :)
How did you create your render target and back buffer? By default you can't write to a render target multiple times after changing to a different render target. This is why:
http://blogs.msdn.com/b/shawnhar/archive/2007/11/21/rendertarget-changes-in-xna-game-studio-2-0.aspx
You can change the default behavior by creating your render targets with RenderTargetUsage.PreserveContents.
, and the back buffer by overriding GraphicsDeviceManager.PrepareDeviceSettings.
, changing GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage
, as described in the link. Although I believe overriding those settings is done differently in XNA 4.
All that being said, changing away from the default behavior has performance considerations, and is not recommended. You should find a way to do this differently. One possibility would be to create a separate render target for each of your windows, draw all of them, switch to the back buffer and draw the render targets to it.
A better option would be to use the scissor rectangle rasterizer state as proposed by @Blau.
精彩评论