轉載請註明出處: http://blog.csdn.net/tianhai110
光照模型
3D渲染中, 物體表面的光照計算公式爲:
I = 環境光(Iambient) + 漫反射光(Idiffuse) + 鏡面高光(Ispecular);
其中,環境光(ambient)計算公式爲:
Iambient = Aintensity * Acolor ; (Aintensity表示環境光強度,Acolor表示環境光顏色)
漫反射光(diffuse)計算公式爲:
Idiffuse = Dintensity*Dcolor*N.L ; (Dintensity表示漫反射強度,Dcolor表示漫反射光顏色,N爲該點的法向量,L爲光源向量)
鏡面光照(specular)計算公式爲:
Ispecular = Sintensity*Scolor*(R.V)n ; (Sintensity表示鏡面光照強度,Scolor表示鏡面光顏色,R爲光的反射向量,V爲觀察者向量)
綜上所得:整個光照公式爲:
I = Aintensity * Acolor + Dintensity*Dcolor*N.L + Sintensity*Scolor*(R.V)n ;
將一些值合併,並使用白色作爲光照顏色,則上述公式可簡化爲:
I = A + D*N.L + (R.V)n
環境光照:
1. 打開RenderMonkey, 右擊WorkSpace的Effect WorkSpace結點,選擇Add Default Effect->DirectX->DirectX;
2. 這樣建立的效果就是一個環境光照效果,可以雙擊pixel shader, 修改自己喜歡的顏色作爲環境光
效果如下圖:
漫反射光照:
1. 打開RenderMonkey, 右擊WorkSpace的Effect WorkSpace結點,選擇Add Default Effect->DirectX->DirectX;
2. 添加物體位置矩陣:右擊Effect節點 選擇 Add Variable->Matrix->PreDefined->matWorld
3. 添加光源向量: 右擊Effect節點 選擇Add Variable->float->float4; 修改名稱爲vecLightDir, 雙擊設置其值
4. 修改stream Mapping; 添加一個法向量形式
5. 編寫Vertex Shader:
- float4x4 matViewProjection;
- float4x4 matWorld;
- float4 vecLightDir;
- struct VS_INPUT
- {
- float4 Position : POSITION0;
- float3 Norm : NORMAL0;
- };
- struct VS_OUTPUT
- {
- float4 Position : POSITION0;
- float3 Light : TEXCOORD0;
- float3 Norm : TEXCOORD1;
- };
- VS_OUTPUT vs_main( VS_INPUT Input )
- {
- VS_OUTPUT Output;
- Output.Position = mul( Input.Position, matViewProjection );
- Output.Light = normalize(vecLightDir);
- Output.Norm = normalize(mul(Input.Norm, matWorld));
- return( Output );
- }
6. 編寫Pixel Shader:
- float4 ps_main( float3 Light:TEXCOORD0, float3 Norm:TEXCOORD1) : COLOR0
- {
- float4 diffuse = { 1.0f, 1.0f, 1.0f, 1.0f};
- float4 ambient = { 0.3, 0.2, 0.1, 1.0};
- return ambient + diffuse * saturate(dot(Light, Norm));
- }
7. 編譯預覽效果:
鏡面反射光照:
鏡面光照在漫反射基礎上,還需要添加一個視口位置;
1. 打開RenderMonkey, 添加一個渲染節點;Add Default Effect->DirectX->DirectX;
2. 添加攝像機矩陣,Add Variable->Matrix->Predefined->matView;
3. 添加光源方向 Add Variable->float->float4; 改名爲vecLightDir,並設值
4. 添加視點位置 Add Variable->float->float4; 改名爲vecEye; 並設值(0,0,-10,1);
5. 添加紋理 Add Texture->Add 2D Texture->2D Texture; 隨便選擇一張紋理;
6. 右鍵pass0,添加一個紋理對象; Add Texture Object->my2DTexture; 並改名爲baseMap;
7. 修改steam mapping 如下
8. 編寫vertex shader;
- float4x4 matViewProjection;
- float4x4 matView;
- float4 vecLightDir;
- float4 vecEye;
- struct VS_INPUT
- {
- float4 Position : POSITION0;
- float3 Normal : NORMAL0;
- float2 Texcoord : TEXCOORD0;
- };
- struct VS_OUTPUT
- {
- float4 Position : POSITION0;
- float2 Texc : TEXCOORD0;
- float3 Light : TEXCOORD1;
- float3 Norm : TEXCOORD2;
- float3 View : TEXCOORD3;
- };
- VS_OUTPUT vs_main( VS_INPUT Input )
- {
- VS_OUTPUT Output;
- Output.Position = mul( Input.Position, matViewProjection );
- Output.Light = vecLightDir;
- float3 posWorld = normalize(mul(Input.Position, matView));
- Output.View = vecEye - posWorld;
- Output.Norm = mul(Input.Normal, matView);
- Output.Texc = Input.Texcoord;
- return( Output );
- }
9. 編寫 pixel shader;
- sampler2D baseMap;
- float4 ps_main( float2 Texc:TEXCOORD0, float3 Light:TEXCOORD1,
- float3 Norm:TEXCOORD2, float3 View:TEXCOORD3) : COLOR0
- {
- float4 ambient = { 0.3686f, 0.3686f, 0.3686f, 1.0f};
- float4 diffuse = { 0.88f, 0.88f, 0.88f, 1.0f};
- float3 Normal = normalize( Norm);
- float3 LightDir = normalize( Light);
- float3 ViewDir = normalize( View);
- float4 diff = saturate( dot( Normal, LightDir));
- float3 Reflect = normalize( 2 * diff * Normal - LightDir);
- float4 specular = pow(saturate(dot(Reflect, ViewDir)), 8);
- float4 fvBaseColor = tex2D( baseMap, Texc );
- float4 fvTotalAmbient = ambient * fvBaseColor;
- float4 fvTotalDiffuse = diffuse * diff * fvBaseColor;
- return fvTotalAmbient + fvTotalDiffuse + specular;
- }
10. 運行結果:
該實例可通過Add Default Effect->DirectX->TexturedPhong 自動生成;