CG experiment Ⅱ: Ray tracing
Experiment introduction:
Here comes the new project.This project may be a little difficult.You have 2 choices:
1:Based on last project:Let's your sitck man move
2:Create your own scene,you can place anything in it
Choose one and use at least two different method such as Phong model, Gouraud model to complete this project.
demo:
detail:
Phong光照模型
Phong模型是最常用的局部光照模型,此模型把从表面的光分解为3个独立项:
环境项:模拟场景的整体光照水平。
漫反射:模拟直接光源在表面均匀地向各个方向反射。
镜面反射:在光滑表面均匀反射的高光。
先来看一下phong光照模型的数学公式(单个光源):
I = Ka * LA + LL * Kd * max( ( dot (N,L),0 ) + LL * Ks* max (dot ( R,V )^,shininess,0 )
从公式可以看出,计算表面上某点的phong反射时需要输入一些参数,这些参数包括:
-环境反射量Ka
-漫反射量kd
-镜面反射量Ks
-镜面光滑度shininess
此处可以用物体材质结构来描述:
struct Matrial
{
float ka ;
float kd ;
float ks ;
float shininess;
}
有关向量可以参考下面的图。图中的H向量在这里并没有用到,它是另一个光照模型Blina-Phong中的一个向量。
L:从表面上某点(受到光照的那点)指向光源的方向向量
V:从表面上某点指向摄像机的方向向量
N:表面上某点的法向量
R:L关于N的反射向量
其中R向量的计算方法为:
任何向量都可以表示为切线向量和法线向量之和,例如对于向量L,它可以表示为:
L = Ln + Lt ;
Ln指的是L在法线向量N上的投影长度,它可以这样计算:
Ln = dot ( N, L )N ; (N是个单位向量)
Ln计算出来了,自然的,Lt可以由L与Ln来计算:
Lt = L - Ln;
对于R向量,它是向量L关于法向量N的反射向量,故R与L有同一个法线分量Ln,但又相反的切线分量Lt,因此,我们可以这样求R:
R = Rn + Rt= Ln - Lt= Ln - (L- Ln)= 2Ln - L= 2( dot ( N , L )N ) - L
依据公式,phong光照模型的CG代码可以编写如下:
struct Matrial
{
float ka ; //环境反射量
float kd ; //漫反射量
float ks ; //镜面反射量
float shininess; //物体表面光泽度
}
struct Light
{
float3 position ; //灯光的位置
float3 color ; //灯光的颜色
}
void PhongModle (
out float3 oposition:POSITION,
out float3 color :COLOR,
float4 position:POSITION,
float3 normal:NORMAL,
uniform float4x4 modelViewPrij,
uniform float3 globalAmbient ,
uniform float3 eyePosition,
uniform Light light ,
uniform Material material,
)
{
oposition = mul (modelViewPrij,P);
float3 P = position.xyz;
float3 N = normal;
//计算环境光贡献
float3 ambient = material.ka * globalAmbient;
//计算向量L
float3 L = normalize( light.position -P );
//计算向量V
float3 V = normalize (eyePosition -P);
//计算向量R
float3 R = 2 * (dot (N,L)*N )-L ;
//计算漫反射贡献
float3 diffuse = material.kd * light.color * max (dot (N,L),0);
//计算镜面反射贡献
float3 specular = material.ks * light.color * max (dot (R,V)^shininess,0);
//三种光加和
color.xyz = ambient + diffuse +specular ;
color .w = 1;
}
Lambert光照模型
Lambert光照模型是最简单的漫反射模型。物体发生理想漫反射时,光线照射到比较粗糙的物体表面,从物体表面向各个方向发生了反射,
从而无论从哪个角度来看表面,表面某点的明暗程度都不随观测者的位置变化而变化。例如你观察黑板时,
黑板上发生的就是漫反射。
Lambert光照模型的数学表达式可以写为:
Ip = Ia * kd + II * kd * ( dot ( N,L ) )
其中:
- kd为物体表面的漫反射系数。
- Ia为环境光,Ia*kd为环境光对物体表面漫反射所贡献的光照。
- II表示环境光外其他光如方向光或点光源。
- N为物体表面p点的法向量。
- L为P点指向灯源的方向向量。
Lambert光照模型的CG代码为:
//灯光
struct Light
{
float3 color ;
float3 position;
}
//物体
struct Material
{
float kd ;
}
void LambertModel(
out float4 oposition:POSITION,
out float3 color :COLOR,
loat4 position:POSITION,
float3 normal:NORMAL,
uniform float4x4 modelViewPrij,
uniform float3 globalAmbient ,
uniform float3 eyePosition,
uniform Light light ,
uniform Material material,
)
{
oposition = mul (modelViewPrij,P);
float3 P = position.xyz;
float3 N = normal;
float3 ambient = material.kd * globalAmbient;
float3 L = normalize( light.position -P );
float3 specular = light.color * material.kd * max( dot(N,L),0 ) ;
color.xyz = ambient + specular ;
color.w = 1;
}