Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Nominations have been announced for this years Unity Awards. Celebrate the wonderful projects made by your peers this year and get voting! Vote here!
    Dismiss Notice
  6. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

CommandBuffer.Blit() - Unexpected behaviour

Discussion in 'General Graphics' started by Freaking-Pingo, Dec 6, 2018.

  1. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    289
    Hi Uniteers

    I wish to do some post-processing effects in Unity 2018.2.14f1. I can't get
    CommandBuffer.Blit()
    to work because I am seeing unexpected behaviours.
    1. When using
      CommandBuffer.Blit(src, dest)
      , the result is upside-down.
      Code (CSharp):
      1. int texID = Shader.PropertyToID("_SomeProperty");
      2. cameraBuffer.GetTemporaryRT(texID, camera.pixelWidth, camera.pixelHeight);
      3. cameraBuffer.Blit(BuiltinRenderTextureType.CameraTarget, texID);
      4. cameraBuffer.Blit(texID, BuiltinRenderTextureType.CameraTarget);

    2. When using
      CommandBuffer.Blit(src, dest, new Material(Shader.Find("Hidden/BlitCopy")));
      the
      "_MainTex"
      property is not populated
    Code (CSharp):
    1.  int texID = Shader.PropertyToID("_SomeProperty");
    2. cameraBuffer.GetTemporaryRT(texID, camera.pixelWidth, camera.pixelHeight);
    3. cameraBuffer.Blit(BuiltinRenderTextureType.CameraTarget, texID , new Material(Shader.Find("Hidden/BlitCopy")));
    4. cameraBuffer.Blit(texID, BuiltinRenderTextureType.CameraTarget);

    Solution attempts:
    • For the upside-down error I tried setting
      camera.forceIntoRenderTexture = true;
      and applying HDR button on the Camera
    • For the missing
      "_MainTex"
      property I have tried adding a global texture property
      "_MainTex"
      :

    Code (CSharp):
    1.  int texID = Shader.PropertyToID("_SomeProperty");
    2. cameraBuffer.GetTemporaryRT(texID, camera.pixelWidth, camera.pixelHeight);
    3. cameraBuffer.SetGlobalTexture("_MainTex", BuiltinRenderTextureType.CameraTarget);
    4. cameraBuffer.Blit(BuiltinRenderTextureType.CameraTarget, texID , new Material(Shader.Find("Hidden/BlitCopy")));
    5. cameraBuffer.Blit(texID, BuiltinRenderTextureType.CameraTarget);

    I have found two threads with similar issues:
    @AaronBrownLM: https://forum.unity.com/threads/com...er-blit-with-internal_blitcopy-shader.432699/
    @Simod: https://forum.unity.com/threads/how-to-use-hidden-blitcopy-shader.447041/

    Anyone with a solution or idea of why this is happening?
     
    Last edited: Dec 6, 2018
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    5,354
    Because Direct3D is weird and flips render targets upside down when MSAA is enabled.

    My understanding of what's happening is Unity has internal code that tries to keep track of if the render buffer is flipped or not so it knows to invert it before showing it on screen. However when you use Blit() it assumes you've flipped it and doesn't invert it anymore. The default blit (which uses "Hidden/BlitCopy" already) doesn't have any of that code and just directly copies the contents.

    This information is conveniently hidden, er, I mean documented here:
    https://docs.unity3d.com/Manual/SL-PlatformDifferences.html
     
    AcidArrow likes this.
  3. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    289
    I did not know of this ressource, thank you for showing it.

    I tried disabling MSAA from the camera, but that did not resolve the upside-down issue.

    I guess I could resolve the up-side down issue by applying a shader as the third parameter in commandBuffer.Blit() but for some reason the "_MainTex" parameter is not getting populated. I tried the fix mentioned by others but when observing it through the frame debugger the "_MainTex" is still not populated. The fix is the following code:

    Code (CSharp):
    1. int texID = Shader.PropertyToID("_SomeProperty");
    2. cameraBuffer.GetTemporaryRT(texID, camera.pixelWidth, camera.pixelHeight);
    3. cameraBuffer.SetGlobalTexture("_MainTex", BuiltinRenderTextureType.CameraTarget);
    4. cameraBuffer.Blit(BuiltinRenderTextureType.CameraTarget, texID , new Material(Shader.Find("Hidden/BlitCopy")));
    5. cameraBuffer.Blit(texID, BuiltinRenderTextureType.CameraTarget);
    Any idea of why this is happening? The bug and fix is mentioned in these threads.

    https://forum.unity.com/threads/com...internal_blitcopy-shader.432699/#post-2891602

    https://forum.unity.com/threads/com...-material-source-texture-is-incorrect.454404/

    I tried with the following code:
     
    Last edited: Dec 9, 2018
  4. Freaking-Pingo

    Freaking-Pingo

    Joined:
    Aug 1, 2012
    Posts:
    289
    Alright, so I believe to have resolved the issue. I ended up doing the following:

    Code (CSharp):
    1. int texID = Shader.PropertyToID("_MainTex");
    2. cameraBuffer.GetTemporaryRT(texID, camera.pixelWidth, camera.pixelHeight);
    3. cameraBuffer.Blit(BuiltinRenderTextureType.CameraTarget, texID);
    4. cameraBuffer.Blit(texID, BuiltinRenderTextureType.CameraTarget, new Material(Shader.Find("Hidden/BlitCopyUpsideDown")));
    I can't explain fully why this work, but I guess it has to do with the fact that the property I have populated is named "_MainTex" and therefore it is populated in the shader field "_MainTex". My assumption was that this should not be necessary, but I guess I am in the wrong.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    5,354
    I don't have an explanation for why _MainTex isn't getting populated in the general case. However if the src and dst of a blit are the same texture, only the destination will be populated since you cannot read from the texture that is the current target.