Unity 之残影实现
分享部分代码如下,可做为参考:
1 using System.Collections; 2 using UnityEngine; 3 4 namespace ACTBook 5 { 6 public class ShadowFx : MonoBehaviour 7 { 8 const string SHADOW_FX_NAME_PREFIX = "Shadow_"; 9 public Shader shader;//透明边缘泛光Shader 10 public SkinnedMeshRenderer skinnedMeshRenderer;//蒙皮网格 11 public float fadeTime = 0.5f;//淡出时间 12 public MonoBehaviour coroutineMonoBehaviour; 13 //协程开启对象,防止因自身关闭导致残影协程停止 14 GameObject mShadowFxGO; 15 16 17 void OnEnable() 18 { 19 coroutineMonoBehaviour.StartCoroutine(ShadowFxTrigger());//残影特效触发协程 20 } 21 22 void OnDestroy() 23 { 24 if (mShadowFxGO)//特殊情况残影销毁处理 25 Destroy(mShadowFxGO); 26 } 27 28 IEnumerator ShadowFxTrigger() 29 { 30 mShadowFxGO = new GameObject(SHADOW_FX_NAME_PREFIX + Time.time); 31 mShadowFxGO.transform.position = skinnedMeshRenderer.transform.position; 32 mShadowFxGO.transform.rotation = skinnedMeshRenderer.transform.rotation; 33 mShadowFxGO.transform.localScale = skinnedMeshRenderer.transform.localScale; 34 //拷贝变换信息 35 var meshRenderer = mShadowFxGO.AddComponent<MeshRenderer>(); 36 var meshFilter = mShadowFxGO.AddComponent<MeshFilter>(); 37 var mesh = new Mesh() { name = mShadowFxGO.name }; 38 skinnedMeshRenderer.BakeMesh(mesh);//烘焙残影 39 meshFilter.sharedMesh = mesh; 40 var mat = new Material(shader); 41 mat.CopyPropertiesFromMaterial(skinnedMeshRenderer.sharedMaterial); 42 //从主材质球拷贝参数 43 meshRenderer.sharedMaterial = mat; 44 var cacheMatColor = mat.color; 45 var beginTime = Time.time; 46 for (var duration = fadeTime; Time.time - beginTime <= duration;) 47 { 48 var t = (Time.time - beginTime) / duration; 49 mat.color = new Color(cacheMatColor.r, cacheMatColor.g, cacheMatColor.b, Mathf.Lerp(1f, 0f, t)); 50 yield return null; 51 }//残影消隐插值 52 //Destroy(mShadowFxGO);//销毁残影 53 } 54 } 55 }
shader如下:
1 Shader "ACTBook/RimFxShader" 2 { 3 Properties 4 { 5 _Color ("Color", Color) = (1,1,1,1) 6 _MainTex ("Albedo (RGB)", 2D) = "white" {} 7 _Glossiness ("Smoothness", Range(0,1)) = 0.5 8 _Metallic ("Metallic", Range(0,1)) = 0.0 9 //一些常规字段 10 _BumpMap("Normal Texture (RGB)", 2D) = "white" {}//法线贴图 11 _RimColor("Rim Color", Color) = (1,0.0, 0.0, 0.0)//发光颜色 12 _RimPower("Rim Power", float) = 2.0//发光强度 13 } 14 SubShader 15 { 16 Tags 17 { 18 "Queue" = "Transparent" 19 "RenderType" = "Transparent" 20 }//半透明Shader标签声明 21 22 Pass 23 { 24 ZWrite On 25 ColorMask 0 26 }//预先写深度 27 28 CGPROGRAM 29 #pragma surface surf Standard fullforwardshadows alpha:fade 30 //留意alpha:fade,使用半透明Shader须加入这一段 31 #pragma target 3.0 32 sampler2D _MainTex; 33 fixed4 _RimColor;//边缘发光的颜色 34 half _RimPower;//边缘发光的强度 35 struct Input 36 { 37 float2 uv_MainTex; 38 float2 uv_BumpMap; 39 half3 viewDir; 40 //边缘发光所需要的缺省参数 41 }; 42 sampler2D _BumpMap; 43 half _Glossiness; 44 half _Metallic; 45 fixed4 _Color; 46 UNITY_INSTANCING_BUFFER_START(Props) 47 UNITY_INSTANCING_BUFFER_END(Props) 48 49 void surf (Input IN, inout SurfaceOutputStandard o) 50 { 51 o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); 52 half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal)); 53 //计算边缘光强度 54 fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 55 o.Albedo = c.rgb; 56 o.Metallic = _Metallic; 57 o.Smoothness = _Glossiness; 58 o.Emission = _RimColor.rgb * pow(rim, _RimPower); 59 //乘以边缘光颜色并赋予自发光通道 60 o.Alpha = rim * c.a;//边缘光强度与颜色alpha相乘,并赋予Alphat通道 61 } 62 ENDCG 63 } 64 }