Search Unity

Drawing to back buffer directly

Discussion in 'General Graphics' started by victor_apihtin, Jun 18, 2021.

  1. victor_apihtin

    victor_apihtin

    Unity Technologies

    Joined:
    Mar 2, 2021
    Posts:
    28
    So I am trying to systemize my understanding behind Camera.targetTexture in built-in render pipeline.

    Ideally, I want all my cameras to draw sequencially into a render texture with a lower resolution. After that the last camera would make an extra blit of the result into the back buffer.

    I think this is a fair wish, because it is intutive and simple enough. Documentation [https://docs.unity3d.com/ScriptReference/Graphics.Blit.html] mentions that in order to blit into the back buffer, one needs to Blit into null, but only if the main camera does not have targetTexture assigned. If one does, then one needs to set it to null before calling Blit. Assuming also that it needs to be set to the render texture again after the blit.

    It doesn't menton when though. And why is it the main camera that decides. Having this code on my UI camera (with MainCamera label) doesn't do anything on the screen

    Code (CSharp):
    1.    
    2. private void OnPostRender()
    3. {
    4.     Camera.main.targetTexture = null;
    5.     Graphics.Blit(m_renderBuffer, dest: null);
    6.     Camera.main.targetTexture = m_renderBuffer;
    7. }
    The draw call is drawing into <No name>
    upload_2021-6-18_12-15-41.png

    Which would be the back buffer, but only
    IF the camera either did not have a target texture assigned in inspector and my RT is assigned in OnPreRender() and nullified in OnPostRender() ,
    OR the RT is set in inspector, but the target texture is set to null in OnRenderImage() and manually blitted to dest:null right after and set back to my RT in OnPostRender,
    OR having an extra camera that does entirely nothing, but blitting to the back buffer.

    Otherwise, like having all cameras drawing into RT, and do a manual blit into null, it would show the drawcall to <No name> but it doesn't actually draw it.

    1. In the first scenario the camera is doing a GrabPass + Blit that draws my RT into its temporary render texture, drawing UI elements into it, and then blitting into the back buffer. GrabPass happens because the clear flag is set to Don't clear, thus it implicitelly wants whatever drawn prior. That is 2 unnecessary draw calls.

    upload_2021-6-18_13-11-47.png

    2. The second scenario suffers of GrabPass too, it's only that the blit to backbuffer is being called manually

    upload_2021-6-18_14-8-59.png

    3. The third options seems to be the best for the job considering previous choises, since the last camera has the binding to the back buffer, and it doesnt need to draw anything - thus no need for implicit temporary textures. And yet for some reason this is impossible to rig. The drawcall to <None> is there, but it doesnt actually draw. It is only if it had a command buffer on doing the following:

    Code (CSharp):
    1.  
    2. m_blitToBackBufferCmd = new CommandBuffer { name = "Blit to Back buffer" };
    3. var backBuffer = new RenderTargetIdentifier(Display.main.colorBuffer);
    4. m_blitToBackBufferCmd.Blit(m_renderBuffer, backBuffer);
    5. m_camera.AddCommandBuffer(CameraEvent.AfterEverything, m_blitToBackBufferCmd);
    6.  
    It is working, but again, because there is no .targetTexture assigned, it would either make a GrabPass (with Don't clear flags), or little better but far from perfect. Having Solid color clear flag would request a temporary texture, clear it, and blit it empty to back buffer, after which my command buffer draws the final RT into back buffer

    upload_2021-6-18_15-26-44.png


    SO
    At this point I feel like I am out of options. Having an empty .targetTexture on camera is the only way i could manage something into the back buffer. It has an overhead of either GrabPass or a manual extra blit from RT to the camera's temp texture. So maybe I am missing something, and there is still a hope, like native code or something
     
    Last edited: Jun 20, 2021
  2. victor_apihtin

    victor_apihtin

    Unity Technologies

    Joined:
    Mar 2, 2021
    Posts:
    28
    Holy damn, if one in 2021.1 sets up .targetTexture in Update(), and sets it back to null in OnPostRender(), the camera renders twice, first into RT, the other time into temp texture
    upload_2021-6-19_13-57-16.png
     
  3. ZenTeapot

    ZenTeapot

    Joined:
    Oct 19, 2014
    Posts:
    65
    Bump this. Same question.