2

我正在用最新的 XNA (C#) 编写一个 2D 游戏。我正在对旧代码进行一些大修,并且刚刚放回按钮以更改分辨率。但是,在切换全屏模式或更改窗口大小/分辨率后,屏幕永远只是黑色(我的清除屏幕调用的颜色),尽管游戏仍在运行,因为我可以通过按键退出它。这在我以前的版本中没有发生 - 一切正常 - 但我能找到的相关代码没有区别。但是我确实重做了图形加载以使用我自己的纹理加载器而不是内容加载器 - 这可能是问题吗?

如果没有其他选择,是否有一种简单的方法可以使游戏重新启动,因为图形正常并且重新启动后处于所选格式?

我的代码是:

 public override void Click()
    {
        base.Click();
        Settings.Default.screenWidth = resolution[0];
        Settings.Default.screenHeight = resolution[1];
        Settings.Default.Save();
        Variables.screenWidth = Settings.Default.screenWidth;
        Variables.screenHeight = Settings.Default.screenHeight;

        Game1.graphics.PreferredBackBufferWidth = Variables.screenWidth;
        Game1.graphics.PreferredBackBufferHeight = Variables.screenHeight;
        Game1.graphics.ApplyChanges();
    }

谢谢!

编辑:我的纹理加载代码 - 加载名称包含在枚举中的所有文件作为 Texture2Ds..

public static void LoadAll(string subFolder)
    {
        List<string> s = Directory.GetFiles(path + "\\" + subFolder, "*.png", SearchOption.AllDirectories).ToList<string>();
        foreach (string S in s)
        {
            if (Enum.IsDefined(typeof(T), Path.GetFileNameWithoutExtension(S)))
            {
                FileStream stream = new FileStream(S, FileMode.Open);
                Texture2D t = Texture2D.FromStream(Game1.graphics.GraphicsDevice, stream);
                RenderTarget2D result = null;

                //Setup a render target to hold our final texture which will have premulitplied alpha values
                result = new RenderTarget2D(Game1.graphics.GraphicsDevice, t.Width, t.Height);

                Game1.graphics.GraphicsDevice.SetRenderTarget(result);
                Game1.graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.Black);

                //Multiply each color by the source alpha, and write in just the color values into the final texture
                BlendState blendColor = new BlendState();
                blendColor.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue;

                blendColor.AlphaDestinationBlend = Blend.Zero;
                blendColor.ColorDestinationBlend = Blend.Zero;

                blendColor.AlphaSourceBlend = Blend.SourceAlpha;
                blendColor.ColorSourceBlend = Blend.SourceAlpha;


                Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendColor);
                Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White);
                Game1.spriteBatch.End();

                //Now copy over the alpha values from the PNG source texture to the final one, without multiplying them
                BlendState blendAlpha = new BlendState();
                blendAlpha.ColorWriteChannels = ColorWriteChannels.Alpha;

                blendAlpha.AlphaDestinationBlend = Blend.Zero;
                blendAlpha.ColorDestinationBlend = Blend.Zero;

                blendAlpha.AlphaSourceBlend = Blend.One;
                blendAlpha.ColorSourceBlend = Blend.One;

                Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha);
                Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White);
                Game1.spriteBatch.End();

                //Release the GPU back to drawing to the screen

                Game1.graphics.GraphicsDevice.SetRenderTarget(null);


                t = result;

                textureDictionary.Add(Path.GetFileNameWithoutExtension(S), t);
            }
           // else
            //  Console.WriteLine("Did not load -- " + Path.GetFileNameWithoutExtension(S) + " -- (add to enum to enable loading)");
        }
    }

编辑:遵循以下建议的工作代码 - 可能不是最有效的,但它有效!

public static void LoadAll(string subFolder)
    {
        List<string> s = Directory.GetFiles(path + "\\" + subFolder, "*.png", SearchOption.AllDirectories).ToList<string>();
        foreach (string S in s)
        {
            if (Enum.IsDefined(typeof(T), Path.GetFileNameWithoutExtension(S)))
            {
                FileStream stream = new FileStream(S, FileMode.Open);
                Texture2D t = Texture2D.FromStream(Game1.graphics.GraphicsDevice, stream);
                RenderTarget2D result = null;
                Texture2D resultTexture;

                //Setup a render target to hold our final texture which will have premulitplied alpha values
                result = new RenderTarget2D(Game1.graphics.GraphicsDevice, t.Width, t.Height);

                Game1.graphics.GraphicsDevice.SetRenderTarget(result);
                Game1.graphics.GraphicsDevice.Clear(Microsoft.Xna.Framework.Color.Black);

                //Multiply each color by the source alpha, and write in just the color values into the final texture
                BlendState blendColor = new BlendState();
                blendColor.ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue;

                blendColor.AlphaDestinationBlend = Blend.Zero;
                blendColor.ColorDestinationBlend = Blend.Zero;

                blendColor.AlphaSourceBlend = Blend.SourceAlpha;
                blendColor.ColorSourceBlend = Blend.SourceAlpha;


                Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendColor);
                Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White);
                Game1.spriteBatch.End();

                //Now copy over the alpha values from the PNG source texture to the final one, without multiplying them
                BlendState blendAlpha = new BlendState();
                blendAlpha.ColorWriteChannels = ColorWriteChannels.Alpha;

                blendAlpha.AlphaDestinationBlend = Blend.Zero;
                blendAlpha.ColorDestinationBlend = Blend.Zero;

                blendAlpha.AlphaSourceBlend = Blend.One;
                blendAlpha.ColorSourceBlend = Blend.One;

                Game1.spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha);
                Game1.spriteBatch.Draw(t, t.Bounds, Microsoft.Xna.Framework.Color.White);
                Game1.spriteBatch.End();

                //Release the GPU back to drawing to the screen

                Game1.graphics.GraphicsDevice.SetRenderTarget(null);

                resultTexture = new Texture2D(Game1.graphics.GraphicsDevice, result.Width, result.Height);
                Color[] data = new Color[result.Height * result.Width];
                Color[] textureColor = new Color[result.Height * result.Width];

                result.GetData<Color>(textureColor);

                resultTexture.SetData(textureColor);

                textureDictionary.Add(Path.GetFileNameWithoutExtension(S), resultTexture);
            }
           // else
            //  Console.WriteLine("Did not load -- " + Path.GetFileNameWithoutExtension(S) + " -- (add to enum to enable loading)");
        }
    }
4

1 回答 1

2

根据您更新的代码,您将纹理复制到渲染目标 ( RenderTarget2D)。

与常规纹理不同,这些纹理不受 CPU 端内存的支持。当图形设备丢失时,常规纹理会自动在 GPU 上重新设置它们的数据。但是,渲染目标会引发其ContentLost事件并设置IsContentLost- 然后您需要自己重置其内容!

有几个解决方案: 您可以简单地响应ContentLost并刷新数据。

我更喜欢在加载时使用GetDataandSetData将渲染目标的内容复制到常规Texture2D中,因为这“有效”。尽管对于像切换纹理以使用预乘 alpha 这样的简单情况,我更喜欢将所有内容都保留在 CPU 上。

我在这里得到了关于固定纹理使用的非常详细的答案RenderTarget2D。它包括直接在 CPU 上进行预乘的代码。

尽管在您的情况下,我会尝试使用内容管理器。可以让它处理目录中的所有文件,然后动态加载它们

于 2013-05-29T16:28:41.197 回答