1.1 OpenGL中可以设置物体的点、线、面绘制模式。如果需要同时绘制多种模式,如下以面和线模式绘制两遍模型,可以看到线不连续,当镜头推远推近时会出现闪烁现象。
void glPolygonMode(GLenum face,GLenum mode);
- face :GL_FRONT,GL_BACK,GL_FRONT_AND_BACK;
- mode : GL_POINT、GL_LINE、GL_FILL;
闪烁原因:
- 直线和多边形的光栅化方式并不完全相同,在线上和多边形边缘上产生的像素的深度值通常并不相同。
- 深度是有精度限制的,距离视点越远,进度越低,由于舍入误差会造成判断错误。
解决办法:
- 在深度检测之前,可以对zbuffer值进行一个偏移,即多边形偏移,为片元的z值增加一个适当的偏移值,把重合的z值适当地分开一些,使着重显示的直线与多边形的边缘清晰地分离开来。
glEnable(GL_POLYGON_OFFSET_FILL);
void glPolygonOffset(GLfloat factor,GLfloat units);
偏移值offset = m ∗ f a c t o r + r ∗ u n i t s m * factor + r * units m∗factor+r∗units;
- m是多边形的最大深度斜率,是在光栅化过程中计算的;
- r是保证能够产生可解析区别的窗口坐标深度的最小值,r是一个因OpenGL实现而异的常数。
GL_FILL模式绘制物体 - 打开光照;
- glEnable(GL_POLYGON_OFFSET_FILL);
- glPolygonOffset(1.0,1.0);
- 绘制物体
- glDisable(GL_POLYGON_OFFSET_FILL);
GL_LINE 模式绘制物体
- 关闭光照;
- 绘制物体;
1.2 雾效
雾效就是采用混合计算来实现的。
C
o
l
o
r
=
f
∗
C
o
l
o
r
s
+
(
1
−
f
)
∗
C
o
l
o
r
f
Color = f * Color_s + (1 - f) * Color_f
Color=f∗Colors+(1−f)∗Colorf;
- C o l o r s Color_s Colors表示物体的颜色, C o l o r f Color_f Colorf表示雾的颜色, f f f越大表示物体越清晰;
-
f
f
f为混合因子,有三种计算方式:
GL_LINEAR: f = e n d − z e n d − s t a r t f = \frac{end - z}{end - start} f=end−startend−z,start、end为雾开始和结束的地方,z是物体的深度。
GL_EXP : f = e ( − d e n s i t y ∗ z ) f = e^{(-density * z)} f=e(−density∗z)
GL_EXP2 : f = e ( − d e n s i t y ∗ z ) 2 f = e^{(-density * z)^2} f=e(−density∗z)2
glEnable(GL_FOG);
glFog*()相关函数用来设置与雾相关的参数。
- GL_FOG_MODE、GL_FOG_COLOR,GL_FOG_DENSITY,GL_FOG_START,GL_FOG_END;
glFogCoord*()可以指定每个顶点的雾坐标。
1.3 小结
Fragment模块中的所有操作,顺序如下。
2.1 纹理
2.1.1 Texture
2.1.2 模型的纹理
- 细化模型表面的几何;
- 采用纹理映射的方法;
颜色纹理:二维纹理、三维纹理;
几何纹理:凹凸纹理映射(Bump mapping),位移纹理映射(Displacement mapping);
2.1.3 Texture Mapping(纹理映射、纹理贴图)
纹理映射的主要思想:将一给定的纹理函数(图片)映射到物体表面上,在对物体表面进行光亮度计算时可采用相应的纹理函数值来影响光照明模型中的参数(
k
t
k_t
kt)(如漫反射光亮度)以产生纹理效果。
- 上面只是改变了颜色,纹理映射不仅限于改变颜色;
- 颜色、高光、凸凹、反射、透明度等都可以采用纹理贴图进行改变。
2.1.4 三维纹理映射
又称为“体纹理映射”,三维物体的每一个点(x,y,z)均有一个纹理值t(x,y,z),那么物体空间就可以映射到一个三维纹理空间中;
2.1.5 凹凸纹理映射(Bump mapping)
光滑模型呈现一种凹凸不平的效果,实现思想是对模型表面各采样点的法线做微小的扰动,由于表面光亮度是模型表面的法向的函数,上述法向的扰动必将导致表面光亮度的突变,从而产生表面凹凸不平的效果。
-
用纹理去修改物体的法向而不是颜色;
-
物体表面的几何法向保持不变,仅仅改变光照明模型计算中的法向;
-
物体表面每个点额法向的扰动量就可以定位在一幅纹理中;Bump mapping 的纹理中的三种记录方法:
-
Offset map:法矢量n在u和v方向被凹凸纹理上的( b u , b v b_u,b_v bu,bv)值修改,得到 n’;
-
Height-field map: 如下高度场及其对应的Normal,通过记录高度值,可以间接计算出法向,白的地方高,黑的地方低;
-
Normal map:直接记录法向,如下中的为法向图,及其作用于模型的效果。纹理图偏蓝,RGB对应xyz的话,那么法向大部分都指向z轴;
-
2.1.6 位移纹理映射(Displacement mapping)
如下采用Bump mapping的效果图,可以看出越往模型的边缘,凹凸感越差,轮廓还是光滑的,没有凹凸感,凹凸纹理也不会投下自身阴影;
一些解决方法,如浮雕贴图(Relief Mapping),通过映射一幅高度图,并在关照计算阶段进行遮挡判断而产生的效果。
实现上述效果还有一种更实用的方法,就是真是扰动模型的点位置,从而产生凹凸不平的细节效果,这就是位移纹理映射。
- 物体表面上的每一个点P(u,v),都沿该点处的法向量方向位移F(u,v)各单位长度,位移函数F(u,v)记录在一幅纹理中。
2.1.7 纹理映射关系的确定
二维纹理如何与三维的物体进行映射,对于一般的规则形体来说,对于球体可以采样经纬度来进行对应,对于其他模型,如圆柱,环等可以处理成圆柱,然后再展开为长方形即可映射。
而对于任意一个模型,如何映射纹理,主要有投影式纹理映射(projective texture mapping)、两步法纹理映射。
-
投影式纹理映射:投影式纹理映射从投影点出发,将二维纹理投到三维物体表面上,缺点是再轮廓处会出现极度的变形。
-
两步法纹理映射:先将纹理映射到与模型相近的中间模型上(圆柱),然后再次圆柱映射到模型上。
可以使用很多相近中间面,如平面,六个面,柱面上,球面,然后再进行纹理映射。
-
展UV法:将模型分割,使其部分可展,让后再建立映射关系。
虽然有了很多方法进行纹理映射,但复杂表面的纹理坐标计算仍是目前研究的难点。主要采用纹理函数,纹理函数可以是一幅图像,可以是一个计算函数(过程式纹理映射)。
- 基于样本的模型表面纹理合成;
- 基于过程的纹理合成;