Texture2D变成黑色了。

3
我有一个来自内容管道的 Texture2D,加载工作正常。但是只要我尝试在另一个完全不同的 Texture2D 上使用 SetData,我的游戏中的所有纹理都会变成黑色:

正常

黑色

这发生在我的 HUDMeter 类中,我希望该类只是红色的。

Texture2D colorGrad = Content.Load<Texture2D>(GradientAsset);

Color[,] pixels = new Color[colorGrad.Width, colorGrad.Height];

Color[] pixels1D = new Color[colorGrad.Width * colorGrad.Height];

pixels = GetRedChannel(colorGrad);

pixels1D = Color2DToColor1D(pixels, colorGrad.Width);

System.Diagnostics.Debug.WriteLine(pixels[32,32]);
Gradient = colorGrad;
Gradient.SetData<Color>(pixels1D);

这些内容是使用Riemer的教程。
protected Color[,] GetRedChannel(Texture2D texture)
{
    Color[,] pixels = TextureTo2DArray(texture);

    Color[,] output = new Color[texture.Width, texture.Height];

    for (int x = 0; x < texture.Width; x++)
    {
        for (int y = 0; y < texture.Height; y++)
        {
            output[x,y] = new Color(pixels[x,y].G, 0, 0);
        }
    }

    return output;
}

protected Color[,] TextureTo2DArray(Texture2D texture)
{
    Color[] colors1D = new Color[texture.Width * texture.Height];
    texture.GetData(colors1D);

    Color[,] colors2D = new Color[texture.Width, texture.Height];
    for (int x = 0; x < texture.Width; x++)
        for (int y = 0; y < texture.Height; y++)
            colors2D[x, y] = colors1D[x + y * texture.Width];

    return colors2D;
}

private Color[] Color2DToColor1D (Color[,] colors, int width)
{
    Color[] output = new Color[colors.Length];

    for (int x = 0; x < width; x++)
    {
        for (int y = 0; y < colors.Length / width; y++)
        {
            output[x + y * width] = colors[x % width, y % (colors.Length/width)];
        }
    }

    return output;
}

以下是绘制精灵的代码,这段代码运行良好,也是我一直使用的方法:

batch.Draw(meter.Gradient, new Vector2(X, Y), Color.White);

更新:

我实际上发现那些没有使用相同文件的精灵并不是黑色。Texture2D.SetData<>()是否真的改变了文件本身?那有什么用呢?

更新:

我刚试过使用Alpha以及RGB,它也能正常工作。我想其中一个转换方法可能有问题。


哦,对了,那可能有点困难。它分布在三个类中,但我可以发布我使用SetData方法的位置(可能是错误的方式)。 - annonymously
这也值得发布在哪里调用。 - ChrisF
绘制精灵的代码在哪里? - Dave Carlile
1
Texture2D.SetData<>()会修改内存中的文件。如果您有多个精灵指向内存中的同一文件实例,则所有精灵都将遇到相同的问题。 - Justin Self
好的,既然这个问题解决了,我的原始问题是关于它们为什么变黑的? - annonymously
显示剩余3条评论
1个回答

2
如果你这样做:
Texture2D textureA = Content.Load<Texture2D>("MyTexture");
Texture2D textureB = Content.Load<Texture2D>("MyTexture");

textureAtextureB都指向同一个对象。因此,如果您在其中一个上调用SetData,它将影响两个对象。这是因为ContentManager会保留已加载资源的内部列表,因此它不必重新加载相同的资源。

解决方案是创建一个新的Texture2D对象,大小与之前相同,在由ContentManager加载的纹理上调用GetData,然后在新纹理上调用SetData

示例(未经测试):

Color[] buffer = new Color[textureA.Width * textureA.Height];
Texture2D textureB = new Texture2D(textureA.GraphicsDevice,
                                   textureA.Width,
                                   textureA.Height);
textureA.GetData(buffer);
textureB.SetData(buffer);

在完成使用新纹理后(例如在您的Game.UnloadContent方法中),请使用Dispose()释放它。但是,不要释放由ContentManager加载的纹理(因为,如我所说,它是共享对象;请改用ContentManager.Unload)。请注意保留HTML标签。

我不太清楚如何使用Texture2D的SetData和GetData方法,将位图存储在一维数组中似乎没有意义。 - annonymously
1
检索速度会变慢,因为您需要进行两次数组访问而不是一次。无论如何,它从左到右,然后从上到下,就像一本书一样,所以只需使用ColorArray[(y * width) + x],而不是2DColorArray[X][Y]。 - ClassicThunder
@ClassicThunder 尽管对于使用的 [,] 样式数组,速度是相同的,因为它在底层使用相同的 (y*width)+x。然而,它是一个一维数组,因为你正在使用内存缓冲区 - 注意你可以指定一个起始索引。这允许你做更多的内存重用技巧。 - Andrew Russell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接