C++ SOIL 不加载小图像
C++ SOIL does not load small images
我在尝试使用 SOIL 为我的像素艺术游戏加载较小的纹理时遇到了一些问题。这是加载 40 x 40 图像时的结果:
但是当我切换到 30 x 40 时:
我检查了我的代码,当宽度小于高度时是否有任何问题,对于 40 x 50 一切都很好。我用 Windows' 图像查看器检查了 30 x 40,看起来也不错。当使用坐标轴设置位置时,可能会以任何方式影响装载机的唯一一件事,但是,它工作正常。这是加载纹理的代码:
glGenTextures(1, &actor.texture);
glBindTexture(GL_TEXTURE_2D, actor.texture);
unsigned char* image = SOIL_load_image(("App/Textures/" + name + ".png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
当图像加载到纹理对象时,GL_UNPACK_ALIGNMENT
必须设置为 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
注意,默认情况下该参数为 4。这意味着假设图像的每一行都对齐到 4 的倍数的大小。由于图像数据被紧密打包并且每个像素都有一个大小3 个字节,必须更改对齐方式。
当图像大小为 40 x 50 时,一行的字节大小为 120,可以被 4 整除。
但是如果图像的大小是30 x 40,那么一行的字节大小是90,不能被4整除。
问题不在于小,而是 30 不能被 4 整除:30 = 2 * 3 * 5
。 OpenGL 假定默认的像素存储设置,即行与 4 字节边界对齐。对于40×40的图片正好满足这个条件,因为不管你用什么像素格式,宽度都是4倍
解决方案是告诉 OpenGL,像素行从不同的 n 字节边界开始:
unsigned char* image = SOIL_load_image(…);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(…);
我在尝试使用 SOIL 为我的像素艺术游戏加载较小的纹理时遇到了一些问题。这是加载 40 x 40 图像时的结果:
但是当我切换到 30 x 40 时:
我检查了我的代码,当宽度小于高度时是否有任何问题,对于 40 x 50 一切都很好。我用 Windows' 图像查看器检查了 30 x 40,看起来也不错。当使用坐标轴设置位置时,可能会以任何方式影响装载机的唯一一件事,但是,它工作正常。这是加载纹理的代码:
glGenTextures(1, &actor.texture);
glBindTexture(GL_TEXTURE_2D, actor.texture);
unsigned char* image = SOIL_load_image(("App/Textures/" + name + ".png").c_str(), &width, &height, 0, SOIL_LOAD_RGB);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
SOIL_free_image_data(image);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
当图像加载到纹理对象时,GL_UNPACK_ALIGNMENT
必须设置为 1:
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
注意,默认情况下该参数为 4。这意味着假设图像的每一行都对齐到 4 的倍数的大小。由于图像数据被紧密打包并且每个像素都有一个大小3 个字节,必须更改对齐方式。
当图像大小为 40 x 50 时,一行的字节大小为 120,可以被 4 整除。
但是如果图像的大小是30 x 40,那么一行的字节大小是90,不能被4整除。
问题不在于小,而是 30 不能被 4 整除:30 = 2 * 3 * 5
。 OpenGL 假定默认的像素存储设置,即行与 4 字节边界对齐。对于40×40的图片正好满足这个条件,因为不管你用什么像素格式,宽度都是4倍
解决方案是告诉 OpenGL,像素行从不同的 n 字节边界开始:
unsigned char* image = SOIL_load_image(…);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(…);