这个教程的结构如下:
这节讲的是由关于点光源的
第一,什么是点光源?
首先你得知道到底光照和光源的关系,光源发出光照,关系就是如此的简单。
现在将光照分为DirectionLight(方向光),DiffuseLight(漫反射光),SpecularLight(镜面光),(这里不谈论全局光什么的,其实我现在不懂全局光)
光源分为:类太阳体,点光源,聚光灯。
这里我是不会具体说明上面的每种概念,D3D11龙书都写得很清楚的,
这里只说点光源,上面我说到光源发出光照,更具体的说每种光源都能发出三种光,即
DirectionLight(方向光),DiffuseLight(漫反射光),SpecularLight(镜面光)
自然而然 点光源也能发出这三种光,但是这里我们假设点光源只发出DiffuseLight(漫反射光),
看看点光源的模型吧:
看上面的图,假设Q点为光源原点,假设在Q点(Xq,Yq,Zq)光照强度为PointLightColor=(r,g,b); Q点到P点(Xp,Yp,Zp)的距离为 d, 灯光衰减因子atten1,atten2,atten3(衰减因子由你自己决定的,三个不可同时为0)
那么点光源或者说灯泡照射在P点的强度为: LightIntensity=PointLightColor/(atten1+atten2*d+atten3*d*d);
光入射P点的向量为(Q,P)或者说为(Xp-Xq,Yp-Yq,Zp-Zq);
下面的有些我已经在
D3D11教程五之DiffuseLight(漫射光)说过了,这里不在重复
贴出shader代码,那些累赘重复的代码我没封装成函数,请见谅:
Texture2D ShaderTexture:register(t0); //纹理资源
SamplerState SampleType:register(s0); //采样方式
#define LIGHT_NUM 4
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
matrix WorldInvTranspose;
};
cbuffer CBDiffuseColor:register(b1)
{
float4 diffuseColor[LIGHT_NUM];
};
cbuffer CBLightPos : register(b2)
{
float4 LightPos[LIGHT_NUM];
};
struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0; //多重纹理可以用其它数字
float3 Normal:NORMAL;
};
struct VertexOut
{
float4 Pos:SV_POSITION;
float3 Pos_W:POSITION; //点在世界空间的位置
float2 Tex:TEXCOORD0;
float3 W_Normal:NORMAL; //世界空间的法线
};
VertexOut VS(VertexIn ina)
{
VertexOut outa;
//将模型坐标变到齐次裁剪空间
outa.Pos = mul(float4(ina.Pos,1.0f), World);
outa.Pos = mul(outa.Pos, View);
outa.Pos = mul(outa.Pos, Proj);
//将法向量变到世界空间
outa.W_Normal = mul(ina.Normal, (float3x3)WorldInvTranspose); //此事世界逆转置矩阵的第四行本来就没啥用
outa.W_Normal = normalize(outa.W_Normal);
//纹理坐标
outa.Tex= ina.Tex;
//求点在世界空间的位置
float4 PosW= mul(float4(ina.Pos, 1.0f), World);
outa.Pos_W = PosW.xyz;
return outa;
}
//这里光照发生在世界空间,当然其它空间也行.
float4 PS(VertexOut outa) : SV_Target
{
float4 TexColor; //采集的纹理颜色
float4 color = {0.0f,0.0f,0.0f,0.0f}; //最终输出的颜色
float DiffuseFactor1;
float DiffuseFactor2;
float DiffuseFactor3;
float DiffuseFactor4;
float4 DiffuseColorIntensity1;
float4 DiffuseColorIntensity2;
float4 DiffuseColorIntensity3;
float4 DiffuseColorIntensity4;
float4 DiffuseColor1;
float4 DiffuseColor2;
float4 DiffuseColor3;
float4 DiffuseColor4;
float atten1, atten2, atten3; //衰减系数
//初始化衰减系数
atten1 = 1.0f;
atten2 = 0.5f;
atten3 = 0.0f;
/*灯光一*/
//计算像素到灯光1的向量,照射到像素的光强度,
float3 LookDirection1 = LightPos[0].xyz - outa.Pos_W.xyz;
//计算光源到像素点的距离
float distance1 = length(LookDirection1);
//计算光源照射到像素点的光照强度
DiffuseColorIntensity1 = diffuseColor[0] / (atten1 + atten2*distance1 + atten3*distance1*distance1); //衰减系数注意加括号计算为分母
//将像素点到光源向量进规格化
LookDirection1 = normalize(LookDirection1);
//求出漫反射光因子
DiffuseFactor1 = saturate(dot(outa.W_Normal, LookDirection1));
//求出最终照射在像素点的漫反射光照强度
DiffuseColor1 = DiffuseFactor1*DiffuseColorIntensity1;
/*灯光二*/
//计算像素到灯光2的向量,照射到像素的光强度,
float3 LookDirection2 = LightPos[1].xyz - outa.Pos_W.xyz;
float distance2 = length(LookDirection2);
DiffuseColorIntensity2 = diffuseColor[1] / (atten1 + atten2*distance2 + atten3*distance2*distance2);
LookDirection2 = normalize(LookDirection2);
DiffuseFactor2 = saturate(dot(outa.W_Normal, LookDirection2));
DiffuseColor2 = DiffuseFactor2*DiffuseColorIntensity2;
/*灯光三*/
//计算像素到灯光3的向量,照射到像素的光强度,
float3 LookDirection3 = LightPos[2].xyz - outa.Pos_W.xyz;
float distance3 = length(LookDirection3);
DiffuseColorIntensity3= diffuseColor[2] / (atten1 + atten2*distance3 + atten3*distance3*distance3);
LookDirection3 = normalize(LookDirection3);
DiffuseFactor3= saturate(dot(outa.W_Normal, LookDirection3));
DiffuseColor3= DiffuseFactor3*DiffuseColorIntensity3;
/*灯光四*/
//计算像素到灯光4的向量,照射到像素的光强度,
float3 LookDirection4= LightPos[3].xyz - outa.Pos_W.xyz;
float distance4 = length(LookDirection4);
DiffuseColorIntensity4 = diffuseColor[3] / (atten1 + atten2*distance4 + atten3*distance4*distance4);
LookDirection4= normalize(LookDirection4);
DiffuseFactor4 = saturate(dot(outa.W_Normal, LookDirection4));
DiffuseColor4 = DiffuseFactor4*DiffuseColorIntensity4;
//获取采样颜色
TexColor = ShaderTexture.Sample(SampleType, outa.Tex);
//第五,用灯光颜色调节纹理颜色
color = saturate(DiffuseColor1+ DiffuseColor2+ DiffuseColor3+ DiffuseColor4)*TexColor;
return color;
}
程序运行效果图: