【问题标题】:How do I keep an object always in front of everything else in OpenGL?如何在 OpenGL 中始终将对象保持在其他所有内容的前面?
【发布时间】:2011-07-28 10:56:38
【问题描述】:

我有这个功能,它在屏幕的左下角绘制一个小的 3D 轴坐标系,但根据我面前的东西,它可能会被剪裁。

例如,我在 Y = 0 的 XZ 平面上绘制了地面上的平原地形。相机位于 Y = 1.75(模拟人的平均身高)。如果我向上看,它工作正常,如果我向下看,它会被地平面夹住。

抬头:http://i.stack.imgur.com/Q0i6g.png
往下看:http://i.stack.imgur.com/D5LIx.png

我调用的在角上绘制轴系的函数是这样的:

void Axis3D::DrawCameraAxisSystem(float radius, float height, const Vector3D rotation) {
    if(vpHeight == 0) vpHeight = 1;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport(0, 0, vpWidth, vpHeight);
    gluPerspective(45.0f, 1.0 * vpWidth / vpHeight, 1.0f, 5.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glTranslatef(0.0f, 0.0f, -3.0f);

    glRotatef(-rotation.x, 1.0f, 0.0f, 0.0f);
    glRotatef(-rotation.y, 0.0f, 1.0f, 0.0f);

    DrawAxisSystem(radius, height);
}

现在有几个我认为与问题相关的主要功能:

glutDisplayFunc(renderScene);
glutReshapeFunc(changeSize);

void changeSize(int width, int height) {
    if(height == 0) height = 1;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glViewport(0, 0, width, height);

    gluPerspective(60.0f, 1.0 * width / height, 1.0f, 1000.0f);

    glMatrixMode(GL_MODELVIEW);
}

void renderScene(void) {
    glClearColor(0.7f, 0.7f, 0.7f, 0.0f);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    changeSize(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));

    glLoadIdentity();

    SceneCamera.Move(CameraDirection, elapsedTime);
    SceneCamera.LookAt();

    SceneAxis.DrawCameraAxisSystem(0.03f, 0.8f, SceneCamera.GetRotationAngles());

    glutSwapBuffers();
}

建议?

【问题讨论】:

  • 你已经得到了适当的答案。但是您必须了解一件事:OpenGL 不会将几何图形视为“对象”(OpenGL 对象是不同的东西,例如纹理或顶点缓冲区)。 OpenGL 是一种光栅化器,一张图片一次构建一个三角形。因为询问“如何将对象保持在前面”虽然完全可以理解,但并没有解决实际问题。您想知道的是,如何可靠地在帧缓冲区的现有内容之上绘制一些东西,同时仍然能够使用深度测试。

标签: opengl viewport clipping foreground depth


【解决方案1】:

您可以在渲染叠加层之前glClear(GL_DEPTH_BUFFER_BIT);,而不是禁用深度测试。然后,那里的任何深度信息都消失了,但像素都还在。但是,您的叠加层仍会正确呈现。

【讨论】:

    【解决方案2】:

    您还可以为 3D 轴保留一小部分深度范围。其余的都是你的场景。像这样:

    // reserve 1% of the front depth range for the 3D axis
    glDepthRange(0, 0.01);
    
    Draw3DAxis();
    
    // reserve 99% of the back depth range for the 3D axis
    glDepthRange(0.01, 1.0);
    
    DrawScene();
    
    // restore depth range
    glDepthRange(0, 1.0);
    

    【讨论】:

      【解决方案3】:

      您想禁用深度测试(因此它不会被任何东西截断):

      glDisable(GL_DEPTH_TEST);
      

      如果您已经预先转换了点(看起来您没有),请将视图和投影矩阵设置为恒等。

      编辑:

      如果您需要轴位保持测试并按顺序进行,那么您可能需要在渲染它和主场景之间清除深度缓冲区 (glClear(GL_DEPTH_BUFFER_BIT))。这将重置深度缓冲区,以便绘制标记(因此出现在前面),但仍被正确剔除。

      【讨论】:

      • 如果我在绘制轴系统之前禁用深度测试,轴本身会看起来很奇怪,因为 3 轴之间没有深度。是否可以仅在 2 个视口之间禁用深度测试?我不确定“预转换点”是什么意思,但是在设置每个矩阵模式后会加载单位矩阵,我是否遗漏了什么?
      • 如果你的几何是正确的,那么矩阵就是正确的。要在不破坏轴的情况下修复场景,请参阅编辑。 :)
      【解决方案4】:

      您可以尝试启用混合,然后在片段着色器中手动设置 alpha 和颜色。但这可能是矫枉过正;-)

      【讨论】:

        【解决方案5】:

        `glGetBooleanv(GL_BLEND, &m_origin_blend);

        glGetBooleanv(GL_DEPTH_TEST,&m_origin_depth);

        glGetBooleanv(GL_CULL_FACE, &m_origin_cull);

        setAlphaBlending(true);

        setDepthTest(false);

        setCullFace(假); //石头

        //你的 draw() ...

        setAlphaBlending(m_origin_blend>0?true:false);

        setDepthTest(m_origin_depth>0?true:false);

        setCullFace(m_origin_cull>0?true:false);`

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-01-21
          • 2021-09-08
          • 2011-02-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-19
          • 1970-01-01
          相关资源
          最近更新 更多