Search Unity

Multiple Render Target (MRT) questions

Discussion in 'Shaders' started by kebrus, Aug 14, 2014.

  1. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    There's little documentation and examples about this subject and i can't seem to find what i'm looking for, which got me thinking after a few tries that maybe what i thought about MRT is all wrong

    I want to be able to render my scene to a target and some other information to another target in just one pass

    1. Is it possible?
    2. Should i use RenderWithShader with a second camera or SetReplacementShader with my main camera?
    3. Is the replacement shader the one responsible to render the two colors outputs?
    4. Do i need to use a GL.Quad to use MRT?

    I'm extremely confused about this subject, i was able to create a secondary camera and use renderwithshader with a shader that would render the color in one target and the alpha in another but the draw calls exploded, 2 draw calls per object to be precise, if i just use setreplacementshader in the main camera i get nothing and if i use a GL.Quad without replacement shaders i can renders colors to it but not my scene using this example: http://forum.unity3d.com/threads/mrt-example.152050/#post-1118431

    Could anyone point some directions? I thought the whole purpose in using MRT was to save draw calls by rendering various information at the same time to later use them for screen effects
     
  2. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
    I use MRTs in my code. I just draw a quad and use a specialised output structure.

    https://github.com/brianasu/unitygi/blob/master/Assets/simple voxelisation/Scripts/LightBleeding.cs

    private void RenderMRT(RenderBuffer[] renderBuffers, RenderBuffer depthBuffer)
    {

    Graphics.SetRenderTarget(renderBuffers, depthBuffer);
    GL.Clear(false, true, Color.clear);
    GL.PushMatrix();
    GL.LoadOrtho();
    VoxelMaterial.SetPass(6);
    GL.Begin(GL.QUADS);
    GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(0.0f, 0.0f, 0.1f);
    GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(1.0f, 0.0f, 0.1f);
    GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(1.0f, 1.0f, 0.1f);
    GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.1f);
    GL.End();
    GL.PopMatrix();
    }

    Then i have a fragment shader

    https://github.com/brianasu/unitygi/blob/master/Assets/simple voxelisation/Shader/Voxelize.shader


    struct COL_OUTPUT
    {
    float4 albedo : COLOR0;
    float4 depthNormals : COLOR1;​
    };


    COL_OUTPUT fragDownsampleRSM(v2f IN)
    {
    COL_OUTPUT o;
    .....
    return o;​
    }
     
    mouurusai likes this.
  3. kebrus

    kebrus

    Joined:
    Oct 10, 2011
    Posts:
    415
    I tried the quad method, i couldn't get it to render my scene in a different target... say you want render the scene as is in a target and some other information that comes from the object in another, can i do that with the quad method? i'll definitely try it out, also i notice you are running the code in LateUpdate, i wasn't expecting that, do you have additional draw calls for doing like this?
     
  4. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
    Sorry didn't read your post carefully. I did a quick test and it seems to work. I think the problem might be is that it doesn't seem to work with deferred rendering. You have to switch it to forward rendering. I'm not sure why but I haven't looked yet. I've copy pasted my test code. Hope this helps

    Test Code
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class TestMRT : MonoBehaviour {
    5.  
    6.     public Shader mrtShader;
    7.  
    8.     Camera ppCamera;
    9.     RenderTexture texA;
    10.     RenderTexture texB;
    11.  
    12.     void OnEnable()
    13.     {
    14.         texA = RenderTexture.GetTemporary(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
    15.         texB = RenderTexture.GetTemporary(Screen.width, Screen.height, 16, RenderTextureFormat.ARGB32);
    16.     }
    17.  
    18.     void OnDisable()
    19.     {
    20.         RenderTexture.ReleaseTemporary(texA);
    21.         RenderTexture.ReleaseTemporary(texB);
    22.     }
    23.    
    24.     void Update()
    25.     {
    26.         if(ppCamera == null)
    27.         {
    28.             var go = new GameObject("PP Camera", typeof(Camera));
    29.             ppCamera = go.camera;
    30.  
    31.             ppCamera.enabled = false;
    32.  
    33.         }
    34.         ppCamera.CopyFrom(camera);
    35.         ppCamera.clearFlags = CameraClearFlags.SolidColor;
    36.         ppCamera.backgroundColor = Color.black;
    37.  
    38.         ppCamera.SetTargetBuffers(new RenderBuffer [] { texA.colorBuffer, texB.colorBuffer }, texA.depthBuffer);
    39.         ppCamera.RenderWithShader(mrtShader, "RenderType");
    40.     }
    41.  
    42.     void OnGUI()
    43.     {
    44.         GUI.DrawTexture(new Rect(0, 0, 256, 256), texA);
    45.         GUI.DrawTexture(new Rect(256, 0, 256, 256), texB);
    46.     }
    47. }
    My Shader
    Code (CSharp):
    1. Shader "Hidden/Test MRT" {
    2.  
    3. CGINCLUDE
    4. #include "UnityCG.cginc"
    5. #include "TerrainEngine.cginc"
    6.  
    7. struct v2f {
    8.     float4 pos : POSITION;
    9. };
    10.  
    11. struct COL_OUTPUT
    12. {
    13.     float4 albedoA : COLOR0;
    14.     float4 albedoB : COLOR1;
    15. };
    16.  
    17. v2f vert( appdata_base v ) {
    18.     v2f o;
    19.     o.pos = mul(UNITY_MATRIX_MVP, v.vertex);  
    20.     return o;
    21. }
    22.  
    23. COL_OUTPUT fragMRT(v2f i)
    24. {
    25.     COL_OUTPUT o;
    26.     o.albedoA = float4(1, 0, 0, 1);
    27.     o.albedoB = float4(0, 1, 0, 1);
    28.     return o;
    29. }
    30.  
    31. ENDCG
    32.  
    33. Subshader
    34. {
    35.     Tags {"RenderType"="Opaque"}
    36.     Pass {
    37.         Fog { Mode Off }
    38.  
    39.         CGPROGRAM
    40.         #pragma vertex vert
    41.         #pragma fragment fragMRT
    42.         ENDCG
    43.     }
    44. }
    45.  
    46. Fallback Off
    47. }