2014-12-04 671 views
1

我在OpenGL应用程序中实现了像素缓冲区对象(PBO)。但是,当我尝试使用函数“glTexImage2D”加载纹理时,出现错误1282。这很奇怪,因为问题来自具有特定分辨率的纹理。glTexImage2D失败,错误1282使用PBO(坏纹理分辨率)

为了有更好的理解我的问题让我们来看看3个纹理有3米不同的分辨率:

一)blue.jpg BPP:24 分辨率:259x469

enter image description here

二)绿色.jpg Bpp:24 分辨率:410x489

enter image description here

c)中red.jpg BPP:24 分辨率:640×480

enter image description here

现在,让我们检查而不PBO使用C++代码:

FIBITMAP *bitmap = FreeImage_Load(
    FreeImage_GetFIFFromFilename(file.GetFullName().c_str()), file.GetFullName().c_str()); 
FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap); 

char *pPixels = (char*)FreeImage_GetBits(bitmap); 
uint32_t width = FreeImage_GetWidth(bitmap); 
uint32_t height = FreeImage_GetHeight(bitmap); 
uint32_t byteSize = width * height * (FreeImage_GetBPP(bitmap)/8); //24 bits/8 bits = 3 bytes) 

glGenTextures(1, &this->m_Handle); 
glBindTexture(GL_TEXTURE_2D, this->m_Handle); 
{ 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    std::cout << "ERROR: " << glGetError() << std::endl; 

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, 
     height, 0, GL_BGR, GL_UNSIGNED_BYTE, pPixels); 

    std::cout << "ERROR: " << glGetError() << std::endl; 

    if (this->m_IsMipmap) 
     glGenerateMipmap(this->m_Target); 
} 
glBindTexture(GL_TEXTURE_2D, 0); 

对于3个纹理的输出为总是一样的(所以加载已经正确执行):

$> ERROR: 0 
$> ERROR: 0 

和图形结果也是正确的:

A)蓝色

enter image description here

b)中绿色

enter image description here

C)红

enter image description here

现在,让我们用这个时间PBO检查C++代码:

FIBITMAP *bitmap = FreeImage_Load(
    FreeImage_GetFIFFromFilename(file.GetFullName().c_str()), file.GetFullName().c_str()); 
FIBITMAP *pImage = FreeImage_ConvertTo32Bits(bitmap); 

char *pPixels = (char*)FreeImage_GetBits(bitmap); 
uint32_t width = FreeImage_GetWidth(bitmap); 
uint32_t height = FreeImage_GetHeight(bitmap); 
uint32_t byteSize = width * height * (FreeImage_GetBPP(bitmap)/8); 

uint32_t pboID; 

glGenTextures(1, &this->m_Handle); 
glBindTexture(GL_TEXTURE_2D, this->m_Handle); 
{ 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

    glGenBuffers(1, &pboID); 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pboID); 
    { 
     unsigned int bufferSize = width * height * 3; 

     glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 

     glBufferData(GL_PIXEL_UNPACK_BUFFER, bufferSize, 0, GL_STATIC_DRAW); 
     glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, bufferSize, pPixels); 

     std::cout << "ERROR: " << glGetError() << std::endl; 

     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, 
      height, 0, GL_BGR, GL_UNSIGNED_BYTE, OFFSET_BUFFER(0)); 

     std::cout << "ERROR: " << glGetError() << std::endl; 

     if (this->m_IsMipmap) 
      glGenerateMipmap(this->m_Target); 
    } 
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); 
} 
glBindTexture(GL_TEXTURE_2D, 0); 

为blue.jpg(259x469)和green.jpg(410x489)的输出是下面的:

$> ERROR: 0 
$> ERROR: 1282 

图形输出当然两者是相同的:

enter image description here

但现在最有趣的,如果对纹理[R ed.jpg(640×480),没有任何错误和图形输出是正确的:

enter image description here

因此,使用PBO方法1282错误似乎是指一个纹理分辨率的问题!

OpenGL的文件说,为错误1282(GL_INVALID_OPERATION)关于PBO:

GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER target and the buffer object's data store is currently mapped. 

GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER target and the data would be unpacked from the buffer object such that the memory reads required would exceed the data store size. 

GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER target and data is not evenly divisible into the number of bytes needed to store in memory a datum indicated by type. 

但我不明白什么是错我的代码执行!

我想也许如果我需要使用PBO我可以使用8倍数的分辨率加载纹理......但我希望不会!

UPDATE

我试图添加一行:

glPixelStorei(GL_UNPACK_ALIGNMENT,1); // 1:字节对齐

在调用'glTexImage2D'之前。

错误1282已经消失,但显示不正确的:

enter image description here

我真的输了!

有人能帮助我吗?

+0

也许你应该尝试使用两种纹理的力量? – Nazar554 2014-12-04 15:51:34

回答

1

有意思的是,您加载的图像数据被填充以为每行生成4字节对齐。这是GL预计的默认情况,以及您最有可能在您的非PBO案例中使用的内容。

当您切换到PBO时,您忽略了每行的填充字节,所以缓冲区很小,GL检测到超出范围的访问。

当您最终切换到1的GL_UNPACK_ALIGNMENT时,不再有超出范围的访问,并且错误消失。但是你现在对你的数据格式撒谎。它仍然是填充的,但你告诉GL它不是。对于640x480图像,填充为零字节(因为640 * 3可以被4除尽),但对于其他两个图像,每行末尾都有填充字节。

正确的解决方案是将GL_UNPACK_ALIGNMENT保留为默认值4,并修复bufferSize的计算。你需要找出多少字节有要被添加到每一行,使该行的总字节数是通过再次(这意味着,添加最多3个字节)4整除:

unsigned int padding = (4 - (width * 3) % 4) % 4; 

现在,你可以把这些额外的字节考虑进去,并得到(你的内存有和图像)缓冲区的最终大小:

unsigned int bufferSize = (width * 3 + padding) * height; 
+0

非常感谢您的所有解释!再见。 – user1364743 2014-12-04 22:46:29

0

我有一个类似的问题在那里我得到错误1282,和黑色的质感。 glTexImage2D的第三个参数据说可以接受值1,2,3,4,这意味着每个像素的字节数。但由于某种原因,这突然停止了工作。用'GL_RGBA'代替'4'解决了我的问题。 希望这可以帮助别人。

相关问题