glTexImage2D导致程序崩溃

3

这是我的代码:

int h, w, c;
unsigned char* img = stbi_load("bricks.jpg", &w, &h, &c, 0);
if (img == NULL) {
    printf("Error in loading the image\n");
}
printf("Image loaded with width of %d, height of %d, and %d channels", w, h, c);

GLuint txtr = 0;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &txtr);
glBindTexture(GL_TEXTURE_2D, txtr);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);

由于某种原因,当我取消注释glTexImage2D时,我的窗口不再打开。 wh都是由stbi_load计算的,这是stb_image.h库的一部分。 我在哪里犯了错误?

3个回答

6

这张jpg图像由3个颜色通道(GL_RGB)组成,stbi_load返回一个紧密打包的图像。图像缓冲区(img)的字节数为w * h * 3

默认情况下,OpenGL假定图像的每一行的开头对齐4个字节。这是因为GL_UNPACK_ALIGNMENT参数默认为4。由于图像有3个颜色通道,并且是紧密打包的,所以一行的开头可能对齐不正确。
因此,图像缓冲区的大小被认为是aligne(w*3, 4) * h

崩溃是由于glTexImage2D访问了越界的缓冲区引起的。

在指定二维纹理图像 (glTexImage2D) 之前,将 GL_UNPACK_ALIGNMENT 参数更改为 1:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);

注意,glPixelStorei设置了一个全局状态,该状态将保持不变,直到再次更改为止。

1
我认为你的问题源于stbi_load方法加载的像素图中通道数与你传递给glTexImage2D方法的原始图像格式的通道数不匹配。 基本上,glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, WIDTH, HEIGHT, 0, SOURCE_FORMAT, SOURCE_TYPE, SOURCE_PIXMAP_DATA)会导致OpenGL创建一个2D纹理,该纹理具有内部像素表示INTERNAL_FORMAT,宽度为WIDTH像素,高度为HEIGHT像素,来源于SOURCE_PIXMAP_DATA的源像素图,其中包含以SOURCE_FORMATSOURCE_TYPE编码的像素序列。

我认为stbi_load从文件中读取了一个3通道,每像素24字节(GL_RGBGL_BYTE)的图像,但你告诉OpenGL将源像素图视为4通道,每像素32字节(GL_RGBAGL_BYTE)的图像,这是不正确的。

在指定源像素图格式之前,您应该检查c变量,或通过将4分配给其第四个参数来请求stbi_load加载4色通道图像(该处有很多个4)。


0

嗯,问题显然出在GL_RGBA上。我把它改成了GL_RGB,程序不再崩溃了;尽管我还是想知道为什么一开始会崩溃。


1
你正在读取一个有3个通道的图像,但是告诉OpenGL你的图像数据有4个通道。4 > 3,因此OpenGL将在图像缓冲区外部读取。为了使代码具有鲁棒性,您应该从c的值确定format参数(在您的代码中静态设置为GL_RGB(A))。1→GL_RED(如果您使用OpenGL-3之前的版本,则为GL_LUMINANCE),2→GL_RG,3→GL_RGB,4→GL_RGBA。 - datenwolf

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