这节教程呢,其实结构跟
D3D11教程三十之ProjectiveTexturing(投影纹理) 那节教程一样,我就不放出程序结构图了
这次投影的纹理换为一张光照贴图,模仿光线从窗户照射进的那种情况,
放出Shader代码:ColorShader.fx
Texture2D BaseTexture:register(t0); //基础纹理
Texture2D ProjectiveTexture:register(t1); //投影纹理
SamplerState SampleType:register(s0); //采样方式
//VertexShader
cbuffer CBMatrix:register(b0)
{
matrix World;
matrix View;
matrix Proj;
matrix WorldInvTranspose;
matrix ProjectorView;
matrix ProjectorProj;
};
cbuffer CBLight:register(b1)
{
float4 DiffuseColor;
float3 LightDirection;
float pad;
}
struct VertexIn
{
float3 Pos:POSITION;
float2 Tex:TEXCOORD0; //多重纹理可以用其它数字
float3 Normal:NORMAL;
};
struct VertexOut
{
float4 Pos:SV_POSITION;
float4 ProjPos: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;
//将坐标变换到投影相机下的齐次裁剪空间
outa.ProjPos= mul(float4(ina.Pos, 1.0f), World);
outa.ProjPos = mul(outa.ProjPos, ProjectorView);
outa.ProjPos = mul(outa.ProjPos, ProjectorProj);
return outa;
}
float4 PS(VertexOut outa) : SV_Target
{
float4 TexColor; //采集基础纹理颜色
float2 ProjTex; //投影纹理坐标
float4 LightMapColor;
float4 color = {0.0f,0.0f,0.0f,0.0f}; //最终输出的颜色
float brightness;
float DiffuseFactor;
float4 DiffuseLight; //漫反射光
float4 AmbientColor = { 0.15f,0.15f,0.15f,0.15f }; //环境光
//设置光亮强度(不是严格的点光源强度计算,其实上我们个Shader除 matrix ProjectorView;matrix ProjectorProj就没用到点光源了)
brightness = 1.5f;
//计算漫反射光的反方向
float3 InverseLightDir = -LightDirection;
//计算漫反射光因子
DiffuseFactor = saturate(dot(InverseLightDir, outa.W_Normal));
//漫反射光
DiffuseLight = brightness*DiffuseFactor*DiffuseColor;
//第一,获取采样颜色
TexColor = BaseTexture.Sample(SampleType, outa.Tex);
//第二,获取投影相机下的投影纹理空间的坐标值[0.0,1.0] u=0.5*x+0.5; v=-0.5*y+0.5; -w<=x<=w -w<=y<=w
ProjTex.x =(outa.ProjPos.x/outa.ProjPos.w)*0.5f + 0.5f;
ProjTex.y= (outa.ProjPos.y/outa.ProjPos.w)*(-0.5f) + 0.5f;
//第三,由于3D模型可能超出投影相机下的视截体,其投影纹理可能不在[0.0,1.0],所以得进行判定这个3D物体投影的部分是否在视截体内 (没SV_POSITION签名 显卡不会进行裁剪)
if (saturate(ProjTex.x) == ProjTex.x&&saturate(ProjTex.y) == ProjTex.y)
{
//对投影的光照贴图进行采集像素
LightMapColor = ProjectiveTexture.Sample(SampleType, ProjTex);
color = saturate(DiffuseLight*LightMapColor*TexColor + AmbientColor*TexColor);
}
else
{
color = saturate(AmbientColor*TexColor);
}
return color;
}
放出程序运行图:
我的源代码如下: