二十七 Shader山下平面阴影( 二 )


Stencil{Ref 1//参考值为1 , stencilBuffer值默认为0Comp Greater//stencil比较方式是大于Pass replace//通过的处理是替换 , 就是拿1替换buffer 的值Fail Keep//深度检测和模板检测双失败的处理是保持ZFail keep//深度检测失败的处理是保持}
结果:

二十七  Shader山下平面阴影

文章插图
效果略好 , 但是也并不太理想 , 那是因为原作并不是把绳结物体当成一整个物体对待 , 而是当做一个一个的顶点处理 , 用原顶点和对应的影子顶点计算距离明显有问题 。另外有一种做法是传入对象的世界坐标 , 然后跟世界空间的影子顶点计算距离 , 但其实也略复杂了 , 最简单的就是把o.atten=(,vt)/;这一段替换成:
o.atten=length(vt)/_Intensity;
其实就是计算影子顶点和物体的原点的距离 。
效果如图:
二十七  Shader山下平面阴影

文章插图
这就需要在制作模型的时候把物体的原点设在y=0的平面上 , 这样这种影子才能达到较好的效果 。
最后……需要提一句 , 原作中将物体和影子在一个里渲染 , 我认为这是有问题的 , 因为没法分别设置Queue , 物体的Queue应该是 , 而影子的Queue应该是 。所以正确的做法应该是 , 物体该怎么渲染就怎么渲染 , 影子做一个挂在物体上 , 添加和使用相同的Mesh , 然后里使用阴影的材质 。即上文中的去掉第一个Pass , 并修改Tags 。Blend方法建议修改为Blend , 最后frag方法建议修改为:
float4 frag(v2f i) : COLOR {return float4(0,0,0, smoothstep(1, 0, i.atten / 2));}
综上所述 , 整合一下代码:
【二十七Shader山下平面阴影】Shader "Tut/Shadow/PlanarShadow_Chaos" {Properties{_Intensity("atten",range(1,16))=1}SubShader {Tags{ "LightMode" = "ForwardBase""Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" }pass {Cull FrontBlend SrcAlpha OneMinusSrcAlphaOffset -1,-1Stencil{Ref 1//参考值为1 , stencilBuffer值默认为0Comp Greater//stencil比较方式是大于Pass replace//通过的处理是替换 , 就是拿1替换buffer 的值Fail Keep//深度检测和模板检测双失败的处理是保持ZFail keep//深度检测失败的处理是保持}CGPROGRAM#pragma vertex vert #pragma fragment frag#include "UnityCG.cginc"float4x4 _World2Ground;float4x4 _Ground2World;float _Intensity;struct v2f{float4 pos:SV_POSITION;float atten:TEXCOORD0;};v2f vert(float4 vertex: POSITION){v2f o;float3 litDir;litDir=normalize(WorldSpaceLightDir(vertex));litDir=mul(_World2Ground,float4(litDir,0)).xyz;float4 vt;vt= mul(unity_ObjectToWorld, vertex);vt=mul(_World2Ground,vt);vt.xz=vt.xz-(vt.y/litDir.y)*litDir.xz;vt.y=0;vt=mul(_Ground2World,vt);//back to worldvt=mul(unity_WorldToObject,vt);o.pos=UnityObjectToClipPos(vt);o.atten=length(vt)/_Intensity;return o;}float4 frag(v2f i) : COLOR {return float4(0,0,0, smoothstep(1, 0, i.atten / 2));}ENDCG }//}}