Windows Phone 8的Monogame:停用后的黑色纹理

时间:2014-03-28 14:42:23

标签: c# windows-phone-8 monogame

我在我的monogame(3.1)windows phone 8应用程序中遇到了一个奇怪的问题。当应用程序停用然后激活时,所有纹理都变黑。这也发生在锁定屏幕(启用UserIdleDetectionMode)之后。

我已经检查了GraphicsDevice.IsDisposed,GraphicsDevice.IsContentLost,GraphicsDevice.ResourcesLost,但一切看起来都不错。我已经在Activated和Unobscured事件上重新加载了所有纹理,但是全纹理重新加载需要花费太多时间。在Marketplace上的同一时间,我看到monogame apps很容易处理desactivate-activate。此外,写在xna上的Windows Phone 7的相同应用程序,恢复非常快。我对monogame做错了什么? 我的应用程序基于monogame WP8模板。

更新:

刚刚发现通过Content.Load(...)加载的所有纹理都可以非常快速地恢复。但是我的所有纹理都是用手写的:我从TileContainer加载一个文件,解压缩它,用ImageTools读取它的数据,创建Texture2D并用加载的数据设置它的像素。 Jpeg文件也作为BGR565渲染到RenderTarget2D以消耗空间。 此外,我广泛使用RenderTarget2D来渲染带有阴影,精灵运行时组合等的文本标签。所以看起来Monogame只是不想恢复由Content.Load加载的图像。 继续调查......

2 个答案:

答案 0 :(得分:0)

我刚收到汤姆斯皮尔曼在Monogame论坛上的回复,显然Content.Load的内容正常恢复,其他数据需要由程序重新初始化。您可以做的是连接到 GraphicsDevice.DeviceResetting 事件,以便在进行此重置时收到通知。

答案 1 :(得分:0)

根据monogame开发者丢失纹理是正常情况。 我在GraphicsDevice.DeviceReset事件中完成了纹理重新加载。为了使其快速工作,我已经实现了xnb未压缩文件的加载。只要此格式中包含像素值,它就非常简单。这是唯一的解决方案。

以下是如何从未压缩的xnb中读取:

private static Texture2D TextureFromUncompressedXnbStream(GraphicsDevice graphicsDevice, Stream stream)
{
    BinaryReader xnbReader = new BinaryReader(stream);
    byte cx = xnbReader.ReadByte();
    byte cn = xnbReader.ReadByte();
    byte cb = xnbReader.ReadByte();
    byte platform = xnbReader.ReadByte();

    if (cx != 'X' || cn != 'N' || cb != 'B')
        return null;

    byte version = xnbReader.ReadByte();
    byte flags = xnbReader.ReadByte();

    bool compressed = (flags & 0x80) != 0;
    if (version != 5 && version != 4)
        return null;
    int xnbLength = xnbReader.ReadInt32();
    xnbReader.ReadBytes(0x9D);//skipping processor string
    SurfaceFormat surfaceFormat = (SurfaceFormat)xnbReader.ReadInt32();
    int width = (xnbReader.ReadInt32());
    int height = (xnbReader.ReadInt32());
    int levelCount = (xnbReader.ReadInt32());
    int levelCountOutput = levelCount;

    Texture2D texture = texture = new Texture2D(graphicsDevice, width, height, false, SurfaceFormat.Color);

    for (int level = 0; level < levelCount; level++)
    {
        int levelDataSizeInBytes = (xnbReader.ReadInt32());
        byte[] levelData = xnbReader.ReadBytes(levelDataSizeInBytes);
        if (level >= levelCountOutput)
            continue;
        texture.SetData(level, null, levelData, 0, levelData.Length);
    }
    xnbReader.Dispose();
    return texture;
}