XNA 中的 RenderTargets 绘制顺序

发布于 12-01 18:16 字数 1334 浏览 0 评论 0原文

我认为我从根本上误解了渲染目标的工作方式。根据我的理解,RenderTargets 只是 spritebatch 绘制调用绘制到的纹理。

因此,我尝试使用这段代码来渲染 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 设置为临时画布时调用清除。

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)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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我认为绘制 gui 控件的最佳方法是使用 ScissorRectangle,因为我们只能在该矩形内绘制,这可以是 gui 控件的客户区域。

MSDN:GraphicsDevice.ScissorRectangle

您需要通过 RasterizerState 启用此功能。

 RasterizerState ScissorState = new RasterizerState() 
 { 
     ScissorTestEnabled = true; 
 }

在绘制之前,请使用此状态调用 SpriteBatch.Begin。

我自己的 gui 在 xbox360 中运行的视频:)

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 :)

ゝ偶尔ゞ2024-12-08 18:16:08

您是如何创建渲染目标和后台缓冲区的?默认情况下,在更改为不同的渲染目标后,您无法多次写入渲染目标。这就是为什么:

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 提出的剪刀矩形光栅化器状态。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文