最近尝试制作一些酷炫的残影效果,比较了很多方法,觉得这个办法是比较稳定靠谱的,选择Lateupdate为调用时机很好的展示了对Monobehaviour的深刻理解,非常棒的设计,受益匪浅!
残影Shader
Shader "Wonderm/Ghost" {
Properties{
_MainTex("Texture", 2D) = "white" {}
_BumpMap("Bumpmap", 2D) = "bump" {}
_RimColor("Rim Color", Color) = (0.46,0.0,1.0,0.0)
_RimPower("Rim Power", Range(0.2,2.0)) = 0.5
_Brightness("Brightness",Range(0.0,3.0)) = 1.0
}
SubShader{
Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "IgnoreProjector" = "True"}
// extra pass that renders to depth buffer only
Pass {
ZWrite On
ColorMask 0
}
CGPROGRAM
#pragma surface surf Lambert alpha noambient nolightmap nodirlightmap novertexlights
struct Input {
float2 uv_MainTex;
float2 uv_BumpMap;
float3 viewDir;
};
sampler2D _MainTex;
sampler2D _BumpMap;
float4 _RimColor;
float _RimPower;
float _Brightness;
void surf(Input IN, inout SurfaceOutput o) {
half4 basecol = tex2D(_MainTex, IN.uv_MainTex);
half3 graycol = dot(basecol.rgb,float3(0.3,0.59,0.11));
o.Albedo = graycol;
o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
o.Emission = _RimColor.rgb * pow(rim, _RimPower) * _Brightness;
o.Alpha = (o.Emission.r + o.Emission.g + o.Emission.b) / 3.0;
}
ENDCG
}
Fallback "Diffuse"
}
代码
public static void ShowGhost(SkinnedMeshRenderer render, Color color, Vector3 pos, Quaternion rot, float fadeOutTime)
{
if (fadeOutTime == 0 || render == null) return;
var ghostMat = new Material(Shader.Find("Wonderm/Ghost"));
ghostMat.SetColor("_RimColor", color);
var newMesh = new Mesh();
render.BakeMesh(newMesh);
var newMats = new Material[render.sharedMaterials.Length];
for (int i = 0; i < newMats.Length; i++) { newMats[i] = ghostMat; }
var obj = new GameObject("Ghost");
obj.transform.position = pos;
obj.transform.rotation = rot;
var newFilter = obj.AddComponent<MeshFilter>();
newFilter.sharedMesh = newMesh;
var newRender = obj.AddComponent<MeshRenderer>();
newRender.sharedMaterials = newMats;
newRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
newRender.receiveShadows = false;
/*
此处添加淡出代码
*/
if (fadeOutTime > 0)
GameObject.Destroy(obj, fadeOutTime);
}