c++ - 上传压缩纹理时出现 GL_INVALID_OPERATION

标签 c++ qt opengl texture2d

每次我尝试使用 Qt QOpenGLTexture 上传具有多个 mipmap 级别的 DXT1 纹理时,我都会收到 GL_INVALID_OPERATION。对于 mipmap 级别 0,一切正常,但对于任何其他级别,我在 Qt 库中的 glCompressedTexSubImage2DEXT() 处得到 GL_INVALID_OPERATION。我的错误在哪里?

代码:

QOpenGLVertexArrayObject::Binder vaoBinder(&mVAO);
bindProgram();
glActiveTexture(GL_TEXTURE0);

const dds::Image *base = parser.getImageData(0);

mTexture.setFormat(QOpenGLTexture::RGB_DXT1);
mTexture.setSize(base->width, base->height);
mTexture.setMipLevelRange(0, parser.getMipmapCount());
mTexture.allocateStorage();
mTexture.bind();

for (size_t i = 0; i < parser.getMipmapCount(); i++)
{
    // Image data represents a single mipmap level of a texture.
    const dds::Image *img = parser.getImageData(i);

    mTexture.setCompressedData(i, img->dataSize, img->data);
    qDebug() << "size: " << img->width << img->height;
    qDebug() << "i: " << i << " error: " << glGetError();
}

mTexture.setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
mProgram.setUniformValue("objectTexture", 0);

unbindProgram();

这是程序日志:

size:  2048 2048
i:  0  error:  0
size:  1024 1024
i:  1  error:  1282
size:  512 512
i:  2  error:  1282
size:  256 256
i:  3  error:  1282
...
size:  1 1
i:  11  error:  1282

这是 glIntercept 日志的一部分:

glGenTextures(1,00000000006DCE68)
glTextureParameteriEXT(1,GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0)
glTextureParameteriEXT(1,GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,11)
glTextureStorage2DEXT(1,GL_TEXTURE_2D,1,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,2048,2048)
glBindTexture(GL_TEXTURE_2D,1)
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,0,0,0,2048,2048,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,2097152,00000000147A0080)
glGetError()=GL_NO_ERROR 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,1,0,0,1024,1024,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,524288,00000000149A0080) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,2,0,0,512,512,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,131072,0000000014A20080) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,3,0,0,256,256,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,32768,0000000014A40080) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,4,0,0,128,128,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,8192,0000000014A48080) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,5,0,0,64,64,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,2048,0000000014A4A080) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,6,0,0,32,32,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,512,0000000014A4A880) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,7,0,0,16,16,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,128,0000000014A4AA80) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,8,0,0,8,8,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,32,0000000014A4AB00) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,9,0,0,4,4,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,8,0000000014A4AB20) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,10,0,0,2,2,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,8,0000000014A4AB28) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glCompressedTextureSubImage2DEXT(1,GL_TEXTURE_2D,11,0,0,1,1,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,8,0000000014A4AB30) glGetError() = GL_INVALID_OPERATION
glGetError()=GL_INVALID_OPERATION 
glTextureParameteriEXT(1,GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,9729)
glTextureParameteriEXT(1,GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,9729)

最佳答案

当您调用 glTextureStorage2DEXT 时,您只是为单个 mipmap 分配了足够的内存。第三个参数是您要分配的 mipmap 级别数 - 在您的情况下,这应该是 11:

glTextureStorage2DEXT(1,GL_TEXTURE_2D,11,GL_COMPRESSED_RGB_S3TC_DXT1_EXT,2048,2048)

对于给定的宽度和高度,您可以使用 floor(log2(max(width, height))) + 1 计算生成完整 mipmap 链所需的级别数。


对不起,我没有完全回答这个问题!您应该调用 setMipLevels 而不是调用 setMipLevelRange .如 setMipLevels 的 Qt 文档中所述:

For texture targets that support mipmaps, this function sets the requested number of mipmap levels to allocate storage for. This function should be called before storage is allocated for the texture.

这应该有效:

mTexture.setMipLevels(floor(log2(max(width, height))) + 1);

或者使用您的parser.getMipmapCount() 方法:

mTexture.setMipLevels(parser.getMipmapCount());

关于c++ - 上传压缩纹理时出现 GL_INVALID_OPERATION,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26193815/

相关文章:

c++ - 变量 "variable name"周围的堆栈已损坏 C++

c++ - Matrix Hell - 将 3D 纹理中的点转换为世界空间

c++ - 在 C++ 中包装 std::iterator

c++ - 如何重构此类模板以最小化样板代码?

qt - 如何在QApplication执行之前获取QScreen

qt - 捕捉 QGraphicsScene 的 selectionChanged() 信号

json - 在 Qt 4.7 中发布 JSON 请求

c++ - Spritebatch 只绘制第一个 Sprite

opengl - 我在 VRAM 上存储的数据多于实际大小。这怎么可能?

c++ - 在 GLFW 中单击无需鼠标拖动