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

发布于 2024-10-05 09:06:46 字数 1615 浏览 0 评论 0原文

许多 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 的着色器无法访问我的投影/变换矩阵,因此我的红色三角形开始绘制 - 但可能在屏幕外的某个地方。

Many of you Qt (4.6 specifically) users will be familiar with the Overpainting example supplied in the OpenGL tutorials, I'm trying to do something very similar but using shaders for the pure OpenGL data, instead of the old fixed-function pipeline.

//  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();

I'm building a 3D asset application hence the grid stuff. To make it really obvious when it works, a big red rectangle should appear in the top left corner of the widget - but it doesn't.

The 3D works fine, but QPainter gets nothing to the screen. The only real difference I can see between mine and the docs is that the all the projection and transformation matrix calculations are hidden away in other functions and then uploaded to the shader via glUniform. Presumably as QPainter splits the 2D assets into triangles, this means that QPainter's shaders don't have access to my projection/transformation matrices, so my red triangle is begin drawn - but perhaps somewhere offscreen.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

飘逸的'云 2024-10-12 09:06:46

在进行 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 ) );

Call beginNativePainting() before making OpenGL calls. A glPush/Pop of the OpenGL state may also be necessary. Try something like the following:

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 ) );
檐上三寸雪 2024-10-12 09:06:46

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

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

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

glBindBuffer(GL_ARRAY_BUFFER,0);

第二个参数 0 取消绑定缓冲区)来解决该问题。

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

I'm posting this answer to strengthen and clarify what I regard as the true solution, found by cmannet85 (comment to answer by baysmith above), which is to clean up OpenGL vertex buffer bindings before calling QPainter code.

I had an almost identical problem, in that I needed to switch between using QPainter functions and OpenGL functions. As cmannet85 found out, one cause is that if OpenGL functions leave bound vertex buffers behind, they interfere with QPainter's use of OpenGL.

I was able to fix the problem by adding this statement at the end of all the parts of my OpenGL ES 2.0 code which called glBindBuffer:

glBindBuffer(GL_ARRAY_BUFFER,0);

A second parameter of 0 unbinds the buffer.

There was no need for any other changes such as adding calls to beginNativePainting ... endNativePainting, etc.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文