Unity残影
2016-01-29 21:59
507 查看
可以用两种方式实现残影:1. 新建一个Mesh,记录前几帧的人物的影像,然后通过后处理混合上去。2.记录前几帧的人物位置,将其传入shader中,对每个位置进行一个pass渲染。
第一方式
第二种方法(主要参考http://www.cnblogs.com/foxianmo/p/4946116.html?utm_source=tuicool&utm_medium=referral)
个人比较喜欢第一种方法,第二种方法要更改原物体的shader,要同时存在几种效果的时候会变得很麻烦
第一方式
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,要同时存在几种效果的时候会变得很麻烦
相关文章推荐
- unity下lua.txt 在notepad++中开发环境配置
- 关于如何彻底消除unity中的弹力
- Unity Profiler之Android真机调测
- 基础差不得不学啊(unity shader中的矩阵学习一)
- unity3d 项目测试笔记
- libnuma.so.1()(64bit) is needed by mysql-community-server-5.7.9-1.el6.x86_64
- unity XML 初初初入门
- Unity Shader 学习笔记(十二)漫反射卷积光照模型
- Unity5 GI与PBS渲染从用法到着色代码
- Unity优化总结
- Unity5特殊目录及其目录中脚本的编译顺序
- Unity 自动导出 AndroidStudio 项目
- unity 对象池
- 在Unity中StartCoroutine/yield return的原理和模式
- 【官方说明】Unity 5 引擎专业版和个人版解析
- Unity协程(Coroutine)原理深入剖析
- [Unity3D]脚本中Start()和Awake()的区别
- Unity3D研究院之两种方式播放游戏视频(二十五)
- Unity 安卓项目 接入调用java代码
- Unity3D 画线插件 Vectrosity_Simple2DLine