无法使用 glGetTexImage 读取深度图纹理

Posted

技术标签:

【中文标题】无法使用 glGetTexImage 读取深度图纹理【英文标题】:Can't use glGetTexImage to read a depth map texture 【发布时间】:2020-06-17 07:31:07 【问题描述】:

我已经成功创建了一个帧缓冲区对象并创建了一个包含场景深度图的纹理。我知道我这样做是正确的,因为我将我的纹理应用到一个矩形并且它看起来很好:

现在我想从我在主程序中创建的纹理中读取值,而不是在着色器中。研究了一下,我发现了两个函数,即:glGetTexImage() 和 glReadPixels()。由于我对 openGL 很陌生,因此有关这些的文档带来的问题多于答案。在这里查看其他人的代码后,这是我找到解决方案的壁橱:

    renderSceneOnFrameBuffer();//I'm excluding the first pass code since it works fine
    GLfloat *data = new GLfloat(1024 * 768);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, fbTexture);
    glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_FLOAT, data);//Access Violation Error

    // Rectangle 
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glUseProgram(rectShaderProgram);
    glBindVertexArray(rectangleVAO);
    glUniform1i(khTextureLocation, 0);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

使用 glGetTexImage 时出现访问冲突错误。我究竟做错了什么?

我将包括我声明我的 FBO 的代码行以防万一:

glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);

glGenTextures(1, &fbTexture);
glBindTexture(GL_TEXTURE_2D, fbTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 1024, 768, 0, GL_DEPTH_COMPONENT,
    GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D,
    fbTexture, 0);

glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);

另外,像这样使用 glReadPixels() 时,我遇到了同样的违规错误

    `GLfloat *data = new GLfloat(1024 * 768);
    glBindFramebuffer(GL_READ_FRAMEBUFFER, FBO);
    glReadPixels(0, 0, 1024, 768, GL_DEPTH_COMPONENT, GL_FLOAT, data);`

【问题讨论】:

【参考方案1】:

帧缓冲区可能有多个附件以及深度。当要读回帧缓冲区附件时,请使用 glReadPixel()。

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);

data  = (GLfloat *) malloc(1024* 768 * sizeof(GLfloat));
assert(data!=nullptr);

glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId);
glReadBuffers(GL_NONE); // Do this call only if you dont have any other attachment that color in Frame buffer
glReadPixels(0, 0, 1024, 768, GL_DEPTH_COMPONENT, GL_FLOAT, &data[0]);

glGetTexture() 用于从纹理中读取数据。

还有一件事。在创建帧缓冲纹理时使用调整大小的格式,如 GL_DEPTH_COMPONENT32F-> 将映射到 readpixel 为 GL_DEPTH_COMPONENT、GL_FLOAT。

【讨论】:

我也试过 glReadPixels。它给出了相同的违规错误。 fbo怎么会有多个附件?我只添加了一个深度附件。在这一点上,我什至不知道如何添加倍数。 我已经更新了代码。请按原样使用它并告诉我它是否解决了问题。 还是同样的错误。我什至尝试制作 rgb 纹理而不是深度图。在某些情况下,glReadPixels 使用 rgb 纹理,但由于某种原因,数据几乎是随机的。我在网上找不到好的教程或一些好的例子。最后可能需要一本关于openGL的教科书...... 对于 RGB 像素,情况有所不同,您必须为数据正确分配内存。假设每个像素为 8 位,即 uint_8* data = (uint_8*) malloc(1024 * 768 * 3 * sizeof(uint_8)); 还有一件事。创建帧缓冲纹理时使用大小格式,如 GL_DEPTH_COMPONENT32F-> 将映射到 readpixel 为 GL_DEPTH_COMPONENT、GL_FLOAT

以上是关于无法使用 glGetTexImage 读取深度图纹理的主要内容,如果未能解决你的问题,请参考以下文章

在 nvidia opengl 上混合 glGetTexImage 和 imageStore 的问题

使用 glTexImage2D 和 glGetTexImage 的一些问题

glGetTexImage() 在 ATI 卡上不能正常工作?当 miplevel > 0 时失败

检测到堆栈粉碎 glGetTexImage

glReadPixels 可以用来从 GL_TEXTURE_3D 读取图层吗?

像素缓冲区对象PBO 记录