我认为我从根本上误解了渲染目标的工作方式。在我的理解中,RenderTargets只是spritebatch draw调用draw的纹理。
所以我尝试使用此代码来渲染GUI窗口,以确保它们只能在其客户区域中绘制并在其外部进行裁剪。
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)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();
}
然而,此代码仅绘制列表中的最后一个表单,这意味着它必须以某种方式清除主RT,但我不明白为什么。当RT设置为临时画布时,我只调用clear。
答案 0 :(得分:0)
我认为绘制gui控件的最佳方法是使用ScissorRectangle,因为我们只能在该矩形内部绘制,这可以是gui控件的客户区。
MSDN: GraphicsDevice.ScissorRectangle
您需要通过RasterizerState启用此功能。
RasterizerState ScissorState = new RasterizerState()
{
ScissorTestEnabled = true;
}
在绘制之前,请使用此状态调用SpriteBatch.Begin。
答案 1 :(得分:0)
您是如何创建渲染目标和后台缓冲区的?默认情况下,在更改为其他渲染目标后,您无法多次写入渲染目标。这就是原因:
http://blogs.msdn.com/b/shawnhar/archive/2007/11/21/rendertarget-changes-in-xna-game-studio-2-0.aspx
您可以通过使用RenderTargetUsage.PreserveContents.
创建渲染目标来更改默认行为,并通过覆盖GraphicsDeviceManager.PrepareDeviceSettings.
来更改后缓冲区,更改GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage
,如链接中所述。虽然我认为在XNA 4中以不同方式完成覆盖这些设置。
所有这一切,改变远离默认行为都有性能方面的考虑因素,不建议这样做。你应该找到一种方法来做到这一点。一种可能性是为每个窗口创建一个单独的渲染目标,绘制所有窗口,切换到后缓冲区并将渲染目标绘制到它。
更好的选择是使用@Blau提出的剪刀矩形光栅化器状态。