OPENGL固定图形渲染管线操作细节
本文结合OPENGL技术文档和程序实验探求在OPENGL中综合使用了 顶点颜色,光照(材质),纹理,片元混合 后的应该得到的绘制效果。
本文的可执行程序如下:
http://download1.csdn.net/down3/20070517/17205731333.rar
OPENGL状态机保持一个当前RGBA颜色,除非应用程序指定使用一个更复杂的颜色模型,例如光照模型或是纹理映射模型,否则,绘制的任何一个物体都使用OPENGL状态机保持的这个当前RGBA颜色。
下图的绘制状态
颜色型指没有使用光照模型。 |
当使用OPENGL命令glEnable(GL_LIGHTING)后,OPENGL状态机的绘制模式转为使用光照模型:
(A). OPENGL光照模型中,场景的光线来自于不同的光源,光源的开关相互独立。OPENGL假定光源只对吸收或反射光线的表面产生影响。绘制场景时,OPENGL至少支持加入8个光源。
(B). 同时,每个表面都认为由不同属性的材质构成,材质可能将入射光散射到各个方向,可能将大部分光线反射到特定方向,材质本身也能产生光线。
只要当前的绘制是使用光照模型,那么材质属性就要被计算,材质是OPENGL状态机中的一组状态,五个参数:
(1). 环境颜色(GL_AMBIENT)默认值(0.2,0.2,0.2,1.0)
(2). 散射颜色(GL_DIFFUSE),默认值(0.8,0.8,0.8,1.0)
(3). 放射光颜色(GL_EMISSION),默认值(0.2,0.0,0.0,1.0)
(4). 镜面反射颜色(GL_SPECULAR),默认值(0.0,0.0,0.0,1.0)
(5). 镜面反射参数(GL_SHININESS)。默认值0.0,取值范围[0.0, 128.0]
使用函数glMaterial*()设置改变这五个参数。
不论其他参数的alpha值为多少,顶点alpha值就是材质散射颜色(GL_DIFFUSE)的alpha值。
物体的颜色很大程度上受散射光的影响,它取决于入射光的散射分量和入射光相对物体表面法线的角度(角度越小,散射光强越大),和视点无关。真实世界中的散射光和环境光通常是同样颜色。
(C). OPENGL光照模型将光照(光源和拥有材质属性的物体表面作用后的视觉效果)分成四个独立的成分:环境光效果(ambient)、散射光效果(diffuse)、镜面反射光效果(specula)和发射光效果(emission)。四种成分独立计算然后混合到一起。
(D). 光照模型有四个参数(和前面描述的光照的四个独立成分不是一回事):
(1).全局环境光强(GL_LIGHT_MODEL_AMBIENT),默认值是(0.2,0.2,0.2,1.0)。
(2).观察者位置模式(GL_LIGHT_LOCAL_VIEWER)(和计算镜面反射分量相关),默认值GL_FALSE,即观察者在无穷远处。
(3).单面光照or双面光照(GL_LIGHT_MODEL_TWO_SIDE),默认值GL_FALSE,单面光照。
(4).是否分离镜面颜色(GL_LIGHT_MODEL_COLOR_CONTROL)(和纹理映射效果相结合),默认值为GL_SINGLE_COLOR。
光照使用函数glLightModel*()指定光照模型的四个参数。
(E). 使用glEnable(GL_COLOR_MATERIAL),指明OPENGL状态机使用” 颜色材料模式”。在该模式下,使用glColorMaterial()可以指定材质的某一个材质材质参数根据当前绘制的面片的颜色而改变。
自定义材质: Ambient={ 0.75f , 0.4f , 0.4f , 0.5f } Difuse={ 0.75f , 0.4f , 0.4f , 0.5f } Specular={ 0.75f , 0.4f , 0.4f , 0.5f } Shiness=128 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f };
|
当使用OPENGL命令glEnable(GL_TEXTURE2D)后,OPENGL状态机控制下的绘制流程中将会加入纹理映射这一步骤。
(A). OPENGL程序中设置纹理映射,通常的步骤是:
(1)使用glGenTextures()得到一个纹理序号。
(2)使用glBindTexture()使用纹理属性的默认值创建一个心得纹理对象。
(3)使用glTexImage2D()或是gluBuild2DMipmaps()在纹理对象中存储数据。
(B). OPENGL程序中在完成上面的步骤后应该使用glTexParameter*()设置纹理映射的几个参数:
(1)在纹理贴图映射到片元时,放大和缩小需要指定某种滤波方式。如
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
(2)在处理不在[0.0,1.0]的纹理坐标时,需要指定覆盖重复方式
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
(C). 纹理模式设置:根据纹理坐标从纹理中取出每个片元对应的颜色、片元颜色,它们如何合成成新的颜色再沿渲染管线向后传递决定于纹理模式和纹理基准内部格式(一般都射为RGBA)。OPENGL提供四种纹理模式:
(1)纹理颜色替代(GL_REPLACE):纹理颜色(连同alpha分量)替换片元颜色成为新的片元颜色。
(2)纹理颜色调制(GL_MODULATE):纹理颜色(连同alpha分量)和片元颜色相乘成为新的片元颜色。
(3)纹理颜色贴花(GL_DECAL):使用该模式需要先使用glTexEnvfv(GL_TEXTURE_ENV,GL_TEXTURE_ENV_COLOR,envColor)指定一个纹理模式颜色。
新的片元颜色(RGB分量)= 纹理颜色alpha * 纹理模式颜色 + (1-纹理颜色alpha)*片元颜色。新的片元颜色alpha不变。
(4)纹理颜色混合(GL_BLEND):同上也需要纹理模式颜色。新的片元颜色(RGB分量)为((1.0,1.0,1.0)-纹理颜色)*片元颜色 +纹理颜色 * 纹理模式颜色 。新的片元颜色alpha为 原alpha*纹理alpha。
自定义材质: Ambient={ 0.75f , 0.4f , 0.4f , 0.5f } Difuse={ 0.75f , 0.4f , 0.4f , 0.5f } Specular={ 0.75f , 0.4f , 0.4f , 0.5f } Shiness=128 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f };
|
自定义材质: Ambient={ 0.75f , 0.4f , 0.4f , 0.5f } Difuse={ 0.75f , 0.4f , 0.4f , 0.5f } Specular={ 0.75f , 0.4f , 0.4f , 0.5f } Shiness=128 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f };
|
自定义材质: Ambient={ 0.75f , 0.4f , 0.4f , 0.5f } Difuse={ 0.75f , 0.4f , 0.4f , 0.5f } Specular={ 0.75f , 0.4f , 0.4f , 0.5f } Shiness=128 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f }; 纹理模式颜色 envColor[]={ 0.8f , 0.8f , 0.8f , 0.8f }; |
自定义材质: Ambient={ 0.75f , 0.4f , 0.4f , 0.5f } Difuse={ 0.75f , 0.4f , 0.4f , 0.5f } Specular={ 0.75f , 0.4f , 0.4f , 0.5f } Shiness=128 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f }; 纹理模式颜色 envColor[]={ 0.8f , 0.8f , 0.8f , 0.8f }; |
当使用OPENGL命令glEnable(GL_BLEND)后,OPENGL状态机控制下的绘制流程中将会加入片元混合这一步骤。
混合操作是在片元颜色值写入到帧缓存对应位置前,和帧缓存该位置已存在的颜色值进行的一个四参数的线性运算。四个参数为:
片元颜色(RGBA向量)FC、
片元因子(4维向量)FF、
帧缓存颜色(RGBA向量)BC、
帧缓存因子(4维向量)BF。
线性运算为:
新的帧缓存颜色(R) = FC[R]*FF[R] + BC[R]*BF[R]
新的帧缓存颜色(G) = FC[G]*FF[G] + BC[G]*BF[G]
新的帧缓存颜色(B) = FC[B]*FF[B] + BC[B]*BF[B]
新的帧缓存颜色的A的计算同上,如果帧缓存数据直接就绘制到屏幕,A值不影响屏幕上的像素颜色没有。
片元混合需要使用函数glBlendFunc()设定混合的片元因子(4维向量)FF和帧缓存因子(4维向量)BF。最常用的,设置片元因子为片元颜色的A值,即(FC[A], FC[A], FC[A], FC[A]).设置帧缓存因子为(FC[A], FC[A], FC[A], FC[A])。这样片元颜色的A值得意义就名副其实是片元的不透明度。
颜色模式(没有光照)
颜色材质模式 GL_AMBIENT_AND_DIFFUSE跟踪当前颜色;specular= { 0.0f , 0.0f , 0.0f ,1.0};
|
下图的绘制状态
颜色材质模式 GL_AMBIENT_AND_DIFFUSE跟踪当前颜色;specular= { 0.0f , 0.0f , 0.0f ,1.0}; 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f };
|
下图的绘制状态
自定义材质: Ambient={ 0.75f , 0.4f , 0.4f , 0.5f } Difuse={ 0.75f , 0.4f , 0.4f , 0.5f } Specular={ 0.75f , 0.4f , 0.4f , 0.5f } Shiness=128 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f };
|
下图的绘制状态
自定义材质: Ambient={ 0.75f , 0.4f , 0.4f , 0.5f } Difuse={ 0.75f , 0.4f , 0.4f , 0.5f } Specular={ 0.75f , 0.4f , 0.4f , 0.5f } Shiness=128 光照设置 amlight={0.3,0.0,0.3,1.0}; dflight={0.7,0.0,0.7,1.0}; specular= { 1.0f , 1.0f , 1.0f , 1.0f };
|
OPENGL固定图形渲染管线可以粗略地认为由下面的阶段衔接而成:
顶点颜色,光照,材质三个输入在光栅化前控制绘制管线的操作。光照和材质不能单独使用。顶点颜色,光源颜色,材质颜色都有alpha值,它们的alpha经过运算最后会保存在光栅化后的图元中,也就是说它们的影响也就在上图中红色虚线上方。输入是顶点(几何坐标、顶点颜色),矩阵,光照(光源,参数),材质,输出是片元。
纹理映射的过程的本质是根据纹理信息对片元的再处理,这个过程可能改变片元的alpha值。输入是片元,纹理(纹理坐标、各种参数),输出还是片元。
Alpha值最终通过Alpha混合阶段影响绘制效果,输入时片元,输出是帧缓存颜色值。