-1

I'm using PyOpenGL and GLUT to draw a square that moves in a circle. I do not clear the screen after drawing squares, because I desire a trailing effect. For some reason, squares that have been drawn already will move when new ones are drawn.

Notice, the extra pixel in the stroke of the squares is not the issue. It is the fact that the trail of squares is not static.

Here is an example of the effect

I'm providing code that I think is relevant. First, the code that I use to initialize the window:

glutInit()
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)
glutInitWindowSize(width, height)

Second, this piece of code is called once before every square being drawn.

glLoadIdentity()
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0.0, width, 0.0, height, 0.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

Third, the actual drawing of the square

def rect_fill(x, y, w, h):
    glBegin(GL_QUADS)
    glVertex2f(x, y)
    glVertex2f(x + w, y)
    glVertex2f(x + w, y + h)
    glVertex2f(x, y + h)
    glEnd()

def rect_stroke(x, y, w, h, lw):
    lw = lw / 2
    glBegin(GL_LINES)
    glVertex2f(x - lw, y)
    glVertex2f(x + w + lw, y)

    glVertex2f(x + w, y - lw)
    glVertex2f(x + w, y + h + lw)

    glVertex2f(x + w + lw, y + h)
    glVertex2f(x - lw, y + h)

    glVertex2f(x, y + h + lw)
    glVertex2f(x, y - lw)
    glEnd()

I have been at this for a while, and haven't been able to find anyone with similar issues. Thank you for any help.

Enrico Borba
  • 1,877
  • 2
  • 14
  • 26

1 Answers1

0

The issue is with the line

glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH)

GLUT_DOUBLE Enables double buffering. Double buffering provides two complete color buffers for use in drawing. One buffer is displayed while the other buffer is being drawn into. When the drawing is complete, the two buffers are swapped so that the one that was being viewed is now used for drawing.

That is what is causing this odd changing between two different squares effect.

Enrico Borba
  • 1,877
  • 2
  • 14
  • 26
  • 1
    Could you elaborate how double buffering could cause these artifacts? Most probably these additional pixel happen because you don't take the aspect ratio into account when calculating the offsets during stroke rendering (or you don't take pixel centers into account, which is impossible to tell because you don't show with which parameters you call `rect_stroke`). – BDL Mar 12 '17 at 23:36
  • So, my issue wasn't the extra pixel. It was the fact that the trail of squares being drawn was not static. It's clearly "jittering" or "shaking", which I thought was weird because those squares had already been drawn, and weren't being modified further. The double buffer was the cause because, one square would be drawn, then the buffer would swap, and I would not see the first square I drew. That is, each square would be on only one buffer, but not both. – Enrico Borba Mar 12 '17 at 23:46
  • 1
    I agree with @EnricoBorba. The "shaking" effect is due to drawing in alternating buffers without clearing them. This can be avoided by storing each already drawn buffer in a texture and drawing this texture in each frame before the new square. This way double buffering can be enabled. – Ripi2 Mar 12 '17 at 23:52
  • I feel like having all of these textures would ruin the efficiency though. I don't see a reason to double buffer, as I want to keep all previous frames. So, I'm not too familiar with graphics, but is there too much of an issue with me disabling double buffering? – Enrico Borba Mar 13 '17 at 00:22
  • @EnricoBorba: Here's a quick experiment for you: Resize your window while your program runs. This is not about double buffering vs. not double buffering but that you assume persistence of your main window framebuffer. Hint: It's not. **The main window framebuffer may be cleared/damaged/etc. at any time between frame updates.** The only way for your program to behave correctly is to draw to a texture or off-screen renderbuffer (using a framebuffer object), which is guaranteed to be persistent, And it's not expensive at all. – datenwolf Mar 13 '17 at 12:05
  • Alright so, if I understand this correctly, every frame I have to recopy this entire off-screen renderbuffer over to the framebuffer, to ensure that, even if it has been cleared, it still remains persistent? – Enrico Borba Mar 13 '17 at 19:36