结合Projector和Rendertexture实现实时阴影及软阴影效果

说到实时阴影的实现,一般比较容易想到使用ShadowMap,通过投射灯光空间的深度图,并在投射物体上进行深度比较,判断是否处于阴影的范围,以此来渲染阴影。深度图投射到接受阴影的物体上的效果如图所示:


深度图投射

你所需要做的就是在灯光空间渲染一张深度纹理,并投射到接受阴影的物体上,并和接受阴影的物体上对应像素位置的深度(灯光空间)进行比较,来确定当前像素是否处于阴影即可,此外还要考虑深度图的精度以及以此会造成的ZFighting等,当然这并不是本文讨论的重点。

本文主要介绍一种直接投射灯光空间摄像机的Rendertexture来实现阴影的方法,并将在稍后将其和projector结合。当然同时熟悉这两项技术的开发者应该已经清楚,使用projector实现阴影意味着你将会消耗额外的drawcall,实际上被投射projector并且未在shader中使用"IgnoreProjector"="true"的物体都会在自身shader渲染完(也可能是渲染前,具体看自身渲染队列和projector的shader的渲染队列的先后顺序)后再次使用projector的shader渲染一次。

首先比较一下这种技术和shadowmap技术,实际上个人感觉很大程度上两者的技术其实差不多,都需要用到屏幕投影,只不过shadowmap投射的是深度图(深度缓冲),而本文介绍的是直接投射屏幕纹理(帧缓冲),因此投射的纹理是带Alpha通道的,


注意灯光空间的摄像机背景颜色的Alpha因为0,否则会把背景色也投射到接受阴影的物体上

和shadowmap不同的是,灯光空间的摄像机应该只看到投射阴影的物体:


此时投射后的效果大致如图所示:


当然使用这种方式投射rendertexture必然造成的一个问题是,由于没有投射接受阴影的平面,导致一旦投射阴影的物体穿透接受阴影的物体时会造成阴影的穿帮:


阴影投射物体穿透阴影接受物体

接受阴影物体Shader主要实现代码:


其中viewMatrix为灯光空间摄像机的worldToCameraMatrix,projMatrix为灯光空间摄像机的投影矩阵。

当然使用这种方式实现阴影的不足之处在于需要明确的知道投射阴影的物体和接受阴影的物体。

接下来将尝试将其与Projector结合,注意之前已经讨论过,使用projector意味着额外的drawcall,尤其是场景中物件很多且全部都是分离的物体时,不建议使用这种方式。当然如果场景中只有极少部分物体需要接受阴影,比如只有主要地形,则不妨可以尝试使用这种方式,因为使用projector,你可以很方便的在shader中加入IgnoreProjector标签来忽略投影机的作用,或者直接在projector上修改projector影响的层。

从unity标准资源包中的projector shader我们大致可以了解,projector shader中需要两个4阶矩阵,分别为_Projector和_ProjectorClip,其中后者主要用于近远裁面的淡入淡出,并不是必须的。而前者的_Projector,注意这个矩阵应该区别于摄像机的projection矩阵(尽管摄像机和projector在很多参数上很相似),原因是官方的projector shader中直接通过:o.uvShadow = mul (_Projector, vertex);计算得到投影纹理坐标,这意味着_Projector矩阵应该同时实现将vertex转换到世界空间,再转换到projector的局部空间,最后转换到projector的投影空间的功能,所以其性质应该类似UNITY_MATRIX_MVP矩阵,所以使用projector实现投射rendertexture的效果,只需要添加一个脚本,其会创建一个摄像机,并使用projector的参数,并将这个摄像机的rendertexture传递给projector的material,具体实现如下:


其中_FadeTex是一张表示阴影衰减的贴图,其r、g通道效果如下:


这是实现后的阴影效果:


这里由于使用的RT是原始摄像机尺寸的1/2所以阴影质量有所下降

另外由于投射的是带Alpha通道的Rendertexture,意味着可以方便的对其使用模糊shader完成模糊效果,这里是我自己编写的模糊脚本效果图:


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 111. [动画系统]如何将其他类型的动画转换成关键帧动画? 动画->点缓存->关键帧 112. [动画]Unit...
    胤醚貔貅阅读 13,239评论 3 89
  • Why Bothers? 为什么已经有ShaderForge这种可视化Shader编辑器、为什么Asset Sto...
    DonaldW阅读 76,298评论 16 183
  • 我们需要的是真正有用的知识。知识改变命运,被大众所熟知,正因为熟知,大家也并没有去探求这句话真正的含义。一股脑的学...
    李阳_98d1阅读 171评论 0 0
  • UIButton共有三个相关属性:1.contentEdgeInsets2.titleEdgeInsets3.im...
    啃手高手阅读 15,158评论 22 56
  • 不知道你们有没有过这种体验?每次有一个任务必须要完成的时候,常常在截止时间之前才开始准备,那个时候感觉自己效率比以...
    寻野见阅读 449评论 0 5