我在XNA工作,遇到了以下问题:我的目标是将一些不同的纹理绘制到纹理,然后使用给定的alpha值将最终纹理绘制到屏幕上。
问题在于我绘制的纹理是全屏并且填充了颜色而不是透明度,因此它会阻挡其背后的所有内容。
一切都是2d,这是我的代码:
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);
答案 0 :(得分:1)
您遇到的问题是设置渲染目标 - 并且后备缓冲区计为渲染目标 - 将清除渲染目标。
至少设置RenderTargetUsage.DiscardContents
(MSDN)。这是默认设置,因为它是唯一一个在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,则应该只使用第二种方法。