Unity使用RenderTexture实现实时阴影绘制
发表于2018-11-21
一般实时阴影主要还在出现在角色、怪物的脚底为了然场景表现的更加逼真,实现起来主要会用到这三种方式:脚底放个阴影图片跟着主角动,通过摄像机的RenderRexture绘制显示,直接使用Unity的Projector组件。在2D场景中,为了方便,游戏中通常会直截了当的放一快灰色背景,实现的效果虽然少了几分逼真性,但也足够用。
但是如果想要在3D场景绘制脚底阴影,直接放阴影图就不合适了,为了让阴影效果更加逼真,下面就给大家介绍下使用RenderTexture的方式实现实时阴影绘制的效果吧。
基本思路其实就是多用了一个摄像机,将照相机把你需要照到的主角的内容呈现到一张单独的面片上,这个面片就摆在人较低作为它的阴影。看起来像简单版的一个小地图:只有主角的小地图。
场景中所需要的对象如图,对于map节点显示RenderTexteure的地方只要空的材质球就行了,要呈现摄像机照射的内容。直接用Plane对象或Quad对象都可以的。
此外,为了让阴影真实点,显示阴影的面片一般是灰色透明的,我们还要单独设置下,不然默认摄像机照出来的角色就是我们真实看到的世界:
紧接着还需要一个脚本告诉摄像机把内容写到我们的map面片上。
在场景中的display节点身上绑定脚本ShadowScript:
public class ShadowScript : MonoBehaviour { public GameObject display; //角色形象 private GameObject ShadowCamera; private GameObject map; private RenderTexture mTex = null; //即为显示阴影的RenderTexutre public int AntiAliasing = 4; Transform child; // Use this for initialization void Start () { child = this.transform.FindChild(“qiangu1”); map = child.FindChild(“child/map”).gameObject; ShadowCamera = child.FindChild(“child/camera”).gameObject; if (!display) display = this.transform.parent.gameObject; mTex = new RenderTexture(2000, 2000, 0); mTex.name = “Shadow” + GetInstanceID(); Camera mCamera = ShadowCamera.GetComponent<Camera>(); mCamera.cullingMask = GetLayerMask(display.gameObject.layer); mCamera.targetTexture = mTex; } public LayerMask GetLayerMask(int layer) { LayerMask mask = 0; mask |= 1 << layer; return mask; } // Update is called once per frame void Update () { if(display!=null) { mTex.anisoLevel = AntiAliasing; } map.renderer.maternTexture = mTex; } }
很简单吧?跑起来直接就可以看到实时的阴影效果了!
自己给小骨模型做了一个御剑的动画!然而一时找不到好看的剑模型,我只好找了张jpg的剑扣一个出来,也是大费周折,不过可以看出来阴影效果比较好,因为阴影作为一个独立的GameObject直接少了很多调层级的麻烦,现在是只显示主角阴影的效果。
但是当我把剑贴图所在的面片layer调整的也和主角模型一样的时候,发现居然还是看不到剑的阴影。
这个时候还对专门针对map(显示阴影的面片)材质写一个Shader,就不能用默认的Transparent/Diffuse了,并且最终剑这种透明贴图的还需要使用Unlit/Transparent,新添加的Shader详细代码如下:
///作为带Alpha通道的模型贴图的shader Shader “MyShader/AlphaSkinShader” { Properties { _Color(“Main Color”,Color)=(1,1,1,1) _MainTex (“Base (RGB)”, 2D) = “white” {} _Cutoff(“Base Alpha cutoff”,Range(0,0.9))=0.2 } SubShader { Tags { “Queue”=“Transparent” } LOD 200 Lighting Off ZWrite Off Cull off Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include “UnityCG.cginc” struct appdata_t { float4 vertex:POSITION; float4 color:COLOR; float2 texcoord:TEXCOORD; }; struct v2f { float4 vertex:SV_POSITION; float4 color:COLOR; float2 texcoord:TEXCOORD; }; sampler2D _MainTex; float4 _MainTex_ST; float _Cutoff; v2f vert(appdata_t v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP,v.vertex); o.color=v.color; o.texcoord=TRANSFORM_TEX(v.texcoord,_MainTex); return o; } float4 _Color; half4 frag(v2f i):SV_Target { half4 col = tex2D(_MainTex,i.texcoord); if(col.a<_Cutoff) { clip(col.a-_Cutoff); } else { col.rgb=col.rgb*float3(0,0,0); col.rgb=col.rgb+_Color; col.a=_Color.a; } return col; } ENDCG } } FallBack “Diffuse” }
修改之后靓丽的运行效果: