If you search for "opengl rubber band" you will undoubtedly run across the somewhat antiquated OpenGL FAQ. Further searching on this method reveals a few hits that suggest XOR-ing color bits in the front buffer. This is not correct. Writing to the front buffer is not legal in OpenGL and as of Vista, it can result in unpredictable behavior.
An alternate solution is to do rubber band drawing in the back buffer. However, once the back buffer has been swapped, it is no longer guaranteed to be in sync with the front buffer. In order to ensure that the back buffer stays in sync glCopyPixels(...) can be used on most graphics hardware to copy the front buffer to the back buffer before rubber banding. Below is some sample code showing one method to do rubber banding in OpenGL:
CRect wndRect;
GetClientRect( hWnd, wndRect );
//copy front buffer to back buffer...
glReadBuffer( GL_FRONT );
glDrawBuffer( GL_BACK );
glCopyPixels(wndRect.left, wndRect.top, wndRect.Width(), wndRect.Height(), GL_COLOR);
StartGL2DDrawing(); //set up ortho mode and disable lighting
DisableGLTransparency();
glOrtho(double(wndRect.left), double(wndRect.right), double(wndRect.bottom), double(wndRect.top), -1., 1. );
glDisable( GL_DEPTH_TEST );
glColor3f(1.f, 1.f, 1.f);
glPointSize( float(ptSize) );
glLineWidth( 1.f );
glEnable(GL_COLOR_LOGIC_OP);
glLogicOp(GL_XOR);
glBegin( GL_LINES );
glVertex2s( short( m_curStartPos.x ), short( m_curStartPos.y ) );
glVertex2s( short( m_curEndPos.x ), short( m_curEndPos.y ) );
glEnd();
glDisable(GL_COLOR_LOGIC_OP);
// finish - restore state
glEnable( GL_DEPTH_TEST );
EndGL2DDrawing();
SwapBuffers( wglGetCurrentDC() /*pDC->GetSafeHdc()*/ );
// toggle the visibility state
m_bIsOn = !m_bIsOn;
return;
5 comments:
Unfortunately, on some Vista desktops you can't even *read* from the front buffer.
Hi Hugo,
Thanks for letting us know. So if reading the front buffer is not allowed, do you have a better solution?
No :(
I’ve tried several different approaches (yours, using glCopyPixels() instead of SwapBuffers(), etc.) and all of them failed at some systems.
It seems to me that the only reliable way to do it is trough triple buffering (using an OpenGL extension for off-screen rendering)
This is just crazy! It is such a simple and fundamental thing for CAD and yet it is impossible to do now.
I have found that, while glCopyPixels can be slow it seems to be supported on all machines I have tested. Definitely more so than overlay planes. So for now, this is what I am using. If anyone else comes up with a better solution please let me know!
Another method:
To draw big scene
draw scene => back buffer
save back buffer to bitmap
then...
-swapbuffers
-restore back buffer from bitmap
To draw rubberband
Draw to back buffer (XOR optional)
swapbuffer
restore back buffer from bitmap.
Post a Comment