1

我在 XNA 中工作,遇到了以下问题:我的目标是将许多不同的纹理绘制到纹理上,然后使用给定的 alpha 值将最终纹理绘制到屏幕上。

问题是我绘制的纹理是全屏的,并且填充了颜色而不是透明度,因此它遮挡了它后面的所有内容。

一切都是二维的,这是我的代码:

public void Draw(SpriteBatch sb)
            {
            if (opacity > 0)
                {
                gd.SetRenderTarget(formTexture);
                gd.Clear(Color.Transparent);
                for (int i=0; i<formItems.Count; i++)
                    {
                    ((FormItem)formItems[i]).draw(sb);
                    }
                sb.Begin(SpriteSortMode.Immediate, BlendState.Additive);
                    for (int i=0; i<formItems.Count; i++)
                        {
                        FormItem fi = (formItems[i] as FormItem);
                        if (fi.glow != null)
                            {
                            sb.Draw(fi.glow, new Rectangle((int) fi.location.X + fi.width/2 - fi.glow.Width/2, (int) fi.location.Y + fi.height/2 - fi.glow.Height/2, fi.glow.Width, fi.glow.Height), Color.White);
                            }
                        }
                sb.End();
                gd.SetRenderTarget(null);
                sb.Begin();
                sb.Draw(formTexture, new Rectangle(0, 0, gd.Viewport.Width, gd.Viewport.Height), Color.White*opacity);
                sb.End();
                }
            }

formTexture 是一个 RenderTarget2D 对象,gd 是图形设备。这是 formTexture 的初始化方式:

formTexture = new RenderTarget2D(this.gd, this.windowWidth, this.windowHeight);
4

1 回答 1

1

您遇到的问题是设置渲染目标 -并且后台缓冲区算作渲染目标- 将清除该渲染目标

至少如果RenderTargetUsage.DiscardContentsMSDN)设置。这是默认设置,因为它是唯一在 Xbox 360 上表现良好的设备,在 Xbox 360 上保留内容需要昂贵的副本。(它是 Windows 上的默认设置,只是为了保持跨平台的行为相同)。

您的后台缓冲区正在被清除为“哎呀,这是一个新的缓冲区”颜色(通常是紫色)在这一行:

gd.SetRenderTarget(null);

有两种方法可以解决这个问题:

首选方法是对所有渲染进行排序,以便在帧的开头设置渲染目标,然后将场景绘制到后备缓冲区。切勿多次触摸渲染目标。


另一种方法是附加一个事件来GraphicsDeviceManager.PreparingDeviceSettings设置后台缓冲区使用RenderTargetUsage.PreserveContents

void SetBackbufferPreserveContents(object sender,
                                   PreparingDeviceSettingsEventArgs e)
{
    e.GraphicsDeviceInformation.PresentationParameters.RenderTargetUsage
            = RenderTargetUsage.PreserveContents;
}

// in your game constructor:
graphics.PreparingDeviceSettings += SetBackbufferPreserveContents;

如果您的游戏专门针对 Windows,您应该只使用第二种方法。

于 2012-09-11T08:37:38.977 回答