Unity3D-Shader-人物殘影效果


【舊博客轉移 - 2016年1月7日 00:24 】

前面的話

上一篇講了一下人物邊緣發光效果,鏈接: Unity-ShaderLab-實現X光效果,這次我們利用這個Shader來實現人物殘影效果

先來看一下效果  →_→

 

大概的原理

  • 創建殘影:拷貝人物當前Mesh數據作為殘影,用MeshFilter+MeshRenderer渲染出來
  • 殘影有生命周期、創建間隔:殘影從創建到慢慢消失的過程,這里采用透明度淡出
  • 使用X光Shader
Mesh mesh = new Mesh ();
meshRender[i].BakeMesh(mesh);

 

BakeMesh拷貝網格

 
        

拷貝網格很簡單,調用SkinnedMeshRenderer的BakeMesh方法

用MeshFilter跟MeshRenderer渲染網格

MeshFilter filter = go.AddComponent<MeshFilter>();
filter.mesh = mesh;

MeshRenderer meshRen = go.AddComponent<MeshRenderer>();

meshRen.material = meshRender[i].material;
meshRen.material.shader = ghostShader;//設置xray效果

 

MeshFilter:網格過濾器用於從你的資源中獲取網格信息(Mesh)並將其傳遞到用於將其渲染到屏幕的網格渲染器當中

MeshRenderer:但是想要渲染出網格,還需要用到MeshRenderer哦

完整代碼

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

public class GhostShadow : MonoBehaviour {
    //持續時間
    public float duration = 2f;
    //創建新殘影間隔
    public float interval = 0.1f;
    
    //邊緣顏色強度
    [Range(-1, 2)]
    public float Intension = 1;
    
    //網格數據
    SkinnedMeshRenderer[] meshRender;
    
    //X-ray
    Shader ghostShader;
    
    void Start () {
        //獲取身上所有的Mesh
        meshRender = this.gameObject.GetComponentsInChildren<SkinnedMeshRenderer> ();
        
        ghostShader = Shader.Find("lijia/Xray");
    }
    
    private float lastTime = 0;
    
    private Vector3 lastPos = Vector3.zero;
    
    void Update () {
        //人物有位移才創建殘影
        if (lastPos == this.transform.position)
        {
            return;
        }
        lastPos = this.transform.position;
        if(Time.time - lastTime < interval){//殘影間隔時間
            return;
        }
        lastTime = Time.time;
        
        if (meshRender == null)
            return;
        for (int i = 0; i < meshRender.Length; i++) {
            Mesh mesh = new Mesh ();
            meshRender[i].BakeMesh(mesh);
            
            GameObject go = new GameObject();
            go.hideFlags = HideFlags.HideAndDontSave;
            
            GhostItem item = go.AddComponent<GhostItem>();//控制殘影消失
            item.duration = duration;
            item.deleteTime = Time.time + duration;
            
            MeshFilter filter = go.AddComponent<MeshFilter>();
            filter.mesh = mesh;
            
            MeshRenderer meshRen = go.AddComponent<MeshRenderer>();
            
            meshRen.material = meshRender[i].material;
            meshRen.material.shader = ghostShader;//設置xray效果
            meshRen.material.SetFloat("_Intension", Intension);//顏色強度傳入shader中
            
            go.transform.localScale = meshRender[i].transform.localScale;
            go.transform.position = meshRender[i].transform.position;
            go.transform.rotation = meshRender[i].transform.rotation;
            
            item.meshRenderer = meshRen;
        }
    }
}

 

GhostItem

using System;
using UnityEngine;

public class GhostItem : MonoBehaviour
{
    //持續時間
    public float duration;
    //銷毀時間
    public float deleteTime;
    
    public MeshRenderer meshRenderer;
    
    void Update(){
        float tempTime = deleteTime - Time.time;
        if (tempTime <= 0) {//到時間就銷毀
            GameObject.Destroy (this.gameObject);
        } else if(meshRenderer.material){
            float rate = tempTime/duration;//計算生命周期的比例
            Color cal = meshRenderer.material.GetColor("_RimColor");
            cal.a *= rate;//設置透明通道
            meshRenderer.material.SetColor("_RimColor", cal);
        }
        
    }
}

 

最后的話

這篇就寫完啦,這種實現方式的優點就是殘影可以實時捕捉動作,比較動態。缺點是比較消耗性能,頻繁創建網格,相當於要多渲染那么多個人物。

如果有好的的優化思路,歡迎在下面評論


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM