glGetTexImage使用纹理格式GL_ALPHA读取了太多数据

3

我正在尝试通过glGetTexImage检索仅包含alpha通道的纹理的像素信息。

问题在于,glGetTexImage调用似乎读取了比它应该读取更多的数据,导致内存损坏并在delete[]调用时崩溃。以下是我的代码:

int format;
glGetTexLevelParameteriv(target,0,GL_TEXTURE_INTERNAL_FORMAT,&format);
int w;
int h;
glGetTexLevelParameteriv(target,0,GL_TEXTURE_WIDTH,&w);
glGetTexLevelParameteriv(target,0,GL_TEXTURE_HEIGHT,&h);
if(w == 0 || h == 0)
    return false;
if(format != GL_ALPHA)
    return false;
unsigned int size = w *h *sizeof(unsigned char);
unsigned char *pixels = new unsigned char[size];
glGetTexImage(target,level,format,GL_UNSIGNED_BYTE,&pixels[0]);
delete[] pixels;

glGetError报告没有错误,而且在没有glGetTexImage调用的情况下不会崩溃。

'target'是GL_TEXTURE_2D(纹理在显示的代码之前有效并已绑定),'w'为19,'h'为24,'level'为0。

如果我将数组大小增加到(w * h * 100),它也不会崩溃。我知道GL_UNSIGNED_BYTE在我的系统上与unsigned char具有相同的大小,所以我不明白发生了什么。

额外的数据来自哪里,如何确保我的数组足够大?


3
默认情况下,由OpenGL像glGetTexImage这样的像素操作写入的每行数据都会按照4字节边界对齐,这可能会添加一些填充。请查阅GL_[UN]PACK_ALIGNMENT - Colonel Thirty Two
那么,我可以将GL_UNPACK_ALIGNMENT设置为1吗?还是这取决于创建纹理时GL_PACK_ALIGNMENT的设置?我尝试在glGetTexImage调用之前将GL_UNPACK_ALIGNMENT设置为1,但似乎没有帮助。 - Silverlan
1
打包和解包只影响像素传输。也就是说,当您上传它时,解包对齐方式用于GL解释将要存储在其选择的本地格式中的数据,然后它就不再重要了。同样,当您下载图像时,您可以让GL根据某些规则打包返回的图像,这些规则可能与其内部使用的规则不同。但在两种情况下,一个真正不会影响另一个。 - Andon M. Coleman
2
为此,在下载纹理图像之前设置解包对齐方式是没有任何作用的。您需要设置打包对齐方式。您基本上混淆了这两个事情。 - Andon M. Coleman
谢谢,现在我明白了。改变包对齐方式就解决了问题。 - Silverlan
1个回答

10

默认情况下,由OpenGL像素操作(如glGetTexImage)写入或读取的每一行都对齐到4字节边界,这可能会添加一些填充。

要修改对齐方式,请使用glPixelStoreiGL_[UN]PACK_ALIGNMENT设置。 GL_PACK_ALIGNMENT影响从OpenGL内存读取的操作(glReadPixelsglGetTexImage等),而GL_UNPACK_ALIGNMENT影响写入OpenGL内存的操作(glTexImage等)。

对齐方式可以是1(紧密打包,没有填充),24(默认值)或8

因此,在您的情况下,在运行glGetImage2D之前运行glPixelStorei(GL_PACK_ALIGNMENT, 1);


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