2013-07-16 26 views
0

我正在执行自定义的QDeclarativeItem QML组件,该组件使用OpenGL调用呈现3D内容。我对OpenGL相当陌生,但经过多次测试并失败后,我才能够完成绘图工作。不幸的是,我的组件似乎打破了其他QML组件的绘制,例如一些组件根本不会被绘制。原因可能是我没有正确重置QPainter的状态。QDeclarativeItem中的OpenGL绘图混淆了其他QML绘图

这是我要做的事现在:

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纹理处理的正确方法是什么。有什么建议么?

+0

不,它可能是您不能正确还原的OpenGL状态。尝试启用后禁用剪刀测试。 – user1095108

+0

glPushAttrib(GL_ALL_ATTRIB_BITS)和glPopAttrib()应保存并恢复剪切测试。尽管如此,我还试图用glDisable(GL_SCISSOR_TEST)禁用剪刀测试,但它没有帮助。 – ronkot

+0

我更新了一些附加信息的问题。 – ronkot

回答

1

这个问题是由将我们的纹理数据加载到QML框架也使用的默认纹理对象引起的。解决方案是在我们自己的纹理处理中生成并绑定独特的纹理。对于像我这样的OpenGL初学者来说,这是关于纹理处理的一个很好的教训。

要处理其他OpenGL状态更改,在我们的图形周围添加glPushAttrib(GL_ALL_ATTRIB_BITS)glPopAttrib()就足够了。