最近搞opengl,本来以为自己对glortho这个函数已经了解了,结果发现自己根本不理解。
首先,glortho函数的原型是void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far)。我原先一直认为near和far指定的就是近平面和远平面的z坐标,知道今天自己开始写OpenGL的程序才发现不是这样。首先该函数定义的绘图空间是下面这样的:
我们自己所绘制的图形的坐标只能在这个空间里,不然不能看到自己绘制的图形。
但是near和far却不是上图中所示的近平面和远平面的z坐标。近平面矩形的左下角的坐标是(left,bottom,-near),右上角的坐标是(right,top,-near);远平面矩形的左下角坐标是(left,bottom,-far),右上角坐标是(right,top,-far)。所以说,实际的远近平面坐标并不是简单地由near和far指定,而是由-near和-far指定。
那么,远近平面对我们来说有什么作用呢?其中最重要的一个就是深度测试。如果我们想实现靠近我们的物体遮挡住远处的物体,那么我们应该通过glEnable(GL_DEPTH_TEST)启用深度测试,这个时候每一个物体绘制前,都会和当前的深度缓冲区进行比较,然后决定要不要渲染当前输入的绘图指令。首先,如果我们启用深度测试我们一般在绘图之前使用glClear(GL_DEPTH_BUFFER_BIT),把所有深度缓冲区的值设置为最大值(一般就是前面说过的远平面的值)。在以后的绘图过程中,会将当前绘图指定中的图形深度值即z值与深度缓冲区中对应像素点的值进行比较,如果更加靠近近平面(并不是简单地比较数值大小,而是看相对于近平面的位置),则绘制该图形,并把深度缓冲区中的值修改为当前绘图指定中指定图形的z值;否则,不绘制图形,同时深度缓冲区中的值不变。
在进行混合的时候,深度测试也很重要。首先,如果在需要渲染的场景中,如果存在透明的物体,那么先要绘制不透明的物体。因为,绘制透明物体时,当前绘图指令指定的物体的颜色为源颜色,而当前颜色缓冲区中的颜色为目标颜色,源颜色会与目标颜色按一定公式进行混合(公式参考文献3)。例如,先绘制背景,再绘制透明物体,再绘制一个位置位于透明物体后面(相对于透明物体,远离近平面)的不透明物体,则不会获得你所期望的效果。这是因为,当你绘制透明物体时,当前颜色缓冲区中存放的背景颜色,那么透明物体的颜色会与背景颜色混合。当你再绘制不透明物体时,即使不透明物体比透明物体大而导致透明物体不能遮挡不透明物体,由于深度测试的存在,也不会在透明物体的区域上绘制不透明物体,这时不透明物体位置处的颜色就是不透明物体和背景的混合色,而没有产生你想要的透明物体与不透明物体的混合。
那么,在存在混合的情况时,一般的做法是先打开深度测试,然后绘制所有的不透明物体,由于这个时候存在深度测试,绘制的顺序不一定要按照物体距离近平面的近远顺序绘制。然后利用函数glDepthMask(GL_FALSE)将深度缓冲区设置为只读模式(此时,没必要关闭深度检测,因为无论启不启用深度检测对于透明物体都要按照先远后近的顺序绘制),此时深度缓冲区的值不会随着后面绘制的不透明物体的深度值而改变。接着,按照先远后近的顺序绘制各个透明物体。
可能讲的不太清楚,大家结合参考文献应该都能理解。
参考1:http://blog.csdn.net/shuaihj/article/details/7228882
参考2:http://blog.csdn.net/j123kaishichufa/article/details/6603888
参考3:http://blog.sina.com.cn/s/blog_6c8369530100m0x8.html