书接上回,说完了绘制(其实绘制说的很简略,有空再补上吧),现在就该聊一聊光照了。
因为光照比前面的绘制有趣些,所以就多说几句吧。:)
在D3D中(当然,OpenGL也如此),光被分成三种类型:
环境光(Ambient),漫射光(Diffuse),镜面光(Specular),这三种光可以同时混合使用,也可使用其中某一种或几种光。值得注意的是,镜面光在默认情况下是不会被D3D计算的,只有你将相应的绘制状态设置为true之后,才会做镜面光计算 device->SetRenderState(D3DRS_SPECULARENABLE, true) 。之所以在默认情况下,镜面光是关闭的,因为这种光涉及的计算量相当庞大,不太适合于实时渲染,所以通常是关闭的。
环境光:顾名思义,就是在环境中的光线,它是一个平行光(就像太阳光),来自某个方向,射向物体表面,形成明暗差别。这种方式的计算量较小,但拟真度不高,所以在低拟真度高实时性限制下,可以凑合着用。
漫射光:这种光来自某个光源,然后到达物体表面后,被均匀的漫反射开,所以,这就导致不管观察者从哪个角度看,物体所反射的亮度都差不多。也正是这个特性,帮我们大大简化了漫反射计算方程。当然,要注意的是,因为漫反射会均匀反射光线,所以,这种光用多了之后,会导致物体的立体感降低。
镜面光:显然,这种光的特性就是像镜子一样,将光按照规定的法线反射出去。比如,有些物体在某一点上会特别的亮,这就是镜面光使然。
上面说到的3种光,其实都是需要作用在物体表面才能被大家感知的。不同的物体表面特性,就会产生不同强度的 环境光分量,漫射光分量和镜面光分量(如果开启镜面光的话)。描述这种表面特性的参数 就叫 材质(material)。
D3D对 material定义如下:
typedef struct D3DMATERIAL9{
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;
float Power;
} D3DMATERIAL9
大家可以发现,一个材质变量,包含了环境光、漫反射、镜面光这3个分量的反射强度描述。采用COLOR表示,也就是说,可以分别描述三个光分量对 R、G、B的反射特性。D3D会根据这些值来分别计算反射出来的光的强度和颜色。
除了3个光分量外,还有一个Emissive量,这个量描述了物体的自发光强度,就是说如果物体本身在发光,那么,就可以对Emissive进行设定,分别设定R、G、B强度。
最后一个成员,Power,它定义了高光点的锐度,值越大,锐度越大。
例子:
比如,我们想要一个物体,它只漫反射红光,镜面反射绿光,反射的环境光为蓝色,就可以设定为:
D3DMATERIAL9 color_obj;
color_obj.Diffuse = D3DXCOLOR(0.5, 0.0f, 0.0f, 0.0f); //RGBA
color_obj.Ambient = D3DXCOLOR(0.0f, 0.0f, 1.0f, 0.0f);
color_obj.Specular = D3DXCOLOR(0.0f, 1.0f, 0.0f, 0.0f);
上面就描述了一个材质,漫反射光只反射50%的红色,而蓝色和绿色被完全吸收(就是不反射);环境反射光对绿色100%反射,对红色和蓝色完全吸收......以此类推。
因此,当我们用蓝色光源照射只反射红色光的材质时,该物体将会是黑色,因为蓝色被完全吸收了。
To be continued...