Directx11教程三十二之MultipleLightShadowMapping
2016-11-04 19:37
477 查看
这节教程采用的结构和上一节教程“D3D11教程三十一之ShadowMap(阴影贴图)”
是一样的,上节教程是一个点光源而已,而这一节教程是采用多个点光源,来加深我们对ShadowMap的理解。
这节教程没多少好说的,直接放出我的Shader
Light.fx (直接定义计算点光源光照的函数)
DrawShadowShader.fx
这里有两个点光源,PointLight1和PointLight2,位置分别为(-5.0f,8.0f, -5.0f)和(5.0f, 8.0f, -5.0f)
点光源1和点光源2都发出白色的光, 环境光AmbientColor(0.20f, 0.20f, 0.20f, 1.0f)
点光源1发出红色的光,点光源2发出绿色的光, 环境光AmbientColor(0.20f, 0.20f, 0.20f, 1.0f)
最后得注意的是:一个点光源使用一张ShadowMap,多个点光源就使用多张ShadowMap
下面放出我的源代码链接:
http://download.csdn.net/detail/qq_29523119/9673575
是一样的,上节教程是一个点光源而已,而这一节教程是采用多个点光源,来加深我们对ShadowMap的理解。
这节教程没多少好说的,直接放出我的Shader
Light.fx (直接定义计算点光源光照的函数)
//这个文件包含一些计算光效果的函数 //这个函数用于计算点光源的衰减强度 //第一个参数为点光源位置,第二个参数为像素位置,第三个参数为像素法线量,第四个参数为在点光源处最初的漫反射光颜色 float4 ComputePLightDiffuse(float3 LightPos, float3 PixelPos,float3 PixelNormal,float4 DiffuseColor) { float DiffuseIntensity; float3 DiffuseDir; float3 InvseDiffuseDir; float DiffuseFactor; float4 FinalDiffuseLight; //求出漫反射光的的方向 DiffuseDir = PixelPos - LightPos; //求出点光源和像素(片元)之间的距离 float distance = length(DiffuseDir); //三个衰减系数 float atten1 = 1.0f; float atten2 = 0.2f; float atten3 = 0.0f; //求出衰减强度 DiffuseIntensity = 1.0f / (atten1 + atten2*distance + atten3*distance*distance); //求出漫反射光的反方向 InvseDiffuseDir = -DiffuseDir; //求出漫反射因子,范围[0.0,1.0] DiffuseFactor= saturate(dot(InvseDiffuseDir, PixelNormal)); //求出最终照射在该像素点上的漫反射光 FinalDiffuseLight= DiffuseFactor*DiffuseIntensity*DiffuseColor; return FinalDiffuseLight; }
DrawShadowShader.fx
#include"Light.fx" //用于计算点光源漫反射光的函数 Texture2D BaseTexture:register(t0); //基础纹理 Texture2D ShadowMap1:register(t1); //投影纹理 Texture2D ShadowMap2:register(t2); //投影纹理 SamplerState WrapSampleType:register(s0); //采样方式 SamplerState ClampSampleType:register(s1); //采样方式 //VertexShader cbuffer CBMatrix:register(b0) { matrix World; matrix View; matrix Proj; matrix WorldInvTranspose; matrix ProjectorView1; matrix ProjectorProj1; matrix ProjectorView2; matrix ProjectorProj2; }; cbuffer CBLight:register(b1) { float4 AmbientColor; float3 PointLightPos1; float pad1; float4 diffuseColor1; float3 PointLightPos2; float pad2; float4 diffuseColor2; } struct VertexIn { float3 Pos:POSITION; float2 Tex:TEXCOORD0; //多重纹理可以用其它数字 float3 Normal:NORMAL; }; struct VertexOut { float4 Pos:SV_POSITION; float4 ProjPos1:POSITION; //基于点光源投影在齐次裁剪空间的坐标 float4 ProjPos2:POSITION1; //基于点光源投影在齐次裁剪空间的坐标 float2 Tex:TEXCOORD0; float3 W_Normal:NORMAL; //世界空间的法线 float3 Pos_W:NORMAL1; //物体在世界空间的顶点坐标 }; 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; //将坐标变换到投影相机1下的齐次裁剪空间 outa.ProjPos1= mul(float4(ina.Pos, 1.0f), World); outa.ProjPos1 = mul(outa.ProjPos1, ProjectorView1); outa.ProjPos1 = mul(outa.ProjPos1, ProjectorProj1); //将坐标变换到投影相机1下的齐次裁剪空间 outa.ProjPos2 = mul(float4(ina.Pos, 1.0f), World); outa.ProjPos2 = mul(outa.ProjPos2, ProjectorView2); outa.ProjPos2 = mul(outa.ProjPos2, ProjectorProj2); //获取物体在世界空间下的坐标 outa.Pos_W= (float3)mul(float4(ina.Pos, 1.0f), World); return outa; } float4 PS(VertexOut outa) : SV_Target { float4 TexColor; //采集基础纹理颜色 float ShadowMapDepth; //a,g,b存储的都是深度 float4 DiffuseLight; //点光源照射在像素点的漫反射光 float2 ShadowTex; //阴影纹理坐标 float4 color = {0.0f,0.0f,0.0f,0.0f}; //最终输出的颜色 float Depth; float bias; //设置偏斜量 bias = 0.001f; //第一,获取基础纹理的采样颜色 TexColor = BaseTexture.Sample(WrapSampleType, outa.Tex); //第二,不管有没有遮挡,都应该具备环境光,注意环境光不生成阴影,这里仅仅是漫反射光生成阴影 color = AmbientColor; //第三,求出相应顶点坐标对应在ShdowMap1上的深度值 //获取投影相机1下的投影纹理空间的坐标值[0.0,1.0] u=0.5*x+0.5; v=-0.5*y+0.5; -w<=x<=w -w<=y<=w ShadowTex.x = (outa.ProjPos1.x / outa.ProjPos1.w)*0.5f + 0.5f; ShadowTex.y = (outa.ProjPos1.y / outa.ProjPos1.w)*(-0.5f) + 0.5f; //第四,由于3D模型可能超出投影相机下的视截体,其投影纹理可能不在[0.0,1.0],所以得进行判定这个3D物体投影的部分是否在视截体内(没SV_POSITION签名 显卡不会进行裁剪) if (saturate(ShadowTex.x) == ShadowTex.x&&saturate(ShadowTex.y) == ShadowTex.y) { //求出顶点纹理坐标对应的深度值 ShadowMapDepth = ShadowMap1.Sample(ClampSampleType, ShadowTex).r; //求出顶点坐标相应的深度值(点光源到渲染点的深度值) Depth = outa.ProjPos1.z / outa.ProjPos1.w; //减去阴影偏斜量 Depth = Depth - bias; //如果不被遮挡,则物体具备漫反射光 if (ShadowMapDepth >= Depth) { //求出漫射光 DiffuseLight =ComputePLightDiffuse(PointLightPos1, outa.Pos_W, outa.W_Normal, diffuseColor1); //颜色加上漫反射光 color += DiffuseLight; color = saturate(color); } } //第五,求出相应顶点坐标对应在ShdowMap2上的深度值 //获取投影相机1下的投影纹理空间的坐标值[0.0,1.0] u=0.5*x+0.5; v=-0.5*y+0.5; -w<=x<=w -w<=y<=w ShadowTex.x = (outa.ProjPos2.x / outa.ProjPos2.w)*0.5f + 0.5f; ShadowTex.y = (outa.ProjPos2.y / outa.ProjPos2.w)*(-0.5f) + 0.5f; //第六,由于3D模型可能超出投影相机下的视截体,其投影纹理可能不在[0.0,1.0],所以得进行判定这个3D物体投影的部分是否在视截体内(没SV_POSITION签名 显卡不会进行裁剪) if (saturate(ShadowTex.x) == ShadowTex.x&&saturate(ShadowTex.y) == ShadowTex.y) { //求出顶点纹理坐标对应的深度值 ShadowMapDepth = ShadowMap2.Sample(ClampSampleType, ShadowTex).r; //求出顶点坐标相应的深度值(点光源到渲染点的深度值) Depth = outa.ProjPos2.z / outa.ProjPos2.w; //减去阴影偏斜量 Depth = Depth - bias; //如果不被遮挡,则物体具备漫反射光 if (ShadowMapDepth >= Depth) { //求出漫射光 DiffuseLight = ComputePLightDiffuse(PointLightPos2, outa.Pos_W, outa.W_Normal, diffuseColor2); //颜色加上漫反射光 color += DiffuseLight; color = saturate(color); } } //第七,用灯光颜色调节纹理颜色 color = color*TexColor; return color; }
这里有两个点光源,PointLight1和PointLight2,位置分别为(-5.0f,8.0f, -5.0f)和(5.0f, 8.0f, -5.0f)
点光源1和点光源2都发出白色的光, 环境光AmbientColor(0.20f, 0.20f, 0.20f, 1.0f)
点光源1发出红色的光,点光源2发出绿色的光, 环境光AmbientColor(0.20f, 0.20f, 0.20f, 1.0f)
最后得注意的是:一个点光源使用一张ShadowMap,多个点光源就使用多张ShadowMap
下面放出我的源代码链接:
http://download.csdn.net/detail/qq_29523119/9673575
相关文章推荐
- Directx11教程三十五之ShadowMappingAndTransparency(实现树叶的影)
- Directx11教程二十二之Multiple Point Lights(多个点光源)
- Directx11教程三十六之ManagingMultipleShaders(组织多个Shader)
- Directx11教程五之DiffuseLight(漫射光)
- [gpu pro]shadow map for omnidirectinal light using tetrahedron mapping
- Directx11教程二十五之ZBuffer(深度缓存,DepthBuffer)
- CSS3属性box-shadow使用详细教程
- Variance Shadow Mapping(译)
- Directx11教程四十二中之3D动画格式M3D
- C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(三十二) 雷、混、冰、毒、火、风 - 幻化中的魔法魅力!
- Directx11地形渲染教程二十一之CubeMap实现SphereReflection(球面反射)
- 第六章代码的问题——基于DirectX11的3D图形程序设计案例教程——重庆大学出版社
- Directx11教程(18) D3D11管线(7)
- Directx11教程(21) 修正程序最小化异常bug
- Scott Mitchell 的ASP.NET 2.0数据教程之三十二:: 数据控件的嵌套
- Directx11地形渲染教程一之FirstCamera(第一人称相机)
- analysis of ShadowMapping Sample with GLSL
- Directx11教程36 纹理映射(6)
- Directx11教程(63) tessellation学习(5)
- NBear.Mapping使用教程(4):实体对象与ADO.NET对象的转换