glReadPixels GL_DEPTH_COMPONENT 使 QT 应用程序崩溃

Posted

技术标签:

【中文标题】glReadPixels GL_DEPTH_COMPONENT 使 QT 应用程序崩溃【英文标题】:glReadPixels GL_DEPTH_COMPONENT crashes QT application 【发布时间】:2016-03-27 15:04:43 【问题描述】:

我想在我的 QT 应用程序中使用带有 GL_DEPTH_COMPONENT 的 glReadPixels,以确保用户只能用鼠标选择可见顶点。当我尝试这样做时,我的应用程序崩溃并出现以下错误:

在 0x00007FFF94E60823 (ig75icd64.dll) 处未处理的异常 qtopenglsphere.exe: 0xC0000005: 访问冲突读取位置 0x00000000000000A8.

几点说明:

将 glreadpixels 与 GL_RED 一起使用会返回正确的结果

我的集成 GPU 是 Intel HD 4600。上面错误中的 ig75icd64.dll 似乎是它的 OpenGL 驱动程序。 “OpenGL 扩展查看器”报告此 GPU 与 OpenGL 4.3 及更早版本 100% 兼容。

目前程序正在绘制一个启用深度测试的透视 3D 立方体,并且立方体看起来很好。

Main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QOpenGLFunctions>
#include <QTextStream>

int main(int argc, char *argv[])

    QSurfaceFormat format;
    format.setSamples(16);
    format.setDepthBufferSize(24);
    QSurfaceFormat::setDefaultFormat(format);
    format.setRenderableType(QSurfaceFormat::OpenGL);
    format.setVersion(4, 0);
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();

glwidget.cpp - 初始化GL()

void GLWidget::initializeGL()

    initializeOpenGLFunctions();
    glClearColor(0,0,0,1);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);

    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
        "uniform mat4 mvpMatrix;\n"
        "in vec4 vertex;\n"
        "in vec4 color;\n"
        "out vec4 varyingColor;\n"
        "void main(void)\n"
        "\n"
        "varyingColor = color;\n"
        "gl_Position = mvpMatrix * vertex;\n"
        "");
    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
        "in vec4 varyingColor;\n"
        "out vec4 fragColor;\n"
        "void main(void)\n"
        "\n"
        "   gl_FragColor = varyingColor;\n"
        "");
    shaderProgram.link();

<definition of cube vertices>


glwidget.cpp-paintGL()

void GLWidget::paintGL()

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    mMatrix.setToIdentity();
    vMatrix.setToIdentity();

    QMatrix4x4 cameraTransformation;
    cameraTransformation.rotate(alpha, 0, 1, 0);
    cameraTransformation.rotate(beta, 1, 0, 0);
    QVector3D cameraPosition = cameraTransformation* QVector3D(0, 0, distance);
    QVector3D cameraUpDirection = cameraTransformation * QVector3D(0, 1, 0);
    QVector3D cameratranslate(panx,pany,0);
    cameratranslate = cameraTransformation*cameratranslate;
    cameraPosition += cameratranslate;
    vMatrix.lookAt(cameraPosition, cameratranslate, cameraUpDirection);

    shaderProgram.bind();
    shaderProgram.setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix);
    shaderProgram.setAttributeArray("vertex", vertices.constData());
    shaderProgram.enableAttributeArray("vertex");
    shaderProgram.setAttributeArray("color", colors.constData());
    shaderProgram.enableAttributeArray("color");
    glDrawArrays(GL_TRIANGLES, 0, vertices.size());
    shaderProgram.disableAttributeArray("vertex");
    shaderProgram.disableAttributeArray("color");

    shaderProgram.release();

glwidget.cpp - findSelectedVertex(QPoint)

void GLWidget::findSelectedVertex(QPoint clickpoint)

    float mousex = clickpoint.x();
    float mousey = clickpoint.y();
    float renderedPixelDepth;
    glReadPixels(mousex,height()-mousey,1,1,GL_DEPTH_COMPONENT,GL_FLOAT,&renderedPixelDepth);// EXCEPTION THROWN HERE
    QTextStream(stdout) << "Clicked point value = " << renderedPixelDepth << endl;

对我来说似乎很奇怪我可以将 glReadPixels 与 GL_RED 一起使用,但不能与 GL_DEPTH_COMPONENT 一起使用。我试图确保我使用的是 OpenGL4.0 而不是 OpenGL ES 2.0(它没有 GL_DEPTH_COMPONENT),但也许我遗漏了一些东西。

【问题讨论】:

【参考方案1】:

一个兼容的 OpenGL 实现不允许抛出异常,因为它为 GL_DEPTH_COMPONENTglReadPixels 等驱动程序不支持的操作提供枚举或值。如果不受支持,该操作将记录一个可由glGetError 检索的错误并继续进行,就像从未调用过该操作一样。

您不清楚哪条线路崩溃了。我的猜测是 glReadPixels 操作失败,因为不支持 GL_DEPTH_COMPONENT+GL_FLOAT 并且现在未初始化的浮点数会导致打印操作出现问题。如果那是从哪里引发异常的话。

【讨论】:

谢谢安德烈亚斯。 glReadPixels 行是问题并导致异常。我从来没有真正到达我打印的行。使用 GL_RED 和 float 返回一个从 0 到 1 的值,这与 GL_DEPTH_COMPONENT 的预期相同,所以我也不认为这可能是个问题。 我有相当一部分不可靠的调试器...是否打开了任何可能干扰调试器的优化?您是否尝试过在 gDEBugger 或 CodeXL 等图形调试器中执行应用程序并在出错时中断?至于解决你的问题,我很茫然。代码对我来说看起来不错。我一直在使用不支持某些 glReadPixels 枚举(Mesa)的平台,结果是 OpenGL 错误和未写入数据,正如标准所定义的那样。然后再次从 OpenGL 中无法查询支持哪个子集,因为子集实际上是不兼容的。

以上是关于glReadPixels GL_DEPTH_COMPONENT 使 QT 应用程序崩溃的主要内容,如果未能解决你的问题,请参考以下文章

glReadPixels 移动坐标与缩放

为啥 glreadpixels 仅在某些情况下有效?

从 glReadPixels 创建 HBITMAP

如何使用 glReadPixels 读取浮点数据

opengl glReadPixels

OpenGL glReadPixels 性能