glTexImage2D 崩溃程序
glTexImage2D crashing program
这是我的代码:
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
时,我的 window 不再打开。 w
和 h
都是由 stbi_load
计算的,它是 stb_image.h
库的一部分。我的错误在哪里?
好吧,问题显然出在 GL_RGBA
上。我改成GL_RGB
,程序不再崩溃;不过,我确实想知道为什么它一开始就崩溃了。
我想你的问题的根源是 stbi_load
方法加载的像素图中的通道数与你作为第 7 个参数传递给 [=] 的原始图像格式的通道数不匹配11=] 方法。
基本上,glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, WIDTH, HEIGHT, 0, SOURCE_FORMAT, SOURCE_TYPE, SOURCE_PIXMAP_DATA)
导致 OpenGL 创建一个 2D 纹理,其具有 INTERNAL_FORMAT
的内部像素表示,从源像素图 SOURCE_PIXMAP_DATA
由 SOURCE_FORMAT
、SOURCE_TYPE
.
中编码的像素序列组成
我认为 stbi_load
从文件中读取一个 3 通道、每像素 24 字节的图像(GL_RGB
、GL_BYTE
),但是您告诉 OpenGL 将源像素图视为 4通道,每像素 32 字节 (GL_RGBA
, GL_BYTE
) 图像。这是不正确的。
您应该在指定源像素图格式之前检查 c
变量,或者请求 stbi_load
通过将 4
分配给它的第 4 个参数来加载 4 色通道图像(该死的,这里有很多 4)。
jpg 图像由 3 个颜色通道 (GL_RGB
) 和 stbi_load
returns 紧凑的图像组成。图片缓冲区(img
)的字节数为w * h * 3
.
默认情况下,OpenGL 假定图像的每一行的开头对齐 4 个字节。这是因为默认情况下 GL_UNPACK_ALIGNMENT
参数为 4。由于图像具有 3 个颜色通道,并且排列紧密,行的开头可能未对齐。
因此图像缓冲区的大小假定为 aligne(w*3, 4) * h
。
导致崩溃,因为glTexImage2D
。越界访问缓冲区。
将GL_UNPACK_ALIGNMENT
参数改为1,在指定二维纹理图像之前(glTexImage2D
):
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
注意,glPixelStorei
设置了一个全局状态,该状态会一直保持到再次更改。
这是我的代码:
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
时,我的 window 不再打开。 w
和 h
都是由 stbi_load
计算的,它是 stb_image.h
库的一部分。我的错误在哪里?
好吧,问题显然出在 GL_RGBA
上。我改成GL_RGB
,程序不再崩溃;不过,我确实想知道为什么它一开始就崩溃了。
我想你的问题的根源是 stbi_load
方法加载的像素图中的通道数与你作为第 7 个参数传递给 [=] 的原始图像格式的通道数不匹配11=] 方法。
基本上,glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT, WIDTH, HEIGHT, 0, SOURCE_FORMAT, SOURCE_TYPE, SOURCE_PIXMAP_DATA)
导致 OpenGL 创建一个 2D 纹理,其具有 INTERNAL_FORMAT
的内部像素表示,从源像素图 SOURCE_PIXMAP_DATA
由 SOURCE_FORMAT
、SOURCE_TYPE
.
我认为 stbi_load
从文件中读取一个 3 通道、每像素 24 字节的图像(GL_RGB
、GL_BYTE
),但是您告诉 OpenGL 将源像素图视为 4通道,每像素 32 字节 (GL_RGBA
, GL_BYTE
) 图像。这是不正确的。
您应该在指定源像素图格式之前检查 c
变量,或者请求 stbi_load
通过将 4
分配给它的第 4 个参数来加载 4 色通道图像(该死的,这里有很多 4)。
jpg 图像由 3 个颜色通道 (GL_RGB
) 和 stbi_load
returns 紧凑的图像组成。图片缓冲区(img
)的字节数为w * h * 3
.
默认情况下,OpenGL 假定图像的每一行的开头对齐 4 个字节。这是因为默认情况下 GL_UNPACK_ALIGNMENT
参数为 4。由于图像具有 3 个颜色通道,并且排列紧密,行的开头可能未对齐。
因此图像缓冲区的大小假定为 aligne(w*3, 4) * h
。
导致崩溃,因为glTexImage2D
。越界访问缓冲区。
将GL_UNPACK_ALIGNMENT
参数改为1,在指定二维纹理图像之前(glTexImage2D
):
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, img);
注意,glPixelStorei
设置了一个全局状态,该状态会一直保持到再次更改。