【发布时间】:2016-04-05 23:15:32
【问题描述】:
我有一个byte[] 的颜色,需要通过SetPixels(Color32[]) 转移到Texture2D 对象。
我想知道从byte[] 创建Color32[] 的最快方法是什么。
由于每个Color32 是 4 个字节(每个通道 1 个字节),因此元素数量将是四分之一。
Array.CopyTo 不允许不同的对象数组类型。
根据我的阅读,托管代码似乎无法将 byte[] 重新解释为 Color32[] 并完全跳过副本。
与此相反 (Color32[] -> byte[]) has a SO solution 通过编组,但似乎涉及大量复制。
private static byte[] Color32ArrayToByteArray(Color32[] colors)
{
int length = 4 * colors.Length;
byte[] bytes = new byte[length];
IntPtr ptr = Marshal.AllocHGlobal(length); // unmanaged memory alloc
Marshal.StructureToPtr(colors, ptr, true); // memcpy 1
Marshal.Copy(ptr, bytes, 0, length); // memcpy 2
Marshal.FreeHGlobal(ptr);
return bytes;
}
就我而言,我正在使用:
int length = bytes.Length;
IntPtr ptr = Marshal.AllocHGlobal(length); // unmanaged mem alloc
Marshal.Copy(bytes, 0, ptr, length); // memcpy 1
Marshal.PtrToStructure(ptr, colors); // memcpy 2
Marshal.FreeHGlobal(ptr);
但是,在执行myTexture.SetPixels(colors) 之后,我没有看到纹理更新。仍在试图找出原因。
无论如何,我是否必须做 2 个内存副本才能在 C# 中完成此操作?好像很浪费。。 我正在查看 C# 中的联合以绕过副本。
【问题讨论】:
-
我在上面的描述中明确提到了这个问题。该链接提供了一种可能的解决方案(在我的情况下不起作用),更重要的是,这是一个关于是否可以避免 2 个副本的问题。
-
为什么不能使用 Texture2D 对象的 LoadRawTextureData()?文档说在更改纹理后调用 Apply() 以便实际将更改上传到显卡。
-
我怎么会错过这个功能? :( 完美,谢谢。我的联合解决方案也有效,但这更容易。有趣的部分是 Texture2D.SetPixels 需要时间,我将使用本机插件解决方案将图像数据blit到 gfx 纹理资源上。我怀疑它使用
UpdateSubresource并且每帧都这样做会杀死一点性能。
标签: c# unity3d marshalling arrays