一、相关概念
1.1 Phong、Blinn-Phong光照模型是一种简单光照模型,它仅考虑了光源直接照射的效果,没有考虑非直接光照的效果。如下直接光照与间接光照。
1.2 上述模型在考虑间接光照(环境光)时,采用的是一个常数来表示,因此存在一定的局限性。全局光照模拟(Global illumination,GI)= 直接光照 + 间接光照。为了实时计算光照,引入了很多间接光照的计算方法,光线跟踪算法,考虑了光滑表面对环境光的反射和折射。
辐射度法能够模拟漫射表面的颜色辉映的效果。
光子映射算法可以有效表达这种焦散半透明的效果。
1.3 相关书籍
- 《Advanced Global illumination》
- 《Real-time Rendering》
- 《Physically Based Rendering :From Theroy to Implementation》
- 《全局光照技术:从离线到实时渲染》
二、OpenGL光照参数的设置
2.1 OpenGL中进行光照计算,需要设置相应的参数,主要分为:
-
设置物体的法向:glNormal3f(Nx,Ny,Nz);
- 面片的法向:通过面上两条边的单位向量叉乘即可得到面片的法向;
- 顶点的法向:把它周围三角面片的法向计算出来,在相加计算各平均值即可得到顶点的法向;
-
打开光照:glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);
- OpenGL中,可以用八盏灯,为GL_LIGHT0 - GL_LIGHT7;
-
设置关照参数:Ambient为公式中的IaI_aIa,公式里面的IlI_lIl为diffuse和Specular;OpenGL里实际为IdI_dId和IsI_sIs;
glLightfv(GL_LIGHT0,GL_AMBIENT,vLitAmbient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,vLitDiffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,vLitSpecular);glLightfv(GL_LIGHT0,GL_POSITION,vLitPosition);
-
设置材质参数:
- GL_FRONT/GL_BACK/GL_FRONT_AND_BACK参数:指定设置前向面或者后向面,物体的法向的面为前向面,相反的面为后向面;
//设置前向面的Ka、kd、ks,高光指数,自发光
glMaterialfv(GL_FRONT,GL_AMBIENT,vMatAmb);
glMaterialfv(GL_FRONT,GL_DIFFUSE,vMatDif);
glMaterialfv(GL_FRONT,GL_SPECULAR,vMatSpe);
glMaterialfv(GL_FRONT,GL_SHININESS,vShininess);
glMaterialfv(GL_FRONT,GL_EMISSION,vEmission);
2.2 聚光灯参数设置
设置聚光灯的方向,设置光线角度,衰减系数(不是距离衰减而是偏离的角度的光线衰减)等。
glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,vSpotDir);
glLightfv(GL_LIGHT0,GL_SPOT_CUTOFF,vLitCutoff);
glLightfv(GL_LIGHT0,GL_SPOT_EXPONENT,vSpotExp);
2.3 光照的衰减参数
OpenGL里面可以设置光照的衰减参数,衰减公式如下,设置了随距离的衰减情况。
glLightfv(GL_LIGHT0,GL_CONSTANT_ATTENUATION,kc);
glLightfv(GL_LIGHT0,GL_LINEAR_ATTENUATION,kl);
glLightfv(GL_LIGHT0,GL_QUADRATIC_ATTENUATION,kq);
OpenGL中所有状态参数都有一个默认值,不设置OpenGL也能正常进行,此处,kc默认值为1,kl和kq默认值为0。
三、光照模式
3.1 方向性光源与位置性光源
光照的方向直接影响公式中的L以及R,计算每一点的L,光源与点的连线所在的方向为L。方向性光源,即平行光,类似于太阳光,L的计算相对简单,都是一个值,而位置性光源,每个点的L不同,需要单独计算。
Glfloat vLitPosition[] = {1,0,1.0,1.0,0.0};
//若vLitPosition中的w为0.0,则为方向性光源,否则为位置性光源。
glLightfv(GL_LIGHT0,GL_POSITION,vLitPosition);
3.2 本地视点于无限远视点
视点主要影响V的计算,在Blinn中,影响H的计算,无限远视点,可以认为每个点的V都相同,即平行,为本地视点,每个点的视线方向不同,都需要单独计算。
//GL_TRUE,则设置为本地视点
glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE);
3.3 双面光照
//是否设置双面光照,0.0,否;
glLightModelf(GL_LIGHT_MODEL_TWO_SIDE,0.0);
双面光照,主要影响背向面的计算,在计算背向面时,计算公式中的N将被OpenGL变换为负N;当背向面能被看得到时,需要计算背向面的光照情况,否则无需计算。
3.4 光源的运动
主要有两种方式来改变光源的位置。
- 通过如下方式改变光源的位置;
glLightfv(GL_LIGHT0,GL_POSITION,vLitPosition);
- 比较常用的方式是:光源可以认为是一个几何物体,将受到几何变换矩阵的影响;
gluLookAt()函数可以实现这种效果;
3.5 光照下物体的颜色的决定因素
-
主要由光源的颜色和材质来决定,通过影响光照明方程的计算,最终影响物体的颜色。
- 光源:glLightfv;
- 材质:glMaterialfv;
-
当对物体开启了光照,光源和材质影响了物体的颜色,而此时glColor()函数将不再生效,但是可以通过如下方式发生作用;
- 采用Color值作为Material的值;
//指定了color作为前向面和后向面的ambient的值
glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT);