移动端实时阴影+自投影技术实现

Posted 海洋_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了移动端实时阴影+自投影技术实现相关的知识,希望对你有一定的参考价值。

说到实时阴影,现在市面上各个项目实现的实时阴影大部分都是平面阴影,比如王者荣耀实现的实时阴影以及一些RPG网络游戏实现实时阴影,所以项目在设计地形时都是有意回避地形高度差的出现,尽量让地形是平坦的。本篇博客介绍的实时阴影是可以在平面以及地形上进行的渲染。这样实现的实时阴影就可以在不同的地形上进行投影,实现方式采用的还是比较传统的实时阴影算法比如ShadowMap,CSM算法或者PSM算法等等都可以实现出来,另外,除了阴影投影到地面上的,我们还可以实现阴影的自投影,比如角色身上的盔甲可以投影到身体上面,类似崩坏三实现的效果。如下所示:

角色的投影地面并不是平坦的,再看一下自身投影的实现效果:

角色身上的头发或者裙子在自己身上投影。自身的投影实现相对来说比较耗,它要实时的计算遮挡关系。下面先给读者介绍将投影投到任意地形上面,实现的算法可以使用CSM算法,这个也是Unity引擎使用的算法。CSM算法是通过摄像机根据距离对场景由远及近进行划分,近处的物体投影比较精细,远处的物体投影相对来说比较简陋,这样对性能来说也是一种优化,如下所示:

摄像机生成好了后,需要加入Shader生成阴影其实简单点说就是像素深度的判断
代码如下所示:

		fixed4 frag (v2f i) : COLOR
		
			float depth = i.depth.x/i.depth.y;

		#if defined (SHADER_TARGET_GLSL) 
			depth = depth*0.5 + 0.5; //(-1, 1)-->(0, 1)
		#elif defined (UNITY_REVERSED_Z)
			depth = 1 - depth;       //(1, 0)-->(0, 1)
		#endif

			return EncodeFloatRGBA(depth);
		

我们投影是投影到地面上或者墙上,从优化角度讲,我们会选择哪些可以接收阴影,哪些不接受阴影。这些需要接收的阴影的对象需要挂接一个Shader用于接收阴影,片段着色器代码如下所示:

			fixed4 frag (v2f i) : COLOR0 
			
				fixed4 weights = getCascadeWeights(i.eyeZ);
				fixed4 coord = getShadowCoord(i.worldPos, weights);
				i.shadowCoord.xy = i.shadowCoord.xy/i.shadowCoord.w;
				float2 uv = i.shadowCoord.xy;
				uv = uv*0.5 + 0.5; //(-1, 1)-->(0, 1)
				fixed4 texcol = tex2D(_MainTex, uv);

				float depth = i.shadowCoord.z / i.shadowCoord.w;

			#if defined (SHADER_TARGET_GLSL)
				depth = depth*0.5 + 0.5; //(-1, 1)-->(0, 1)
			#elif defined (UNITY_REVERSED_Z)
				depth = 1 - depth;       //(1, 0)-->(0, 1)
			#endif
				// sample depth texture
				float4 col = SampleShadowTexture(i.worldPos, weights) * texcol;
				return col;
				

这样我们就完成了阴影的实现,效果如下所示:

这样我们的角色实现了可以将阴影投影到不同的地形上,下面再看看通过设置裁剪距离实现自身投影效果,如下所示:

大家可以看到红色方框内的阴影是角色衣服和武器投影到上面的,完美解决了该问题。

代码后续奉上。。。。。。。。。。

以上是关于移动端实时阴影+自投影技术实现的主要内容,如果未能解决你的问题,请参考以下文章

Unity5.0实时阴影的优化

体素化阴影纹理研究 (Voxelized Shadow Map)

ue4太阳光下阴影有断点

UE4移动端动态阴影ShadowMap使用率过低问题

UE4 定向光(DirectionalLight)下小物体阴影消失或不清晰问题解决方案

shader之——移动端阴影实现