Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Trail shader

Discussion in 'Shaders' started by Grhyll, Feb 8, 2017.

  1. Grhyll

    Grhyll

    Joined:
    Oct 15, 2012
    Posts:
    119
    Hi!

    I've been working for some time now on way to have objects leave a trail, and I'm reaching a point where I just don't understand what could possibly be wrong in my code.

    The principle is quite simple:
    - I use a special camera to render only the objects that should leave a trail.
    - I print them on a Trail texture that I faded a bit so that its info slowly disappears.
    - I print this texture above the view of lower cameras.

    The issue is that if I try for example to fade the trail texture by 10% before printing new info on it, I would expect my objects to have a trail of 10 instances of my "remanent" object, each one of them more transparent than the previous one, and it's not the case, it only gives me 4 instances.
    As far as I can tell, there must be something I don't understand about rendering, or the way the textures work, but I can't figure out what.

    My post effect code (set on the main camera which renders the background):
    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3.  
    4. public class RemanentPostEffect : MonoBehaviour
    5. {
    6.     public Material remanentMaterial;
    7.     public Material alphaMergeMaterial;
    8.    
    9.     public Camera remanentCamera;
    10.  
    11.     RenderTexture trailTexture;
    12.    
    13.  
    14.     void OnRenderImage(RenderTexture source, RenderTexture destination)
    15.     {
    16.         if(trailTexture == null)
    17.         {
    18.             //Create a texture to store the current trail
    19.             trailTexture = new RenderTexture(source.width, source.height, 24, RenderTextureFormat.ARGB32);
    20.             trailTexture.Create();
    21.             remanentMaterial.SetTexture("_TrailTexture", trailTexture);
    22.             remanentMaterial.SetFloat("_FrameFadeAmount", 0.1f);
    23.         }
    24.        
    25.         RenderTexture currentRemanentObjectsViewTexture = RenderTexture.GetTemporary(source.width, source.height, 24, RenderTextureFormat.ARGB32);
    26.         RenderTexture remanentObjectsWithTrailTexture = RenderTexture.GetTemporary(source.width, source.height, 24, RenderTextureFormat.ARGB32);
    27.  
    28.         //Clear those texture since they can contain some info already
    29.         RenderTexture.active = currentRemanentObjectsViewTexture;
    30.         GL.Clear(true, true, Color.clear);
    31.         RenderTexture.active = remanentObjectsWithTrailTexture;
    32.         GL.Clear(true, true, Color.clear);
    33.         RenderTexture.active = null;
    34.  
    35.         //Render view from remanent camera only
    36.         remanentCamera.targetTexture = currentRemanentObjectsViewTexture;
    37.         remanentCamera.Render();
    38.         remanentCamera.targetTexture = null;
    39.        
    40.         //Blit using the remanent material, with MainTex the current render from the remanent camera
    41.         Graphics.Blit(currentRemanentObjectsViewTexture, remanentObjectsWithTrailTexture, remanentMaterial);
    42.  
    43.         //Merge remanent objects and their trail with the source texture
    44.         alphaMergeMaterial.SetTexture("_HoverTex", remanentObjectsWithTrailTexture);
    45.         Graphics.Blit(source, destination, alphaMergeMaterial);
    46.  
    47.         //Save trail texture to use in next frame
    48.         RenderTexture.active = trailTexture;
    49.         GL.Clear(true, true, Color.clear);
    50.         RenderTexture.active = null;
    51.         Graphics.Blit(remanentObjectsWithTrailTexture, trailTexture);
    52.  
    53.         RenderTexture.ReleaseTemporary(currentRemanentObjectsViewTexture);
    54.         RenderTexture.ReleaseTemporary(remanentObjectsWithTrailTexture);
    55.     }
    56. }

    The shader I use to create the trail (generated with Shader Forge):

    Code (CSharp):
    1. // Shader created with Shader Forge v1.33
    2. // Shader Forge (c) Neat Corporation / Joachim Holmer - http://www.acegikmo.com/shaderforge/
    3.  
    4. Shader "Shader Forge/RemanentPostEffect" {
    5.     Properties {
    6.         _MainTex ("MainTex", 2D) = "white" {}
    7.         _TrailTexture ("TrailTexture", 2D) = "white" {}
    8.         _FrameFadeAmount ("FrameFadeAmount", Float ) = 0.1
    9.         [HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 1
    10.     }
    11.     SubShader {
    12.         Tags {
    13.             "IgnoreProjector"="True"
    14.             "Queue"="Transparent"
    15.             "RenderType"="Transparent"
    16.         }
    17.         Pass {
    18.             Name "FORWARD"
    19.             Tags {
    20.                 "LightMode"="ForwardBase"
    21.             }
    22.             Blend SrcAlpha OneMinusSrcAlpha
    23.             ZWrite Off
    24.            
    25.             CGPROGRAM
    26.             #pragma vertex vert
    27.             #pragma fragment frag
    28.             #define UNITY_PASS_FORWARDBASE
    29.             #include "UnityCG.cginc"
    30.             #pragma multi_compile_fwdbase
    31.             #pragma only_renderers d3d9 d3d11 glcore gles n3ds wiiu
    32.             #pragma target 3.0
    33.             uniform sampler2D _MainTex; uniform float4 _MainTex_ST;
    34.             uniform sampler2D _TrailTexture; uniform float4 _TrailTexture_ST;
    35.             uniform float _FrameFadeAmount;
    36.             struct VertexInput {
    37.                 float4 vertex : POSITION;
    38.                 float2 texcoord0 : TEXCOORD0;
    39.             };
    40.             struct VertexOutput {
    41.                 float4 pos : SV_POSITION;
    42.                 float2 uv0 : TEXCOORD0;
    43.             };
    44.             VertexOutput vert (VertexInput v) {
    45.                 VertexOutput o = (VertexOutput)0;
    46.                 o.uv0 = v.texcoord0;
    47.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex );
    48.                 return o;
    49.             }
    50.             float4 frag(VertexOutput i) : COLOR {
    51.                 float4 _MainTex_var = tex2D(_MainTex,TRANSFORM_TEX(i.uv0, _MainTex));
    52.                 float4 _TrailTexture_var = tex2D(_TrailTexture,TRANSFORM_TEX(i.uv0, _TrailTexture));
    53.                 float3 emissive = ((_MainTex_var.rgb*_MainTex_var.a)+((1.0 - _MainTex_var.a)*_TrailTexture_var.rgb));
    54.                 float3 finalColor = emissive;
    55.                 return fixed4(finalColor,max(_MainTex_var.a,saturate((_TrailTexture_var.a+(-1*_FrameFadeAmount)))));
    56.             }
    57.             ENDCG
    58.         }
    59.     }
    60.     FallBack "Diffuse"
    61. }
    I am attaching the project as unity package, in case anyone would want more precise information.
    Also attached, a screenshot of the result with alpha from the trail being reduced by 0.1 each render (disregard the second ball, I have the issue where the final render is flipped, but I haven't seriously looked into that yet).

    (For the record, I initially tried otherwise, my researches can be found here: https://forum.unity3d.com/threads/texture2d-getpixels-without-alloc.454664/ )
     

    Attached Files:

  2. Grhyll

    Grhyll

    Joined:
    Oct 15, 2012
    Posts:
    119
    Bump?
     
  3. dakshesh1010

    dakshesh1010

    Joined:
    Aug 3, 2015
    Posts:
    3
    I downloaded your package. Can I manipulate the trail size with anything? I wanted to create a similar trail in my project.