以前没有用过FX Composer,今天用这个写了一下per pixel lighting 和 per vertex lighting,主要参考了http://dev.gameres.com/Program/Visual/3D/PPL.htm和《3D绘图程序设计》。
per vertex lighting顾名思义主要是对三角形或者四边形的顶点进行光照计算,然后内插得到其他顶点的光照,当三角形面很大时,效果不是很好,而且容易出现马赫带想象,vs和ps代码如下:
struct
VS_INPUT
{
float4 Position : POSITION;
float3 Normal : Normal;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR;
};
VS_OUTPUT mainVS(VS_INPUT In){
VS_OUTPUT Out;
Out.Position = mul(float4(In.Position.xyz, 1.0 ), WorldViewProj);
float3 vWorldNormal = mul(In.Normal,(float3x3) WorldXf);
float3 vWorldPosition = mul(In.Position,WorldXf).xyz;
float3 vDir = normalize(Light0Pos - vWorldPosition);
Out.Color.rgb = Light0Color * saturate(dot(vDir,vWorldNormal));
Out.Color.a = 1.0f ;
return Out;
}
float4 mainPS(VS_OUTPUT In) : COLOR {
return In.Color;
}
{
float4 Position : POSITION;
float3 Normal : Normal;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR;
};
VS_OUTPUT mainVS(VS_INPUT In){
VS_OUTPUT Out;
Out.Position = mul(float4(In.Position.xyz, 1.0 ), WorldViewProj);
float3 vWorldNormal = mul(In.Normal,(float3x3) WorldXf);
float3 vWorldPosition = mul(In.Position,WorldXf).xyz;
float3 vDir = normalize(Light0Pos - vWorldPosition);
Out.Color.rgb = Light0Color * saturate(dot(vDir,vWorldNormal));
Out.Color.a = 1.0f ;
return Out;
}
float4 mainPS(VS_OUTPUT In) : COLOR {
return In.Color;
}
而per pixel lighting由于把光照以后,相当于对每个像素进行光照计算,而插值的部分主要是法线向量,所以计算量比较大,但是效果要细致。shader代码如下:
struct
VS_INPUT
{
float4 Position : POSITION;
float3 Normal : Normal;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float3 WorldNormal : TEXCOORD0;
float3 WorldPosition : TEXCOORD1;
};
VS_OUTPUT mainVS(VS_INPUT In){
VS_OUTPUT Out;
Out.Position = mul(float4(In.Position.xyz, 1.0 ), WorldViewProj);
Out.WorldNormal = mul(In.Normal,(float3x3) WorldXf);
Out.WorldPosition = mul(In.Position,WorldXf).xyz;
return Out;
}
float4 mainPS(VS_OUTPUT In) : COLOR {
float4 color;
float3 vDir = normalize(Light0Pos - In.WorldPosition);
color.rgb = Light0Color * saturate(dot(vDir,In.WorldNormal));
color.a = 1.0f ;
return color;
}
{
float4 Position : POSITION;
float3 Normal : Normal;
};
struct VS_OUTPUT
{
float4 Position : POSITION;
float3 WorldNormal : TEXCOORD0;
float3 WorldPosition : TEXCOORD1;
};
VS_OUTPUT mainVS(VS_INPUT In){
VS_OUTPUT Out;
Out.Position = mul(float4(In.Position.xyz, 1.0 ), WorldViewProj);
Out.WorldNormal = mul(In.Normal,(float3x3) WorldXf);
Out.WorldPosition = mul(In.Position,WorldXf).xyz;
return Out;
}
float4 mainPS(VS_OUTPUT In) : COLOR {
float4 color;
float3 vDir = normalize(Light0Pos - In.WorldPosition);
color.rgb = Light0Color * saturate(dot(vDir,In.WorldNormal));
color.a = 1.0f ;
return color;
}
两者效果对比如下(左边为per vertex,右边为per pixel):
.