2016-06-20 38 views
1

Als Teil eines 3D-Mesh-Viewers, den ich in QT mit QOpenGLWidget mache, muss ich einem Benutzer die Möglichkeit bieten, auf einen Knoten innerhalb des Modells zu klicken. Um die Auswahl nur auf sichtbare Knoten zu beschränken, habe ich versucht, glReadPixels (GL_DEPTH_COMPONENT) in meinen Auswahlalgorithmus aufzunehmen.QOpenGLWidget und glReadPixels und Tiefenpuffer

Mein Problem ist, dass glReadPixels (Tiefe) immer 0 zurückgibt. Alle Fehlerausgaben im folgenden Code geben auch 0 zurück. glReadPixels (rot) liefert korrekte Werte:

GLenum err = GL_NO_ERROR; 
    QTextStream(stdout) << "error before reading gl_red = " << err << endl; 
    GLfloat winX, winY, myred, mydepth; 
    winX = mousex; 
    winY = this->height() - mousey; 
    glReadPixels(winX,winY,1,1,GL_RED,GL_FLOAT, &myred); 
    QTextStream(stdout) << "GL RED = " << myred << endl; 
    err = glGetError(); 
    QTextStream(stdout) << "error after reading gl_red = " << err << endl; 
    glReadPixels(winX,winY,1,1,GL_DEPTH_COMPONENT,GL_FLOAT, &mydepth); 
    QTextStream(stdout) << "GL_DEPTH_COMPONENT = " << mydepth << endl; 
    err = glGetError(); 
    QTextStream(stdout) << "error after reading gl_depth = " << err << endl; 

Mein normales 3D-Rendering funktioniert gut, ich habe glEnable(GL_DEPTH_TEST) in meiner initializeGL() Funktion. Im Moment verwende ich keine ausgefallenen VBOs oder VAOs. FaceMeshQualityColor und triVertices haben beide den Datentyp QVector<QVector3D>. Mein aktuelles Gesicht Rendering folgt den folgenden Verlauf:

shader = shaderVaryingColor; 
shader->bind(); 
shader->setAttributeArray("color", FaceMeshQualityColor.constData()); 
shader->enableAttributeArray("color"); 
shader->setUniformValue("mvpMatrix", pMatrix * vMatrix * mMatrix); 
shader->setAttributeArray("vertex", triVertices.constData()); 
shader->enableAttributeArray("vertex"); 
glEnable(GL_POLYGON_OFFSET_FILL); 
glPolygonOffset(1,1); 
glDrawArrays(GL_TRIANGLES, 0, triVertices.size()); 
glDisable(GL_POLYGON_OFFSET_FILL); 
shader->disableAttributeArray("vertex"); 
shader->disableAttributeArray("color"); 
shader->release(); 

In meiner Haupt-Datei Ich habe ausdrücklich meine OpenGL-Version etwas mit glReadPixels (GL_DEPTH_COMPONENT) Funktionalität (im Gegensatz zu OpenGL ES 2.0):

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    QSurfaceFormat format; 
    format.setVersion(2, 1); 
    format.setProfile(QSurfaceFormat::CoreProfile); 
    format.setDepthBufferSize(32); 
    QSurfaceFormat::setDefaultFormat(format); 
    MainWindow w; 
    w.showMaximized(); 
    return a.exec(); 
} 

Funktioniert mein Problem mit glReadPixels (depth) nicht irgendwie mit meiner Behandlung meines Tiefenpuffers?

Muss ich den Tiefenpuffer 'aktivieren', um von ihm lesen zu können, bevor ich glReadPixels anrufe? Oder muss der Vertex-Shader explizit die Tiefenposition in ein anderes Objekt schreiben?

Antwort

1

QOpenGLWidget funktioniert in einem zugrunde liegenden FBO und Sie können die Tiefenkomponente aus diesem FBO nicht einfach lesen, wenn Multisampling aktiviert ist. Die einfachste Lösung ist es, die Proben auf Null zu setzen, so dass Ihr Code wie folgt aussehen:

QSurfaceFormat format; 
format.setVersion(2, 1); 
format.setProfile(QSurfaceFormat::CoreProfile); 
format.setDepthBufferSize(32); 

format.setSamples(0); 

QSurfaceFormat::setDefaultFormat(format); 

Oder Sie können Multi-Sampling verwenden, aber eine zusätzliche FBO wird ohne Multisampling erforderlich, wenn die Tiefenpuffer kopiert werden kann.

class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions 
{ 
// 
// OTHER WIDGET RELATED STUFF 
// 
QOpenGLFrameBufferObject *mFBO=0; 

MyGLWidget::paintGL() 
{ 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    // 
    // DRAW YOUR SCENE HERE! 
    // 

    QOpenGLContext *ctx = QOpenGLContext::currentContext(); 

    // FBO must be re-created! is there a way to reset it? 
    if(mFBO) delete mFBO; 

    QOpenGLFramebufferObjectFormat format; 
    format.setSamples(0); 
    format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); 
    mFBO = new QOpenGLFramebufferObject(size(), format); 

    glBindFramebuffer(GL_READ_FRAMEBUFFER, defaultFramebufferObject()); 
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO->handle()); 
    ctx->extraFunctions()->glBlitFramebuffer(0, 0, width(), height(), 0, 0, mFBO->width(), mFBO->height(), GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST); 

    mFBO->bind(); // must rebind, otherwise it won't work! 

    float mouseDepth = 1.f; 
    glReadPixels(mouseX, mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &mouseDepth); 

    mFBO->release(); 
} 
}; 
Verwandte Themen