C# 什么';从tileset图像创建2D阵列纹理的最佳方法是什么?

C# 什么';从tileset图像创建2D阵列纹理的最佳方法是什么?,c#,opengl,opentk,opengl-3,C#,Opengl,Opentk,Opengl 3,最近我一直在学习OpenGL(3.3内核),今天我尝试将我的Tilemap绘图从使用纹理图集转换为使用阵列纹理。主要原因是它避免了瓷砖之间的流血 这是相当容易实现,它与我的简单瓷砖集图像,这是只有3个垂直放置瓷砖工程。然而,当我尝试一个更大的tileset图像,它每行有一个以上的tile时,它就崩溃了,我得到的只是垃圾 原因很快被发现:当tileset图像中每行只有一个tile时,单个tile的像素(rgba字节)是连续的。例如,在32x32平铺上,第一行像素是像素(1)-像素(32),第二行是

最近我一直在学习OpenGL(3.3内核),今天我尝试将我的Tilemap绘图从使用纹理图集转换为使用阵列纹理。主要原因是它避免了瓷砖之间的流血

这是相当容易实现,它与我的简单瓷砖集图像,这是只有3个垂直放置瓷砖工程。然而,当我尝试一个更大的tileset图像,它每行有一个以上的tile时,它就崩溃了,我得到的只是垃圾

原因很快被发现:当tileset图像中每行只有一个tile时,单个tile的像素(rgba字节)是连续的。例如,在32x32平铺上,第一行像素是
像素(1)-像素(32)
,第二行是
像素(33)-像素(64)
,依此类推。但是,当每行有多个磁贴时,
pixel(33)-pixel(64)
不再是第一个磁贴的第二行,而是第二个磁贴的第一行。OpenGL无法创建正确的纹理,因为单个平铺的像素不再连续

因此,我提出了以下代码来手动为每个瓷砖创建纹理:

//加载像素字节
var data=bitmap.LockBits(
新系统。绘图。矩形(0,0,位图。宽度,位图。高度),
System.Drawing.Imaging.ImageLockMode.ReadOnly,
System.Drawing.Imaging.PixelFormat.Format32bppArgb
);
字节[]像素=新字节[data.Stride*data.Height];
System.Runtime.InteropServices.Marshal.Copy(data.Scan0,pixels,0,pixels.Length);
位图。解锁位(数据);
int bytes_per_tile_row=tile_width*4;
int bytes_per_image_row=tiles_per_row*bytes_per_tile_row;
//填充纹理(一次一块瓷砖)
字节[]平铺像素=新字节[平铺宽度*平铺高度*4];
对于(int y=0;y
这是可行的,但感觉更像是一种变通方法,而不是解决方案。

我想知道是否有更好的方法来解决这个问题?

您可以调用glTexSubImage3D,即一次用于
像素[0]
像素[32]
,一次用于
像素[33]
像素[64]
。不过,这可能相当慢,具体取决于驱动程序……老实说,您最好不要存储每行数个磁贴。或者,等等,也许您可以使用glSubImage3D一次存储整行中的一行?如果将宽度设置为平铺的宽度,将高度设置为1,将深度设置为平铺的数量。我自己也没有试过,但这样你就不需要重新组织数据了,我想。@Andrea,这不是只适用于只有一行很宽的图像吗?但我认为你是对的。。。我可能最好提前将图像转换为一个非常高的单列,这样我就不需要在运行时重新组织数据。我在想,在任何一种情况下,您都需要多次调用SubImage3D,这很不幸,我想:/可能最好提前将其转换为一个单列,是的。您可以制作一个小脚本,以在Python中执行此操作,并将其放入构建系统/资产管道中。