1. glCullFace 和 glFrontFace
这两个都是opengl的初级命令,但是其实我都是最近才算得上“用”,以前的话,是因为有一次做billboard广告牌的时候,不剔除面片其中一面的话,很难看出效果成功了没,于是用了一次;最近的话,包括shadow volume中Z-FAIL和Z-PASS都需要正反面分别渲染,shadowmap中在pass 1里剔除正面,在光源视觉下渲染到纹理也用到了,一来减少渲染的”费用”,二来可以提高深度测试的精度(橙书里说的)。以前曾经在哪里看到篇文章说是其实剔除正或反面都提高不了多少效率,首先作者肯定做过测试来了,但是这样算不算武断我也不会说,问过一些搞游戏开发的人,答到“当然能提高效率啦,只不过不可能提高一倍而已”,事实上提高一点点都是很好的说。谁对谁错我也懒得分辨了,因为至少目前我还很少用,而且根据以前尝试的经验决定还是“能不用就不用”,因为正反面判断实在太烦了,有很多时候你用到的是别人弄的模型,而不那么专业的美工会在建模的时候搞乱面片绕序。
所以这组命令除了用在某些特殊场合(实现某些技术所必须),还有就是提高渲染效率的可能性,对某些效果正确性的辅助判断。其中glFrontFace用于指定正面的绕序,默认是“逆时针为正”,即传入参数GL_CCW,可以改成GL_CW顺时针。glCullFace 传入GL_FRONT来剔除正面,或者GL_BACK来剔除背面,之前先得glEnable(GL_CULL_FACE)。
通常情况是这样的:当你想剔除背面的时候,你只需要调用glEnable(GL_CULL_FACE)就可以了,OPENGL状态机会自动按照默认值进行CULL_FACE,默认是glFrontFace(GL_CCW),glCullFace(GL_BACK),当然如果你不想按照默认的来,你就得设置一下了。最后在不再需要剔除的时候调用glDisable(GL_CULL_FACE)。我建议的是“每次开始用,无论是不是默认的你最好都设置一下”,不然你迟些很容易被状态机(保持上一次设置的状态)搞到呕血——除非真的是很简单的demo制作,譬如之前shadow volume中我只是glEnable(GL_CULL_FACE),然后直接glFrontFace(GL_CCW)——它启用剔面功能,指定了“顶点逆时针绕序为正面”,之后的渲染它就会自动剔除那些反面;之后再调用glFrontFace(GL_CW),重新指定为“顶点顺时针绕序为正面”,再渲染一次,注意这时候它同样也是剔除背面(你没改过glCullFace),但是剔除的面就恰恰与前面的相反了。最后在disable前记得先改回glFrontFace(GL_CCW)!否则下次一enable就会按“顺时针绕序为正”了(与常理不一)。(望天!我忘记当时有没设置回来了~)
2.glShadeModel
在opebgl流水线里头,有一个步骤是栅格化(Rasterization),它在顶点组合的几何信息处理后执行,目的是“插值”,vertex shader的varying变量就是在这里被栅格化(/插值),然后再传入fragment shader作象素级别的处理。两顶点之间的象素怎么处理呢?就是靠这两顶点的信息的线性插值。譬如最简单的,颜色,一条线段两顶点A和B的颜色分别为红色和绿色,但是最后“显示颜色”的不可能是顶点,只有象素,因此这两点之间的象素就得按照它们临近的顶点的颜色而获得,越靠近点A的那些象素越红,越靠近点B的那些象素越绿,中间因此呈现渐变效果(一般来说,线段中点有一半红一半绿而成为黄色…)。对于填充的三角形,矩形也是一样的道理,只不过是平面内的线性插值罢了。
说了那么多,其实glShadeModel作用相当于打开/关闭这种功能(栅格化),传入参数GL_FLAT,流水线还是要经过这步骤但相应顶点不被处理,故顶点间的象素的颜色只会参考其中一个点的信息。譬如线段AB上的象素点全是红的或全是绿的——是哪种通常不要紧,因为无论是哪种,出来的结果都会好难看,所以渲染最初(初始化阶段)都会把参数设置成GL_SMOOTH,即启用栅格化功能。当然插值的计算量就上来了…..在渲染不注重效果而只注重速度的时候,譬如我做shadow map的PASS1作场景深度图的离线渲染时,非象素深度的信息根本对我无用,而且象素深度不是插值来的,故关闭栅格化计算,直接glShadeModel(GL_FLAT)再渲染就可以了,之后记得调回glShadeModel(GL_SMOOTH)。
好了,PART 1到此。
原文地址:http://www.zwqxin.com/archives/opengl/opengl-api-memorandum-2.html