【学习OpenGL】(五)——隐藏表面消除(深度测试)

深度测试是一种有效的用于隐藏表面消除的技巧,OpenGL提供了一些函数,允许在幕后完成这个任务。

它的概念非常简单:当一个像素被绘制时,它将被设置一个值(称为Z值,以表示它和观察者之间的距离。以后,当这个屏幕需要绘制另一个像素时,新像素的值就会与原先已经存在的那个像素进行比较。如果新像素的Z值更高,它就更靠近观察者,因此位于以前那个像素的前面如果新像素的Z值更低,则它必须位于原先那个像素的后面,而不能遮住前面的那个像素。

为了启用深度测试,只要简单的调用

glEnable(GL_DEPTH_TEST);

我们通过以下函数绘制一大一小两个球

void DrawBigRedSphere()
{
    GLfloat mat_specular[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_shininess[] = { 50.0 };
    GLfloat mat_ambient[] = { 1.0, 0.0, 0.0, 1.0 };
    GLfloat mat_diffuse[] = { 1.0, 0.0, 0.0, 1.0 };

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

    glutSolidSphere(0.5, 32, 32); 
}

void DrawSmallBlueSphere()
{
    GLfloat mat_specular[] = { 0.0, 0.0, 1.0, 1.0 };
    GLfloat mat_shininess[] = { 50.0 };
    GLfloat mat_ambient[] = { 0.0, 0.0, 1.0, 1.0 };
    GLfloat mat_diffuse[] = { 0.0, 0.0, 1.0, 1.0 };

    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
    glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);

    glutSolidSphere(0.3, 32, 32);
}

DrawBigRedSphere绘制的是大的红球,DrawSmallBlueSphere绘制的是小的蓝球,绘制的时候都采用默认坐标,即绘制在屏幕的中央,并且Z轴也不动,那么,从理论上来讲,大球会包含小球,小球就被大球遮掩了,我们显示要的应该也是这种效果。

看一下未开启深度测试情况下的情况我们先绘制大球,再绘制小球的和用相反顺序再绘制的情形:

代码如下:

void SceneShow(GLvoid)        
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
);    

    glPushMatrix();
    glTranslatef(-0.5, 0.0, 0.0);
    DrawBigRedSphere();
    DrawSmallBlueSphere();
    glPopMatrix();

    glPushMatrix();
    glTranslatef(0.5, 0.0, 0.0);
    DrawSmallBlueSphere();
    DrawBigRedSphere();
    glPopMatrix();

    glFlush();
}  

这里写图片描述

我们会观察到很明显的绘制顺序导致的问题,左边的图因为先绘制大球再绘制小球,小的篮球竟然覆盖掉了应该在其外部的红球。实际使用中,我们可以都自己判断,然后用右边的正确绘制方式,随着图形的增多,会增加一定的计算量,OpenGL提供的深度测试就是为我们提供了更简便高效的方式,事实上,由于OpenGL使用的方式因为可以在测试后,直接绘制出最终图形而忽略绘制被覆盖掉的图形,效率上比覆盖绘制会更高一些(需要硬件支持)。

上述代码,仅仅需要添加一行,

glEnable(GL_DEPTH_TEST);

以启用深度测试,效果大不一样:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_37308779/article/details/79361901
今日推荐