Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 7 of 7

Thread: Draw rubber-band selection box

Hybrid View

  1. #1
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8

    Draw rubber-band selection box

    Hi, I know this has been asked a number of times, but all the ones I found either referred to the old deprecated pipeline or did not answer the question of how to draw the rectangle.

    In the old days it was fairly simple to draw a "rubber-band" selection box:
    1) copy the current front buffer into the back buffer
    2) set the orthographic projection
    3) use glLogicOp(GL_XOR) and Begin(GL_LINES) to draw the box
    4) Swapbuffers

    These days I don't know how it is done. I have listed the code below which does not work on many levels, first glCopyPixels I don't think exists any more so I have no idea how to copy the front buffer into the back buffer.

    Thanks for any advice.

    Code :
    	wglMakeCurrent(m_hDC, m_hRC);
     
    	RECT rc;
    	::GetClientRect(m_hWnd, &rc);
     
    	glReadBuffer(GL_FRONT);
    	glDrawBuffer(GL_BACK);
    	glCopyPixels(rc.left, rc.top, rc.right, rc.bottom, GL_COLOR);
     
    	GLuint pBuffer;
    	glGenBuffers(1, &pBuffer);
     
    	Vector3f box[5] = {
    		{ m_zoomTracker.Left(), m_zoomTracker.Bottom(), 0.f },
    		{ m_zoomTracker.Right(), m_zoomTracker.Bottom(), 0.f },
    		{ m_zoomTracker.Right(), m_zoomTracker.Top(), 0.f },
    		{ m_zoomTracker.Left(), m_zoomTracker.Top(), 0.f },
    		{ m_zoomTracker.Left(), m_zoomTracker.Bottom(), 0.f }
    	};
     
    	glBindBuffer(GL_ARRAY_BUFFER, pBuffer);
    	glEnableVertexAttribArray(AGL_ATTRIBUTE_VERTEX);
    	glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3f)*5, box, GL_STATIC_DRAW);
    	glVertexAttribPointer(AGL_ATTRIBUTE_VERTEX, 3, GL_FLOAT, GL_FALSE, 0, 0);
     
    	m_frustum.SetOrthographic(rc.left, rc.right, rc.top, rc.bottom, -1.f, 1.f);
     
    	glDisable(GL_DEPTH_TEST);
    	glEnable(GL_COLOR_LOGIC_OP);
    	glLogicOp(GL_XOR);
    	glColor3f(1.f, 1.f, 1.f);
    	glLineWidth(2.f);
     
    	glDrawArrays(GL_LINES, 0, 5);
    	//glRectf(m_zoomTracker.Left(), m_zoomTracker.Top(), m_zoomTracker.Right(), m_zoomTracker.Bottom());
     
    	glEnable(GL_DEPTH_TEST);
    	glDisable(GL_COLOR_LOGIC_OP);
     
    	glDeleteBuffers(1, &pBuffer);
     
    	m_frustum.SetPerspective(FOV, m_aspectRatio, 1.0, m_sceneDiagonal * 4);
     
    	SwapBuffers(m_hDC);

  2. #2
    Member Regular Contributor
    Join Date
    Dec 2007
    Posts
    253
    actually in the good ol' days people simply did the rubber banding on the front buffer. No need for the copy to back buffer, and then another buffer swap. It was easy to undo as well as you just draw the same again and it'll disappear.

    You can still do this today, but in Vista (onwards I assume) you need to call glflush or glfinish after you've finished drawing, otherwise the OS doesn't know to update the screen. Since everything is rendered through d3d.

  3. #3
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    Quote Originally Posted by dukey View Post
    actually in the good ol' days people simply did the rubber banding on the front buffer. No need for the copy to back buffer, and then another buffer swap. It was easy to undo as well as you just draw the same again and it'll disappear.

    You can still do this today, but in Vista (onwards I assume) you need to call glflush or glfinish after you've finished drawing, otherwise the OS doesn't know to update the screen. Since everything is rendered through d3d.
    I thought glflush and glfinish only complete the gl commands. In a double buffered system you still need to refresh the screen with a swap. The reason I copy the front to back is that
    1) the back buffer is undefined after a swap
    2) I don't want to redraw the scene, in my case there is no animation so the scene remains the same for duration of the mouse drag.

    Anyways, I tried your suggestion and it still doesn't work. So, assuming you are right, then there must be something wrong with the drawing commands which I can't figure out.

  4. #4
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    I don't know how to refresh the screen in a double-buffered system without a swap, but that's another issue. I decided to just add this function to the end of my draw scene function (after removing the frame buffer commands) and there is definitely a problem with the drawing code that I cannot figure out. The shader I'm binding to does the following, the mvp matrix is just the orthographic projection matrix, there is no modelview transforms since I am drawing on top of the screen.


    Code :
    uniform mat4 mvpMatrix;
    attribute vec4 vVertex;
     
    void main(void)
    {
      gl_Position = mvpMatrix * vVertex;
    }

    Code :
    void main(void)
    {
      gl_FragColor = gl_Color;
    }
    Last edited by jonpb1; 12-11-2012 at 06:16 PM. Reason: change in fragment shader

  5. #5
    Member Regular Contributor
    Join Date
    Dec 2007
    Posts
    253
    I don't know how to refresh the screen in a double-buffered system without a swap,
    glDrawBuffer(GL_FRONT);

    // draw some stuff

    glFlush();

    glDrawBuffer(GL_BACK);

  6. #6
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    I tried that and it didn't do anything. At least by adding the code to the end of the draw scene code it does something, although what it does is erase the screen.

  7. #7
    Junior Member Newbie
    Join Date
    Dec 2012
    Posts
    8
    So it turns out the erasing effect was a bug outside of the opengl code. There is still a problem with this code, that I can't figure out. Whether I use dukey's suggestion to draw to the front buffer or just add it to the end of the draw scene function, still nothing happens. I don't know if it is in the vertex shader or the fragment shader but nothing is happening. Btw, the I edited the fragment shader to correct it.

    Thanks to anyone who see the obvious problem with this code.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •