Unity残影

可以用两种方式实现残影:1. 新建一个Mesh,记录前几帧的人物的影像,然后通过后处理混合上去。2.记录前几帧的人物位置,将其传入shader中,对每个位置进行一个pass渲染。

第一方式

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class AfterImage : MonoBehaviour
{
    List<List<GameObject>> _meshGoList = new List<List<GameObject>>();
    List<SkinnedMeshRenderer> _renderList= new List<SkinnedMeshRenderer>();
    Shader _curShader;
    Shader CurShader
    {
        get
        {
            if(_curShader == null)
            {
                _curShader = Shader.Find("Custom/AfterImage");
            }
            return _curShader;
        }
    }
	// Use this for initialization
	void Start () 
    {
        var renders = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
        _renderList.AddRange(renders);
	}

    int num = 1;
    int max = 5;
    float interval = 0.1f;
    float deltaTime = 0;
    private void DeEffect()
    {
        List<GameObject> meshList = new List<GameObject>();
        for(int i = 0; i < _renderList.Count; ++i)
        {
            string meshName = string.Format("meshName_{0}_{1}", num, i);
            GameObject meshGo = new GameObject(meshName);
            meshGo.transform.position = _renderList[i].gameObject.transform.position;
            meshGo.transform.localRotation = _renderList[i].gameObject.transform.localRotation;
            Mesh mesh = new Mesh();
            _renderList[i].BakeMesh(mesh);
            MeshFilter meshFilter = meshGo.AddComponent<MeshFilter>();
            meshFilter.mesh = mesh;
            MeshRenderer skin = meshGo.AddComponent<MeshRenderer>();
            skin.material = GetMaterial(_renderList[i].material);
//            skin.material = _renderList[i].material;
            meshList.Add(meshGo);
        }
        _meshGoList.Add(meshList);
        num += 1;
    }
	
    private Material GetMaterial(Material mat)
    {
        Material nMat = new Material(CurShader);
        nMat.SetTexture("_MainTex", mat.mainTexture);
        return nMat;
    }

	// Update is called once per frame
	void Update () 
    {
        if (deltaTime >= interval)
        {
            DeEffect();
            deltaTime = 0f;
        }
        else
        {
            deltaTime += Time.deltaTime;
        }
        
        if(_meshGoList.Count > 5)
        {
            for(int i = 0; i < _meshGoList.Count - max; ++i)
            {
                if(_meshGoList[i] != null)
                {
                    for(int j = 0; j < _meshGoList[i].Count; ++j)
                    {
                        if(_meshGoList[i][j] != null)
                        {
                            DestroyImmediate(_meshGoList[i][j]);
                        }
                    }
                }
            }

            for(int i = 0; i < _meshGoList.Count - max; ++i)
            {
                _meshGoList.RemoveAt(0);
            }
        }
	}
}


Shader "Custom/AfterImage" 
{
	Properties 
	{
		_Color ("Color", Color) = (1,0.8,1,0.5)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags {"Queue" = "Transparent" "LightMode" = "Always" "RenderType"="Opaque"}
		
		Pass 
		{
			ZWrite Off 
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc" 
			sampler2D _MainTex;
			fixed4 _Color;
			struct v2f
			{
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0; 
			}; 

			v2f vert( appdata_base v)
			{
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.texcoord;
				return o;
			}

			fixed4 frag(v2f i) : COLOR
			{
				float4 c;
				c = tex2D(_MainTex, i.uv);
				c = c * _Color;
				return c;
			}
			ENDCG
		}

	} 
	FallBack "Diffuse"
}
把这个脚本挂到要产生残影的物体上就可以看到残影了

第二种方法(主要参考http://www.cnblogs.com/foxianmo/p/4946116.html?utm_source=tuicool&utm_medium=referral)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Ghost : MonoBehaviour {
    public Shader curShader;
    private List<Vector3> offsets = new List<Vector3>();
    private List<Material> mats = new List<Material>();
	// Use this for initialization
	void Start ()
    {
        offsets.Add(transform.position);
        offsets.Add(transform.position);
        offsets.Add(transform.position);
        offsets.Add(transform.position);

        var skinMeshRenderer = gameObject.GetComponentsInChildren<SkinnedMeshRenderer>();
        foreach(var mr in skinMeshRenderer)
        {
            mats.Add(mr.material);
        }

        foreach(var mat in mats)
        {
            mat.shader = curShader;
        }
	}
	
	// Update is called once per frame
	void Update () 
    {
	    foreach(var mat in mats)
        {
            mat.SetVector("_Offset0", offsets[3] - transform.position);
            mat.SetVector("_Offset1", offsets[2] - transform.position);
            mat.SetVector("_Offset2", offsets[1] - transform.position);
            mat.SetVector("_Offset3", offsets[0] - transform.position);
        }
        offsets.Add(transform.position);
        offsets.RemoveAt(0);
	}
}


Shader "Custom/Ghosh" {
	Properties {
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_Offset0("Offset 0", vector) = (0, 0, 0, 0)
		_Offset1("Offset 1", vector) = (0, 0, 0, 0)
		_Offset2("Offset 2", vector) = (0, 0, 0, 0)
		_Offset3("Offset 3", vector) = (0, 0, 0, 0)
	}

	CGINCLUDE
	#include "UnityCG.cginc"

	sampler2D _MainTex;
	float4 _Offset0;
	float4 _Offset1;
	float4 _Offset2;
	float4 _Offset3;

	struct v2f 
	{
		float4 pos : POSITION;
		float2 uv : TEXCOORD0; 
	};

	v2f vert_normal( appdata_base v)
	{
		v2f o;
		o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
		o.uv = v.texcoord;
		return o;
	}

	v2f vert_offset_1( appdata_base v)
	{
		v2f o;
		float4 pos = mul(_Object2World, v.vertex);
		o.pos = mul(UNITY_MATRIX_VP, pos + _Offset0);
		o.uv = v.texcoord;
		return o; 
	}

	v2f vert_offset_2( appdata_base v)
	{
		v2f o;
		float4 pos = mul(_Object2World, v.vertex);
		o.pos = mul(UNITY_MATRIX_VP, pos + _Offset1);
		o.uv = v.texcoord;
		return o; 
	}

	v2f vert_offset_3( appdata_base v)
	{
		v2f o;
		float4 pos = mul(_Object2World, v.vertex);
		o.pos = mul(UNITY_MATRIX_VP, pos + _Offset2);
		o.uv = v.texcoord;
		return o; 
	}

	v2f vert_offset_4( appdata_base v)
	{
		v2f o;
		float4 pos = mul(_Object2World, v.vertex);
		o.pos = mul(UNITY_MATRIX_VP, pos + _Offset3);
		o.uv = v.texcoord;
		return o; 
	}

	float4 frag_normal(v2f i) : COLOR
	{
		return tex2D(_MainTex, i.uv);
	}

	float4 frag_color(v2f i) : COLOR
	{
		float4 c;
		c = tex2D(_MainTex, i.uv);
		c.w = 0.5;
		return  c;
	}
	ENDCG

	SubShader 
	{
		Pass 
		{
			ZWrite Off 
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert_offset_4
			#pragma fragment frag_color 
			ENDCG
		}	

		Pass 
		{
			ZWrite Off 
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert_offset_3
			#pragma fragment frag_color 
			ENDCG
		}

		Pass 
		{
			ZWrite Off 
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert_offset_2
			#pragma fragment frag_color 
			ENDCG
		}

		Pass 
		{
			ZWrite Off 
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert_offset_1
			#pragma fragment frag_color 
			ENDCG
		}

		Pass 
		{
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma vertex vert_normal
			#pragma fragment frag_normal  
			ENDCG 
		}
	} 
	FallBack "Diffuse"
}
同样是把脚本挂到要产生残影的物体上就可以看到残影

个人比较喜欢第一种方法,第二种方法要更改原物体的shader,要同时存在几种效果的时候会变得很麻烦


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值