Hello, I’m trying to create an effect that is pretty straightforward in other OpenGL platforms: drawing into an FBO and passing in the previous frame’s texture to accumulate pixel values and create a trail/shadow effect.
I’m trying to mimic this in Unity by creating a camera focused on a quad with attached shader. The camera is outputting to a render texture which is then being fed into the quad shader. The quad frag shader then outputs the sample from the render texture (fed in via “_MaintTex”):
{
// sample the render texture from the camera
fixed4 previous = tex2D(_MainTex, i.uv);
return previous;
}```
In front of the camera, I have a flat red sphere I'm moving around in front of the camera. The result looks like you see below. You can see the circle (pink because the scene lighting) is drawing into the quad, so I know the camera's render texture is making it into the shader.

My thought is this code should set all pixels to the color of the sphere and when I move it around, the pixels should remain that color (the desired effect) and leave a trail of uncleared pixels.
Can anyone help shed light on:
1) Why this approach isn't working?
2) What the better way to do this is?
Still curious to know why the above solution doesn’t work but I found a more efficient way of doing this via a compute shader if anyone else is working with a similar problem…
C# Code
void UpdateComputeShader() {
mCsTrailsHandle = trailsComputeShader.FindKernel("CsComputeTrails");
trailsComputeShader.SetFloat("trailAlpha", trailAlpha);
trailsComputeShader.SetFloat("attenuation", attenuation);
trailsComputeShader.SetVector("trailColor", trailColor);
trailsComputeShader.SetVector("texSize", new Vector4(texW, texH, 0, 0));
trailsComputeShader.SetTexture(mCsTrailsHandle, "TrailsTex", trailsRenderTex);
var userTex = ComputerVisionPipeline.Get().blurredUserMaskTexture;
trailsComputeShader.SetTexture(mCsTrailsHandle, "UserTex", userTex);
trailsComputeShader.SetVector("userTexSize", new Vector4(userTex.width, userTex.height, 0, 0));
// divide by 8 because compute shader usese 8 x 8 thread groups
trailsComputeShader.Dispatch(mCsTrailsHandle, texW / 8, texH / 8, 1);
}
Compute shader Code:
Note: UserTex is coming in from an OpenCV pipeline and has user silhouettes. TrailsTex contains the persistent trails fading away over time.
// Each #kernel tells which function to compile; you can have many kernels
#pragma kernel CsComputeTrails
RWTexture2D<float4> TrailsTex;
Texture2D<float4> UserTex;
float4 userTexSize;
float4 texSize;
float attenuation;
float trailAlpha;
float4 trailColor;
[numthreads(8,8,1)]
void CsComputeTrails (uint3 id : SV_DispatchThreadID)
{
// Map the coordinate in the output texture to the pixel of the smaller user silhouette texture
float2 normCoord = id.xy / texSize.xy;
float2 userTexCoord = userTexSize.xy * normCoord;
float4 userVal = UserTex.Load(int3(userTexCoord.xy, 0));
float4 prevVal = TrailsTex[id.xy];
prevVal = prevVal * attenuation;
// set the threshold image from black/white with alpha 1
// to all white pixels with alpha channel
userVal.a = userVal.r;
userVal.rgb = trailColor.rgb;
float4 outCol;
// Manual blending
outCol.rgb = userVal.rgb * userVal.a + prevVal.rgb * (1 - userVal.a);
outCol.a = userVal.a + prevVal.a * (1 - userVal.a);
outCol.a *= trailAlpha;
TrailsTex[id.xy] = outCol;
}