CameraのRenderTextureはClearFlagsで制御できるけど自分で用意したRenderTextureにいわゆるTrailEffect(GhostEffect)的なのをしたくて、Clearせずに前のFramebufferを徐々に消してくみたいなことをしたかったんだけど中々できずにうーんと悩んでたらCameraのOnRenderImage内でsrc,distに対してRenderTexture保持しておくってサンプルを見つけたのでこちらを元にCamera外で使えるよに書き直す。
要するにここにあるように一度別Textureに書き出さないと保持されないらしい。なんでや。
空のGameObjectに以下をattache.
public class GhostEffect : MonoBehaviour { private Vector2 res = new Vector2(1920, 1080); private RenderTexture rt0, rt1, rt2; private Material drawMat, ghostMat; [Range(0, 0.9999f)] public float intensity; public bool isDebug = true; void Start() { Shader sdr = Shader.Find("Hidden/DrawingLine"); drawMat = new Material(sdr); Shader sdr2 = Shader.Find("Hidden/Ghosting"); ghostMat = new Material(sdr2); rt0 = new RenderTexture((int) res.x, (int) res.y, 0); rt1 = new RenderTexture((int) res.x, (int) res.y, 0); rt2 = new RenderTexture((int) res.x, (int) res.y, 0, GraphicsFormat.R16G16B16A16_SFloat); } void Update() { //drawing Line to src Graphics.Blit(rt0, rt0, drawMat); //drawing output ghostMat.SetTexture("_nowTex", rt0); ghostMat.SetTexture("_preTex", rt2); ghostMat.SetFloat("_Intensity", intensity); Graphics.Blit(rt0, rt1, ghostMat); //buffer copy Graphics.Blit(rt1, rt2); } void OnGUI() { if (isDebug) { Graphics.DrawTexture(new Rect(0, 0, (int) res.x, (int) (res.y * 0.5)), rt0); Graphics.DrawTexture(new Rect(0, (int) (res.y * 0.5)+10, (int) res.x, (int) (res.y * 0.5)), rt2); } } }
最初のdrawMatでrt0に動く線書いて、
Graphics.Blit(rt0, rt1, ghostMat); でrt1に合成。
次のFrameで使うための結果をrt2に保持。って感じ。
blending用のghostMatの中身
Shader "Hidden/Ghosting" { Properties { _nowTex ("Input Render Texture", 2D) = "black" {} _preTex ("prev Render Texture", 2D) = "black" {} _Intensity ("Intensity", Range (0,1)) = 0.5 } SubShader { Pass { CGPROGRAM #pragma vertex vert_img #pragma fragment frag #include "UnityCG.cginc" uniform sampler2D _nowTex; uniform sampler2D _preTex; uniform float _Intensity; float4 frag(v2f_img i) : COLOR{ float4 c1 = tex2D(_nowTex, i.uv); float4 c2 = lerp( float4(0,0,0,0), tex2D(_preTex, i.uv), _Intensity); float4 finl; if(c2.a < 0.1) finl = c1; else finl = c1 + c2; return finl; } ENDCG } } }
で、CameraのOnRenderImage使わなくてもいけた。
たぶんなんかおかしいとこがある気もするけど
初心者のうちは気にしない。←
you