Object moving on display call

I have a couple quads drawn in a scene. They are meant to be the front and back of a cube, but I haven’t drawn the remaining sides because I am having an issue just with the front and back.

When the display function gets called, the quads move. However, I use the same call to gluLookAt and I have not edited the object vertex positions.

Here is my code:

#include <GL/glut.h> 
#include <stdio.h>

float X_MIN = -3.0;
float X_MAX = 3.0;
float Y_MIN = -3.0;
float Y_MAX = 3.0;

int WINDOW_WIDTH = 500;
int WINDOW_HEIGHT = 500;

GLfloat x_view = 3.0, y_view = 3.0, z_view = 0.0;
GLfloat xref = 0.0, yref = 0.0, zref = 0.0;
GLfloat x_up = 0.0, y_up = 1.0, z_up = 0.0;
float v=0.0f;

GLfloat dnear = 1.0, dfar = 8.0;

void setupView()
{ 
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  
  // Specify the viewing parameters
  gluLookAt(x_view, y_view, z_view, xref, yref, zref, x_up, y_up, z_up);

  // Projection
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(120.0, 1.0f, dnear, dfar);

  // Viewport 
  glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);

}


// Clear buffers, setup view, enable depth
void init(void)
{
  glClearColor(1.0,1.0,1.0,0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  setupView();

  glEnable(GL_DEPTH_TEST);
}


// ascii key and (x,y) of mouse when the key is pressed
void keyboardCb(unsigned char key, int x, int y)
{
  
  switch(key)
  {
    case 'a':
      printf("\nPressed a\n");
      v += 0.01;
      break;
  }

  // May have changed the camera location (implement later), so redraw the scene
	glutPostRedisplay();
}


void drawCube()
{
  glColor3f(1.0, 0.0, 0.0);
  int z = 1;

  // front
  glBegin(GL_QUADS);
    glVertex3i(-1, -1, z);
    glVertex3i(1, -1, z);
    glVertex3i(1, 1, z);
    glVertex3i(-1, 1, z);
  glEnd(); 
  
  // back
  glColor3f(0.0, 0.0, 0.0);
  z = -1;
  glBegin(GL_QUADS);
    glVertex3i(-1, -1, z);
    glVertex3i(1, -1, z);
    glVertex3i(1, 1, z);
    glVertex3i(-1, 1, z);
  glEnd();    
}


void display()
{
  // Clear the screen
  glClear(GL_COLOR_BUFFER_BIT);

  // Draw the cube
  drawCube();

  // Setup viewing parameters
  setupView();

  glutSwapBuffers();
}

int main(int argc, char** argv) 
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(50, 100);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutCreateWindow("Hello world!");
    init();

    // Setup callbacks
    glutKeyboardFunc(keyboardCb);
    glutDisplayFunc(display);

    glutMainLoop();
    printf("Exiting normally");
    return 0;
}

Whenever I press the ‘a’ key, glutPostRedisplay gets called, and the object is no longer at its original location. My expectation is that the scene does not change at all since I’m not calling gluLookAt with different values, and I’m not doing anything with the object coordinates.

I am wondering if the matrix calls in setupView get concatenated onto the previous matrix calls in that function? If I remove the call to setupView in display, then when I press ‘a’ I cannot see the quads at all.

Please let me know if you have an idea of why my object is moving around when display gets called despite me not (knowingly) changing the values of gluLookAt or changing object coordinates.

I can’t reproduce your problem on my system (after fixing the code so that it compiles; the posted code doesn’t declare the variable “v”).

No. The glLoadIdentity call resets the matrix.

in your display-function you call setupView after drawCube. probably not the reason for your problem, but still strange.

Oh, so sorry, I removed some other code to make this a minimal example, and accidentally removed that variable. It is simply a global float that I declare at the top. I edited my post to show that.

When I move it before the drawCube call I cannot see the cube at all. Maybe I need to revisit my viewing parameters then…

When I print the modelview and projection matrices, the elements do not change. This is something I expect, but I don’t know what in my scene could be changing that would cause the GL_QUADS to move and eventually go out of view.

The quads move when I press a button or resize the window.

An updated version of the code is the following:

#include <GL/glut.h> 
#include <stdio.h>
#include <math.h>

float X_MIN = -3.0;
float X_MAX = 3.0;
float Y_MIN = -3.0;
float Y_MAX = 3.0;

int WINDOW_WIDTH = 500;
int WINDOW_HEIGHT = 500;

// Viewing parameters
GLfloat cameraLoc[3] = {0, 0, 0};
GLfloat v = 0;
GLfloat u = 0;
GLfloat viewingRadius = 8.0f;

GLfloat x_view = 3.0, y_view = 3.0, z_view = 0.0;
GLfloat xref = 0.0, yref = 0.0, zref = 0.0;
GLfloat x_up = 0.0, y_up = 1.0, z_up = 0.0;

GLfloat dnear = 1.0, dfar = 8.0;

// print a 4x4 matrix
void printMat(GLfloat mat[16])
{
  printf("\n************************");
  printf("\nModelview matrix:");
  for (int r = 0; r < 4; r++)
  {
    printf("\n");
    printf("%f ", mat[r]);
    printf("%f ", mat[r+4]);
    printf("%f ", mat[r+8]);
    printf("%f ", mat[r+12]);
  }
  printf("\n");
}



void setupView()
{ 

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  // Specify the viewing parameters
  // view[] is the origin of the viewing frame
  // ref[] is the reference position (this is NOT projection reference point)
  // up[] is the view up vector
  gluLookAt(x_view, y_view, z_view, xref, yref, zref, x_up, y_up, z_up);

  // Get and print the matrix
  GLfloat mvmat[16];
  glGetFloatv(GL_MODELVIEW_MATRIX, mvmat);
  printMat(mvmat);

  // Projection
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(120.0, 1.0f, dnear, dfar);

  // Get and print the matrix
  GLfloat projmat[16];
  glGetFloatv(GL_PROJECTION_MATRIX, projmat);
  printMat(projmat);




  // Viewport 
  // I get the same results if I call or don't call this
  //glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);

  // Is the above order the correct order to call in OpenGL?
  // the book says model->view->projection->(clipping)->(normalization)->viewport->world
}


// Clear buffers, setup view, enable depth
void init(void)
{
  glClearColor(1.0,1.0,1.0,0.0);
  glClear(GL_COLOR_BUFFER_BIT);

  setupView();

  glEnable(GL_DEPTH_TEST);
}



void reshapeCb(GLint newWidth, GLint newHeight)
{
  glViewport(0, 0, newWidth, newHeight);

  WINDOW_WIDTH = newWidth;
  WINDOW_HEIGHT = newHeight;

  glutPostRedisplay();
}

// ascii key and (x,y) of mouse when the key is pressed
void keyboardCb(unsigned char key, int x, int y)
{
  
  switch(key)
  {
    case 'a':
      printf("\nPressed a\n");
      break;
  }

    // May have changed the camera location, so redraw the scene
	glutPostRedisplay();
}


void drawCube()
{
  glColor3f(1.0, 0.0, 0.0);
  int z = 1;

  // front
  glBegin(GL_QUADS);
    glVertex3i(-1, -1, z);
    glVertex3i(1, -1, z);
    glVertex3i(1, 1, z);
    glVertex3i(-1, 1, z);
  glEnd(); 
  
  // back
  glColor3f(0.0, 0.0, 0.0);
  z = -1;
  glBegin(GL_QUADS);
    glVertex3i(-1, -1, z);
    glVertex3i(1, -1, z);
    glVertex3i(1, 1, z);
    glVertex3i(-1, 1, z);
  glEnd();    
}


void display()
{
  printf("\nIn display\n");

  // Clear the screen
  glClear(GL_COLOR_BUFFER_BIT);

  // Set viewing parameters and projection
  setupView();

  // Draw the cube
  drawCube();

  glutSwapBuffers();
}

int main(int argc, char** argv) 
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(50, 100);
    glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
    glutCreateWindow("Hello world!");
    init();

    // Setup callbacks
    glutReshapeFunc(reshapeCb);
    glutKeyboardFunc(keyboardCb);
    glutDisplayFunc(display);

    glutMainLoop();
    printf("Exiting normally");
    return 0;
}

Again, I can’t reproduce this issue.

Does it still happen if you change GLUT_SINGLE to GLUT_DOUBLE? Single-buffered context are rarely used nowadays so a driver bug which affects them could go unnoticed.

Yes, it still occurs with a double buffer. Would the OS matter at all? I’m on Ubuntu 18.04. My GPU is a GTX 2070.

Okay, so I tried on a different computer and this code works fine. What do you think I can check on the problematic device? I can try to update my graphics driver first of all. Are there other device-specific things I can check for and fix?

Sorry to keep bumping this thread, but another update I have is that if I continuously resize the window (I don’t stop dragging), then the objects will come back and disappear repeatedly. They don’t appear/disappear every other frame, but as I’m dragging the window I can see the objects appear for a frame every now and then.

I’m on the nvidia-440 driver with OpenGL 4.6.0 on Ubuntu 18.04.

With NVidia GL drivers, probably not. They use largely the same drivers across Linux and Windows, barring OS-specific edges.


I compiled your code and ran here here on Linux (OpenSuSE Leap 15.0) with NVidia GL drivers, and reproduced the issue you mentioned.

Here’s your problem:

glEnable(GL_DEPTH_TEST);

Why is that a problem? You’re not allocating a depth buffer:

    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

(no GLUT_DEPTH listed here). And even if you were, you’re not clearing it:

  glClear(GL_COLOR_BUFFER_BIT);

Well, turns out that even though you’re not explicitly requesting a depth buffer, you’re getting one. That’d otherwise be just fine and your app would be oblivious to this overly-generous allocation of resources to your app. But you enabled GL_DEPTH_TEST. So what happens?

In the first frame rendered, you seed the depth buffer with your objects’ depth values (because you’ve enabled GL_DEPTH_TEST, and depth writes are enabled by default, if depth tests are enabled).

But the next frame you render (after you clear the color buffer), your objects end up depth testing against their depth values rendered the last frame, which were never cleared. Because the default glDepthFunc() is GL_LESS, they lose the depth test against those same stale depth values your objects write the last frame, resulting in none of your object fragments from “this” frame actually ever making it to the frame buffer.

You can “fix” it by changing the glDepthFunc() to GL_LEQUAL. With this, they “win” the depth test against the stale state from the last frame (assuming they’re re-rendered with the same transforms+positions). This will work (in your case). But of course this is no serious fix. Don’t do this!

The real fix is to stop enabling depth test when you haven’t allocated a depth buffer. Alternatively, 1) allocate one, 2) clear it every frame, and 3) enable depth test so you can actually make use of it.

Wow thank you so much! I don’t even know where I got that from. I looked back at my opengl textbook and it didn’t have that line to enable the depth test. I think I had it in an old school project that I copied some code from, and I just assumed it was correct since it worked for whatever I was doing back in that project. Thanks again for the in-depth explanation!

No problem!