zoukankan      html  css  js  c++  java
  • 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);
            }
            
        }
    }

    最后的话

    这篇就写完啦,这种实现方式的优点就是残影可以实时捕捉动作,比较动态。缺点是比较消耗性能,频繁创建网格,相当于要多渲染那么多个人物。

    如果有好的的优化思路,欢迎在下面评论

  • 相关阅读:
    反射 Reflect Modifier 修饰符工具类
    【泛型】Generic 参数化类型 类型转换
    泛型 Generic 类型擦除引起的问题及解决方法
    注解 Annotation 简介 总结 MD
    反射 Reflect Class 基础 API MD
    【Type】类型 ParameterizedType
    Java中浮点类型的精度问题 double float
    jQuery之$.ajax()方法详解及实例
    pace.js – 加载进度条插件
    在线代码编辑、保存与运行网址推荐
  • 原文地址:https://www.cnblogs.com/lijiajia/p/6861454.html
Copyright © 2011-2022 走看看