如何在OpenGL中使一个对象始终在其他所有对象的前面?

11
我有一个函数,它在屏幕左下角绘制了一个小的三维坐标系,但根据我面前的物体可能会被裁剪。
例如,我在地面上绘制了一个平面地形,在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();
}
建议?

1
你已经得到了适当的答案。但有一件事情你必须明白:OpenGL不把几何形状看作“对象”(OpenGL对象是另一种东西,例如纹理或顶点缓冲区)。OpenGL是一个光栅化器,一张图片是一次绘制一个三角形。因此,询问“如何将对象保持在前面”,虽然可以理解,但并没有解决实际问题。你想知道的是,如何可靠地在帧缓冲区现有内容的上方绘制某些东西,同时仍然能够使用深度测试。 - datenwolf
5个回答

25

不必禁用深度测试,您只需在渲染覆盖层之前执行glClear(GL_DEPTH_BUFFER_BIT);。然后,所有深度信息都被清除,但像素仍然存在。然而,您的覆盖层仍将正确地呈现。


6

您还可以为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);

1

您想禁用深度测试(以便它不会被任何东西剪裁):

glDisable(GL_DEPTH_TEST);

如果您已经预先转换了点(似乎没有),请将视图和投影矩阵设置为单位矩阵。

编辑:

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


如果我在绘制坐标系之前禁用深度测试,那么坐标轴本身将看起来很奇怪,因为三个轴之间没有深度。是否可能仅在两个视口之间禁用深度测试?我不确定您所说的“预转换点”的含义,但在设置每个矩阵模式后加载了恒等矩阵,我有遗漏吗? - rfgamaral
1
如果你的几何图形正确,那么矩阵也是正确的。要修复场景而不破坏轴,请查看编辑。 :) - ssube

0

`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(false); //由stone设置

//你的draw() ...

setAlphaBlending(m_origin_blend>0?true:false);

setDepthTest(m_origin_depth>0?true:false);

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


0
你可以尝试启用混合,然后在片段着色器中手动设置 alpha 和颜色。但这可能有点过度了;-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接