【问题标题】:Using QPainter over OpenGL in QGLWidget when using shaders使用着色器时在 QGLWidget 中使用 QPainter over OpenGL
【发布时间】:2011-05-17 23:56:55
【问题描述】:

你们中的许多 Qt(特别是 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 的着色器无法访问我的投影/变换矩阵,所以我的红色三角形开始绘制 - 但可能在屏幕外的某个地方。

【问题讨论】:

    标签: qt opengl overlay shader qpainter


    【解决方案1】:

    在调用 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 ) );
    

    【讨论】:

    • 仍然没有运气,3D 数据不受影响,但 QPainter 数据没有出现。我想知道渲染到像素缓冲区是否会更快/更容易,将其作为背景像素图加载到 QPainter 中,然后在绘制到屏幕之前在顶部“绘制”?还是比听起来要慢很多?
    • 不进行3D绘图会出现QPainter数据吗?
    • 我只用 QPainter 调用填充了 paintEvent() 函数(就像在文档中的 2D 绘画示例中一样),屏幕上什么也没有出现 - 除了小部件被填充为黑色。
    • 原始代码片段中没有的东西导致了问题。
    • 解决了!在您的最后一条评论之后,我设法追踪到我在网格的 VAO 未绑定后没有解除 VBO 的绑定,这大概是完全搞砸了 QPainter 调用的顶点指令。非常感谢!
    【解决方案2】:

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

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

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

    glBindBuffer(GL_ARRAY_BUFFER,0);
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-21
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 1970-01-01
      • 2013-12-11
      相关资源
      最近更新 更多