如何在OpenGL中始终将对象保留在其他所有内容之前?

时间:2011-04-03 00:02:48

标签: opengl viewport clipping foreground depth

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

例如,我在地面上绘制了一个平坦的地形,在XZ平面上Y = 0.摄像机位于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();
}

建议?

5 个答案:

答案 0 :(得分:13)

在渲染叠加层之前,您可以glClear(GL_DEPTH_BUFFER_BIT);而不是禁用深度测试。然后,无论深度信息是什么都消失了,但像素仍然存在。但是,您的叠加层仍会正确渲染。

答案 1 :(得分:3)

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

答案 2 :(得分:0)

您想要禁用深度测试(因此不会被任何内容剪切):

glDisable(GL_DEPTH_TEST);

如果你已预先转换了点(它似乎没有),请将视图和投影矩阵设置为标识。

修改

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

答案 3 :(得分:0)

您可以尝试启用混合,然后设置alpha&在片段着色器中手动着色。但这可能有点过分; - )

答案 4 :(得分:0)

`glGetBooleanv(GL_BLEND,& m_origin_blend);

glGetBooleanv(GL_DEPTH_TEST,&安培; m_origin_depth);

glGetBooleanv(GL_CULL_FACE,& m_origin_cull);

setAlphaBlending(真);

setDepthTest(假);

setCullFace(假); // by stone

//你的draw()......

setAlphaBlending(m_origin_blend大于0真:假);

setDepthTest(m_origin_depth大于0真:假);

setCullFace(m_origin_cull大于0真:假);`