11

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.

Kate Gregory
  • 18,808
  • 8
  • 56
  • 85
cmannett85
  • 21,725
  • 8
  • 76
  • 119

2 Answers2

11

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 ) );
baysmith
  • 5,082
  • 1
  • 23
  • 18
  • Still no luck, the 3D data is unaffected but the QPainter data doesn't appear. I'm wondering if it'll be faster/easier to render out to a pixel buffer, load that into a QPainter as a background pixmap, and then 'paint' over the top before drawing to screen? Or is that a lot slower than it sounds? – cmannett85 Nov 30 '10 at 20:12
  • Does the QPainter data appear if you don't perform the 3D drawing? – baysmith Nov 30 '10 at 20:18
  • I filled the paintEvent() function with just the QPainter calls (like in the 2D painting example in the docs) and nothing appears on screen - except the widget is filled black. – cmannett85 Nov 30 '10 at 20:34
  • Something not in the original code fragment is causing a problem. – baysmith Nov 30 '10 at 22:30
  • 3
    Solved! After your last comment I managed to track it to down to me not unbinding a VBO after the grid's VAO was unbound, which presumably was totally screwing the vertex instructions QPainter was calling. Thank you very much! – cmannett85 Dec 01 '10 at 21:12
5

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.

Graham Asher
  • 1,648
  • 1
  • 24
  • 34