Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Sprite outline effect appears one frame later

Discussion in 'General Graphics' started by Menyus777, Oct 18, 2022.

  1. Menyus777

    Menyus777

    Joined:
    Jun 11, 2017
    Posts:
    24
    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 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
    Code (CSharp):
    1. void CreateCommandBuffer()
    2. {
    3.     _outlineMaterial = new Material(Shader.Find("Hidden/Outline Blit"));
    4.  
    5.     _outlineRenderTexture =
    6.         new RenderTexture(_targetCamera.pixelWidth, _targetCamera.pixelHeight, 24);
    7.  
    8.     int activeTex = Shader.PropertyToID("_ActiveTex");
    9.  
    10.     _outlineCommandBuffer = new CommandBuffer();
    11.     _outlineCommandBuffer.name = "Outline Buffer";
    12.  
    13.     _outlineCommandBuffer.GetTemporaryRT(
    14.             activeTex,
    15.             _targetCamera.pixelWidth,
    16.             _targetCamera.pixelHeight,
    17.             24,
    18.             FilterMode.Point,
    19.             RenderTextureFormat.ARGB32
    20.     );
    21.  
    22.     _outlineCommandBuffer.SetRenderTarget(activeTex);
    23.     _outlineCommandBuffer.ClearRenderTarget(true, true, new Color(0f, 0f, 0f, 0f));
    24.  
    25.     foreach (SpriteRenderer spriteRenderer in _spriteRenderers)
    26.         _outlineCommandBuffer.DrawRenderer(spriteRenderer, spriteRenderer.material);
    27.  
    28.     _outlineCommandBuffer.Blit(Texture2D.blackTexture, _outlineRenderTexture);
    29.     _outlineCommandBuffer.Blit(
    30.         activeTex,
    31.        _outlineRenderTexture,
    32.        _outlineMaterial,
    33.        _outlineMaterial.FindPass("Outline")
    34.     );
    35.  
    36.     _outlineCommandBuffer
    37.         .CopyTexture(_outlineRenderTexture, _outlineEffectRenderer.sprite.texture);
    38.  
    39.     _outlineCommandBuffer.ReleaseTemporaryRT(activeTex);
    40.  
    41.     _targetCamera
    42.         .AddCommandBuffer(CameraEvent.AfterImageEffects, _outlineCommandBuffer);
    43. }

    Now, everything is working fine as can be seen in this picture
    upload_2022-10-18_22-45-58.png

    However, when I start moving the object it seems like that the outline effect rendering is 1 frame behind the sprite. 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.
    Rendering bug.gif

    Am I experiencing a bug with Unity or the above solution is not viable at all for this scenario?
    (PS: This is my first time using command buffers)
     
    Last edited: Oct 24, 2022
  2. Menyus777

    Menyus777

    Joined:
    Jun 11, 2017
    Posts:
    24
    Also for some reason this bug only appears in the game view and in the built-game not in the scene view :/
     
  3. Menyus777

    Menyus777

    Joined:
    Jun 11, 2017
    Posts:
    24
    Added the command buffer at camera event BeforeForwardAlpha solved my problem.

    Code (CSharp):
    1. _targetCamera
    2.         .AddCommandBuffer(CameraEvent.BeforeForwardAlpha, _outlineCommandBuffer);