【问题标题】:The HUD is drawn but the OpenGL 3D scene disappersHUD 已绘制,但 OpenGL 3D 场景消失了
【发布时间】:2014-06-23 18:40:38
【问题描述】:

我已经学习了许多教程,但仍然没有掌握如何在不发生某种灾难的情况下使用 3D 场景绘制 2D HUD。我从herehere 收集了一些示例代码,并计算出必须以某种方式处理矩阵的顺序(请参阅here)以实现我所设定的目标。我已经制定了如下所示的渲染代码:

void render()
{
    //Clear screen
    glClearColor(0.2f, 0.0f, 0.2f, 1.0f); // Clear the background of our window to red  
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW); //Switch to the drawing perspective
    glLoadIdentity(); //Reset the drawing perspective

    // Movement as response to input:
    glTranslatef( cam.getEye().getX(), cam.getEye().getY(), cam.getEye().getZ() ); // Translate our object along the y axis  
    glRotatef( cam.getTheta(), 0.0f, 1.0f, 0.0f ); // Rotate our object around the y axis 
    // No pushing/popping a matrix and no gluLookAt() used here.

    // ==================== Drawing scene here: ======================
    // ...
    // =================================== HUD: ==================================

    glMatrixMode(GL_PROJECTION);

    glPushMatrix();
    //glPopMatrix();

    glLoadIdentity();
    gluOrtho2D(0, winW, 0, winH); //left,right,bottom,top
    glMatrixMode(GL_MODELVIEW);

    //glPushMatrix();
    glPopMatrix();
    glLoadIdentity();

    // drawing the HUD rect here:
    glBegin(GL_QUADS);
        // ...
    glEnd();

    glPopMatrix();
    glPopMatrix();
    //glPushMatrix();
    //glPushMatrix();

    // ===============================================================================
    glutSwapBuffers(); //Send scene to the screen to be shown
}

...但由于某种原因,它只显示我的深青色 HUD,3D 场景就消失了。我究竟做错了什么?我错过了什么?我知道我应该推送投影矩阵,然后是模型视图矩阵,然后执行 glOrtho2D(),然后将两个矩阵从堆栈中弹出。那没有用。我厌倦了按随机顺序摆弄推挤和弹出矩阵。

【问题讨论】:

  • 一方面,您不想使用gluOrtho2D (...) 在 z=0 处绘制 HUD。 gluOrtho2D 的 Z 值范围是 [-1,1],它把 z=0 的正方形放在深度缓冲区的中间。您的场景的一半可能会阻碍 HUD,您可能希望在 z=-1 处绘制以确保 HUD 始终位于其他所有内容之上。如果您想知道在这种情况下 Z 来自哪里,glVertex2f0.0 的恒定 Z 坐标和 1.0 的 W 坐标应用于所有顶点。
  • 更严重的是,您的矩阵堆栈因所有未配对的glPopMatrix (...) 调用而下溢。
  • @AndonM.Coleman :好的,我已经将一行改写为gluOrtho2D(-0.5, 0.5, -0.5, 0.5);,并且我已经看到了一个应该坐在 y=0 上的对象,但由于某种原因,我的相机眼睛是固定的在 y = 0。并且 HUD 绘制在不同的位置。然而,这不是我想要的那种观点。我无法将飞机和金字塔视为 3D 场景中的对象。此外,我将推送/弹出命令配对如下:推送投影、推送模型视图、弹出矩阵、弹出投影。到目前为止没有任何效果。
  • 您是否在代码的不同部分设置透视投影矩阵?如果不是,您需要在绘制 3D 对象时设置透视投影,否则它们看起来不是 3D 的。此外,我不确定您的相机是如何设置的,但通常您希望通过负面的眼睛位置进行翻译。
  • 另外,由于矩阵堆栈下溢,我决定使用 PushStack 类进行一些间接推送,但我的 glutil 缺少 boost/array.hpp 。所以,现在我不知道我应该如何推入和弹出堆栈。

标签: c++ opengl 3d render hud


【解决方案1】:

如果您的 HUD 像往常一样是叠加层,您可能需要在绘制 HUD 内容之前禁用深度测试和潜在的深度写入:

glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);

这样,HUD 的 Z 值就无关紧要了。在绘制场景之前不要忘记重新启用。

正如其他人所观察到的,您也有矩阵堆栈问题。单独的堆栈与投影和模型视图矩阵相关联。现在你正在推动投影矩阵和弹出模型视图矩阵,所以你溢出了一个而下溢了另一个。您需要以相同的模式对称地推送和弹出。鉴于您在每种模式下都以 glLoadIdentity() 开头,您可能根本不需要使用矩阵堆栈。

编辑:更直接的答案

你的渲染代码应该是这样的:

void render()
{
  //Clear screen
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  //*************************************************************************
  //* Prepare to render main scene:
  //*************************************************************************
  glEnable(GL_DEPTH_TEST);
  glDepthMask(GL_TRUE);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(...);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef( cam.getEye().getX(), cam.getEye().getY(), cam.getEye().getZ() );
  glRotatef( cam.getTheta(), 0.0f, 1.0f, 0.0f );

  //*************************************************************************
  //* Draw Main Scene Here:
  //*************************************************************************

  // ... 


  //*************************************************************************
  //* Prepare to render HUD overlay:
  //*************************************************************************
  glDisable(GL_DEPTH_TEST);
  glDepthMask(GL_FALSE);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluOrtho2D(...);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  //*************************************************************************
  //* Draw HUD here:
  //*************************************************************************

  // ...


  // Finish the frame:
  glutSwapBuffers(); //Send scene to the screen to be shown
}

现在,由于您将在每次渲染调用期间调整投影矩阵两次,因此您应该从 resizeWindow() 函数中删除 gluPerspective()。此外,我从渲染函数中删除了 glClearColor() 调用——最好在程序开始时设置一次并忘记它。状态更改代价高昂,因此您希望尽可能避免它们。

【讨论】:

  • 我想我必须将 glDepthMask 设置为 GL_FALSE,对吗?另外,你会推荐什么来处理矩阵堆栈?我试过 PushStack 但它没有用,我不能下溢堆栈。我该怎么办?
  • 我已经尝试过您的建议,即在渲染之前禁用深度测试和缓冲区写入,然后再启用它们。我仍然无法让我的场景恢复到原来的状态。
  • 关于 glDepthMask 的更正 - 在我的回答中已修复。另请参阅我的新文本 re:matrix stacks。祝你好运!
  • 我已阅读您的更新答案,但似乎在我的 OP 更新中留下了这段代码,即使 HUD 在那里,我仍然没有得到 3D 场景.
  • @Andrey:我刚刚在我的编辑中为你列出了它。试一试,告诉我们进展如何。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-06
  • 1970-01-01
  • 2016-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多