glPushMatrix()和glPopMatrix()如何使场景保持一致?

时间:2011-08-11 19:40:14

标签: c++ opengl graphics

我在网上发现了一些代码,它会在屏幕上移动一个框,然后在框到达屏幕末尾后重置它。
这是代码:

void display(void) {
  int sign = 1;
  if (lastFrameTime == 0) {
    /*
     * sets lastFrameTime to be the number of milliseconds since
     * Init() was called;
     */
    lastFrameTime = glutGet(GLUT_ELAPSED_TIME);
  }

  int now = glutGet(GLUT_ELAPSED_TIME);
  int elapsedMilliseconds = now - lastFrameTime;
  float elapsedTime = float(elapsedMilliseconds) / 1000.0f;
  lastFrameTime = now;

  int windowWidth = glutGet(GLUT_WINDOW_WIDTH);

  if (boxX > windowWidth) {
    boxX -= windowWidth;
  }
  boxX += (sign)*256.0f * elapsedTime;

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glPushMatrix();
  //creates a new matrix at the top that we can do things to?
  glTranslatef(boxX, 0.0f, 0.0f);

  /*
   * draw a "quad" (rectangle)
   */
  glBegin(GL_QUADS);
  glVertex2f(0.0f, 0.0f);
  glVertex2f(128.0f, 0.0f);
  glVertex2f(128.0f, 128.0f);
  glVertex2f(0.0f, 128.0f);
  glEnd();
  glPopMatrix();
  //pops that matrix off the stack so we can have a "clean" version to do something next time.?

  glutSwapBuffers();
}

现在,我理解glPushMatrix()glPopMatrix()的方式是glPushMatrix()在堆栈上放置(或推送)一个新矩阵,供您执行操作,以便在弹出后它回来了你再次有一个“干净”的石板。这就是为什么,如果我在glPopMatrix()之后忽略glEnd(),我的方块似乎会加速而不是以恒定速度移动。

但是,我在glPushMatrix()glPopMatrix()内所做的更改是如何保留的?当我使用glPushMatrix()并对顶部矩阵进行更改时,它会显示更改,但是当我使用glPopMatrix()时,是不是所有这些更改都消失了?当我再次恢复到“干净”的状态时,我的盒子如何在屏幕上移动?

如果我在进行更改后再次关闭矩阵,那么该翻译的状态如何记录?

3 个答案:

答案 0 :(得分:29)

glPushMatrix复制堆栈顶部的矩阵(您总是使用顶层矩阵)。您正在进行的任何其他转换都会修改此顶部矩阵,即重复的矩阵。当你glPopMatrix时,我们会回到原始矩阵。

例如,假设您想要画一辆汽车。你设置矩阵来绘制汽车车身,我们称之为M1。现在,你想画一个轮子。您可以计算M2 - 车轮正确显示所需的矩阵 - 或者,因为车轮相对于车身(因此,有一个矩阵M3,使M2 = M1 * M3 1}})您修改M1。但是这辆车有4个轮子,你需要保留M1的副本。通过执行glPushMatrix来执行此操作,您可以通过执行glPopMatrix来获取副本。

glPushMatrix and glPopMatrix

当您在屏幕上绘制任何内容时,您将在对象空间中提供坐标。要真正显示某些内容,需要转换这些坐标。为此我们有一些矩阵。

在车轮示例中,您只有一个车轮几何体,但由于您使用的是不同的矩阵,因此将绘制四个车轮。 glPushMatrixglPopMatrix仅适用于矩阵,实际顶点数据保留在GPU中,每个glVertex在此处发送另一个,并且无法删除。参见下图,矩阵仅用于将对象坐标转换为世界坐标(实际上,所有矩阵都可以推入堆栈)

multiple matrices

答案 1 :(得分:6)

OpenGL是一个绘图API。当你调用绘图函数时,在你发出绘图调用的那一刻,事情就会被绘制到帧缓冲区 - 实际上,OpenGL会在内部批量处理所有命令并按顺序处理它们。但是当OpenGL即将处理这些绘图调用时,它将绘制到帧缓冲区,并将矩阵设置为批处理中此特定位置的状态。

所以重新说一下:OpenGL不进行任何类型的场景管理,它只是按顺序绘制帧缓冲区以及发出绘图命令的方式。你发送一个三角形:OpenGL将转换并绘制它。内部没有场景。一旦理解了这一点,理解矩阵堆栈如何能够实现“神奇”就变得微不足道了。

答案 2 :(得分:5)

它只是用于变换坐标的矩阵,由glPopMatrix恢复。不是整个帧缓冲。帧缓冲包含四边形的渲染,之后更改矩阵不会影响已渲染的任何内容。