Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Post Processing with Graphics.DrawMeshNow. Problems with render-to-texture

Discussion in 'Image Effects' started by Kumo-Kairo, Oct 17, 2017.

  1. Kumo-Kairo

    Kumo-Kairo

    Joined:
    Sep 2, 2013
    Posts:
    343
    I'm experimenting with post processing on mobile and trying to use a "Render-To-Texture and Display A Full Screen Quad" method.

    After trying a few things I decided to go with Camera.Render(). It requires a disabled camera and a manual call to this rendering routine. The code looks like this:
    Code (CSharp):
    1. // Setting up things - render texture, screen quad and disabling a camera
    2. private void Start()
    3. {
    4.     _quadMesh = CreateQuadMesh();
    5.     _renderTexture = CreateRenderTexture();
    6.  
    7.     material.SetTexture("_MainTex", _renderTexture);
    8.  
    9.     _camera = GetComponent<Camera>();
    10.     _camera.targetTexture = _renderTexture;
    11.     _camera.enabled = false;
    12. }
    13.  
    14. public void LateUpdate()
    15. {
    16.     _camera.Render();
    17. }
    18.  
    19. //After all rendering is done, display our fullscreen quad
    20. public void OnRenderObject()
    21. {
    22.     material.SetTexture("_MainTex", _renderTexture);
    23.     material.SetPass(0);
    24.     Graphics.DrawMeshNow(_quadMesh, Matrix4x4.identity);
    25. }
    But the screen turns black like nothing gets rendered into a texture:
    upload_2017-10-17_12-24-13.png

    There's a gui button just to make sure everything is rendered below final Canvas.RenderOverlays call (we'll get there in a minute)

    But an interesting thing is that if I have a Frame Debugger enabled, it renderes the scene and applies post-process effect (in this case it's just a simple color-to-grayscale conversion) like it should

    upload_2017-10-17_12-28-47.png

    When I disable Frame Debugger or don't manually check every separate pass - it doesn't render anything but black again (though draw passes are there all the time)

    Sometimes it shows passes like this, without actual rendering.
    upload_2017-10-17_12-30-20.png

    I tried using the approach described here https://forum.unity.com/threads/pos...phics-blit-onrenderimage.414399/#post-2759255
    But using GPU-powered Graphics.Blit results in a moved texture (right top quadrant of the screen) and occasional "Assertion failed (!m_CurrentCamera.IsNull())" errors in the console. It's also doesn't apply the posteffect itself, leaving the picture colored

    upload_2017-10-17_12-46-11.png
    Code (CSharp):
    1. public void OnPreRender()
    2. {
    3.     _renderTexture = RenderTexture.GetTemporary(Screen.width, Screen.height, 16);
    4.     _camera.targetTexture = _renderTexture;
    5. }
    6.  
    7. private void OnPostRender()
    8. {
    9.     _camera.targetTexture = null;
    10.     Graphics.Blit(_renderTexture, null, material, 0);
    11.     RenderTexture.ReleaseTemporary(_renderTexture);
    12. }
    Interesting thing is that if I render Graphics.DrawMeshNow inside the Coroutine with a WaitForEndOfFrame "callback", it renders the texture correctly, but on top of the Overlay Canvas:

    Code (CSharp):
    1. public void LateUpdate()
    2. {
    3.     _camera.Render();
    4. }
    5.  
    6. // Moved OnRenderObject to this coroutine
    7. private IEnumerator WaitAndRender()
    8. {
    9.     while (true)
    10.     {
    11.         yield return new WaitForEndOfFrame();
    12.  
    13.         material.SetTexture("_MainTex", _renderTexture);
    14.         material.SetPass(0);
    15.         Graphics.DrawMeshNow(_quadMesh, Matrix4x4.identity);
    16.     }
    17. }
    Quad is rendered atop of the Overlay Canvas
    upload_2017-10-17_12-35-45.png

    I tried using different Unity Messages for rendering, and I'm positive that LateUpdate + OnRenderObject should work (I've seen a working example on one of the gamedev conferences), but it only renders inside that WaitForEndOfFrame coroutine.

    I think that the problem is somewhere inside that strange Frame Debugger report with just Canvas.RenderOverlays being rendered, but I don't know how to solve this.
    I tried using Unity 5.5 and Unity 2017.2 for this - behavior is completely identical in both versions
     
    Danya232 likes this.
  2. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    245
    Not the answer to your question, but calling Graphics.Blit in the OnRenderImage does exactly what you described, what are you trying to achieve exactly?
    UPD: saw the link that you posted to the other thread, that says
    This is absolutely false. Camera renders into an internal render texture by default, no readpixels on the cpu is used.
     
    Last edited: Oct 18, 2017
  3. Kumo-Kairo

    Kumo-Kairo

    Joined:
    Sep 2, 2013
    Posts:
    343
    I needed to render a custom tesselated mesh to enable different "shockwave" or "raindrop" effects by moving vertex texture coordinates, or the vertices themselves. I also needed to be able to downscale the very first render of the camera. OnRenderImage doesn't allow 3D Scene downscaling only, it's either everything including UI or nothing

    I managed to get my setup working in the end, the problem was that I didn't know that there has to be SOME camera inside a scene, even if it doesn't render anything. It's needed so that Unity knows that I really want to actually render something to the backbuffer (if it doesn't contain any camera that renders to the backbuffer, it just doesn't send anything there)
     
    Last edited: Oct 23, 2017
  4. seb_krueger

    seb_krueger

    Joined:
    Jan 4, 2019
    Posts:
    17
    Do you have an idea how to access this render texture for the use in a native rendering pluing for example? Camera.targetTexture is null in case you didn't set something before...

    Thanks