我在OpenGL应用程序中实现了Pixel Buffer Object(PBO)。但是,当我尝试使用函数'glTexImage2D'加载纹理时,我有错误1282。这很奇怪,因为问题来自具有特定分辨率的纹理。
为了更好地理解我的问题,让我们检查3种具有3种不同分辨率的纹理:
a)blue.jpg Bpp:24 决议:259x469
b)green.jpg Bpp:24 决议:410x489
c)red.jpg Bpp:24 分辨率:640x480
现在让我们检查一下没有使用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)蓝色
b)绿色
c)红色
现在让我们使用这次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
图形输出当然都是相同的:
但现在最有趣的是如果纹理red.jpg(640x480)没有错误,图形输出是正确的:
因此使用PBO方法1282错误似乎是指纹理分辨率问题!
OpenGL文档说明了关于PBO的错误1282(GL_INVALID_OPERATION):
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的倍数的分辨率的纹理......但我希望不会!
更新
我试图添加一行:
glPixelStorei(GL_UNPACK_ALIGNMENT,1); // 1:字节对齐
在调用'glTexImage2D'之前。
错误1282消失但显示不正确:
我真的输了!
有人可以帮助我吗?
答案 0 :(得分:1)
您加载的图像数据被填充以生成每行的4字节对齐。这是GL默认的预期,以及您最可能在非PBO案例中使用的内容。
当您切换到PBO时,您忽略了每行的填充字节,因此您的缓冲区很小,并且GL检测到了超出范围的访问。
当你最终切换到GL_UNPACK_ALIGNMENT
为1时,不再有超出范围的访问,并且错误消失了。但是你现在对你的数据格式撒谎。它仍然是填充的,但你告诉GL它不是。对于640x480图像,填充为零字节(因为640 * 3可以除以4),但对于其他两个图像,每行末尾都有填充字节。
正确的解决方案是将GL_UNPACK_ALIGNMENT
保留为默认值4,并修复bufferSize
的计算。您需要找出每行必须添加多少字节,以便该行的总字节数再次被4整除(这意味着,最多可添加3个字节):
unsigned int padding = ( 4 - (width * 3) % 4 ) % 4;
现在,你可以考虑这些额外的字节,并获得缓冲区的最终大小(以及你在内存中的图像):
unsigned int bufferSize = (width * 3 + padding) * height;
答案 1 :(得分:0)
我有一个类似的问题,我得到错误1282和黑色纹理。 据说glTexImage2D的第三个参数能够接受1,2,3,4的值,即每个像素的字节数。但由于某种原因,这突然停止了工作。替换&#39; 4&#39;与&#39; GL_RGBA&#39;为我解决了这个问题。 希望这有助于某人。