我试图加载.PNG图片,当我尝试使用此代码创建此图像的纹理时
unsigned char *imageData1 = stbi_load("container.jpg", &width1, &height1, &noChannels1, 0); // succeeded to return data
if(imageData1) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData1); // raise an exception here.
}
程序崩溃并引发异常。我发现我应该在数据类型中使用GL_RGB而不是GL_RGBA。
我的问题是有没有办法在OpenGL中捕获和处理这样的异常?
答案 0 :(得分:4)
你从错误的角度接近这个。您应该解决实际问题,而不是尝试解决问题。手头的问题是,您向OpenGL传递了一组不匹配的参数和数据。
OpenGL本身从不引发异常。如果它可以检测到参数无效,它将产生一个内部错误,并且从错误发生的函数返回而不做某事"很奇怪"。
程序在OpenGL函数内部崩溃意味着存在驱动程序错误(非常不可能)或程序中存在错误(可能)。 glTexImage2D
中的崩溃几乎总是由于对传递的数据进行了越界读取。如果宽度,高度,边框(如果使用边框,自OpenGL-3以来不支持),格式和设置为glPixelStore
的像素存储参数的值计算到,则会发生OOB读取比传递给数据的缓冲区大。
因此,在从这样的缓冲区读取时,必须确保将正确的参数传递给OpenGL。正如您已经注意到切换到GL_RGBA可以防止崩溃。现在解决方案是不首先尝试使用GL_RGB,如果是另一种方式则失败。 事实上,异常(也是非关键的)应该从不依赖于某种程序控制流决策逻辑!
STB将为您提供所需的所有信息:宽度,高度,通道数量;采样深度总是假定为每通道像素8位。使用该信息正确参数化OpenGL图像加载。您必须至少调用一次glPixelStore
来将解包对齐设置为1(否则行开始可能会跳过; STB返回紧密打包的图像数据)。将宽度和高度按原样传递到glTexImage2D
并按此
assert( (1 <= channels) && (4 >= channels) );
GLenum glformat;
if( opengl3 ){
switch( channels ){
case 1: glformat = GL_RED; break;
case 2: glformat = GL_RG; break;
case 3: glformat = GL_RGB; break;
case 4: glformat = GL_RGBA; break;
}
} else {
switch( channels ){
case 1: glformat = GL_LUMINANCE; break;
case 2: glformat = GL_LUMINANCE_ALPHA; break;
case 3: glformat = GL_RGB; break;
case 4: glformat = GL_RGBA; break;
}
}