使用着色器时,在QGLWidget中使用QPainter而不是OpenGL

时间:2010-11-30 16:39:17

标签: qt opengl overlay shader qpainter

许多人(特别是4.6)用户将熟悉OpenGL教程中提供的Overpainting示例,我正在尝试做一些非常相似的事情但是使用着色器来处理纯OpenGL数据,而不是旧的固定功能管道

//  Set background and state.
makeCurrent();
qglClearColor( bgColour_ );

glEnable( GL_DEPTH_TEST );
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

if ( smoothLines_ ) {
    glEnable( GL_BLEND );
    glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
    glEnable( GL_LINE_SMOOTH );
    glHint( GL_LINE_SMOOTH_HINT, GL_NICEST );
}

//  Clear the buffers.
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUseProgram( shader_ );

//  Draw the grid.
try {
    glLineWidth( 2.0f );
    manager_->setColour( centreColour_ );
    grid_->draw( oE_GLGrid::Centre );

    glLineWidth( 1.5f );
    manager_->setColour( majorColour_ );
    grid_->draw( oE_GLGrid::Major );

    glLineWidth( 1.0f );
    manager_->setColour( minorColour_ );
    grid_->draw( oE_GLGrid::Minor );
} catch( oE_GLException& e ) {
    cout << "OpenGL Error: " << e.what() << endl;
    return;
}

//  Reset OpenGL state for overlays.
glDisable( GL_DEPTH_TEST );
if ( smoothLines_ ) {
    glDisable( GL_BLEND );
    glDisable( GL_LINE_SMOOTH );
}

//  Draw the overlays.
QPainter p( this );
p.beginNativePainting();
p.fillRect( 10, 10, 100, 100,
        QColor( 255, 0, 0 ) );
p.endNativePainting();

我正在构建一个3D资产应用程序,因此是网格内容。为了使它在工作时非常明显,一个大的红色矩形应该出现在小部件的左上角 - 但事实并非如此。

3D工作正常,但QPainter对屏幕没有任何作用。我可以在我和文档之间看到的唯一真正的区别是,所有投影和变换矩阵计算都隐藏在其他函数中,然后通过glUniform上传到着色器。据推测,当QPainter将2D资源分成三角形时,这意味着QPainter的着色器无法访问我的投影/变换矩阵,因此我的红色三角形开始绘制 - 但可能在屏幕外的某处。

2 个答案:

答案 0 :(得分:10)

在进行OpenGL调用之前调用beginNativePainting()。也可能需要OpenGL状态的glPush / Pop。尝试以下内容:

QPainter p( this );
p.beginNativePainting();

// Maybe necessary
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

// Put OpenGL code here

// Necessary if used glPush-es above
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();

p.endNativePainting();

p.fillRect( 10, 10, 100, 100,
        QColor( 255, 0, 0 ) );

答案 1 :(得分:4)

我发布这个答案是为了加强和澄清我认为真正的解决方案,由 cmannet85 (评论通过上面的 baysmith 回答),这是在调用QPainter代码之前清理OpenGL顶点缓冲区绑定。

我有一个几乎相同的问题,因为我需要在使用QPainter函数和OpenGL函数之间切换。发现 cmannet85 时,一个原因是如果OpenGL函数将绑定的顶点缓冲区留在后面,它们会干扰QPainter对OpenGL的使用。

我能够通过在我的OpenGL ES 2.0代码的所有部分(称为glBindBuffer)的末尾添加此语句来解​​决问题:

glBindBuffer(GL_ARRAY_BUFFER,0);

第二个参数0取消绑定缓冲区。

不需要任何其他更改,例如添加对beginNativePainting的调用... endNativePainting等。