6-11 添加渐变的能力到你的Deferred Shading引擎
问题
虽然你已经掌握了基本的光照在实时的计算机图形中,可以注意你的对象不能蒙上阴影。这是因为你的象素着色器计算光照在一个象素中基于在光的方向和法线之间的角度。直到现在,你的象素着色器不能考虑任何在光和象素之间的对象。
解决方案
一个很好的技术为添加阴影到你的场景中是阴影映射技术。我已经详细的讨论这个技术。
总之,每一个象素的阴影映射技术比较真实的在象素和光照之间的距离,根据距离尽量被光照看见。如果真实的距离比光可以看见的距离大,必须有个对象在象素和灯之间,所以象素不应该被点亮。
允许这个比较,灯照射看见的场景应该首先被绘制,所以每一个象素它自己的距离到这灯能保成一个纹理。
如果你想要执行这个阴影映射的deferred 绘制版本技术,你首先需要生成一个深度图片为你每一个灯。一旦你已经做了这些,阴影影射比较应该运用于deferred绘制的第二步骤。
它如何工作的
这节将建成整个在前面的章节之上,确保你从这些代码开始。
前面章节的步骤1将不会变,因为你仍然需要颜色,法线和深度值为场景中的每一个象素。
Generating the Shadow Maps
XNA代码
在你可以定义你的灯的一个的lighting contribution在步骤2中,虽然,你需要生成阴影影射为这个灯。这个阴影影射包含场景到灯的距离。需要添加一个绘制目标和两个纹理变量:一个保存距离,一个返回图象你重新使用另外一个。
1 RenderTarget2D shadowTarget;
2 Texture2D shadowMap;
3 Texture2D blackImage;
初始化绘制目标和返回图象在你的LoadContent方法中:
2 Texture2D shadowMap;
3 Texture2D blackImage;
1 shadowTarget=new RenderTarget2D(device,width,height,1,SurfaceFormat.Single);
2 blackImage=new Texture2D(device,width,height,1,TextureUsage.None,SurfaceFormat.Color);
接下来,进入你的GenerateShadingMap方法中。这个方法被用来混合所有灯的lighting contribution成一个纹理使用alpha混合。这可以不在被处理,因为你需要生成一个新的阴影影射在两个混合操作之间。换句话说,这将导致在阴影地图混合成阴影影射。2 blackImage=new Texture2D(device,width,height,1,TextureUsage.None,SurfaceFormat.Color);
而不是alpha混合,保存阴影影射在每个灯之后添加它自己的lighting contribution.首先,清除阴影映射通过使用返回的图象:
1 private Texture2D GenerateShadingMap()
2 {
3 shadingMap=blackImage;
4 for(int i=0;i<NumberOfLights;i++)
5 {
6 RenderShadowMap(spotLights[i]);
7 AddLight(spotLights[i]);
8 }
9 return shadingTarget.GetTexture();
10 }
2 {
3 shadingMap=blackImage;
4 for(int i=0;i<NumberOfLights;i++)
5 {
6 RenderShadowMap(spotLights[i]);
7 AddLight(spotLights[i]);
8 }
9 return shadingTarget.GetTexture();
10 }