QDeclarativeItem 中的 OpenGL 绘图搞乱了其他 QML 绘图
Posted
技术标签:
【中文标题】QDeclarativeItem 中的 OpenGL 绘图搞乱了其他 QML 绘图【英文标题】:OpenGL drawing in QDeclarativeItem messes up other QML drawing 【发布时间】:2013-07-16 10:18:15 【问题描述】:我正在做一个自定义的QDeclarativeItem
QML 组件,它使用 OpenGL 调用呈现 3d 内容。我对 OpenGL 相当陌生,但经过多次测试和失败后,我已经能够进行绘图工作。不幸的是,我的组件似乎破坏了其他 QML 组件的绘图,例如一些组件根本没有上漆。原因可能是我没有正确重置QPainter
的状态。
这就是我现在的做法:
void CustomItem::paint(QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget)
painter->save();
painter->beginNativePainting();
// Save all OpenGL states
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glPushAttrib(GL_ALL_ATTRIB_BITS);
// Avoid overpainting the rest of the QML view.
glEnable(GL_SCISSOR_TEST);
int inverted_y = painter->viewport().height() - scenePos().y() - height();
glScissor(scenePos().x(), inverted_y, width(), height());
// Painting is done at this point via our painting framework that
// is shared by QGLWidgets and QDeclarativeItems.
// Restore OpenGL states
glPopAttrib();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
painter->endNativePainting();
painter->restore();
这还不足以隔离 CustomItem 绘画吗?任何线索这里出了什么问题?
更新 1:
所有的绘制都是在 GUI 线程中完成的,所以活动的 OpenGL 上下文应该是正确的。绘画也使用 OpenGL 顶点缓冲区对象 - 可能会导致任何问题..?
更新 2:
好的,问题可能是由纹理处理引起的。如果我禁用自己的纹理处理,QML 会正确呈现。我仍然试图找出将 QML 纹理处理与我自己隔离的正确方法是什么。有什么建议吗?
【问题讨论】:
不,可能是您没有正确恢复的 OpenGL 状态。启用剪刀测试后尝试禁用它。 glPushAttrib(GL_ALL_ATTRIB_BITS) 和 glPopAttrib() 也应该保存和恢复剪刀测试。尽管如此,我也尝试使用 glDisable(GL_SCISSOR_TEST) 禁用剪刀测试,但没有帮助。 我用一些额外的信息更新了这个问题。 再次更新(参见“更新 2”)。 【参考方案1】:问题是由将我们的纹理数据加载到默认纹理对象引起的,该对象也被 QML 框架使用。解决方案是在我们自己的纹理处理中生成和绑定独特的纹理。对于像我这样的 OpenGL 初学者来说,这是关于纹理处理的精彩课程。
要处理其他 OpenGL 状态更改,在我们的绘图周围添加 glPushAttrib(GL_ALL_ATTRIB_BITS)
和 glPopAttrib()
就足够了。
【讨论】:
以上是关于QDeclarativeItem 中的 OpenGL 绘图搞乱了其他 QML 绘图的主要内容,如果未能解决你的问题,请参考以下文章
使用 OpenGL 将图像渲染到子类 QDeclarativeItem