处理glTexImage2D异常

时间:2017-07-16 21:04:19

标签: c++ opengl

我试图加载.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中捕获和处理这样的异常?

1 个答案:

答案 0 :(得分:4)

你从错误的角度接近这个。您应该解决实际问题,而不是尝试解决问题。手头的问题是,您向OpenGL传递了一组不匹配的参数和数据。

OpenGL本身从不引发异常。如果它可以检测到参数无效,它将产生一个内部错误,并且从错误发生的函数返回而不做某事"很奇怪"。

程序在OpenGL函数内部崩溃意味着存在驱动程序错误(非常不可能)或程序中存在错误(可能)。 glTexImage2D中的崩溃几乎总是由于对传递的数据进行了越界读取。如果宽度,高度,边框(如果使用边框,自Ope​​nGL-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;
    }
}