unity-game-engineshaderhlslcgshaderlab

Sprite outline effect appears one frame later


So, I have the following problem in a Unity 2019.4.36f1 fresh project. I would like to outline group of sprites with the Built-in render pipeline. For this, the developer needs to collect the SpriteRenderers it would like to group together. Then the SpriteOutliner script when initializes in OnAwake, creates another SpriteRenderer that will hold this outliner effect. After this a CommandBuffer is created (AfterImageEffects) in which

  1. We draw the collected sprites
  2. Blit a black texture to the outliner's RenderTexture
  3. Blit the drawed sprites with a specific shader to draw the outline effect
  4. Copy this texture to the spriterender

Now, everything is working fine as can be seen in this picture enter image description here

However, when I start moving the object it seems like that the outline effect rendering is one frame behind the sprite's movement. This can be clearly seen when using the frame debugger. Now, the interesting part happens when stepping with the frame debugger and moving the mouse the outline will get corrected and because of this I can not really use the frame debugger to identify what went wrong because the frame debugger will display the correct outline effect not the one seen on the below gif. enter image description here

Am I experiencing a bug with Unity or I have a bug in the above solution? (PS: This is my first time using command buffers)

Here is the CommandBuffer

void CreateCommandBuffer()
{
    _outlineMaterial = new Material(Shader.Find("Hidden/Outline Blit"));

    _outlineRenderTexture =
        new RenderTexture(_targetCamera.pixelWidth, _targetCamera.pixelHeight, 24);

    int activeTex = Shader.PropertyToID("_ActiveTex");

    _outlineCommandBuffer = new CommandBuffer();
    _outlineCommandBuffer.name = "Outline Buffer";

    _outlineCommandBuffer.GetTemporaryRT(
            activeTex,
            _targetCamera.pixelWidth,
            _targetCamera.pixelHeight,
            24,
            FilterMode.Point,
            RenderTextureFormat.ARGB32
    );

    _outlineCommandBuffer.SetRenderTarget(activeTex);
    _outlineCommandBuffer.ClearRenderTarget(true, true, new Color(0f, 0f, 0f, 0f));

    foreach (SpriteRenderer spriteRenderer in _spriteRenderers)
        _outlineCommandBuffer.DrawRenderer(spriteRenderer, spriteRenderer.material);

    _outlineCommandBuffer.Blit(Texture2D.blackTexture, _outlineRenderTexture);
    _outlineCommandBuffer.Blit(
        activeTex,
       _outlineRenderTexture,
       _outlineMaterial,
       _outlineMaterial.FindPass("Outline")
    );

    _outlineCommandBuffer
        .CopyTexture(_outlineRenderTexture, _outlineEffectRenderer.sprite.texture);

    _outlineCommandBuffer.ReleaseTemporaryRT(activeTex);

    _targetCamera
        .AddCommandBuffer(CameraEvent.AfterImageEffects, _outlineCommandBuffer);
}

Solution

  • Inserting the command buffer on BeforeForwardAlpha solved my problem.