局部光照模型
常见的光照模型一般包括四个部分ambient, diffuse, specular, 和emitted light.
即: vertex color = ambient + diffuse + specular + emitted light
Ambient light:环境光,通常定义在光源的中,注意每个光源的衰减量。
Diffuse:漫反射部分,光照找到物体的表面,由于物体的表面凹凸不平而反射到各个方向的光。
Specular :相比于漫反射,一道入射光通过镜面反射只产生一个方向的Specular,遵循反射法则,即入射角和出射角相同。Diffuse和Specular的区别可以参考下面的图。
Emittion:物体的自发光。
根据以上四种光对每个点的光照强度(即)颜色的影响,我们就可以算出每一个点的像素值。
其实我们环境中的物体不是发光的,所以计算时候,只需要计算三部分,环境光,漫反射,镜面反射
小写为下标
- 环境光 Ia=Ii*Ka
- 漫反射 Id=Ii* Kd∗(L*N)
- 镜面反射 Is=Ii* Ks∗(R*V)^n
最后的光照强度就是以上三种之和。
实验要求
实验要求我们利用多种不同的shading 模型,来对一个环境进行渲染处理,了解不同shading模型的原理,以及产生不同效果的原因。
实验准备
在这个实验中我们使用了两个渲染库,freeglut库以及glew库。开发环境为 opengl +vs
实验内容与步骤
Gouraud Shading
- Gouraud 的原理
Gouraud明暗处理只在多边形顶点处采用Phong局部反射模型计算光强,而在多边形内的其他点采用双向线性插值,这样做的优点是高效,但是无法很好的处理镜面高光问题,依赖于其所在多面形的相对位置
- 实现过程
Gouraud之所以高效的原因就是,其只有在顶点处使用PHONG光照模型,而在平面内部,使用光照插值的方法。
varying vec3 N;
varying vec3 v;
void main(void)
{
v = vec3(gl_ModelViewMatrix * gl_Vertex);
N = normalize(gl_NormalMatrix * gl_Normal);
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
- 实现结果
Phong Shading
*Phong 的原理
Phong明暗处理,通过差值计算每个顶点的法向量(3次差值,在x,y,z三个方向分别进行差值计算),然后计算每个点上的光强值,这样效果好,但计算复杂,需要付出比Gouraud 4-5 倍的时间。 通常,在一个比较复杂的场景中,当物体镜面发射很微弱时,我们对其采用Gouraud明暗处理,而对于一些镜面高光的物体,采用Phong明暗处理,这样既保证质量,又保证速度。
- 实现过程 将法向量插值,然后每一个法向量计算光照强度
varying vec3 N;
varying vec3 v;
void main (void)
{
vec3 L = normalize(gl_LightSource[0].position.xyz - v);
vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)
vec3 R = normalize(-reflect(L,N));
//calculate Ambient Term:
vec4 Iamb = gl_FrontLightProduct[0].ambient;
//calculate Diffuse Term:
vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);
// calculate Specular Term:
vec4 Ispec = gl_FrontLightProduct[0].specular
* pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
// write Total Color:
gl_FragColor = gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec;
}
- 实验实现
实验心得
通过本次实验了解了Gouraud着色模型以及Phong着色模型的区别,以及各自的使用的特点,了解了各自的适应情况,加深了对局部光照模型的理解