unity3d 实现残影特效
2016-04-29 17:18
591 查看
c#脚本 挂相机下
用到的shader
//可适应 主相机 在运动的 残影cs
using UnityEngine; using System.Collections; using System.Collections.Generic; //[ExecuteInEditMode] [RequireComponent(typeof(Camera))] public class TestMRT : MonoBehaviour { public Material testMRTMaterial = null; public RenderTexture[] mrtTex = new RenderTexture[2]; public RenderTexture[] TextureA = new RenderTexture[2]; RenderBuffer[] mrtRB = new RenderBuffer[2]; public Camera effectCame; public Texture texture0; public Texture texture1; public RenderTexture sourTexture; public RenderTexture canYanTexture; public RenderTexture curTexture; public Material CreateCanYinMaterial; void Start() { TextureA[0] = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); TextureA[1] = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); Shader testMRT = Shader.Find("Custom/TestMRT"); if (testMRT.isSupported) testMRTMaterial = new Material(testMRT); else return; Shader CanyanCreat = Shader.Find("Custom/CanyanCreat"); if (CanyanCreat.isSupported) CreateCanYinMaterial = new Material(CanyanCreat); else return; StartCoroutine(ShowEffect()); } void OnRenderImage(RenderTexture source, RenderTexture destination) { sourTexture = source; //Graphics.Blit(sourTexture, source, testMRTMaterial, 0); if (!testMRTMaterial.shader.isSupported) { Graphics.Blit(source, destination); return; } //Show the result testMRTMaterial.SetTexture("_Tex0", sourTexture); testMRTMaterial.SetTexture("_Tex1", curTexture); //Graphics.Blit(curTexture, destination, testMRTMaterial, 2); Graphics.Blit(null, destination, testMRTMaterial, 2); } Dictionary<Renderer, Material[]> rendToMat = new Dictionary<Renderer, Material[]>(); void Clear(RenderTexture destTexture) { Graphics.SetRenderTarget(destTexture); GL.PushMatrix(); GL.Clear(true, true, Color.white); GL.PopMatrix(); } void InitCanYanTexture() { playRoot = GameObject.Find("Players").transform; Transform[] chs = playRoot.GetComponentsInChildren<Transform>(); int effectLayer = LayerMask.NameToLayer("ImageEffect"); for (int i = 0, iMax = chs.Length; i < iMax; i++) { chs[i].gameObject.layer = effectLayer; Renderer red = chs[i].GetComponent<Renderer>(); if (red != null) { if (red.sharedMaterial.shader.name == "Toon/Basic" || red.gameObject.name == "m_battle_box01") { Material newMt = GameObject.Instantiate(CreateCanYinMaterial) as Material; newMt.mainTexture = red.sharedMaterial.mainTexture; rendToMat.Add(red, new Material[] { red.sharedMaterial, newMt }); } else Debuger.Log(red.sharedMaterial.shader.name); } } effectCame.cullingMask = 1 << effectLayer; canYanTexture = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); effectCame.targetTexture = canYanTexture; } void CreateCanYanTexture() { int colorId = Shader.PropertyToID("_Color"); Shader sd = CreateCanYinMaterial.shader; float i = 0; foreach (KeyValuePair<Renderer, Material[]> pair in rendToMat) { i += 1f; Renderer rd = pair.Key; rd.sharedMaterial = rendToMat[rd][1]; rd.sharedMaterial.SetColor(colorId, new Color(0, 0, 1,0.7f+0.1f*i)); } //GL.Clear(true, true, Color.clear); effectCame.Render(); foreach (KeyValuePair<Renderer, Material[]> pair in rendToMat) { Renderer rd = pair.Key; rd.sharedMaterial = rendToMat[rd][0]; } } private Transform playRoot; IEnumerator ShowEffect() { InitCanYanTexture(); int ii = 0; while(true) { CreateCanYanTexture(); yield return new WaitForSeconds(0.01f); int a = ii % 2;//0;// int b = ++ii % 2;//1;// curTexture = TextureA[a]; Graphics.SetRenderTarget(curTexture); GL.Clear(false, false, Color.clear); testMRTMaterial.SetTexture("_Tex0", sourTexture); testMRTMaterial.SetTexture("_Tex1", TextureA[b]); testMRTMaterial.SetTexture("_MainTex", canYanTexture); GL.PushMatrix(); GL.LoadOrtho(); testMRTMaterial.SetPass(1); //Pass 0 outputs 2 render textures. GL.Begin(GL.QUADS); GL.TexCoord2(0.0f, 0); GL.Vertex3(0.0f, 0.0f, 0.1f); GL.TexCoord2(1.0f, 0); GL.Vertex3(1.0f, 0.0f, 0.1f); GL.TexCoord2(1.0f, 1); GL.Vertex3(1.0f, 1.0f, 0.1f); GL.TexCoord2(0.0f, 1); GL.Vertex3(0.0f, 1.0f, 0.1f); GL.End(); GL.PopMatrix(); } } }
用到的shader
Shader "Custom/CanyanCreat" { Properties { _MainTex ("", 2D) = "" {} _Color ("Main Color", Color) = (1,1,1,1) } CGINCLUDE #include "UnityCG.cginc" struct v2f { float4 pos : POSITION; float2 uv : TEXCOORD0; }; uniform float4 _Color; sampler2D _MainTex; v2f vert( appdata_img v ) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.texcoord.xy; return o; } float4 fragCanYenCreate(v2f pixelData) : COLOR0 { float4 col1 = tex2D(_MainTex, pixelData.uv);//上一帧的累加图 //float4 col = _Color.a*(col1*0.8f+_Color*(1 - col1.a)); float4 col = _Color+col1; col.a = _Color.a;//1.0f;//0.1f; return col; } ENDCG Subshader { Pass { ZTest Always Cull Off ZWrite Off Fog { Mode off } //Blend one zero CGPROGRAM #pragma glsl #pragma fragmentoption ARB_precision_hint_fastest #pragma vertex vert #pragma fragment fragCanYenCreate #pragma target 3.0 ENDCG } } Fallback off }
Shader "Custom/TestMRT" { Properties { _MainTex ("", 2D) = "" {} } CGINCLUDE #include "UnityCG.cginc" struct v2f { float4 pos : POSITION; float2 uv : TEXCOORD0; }; struct PixelOutput { float4 col0 : COLOR0; float4 col1 : COLOR1; }; sampler2D _MainTex; sampler2D _Tex0; sampler2D _Tex1; v2f vert( appdata_img v ) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.texcoord.xy; return o; } //可以返回多个颜色,对应的 //public static void SetRenderTarget(RenderBuffer[] colorBuffers, RenderBuffer depthBuffer); 可用多个buff接受 //Graphics.SetRenderTarget(mrtRB, mrtTex[0].depthBuffer); PixelOutput fragTestMRT(v2f pixelData) { PixelOutput o; o.col0 = float4(1.0f, 0.0f, 0.0f, 1.0f); o.col1 = float4(0.0f, 1.0f, 0.0f, 1.0f); return o; } float4 fragCanYenAdd(v2f pixelData) : COLOR0 { //float4 col0 = tex2D(_Tex0, pixelData.uv);//当前场景原图 float4 col1 = tex2D(_Tex1, pixelData.uv);//上一帧的累加残影图 float4 colM = tex2D(_MainTex, pixelData.uv);//当前场景新的残影图原图,a通道存放 衰减系数这样就可以控制 残影的长度 float4 col; //col = colM + col1*(1 - colM)*0.9f;//通过*0.9f的衰减系数,控制残影销毁 col.rgb = colM.rbg + col1.rgb*(1 - colM.rgb)*0.9; //col.a = colM.a + col1.a; return col; } float4 fragCanYenBind(v2f pixelData) : COLOR0 { float2 uuv = float2(pixelData.uv.x,1- pixelData.uv.y); float4 col0 = tex2D(_Tex0, uuv);//当前场景原图 float4 col1 = tex2D(_Tex1, pixelData.uv);//上一帧的累加残影图 float4 col; col = col0 + col1*(1 - col0.a); return col; } ENDCG Subshader { Pass { ZTest Always Cull Off ZWrite Off Fog { Mode off } CGPROGRAM #pragma glsl #pragma fragmentoption ARB_precision_hint_fastest #pragma vertex vert #pragma fragment fragTestMRT #pragma target 3.0 ENDCG } Pass { ZTest Always Cull Off ZWrite Off Fog { Mode off } //Blend one zero CGPROGRAM #pragma glsl #pragma fragmentoption ARB_precision_hint_fastest #pragma vertex vert #pragma fragment fragCanYenAdd #pragma target 3.0 ENDCG } Pass { ZTest Always Cull Off ZWrite Off Fog { Mode off } //Blend one zero CGPROGRAM #pragma glsl #pragma fragmentoption ARB_precision_hint_fastest #pragma vertex vert #pragma fragment fragCanYenBind #pragma target 3.0 ENDCG } } Fallback off }
//可适应 主相机 在运动的 残影cs
using UnityEngine; using System.Collections; using System.Collections.Generic; //[ExecuteInEditMode] [RequireComponent(typeof(Camera))] public class TestMRT : MonoBehaviour { public Material testMRTMaterial = null; public RenderTexture[] mrtTex = new RenderTexture[2]; public RenderTexture[] TextureA = new RenderTexture[2]; RenderBuffer[] mrtRB = new RenderBuffer[2]; public Camera effectCame; public Texture texture0; public Texture texture1; public RenderTexture sourTexture; public RenderTexture canYanTexture; public RenderTexture curTexture; public Material CreateCanYinMaterial; void Start() { TextureA[0] = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); TextureA[1] = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); Shader testMRT = Shader.Find("Custom/TestMRT"); if (testMRT.isSupported) testMRTMaterial = new Material(testMRT); else return; Shader CanyanCreat = Shader.Find("Custom/CanyanCreat"); if (CanyanCreat.isSupported) CreateCanYinMaterial = new Material(CanyanCreat); else return; StartCoroutine(ShowEffect()); } void OnRenderImage(RenderTexture source, RenderTexture destination) { sourTexture = source; //Graphics.Blit(sourTexture, source, testMRTMaterial, 0); if (!testMRTMaterial.shader.isSupported) { Graphics.Blit(source, destination); return; } //Show the result testMRTMaterial.SetTexture("_Tex0", sourTexture); testMRTMaterial.SetTexture("_Tex1", curTexture); //Graphics.Blit(curTexture, destination, testMRTMaterial, 2); Graphics.Blit(null, destination, testMRTMaterial, 2); } Dictionary<Renderer, Material[]> rendToMat = new Dictionary<Renderer, Material[]>(); void Clear(RenderTexture destTexture) { Graphics.SetRenderTarget(destTexture); GL.PushMatrix(); GL.Clear(true, true, Color.white); GL.PopMatrix(); } void InitCanYanTexture() { //effectCame; GameObject cameObj = new GameObject("effectCame"); cameObj.transform.parent = Camera.main.gameObject.transform; cameObj.transform.localPosition = Vector3.zero; effectCame = cameObj.AddComponent<Camera>(); effectCame.CopyFrom(Camera.main); effectCame.clearFlags = CameraClearFlags.SolidColor; effectCame.backgroundColor = Color.clear; effectCame.enabled = false; if (playRoot == null) if (GameObject.Find("Players")) playRoot = GameObject.Find("Players").transform; if (playRoot == null) playRoot = GameObject.Find("GameOnly").transform.FindChild("SceneParent/PlayerRoot"); Transform[] chs = playRoot.GetComponentsInChildren<Transform>(); int effectLayer = LayerMask.NameToLayer("ImageEffect"); for (int i = 0, iMax = chs.Length; i < iMax; i++) { chs[i].gameObject.layer = effectLayer; Renderer red = chs[i].GetComponent<Renderer>(); if (red != null) { if (red.sharedMaterial.shader.name == "Toon/Basic" || red.gameObject.name == "m_battle_box01"|| red is SkinnedMeshRenderer) { Material newMt = GameObject.Instantiate(CreateCanYinMaterial) as Material; newMt.mainTexture = red.sharedMaterial.mainTexture; rendToMat.Add(red, new Material[] { red.sharedMaterial, newMt }); } else Debuger.Log(red.sharedMaterial.shader.name); } } effectCame.cullingMask = 1 << effectLayer; canYanTexture = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB32); effectCame.targetTexture = canYanTexture; camePos = Camera.main.transform.position; tarPos = tarObj.position; ccpos = Camera.main.transform.position - tarObj.position; } void CreateCanYanTexture() { int colorId = Shader.PropertyToID("_Color"); Shader sd = CreateCanYinMaterial.shader; float i = 0; foreach (KeyValuePair<Renderer, Material[]> pair in rendToMat) { i += 1f; Renderer rd = pair.Key; rd.sharedMaterial = rendToMat[rd][1]; rd.sharedMaterial.SetColor(colorId, new Color(0, 0, 1,0.7f+0.1f*i)); } //GL.Clear(true, true, Color.clear); effectCame.Render(); foreach (KeyValuePair<Renderer, Material[]> pair in rendToMat) { Renderer rd = pair.Key; rd.sharedMaterial = rendToMat[rd][0]; } } public Transform tarObj; Vector3 camePos = Vector3.zero; Vector3 tarPos = Vector3.zero; Vector3 ccpos = Vector3.zero; void Update() { //Camera.main.transform.position = tarObj.position + ccpos; } private Transform playRoot; IEnumerator ShowEffect() { InitCanYanTexture(); int ii = 0; Vector4 cameMove = Vector4.zero; while(true) { CreateCanYanTexture(); if (camePos != Camera.main.transform.position) { Vector3 newTarPos = tarObj.position; Vector2 pm1 = effectCame.WorldToScreenPoint(tarPos); Vector2 pm2 = effectCame.WorldToScreenPoint(newTarPos); tarPos = newTarPos; camePos = effectCame.transform.position; cameMove = pm2 - pm1; } cameMove.z = Screen.width; cameMove.w = Screen.height; yield return new WaitForSeconds(0.01f); int a = ii % 2;//0;// int b = ++ii % 2;//1;// curTexture = TextureA[a]; Graphics.SetRenderTarget(curTexture); GL.Clear(false, false, Color.clear); GL.PushMatrix(); GL.LoadOrtho(); testMRTMaterial.SetTexture("_Tex0", sourTexture); testMRTMaterial.SetTexture("_Tex1", TextureA[b]); testMRTMaterial.SetTexture("_MainTex", canYanTexture); testMRTMaterial.SetVector("_cameMove", cameMove); testMRTMaterial.SetPass(1); //Pass 0 outputs 2 render textures. GL.Begin(GL.QUADS); GL.TexCoord2(0.0f, 0); GL.Vertex3(0.0f, 0.0f, 0.1f); GL.TexCoord2(1.0f, 0); GL.Vertex3(1.0f, 0.0f, 0.1f); GL.TexCoord2(1.0f, 1); GL.Vertex3(1.0f, 1.0f, 0.1f); GL.TexCoord2(0.0f, 1); GL.Vertex3(0.0f, 1.0f, 0.1f); GL.End(); GL.PopMatrix(); } } }
相关文章推荐
- unity3D 涂涂乐使用shader实现上色效果
- Unity5打包assetbundle
- Vuforia 在Unity 中失焦的问题
- 使用Unity3D 5.3.4 模仿2D游戏 FlappyBird(一)
- unity安装记录
- Unity 编辑器列表控件
- 在unity3d中用EasyTouch的操纵杆控制相对于不同角度的摄像机的第三人物视角的相对位移的代码段
- 简要分析unity3d中剪不断理还乱的yield
- 基于unity的飞行模拟设计
- unity发射弓箭轨迹的实现
- Shader之学习笔记三
- Unity3D 5.3.4的UGUI编程
- unity编译时自动结束项目运行
- unity渲染层级关系小结
- Unity3d碰撞检测中碰撞器与触发器的区别
- Unity3D中世界坐标转换到NGUI坐标
- Unity世界坐标与屏幕坐标之间如何转换
- Unity ScreentoWorldPoint中的z坐标说明
- Unity3D的几种坐标系
- unity3D 彻底搞懂 Quaternion LookRotation FromToRotation SetLookRotation方法