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

Cannot get very basic Camera.SetTargetBuffers to render anything

Discussion in 'General Graphics' started by LazloBonin, Sep 18, 2020.

  1. LazloBonin

    LazloBonin

    Joined:
    Mar 6, 2015
    Posts:
    795
    I'm trying to use Camera.SetTargetBuffers to render to multiple render targets at once (MRT).

    I created a very basic setup to test it in a minimal case, but nothing renders to the target buffers according to the frame debugger.

    First, the camera setup. Note that, as recommended by my research to get STB to work, I use the forward rendering path:

    upload_2020-9-18_17-37-16.png

    Next, I added a small component to the camera to call STB on start:
    upload_2020-9-18_17-38-24.png

    The script is very barebones:

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class MrtTest : MonoBehaviour
    4. {
    5.     public int renderTargetCount = 4;
    6.  
    7.     public RenderTexture[] colorTextures;
    8.  
    9.     public RenderTexture depthTexture;
    10.  
    11.     private new Camera camera => GetComponent<Camera>();
    12.  
    13.     void Start()
    14.     {
    15.         colorTextures = new RenderTexture[renderTargetCount];
    16.         var colorBuffers = new RenderBuffer[renderTargetCount];
    17.  
    18.         depthTexture = new RenderTexture
    19.         (
    20.             camera.pixelWidth,
    21.             camera.pixelHeight,
    22.             24,
    23.             RenderTextureFormat.Depth
    24.         )
    25.         {
    26.             name = "DepthCustom",
    27.             hideFlags = HideFlags.HideAndDontSave
    28.         };
    29.  
    30.         for (var i = 0; i < colorTextures.Length; i++)
    31.         {
    32.             colorTextures[i] = new RenderTexture
    33.             (
    34.                 camera.pixelWidth,
    35.                 camera.pixelHeight,
    36.                 0,
    37.                 RenderTextureFormat.ARGB32
    38.             )
    39.             {
    40.                 name = "ColorCustom" + i,
    41.                 hideFlags = HideFlags.HideAndDontSave
    42.             };
    43.  
    44.             colorBuffers[i] = colorTextures[i].colorBuffer;
    45.         }
    46.  
    47.         camera.SetTargetBuffers(colorBuffers, depthTexture.depthBuffer);
    48.     }
    49. }
    Next, I created a shader and material which I'm rendering on a 3 cubes in the scene:

    Again, the shader is as barebones as it gets. It should output red to the first RT, green to the second RT, then blue, then yellow.

    Code (CSharp):
    1. Shader "Test/MRT"
    2. {
    3.     SubShader
    4.     {
    5.         Pass
    6.         {
    7.             CGPROGRAM
    8.  
    9.             #pragma vertex vert
    10.             #pragma fragment frag
    11.             #include "UnityCG.cginc"
    12.  
    13.             struct appdata
    14.             {
    15.                 float4 vertex : POSITION;
    16.             };
    17.  
    18.             struct v2f
    19.             {
    20.                 float4 vertex : SV_POSITION;
    21.             };
    22.  
    23.             struct f2a
    24.             {
    25.                 fixed4 t0 : SV_Target0;
    26.                 fixed4 t1 : SV_Target1;
    27.                 fixed4 t2 : SV_Target2;
    28.                 fixed4 t3 : SV_Target3;
    29.             };
    30.  
    31.             v2f vert(appdata v)
    32.             {
    33.                 v2f o;
    34.                 o.vertex = UnityObjectToClipPos(v.vertex);
    35.                 return o;
    36.             }
    37.  
    38.             f2a frag(v2f i)
    39.             {
    40.                 f2a output;
    41.                 output.t0 = fixed4(1, 0, 0, 1);
    42.                 output.t1 = fixed4(0, 1, 0, 1);
    43.                 output.t2 = fixed4(0, 0, 1, 1);
    44.                 output.t3 = fixed4(1, 1, 0, 1);
    45.                 return output;
    46.             }
    47.  
    48.             ENDCG
    49.         }
    50.     }
    51. }
    52.  
    And here's the setup for each cube:
    upload_2020-9-18_17-41-0.png

    In edit mode, before I actually set the MRTs, the cubes render fine, albeit only to the default render target:

    upload_2020-9-18_17-42-55.png

    But when I enter play mode, the MRTs get assigned, and the cubes just don't render anything anymore:

    upload_2020-9-18_17-43-46.png

    Am I missing something very obvious here? I can't seem to make this work at all.
     
  2. LazloBonin

    LazloBonin

    Joined:
    Mar 6, 2015
    Posts:
    795
    Figured it out.

    It turns out that everything works, but the Frame Debugger is bugged (lol) and doesn't show the draw calls properly when SetTargetBuffers is used.

    Adding a blit to my script does actually render the proper output on screen, in this case yellow cubes, because RT3:

    Code (CSharp):
    1.     void OnRenderImage(RenderTexture source, RenderTexture destination)
    2.     {
    3.         Graphics.Blit(colorTextures[3], destination);
    4.     }
     
  3. UlfvonEschlauer

    UlfvonEschlauer

    Joined:
    Dec 3, 2014
    Posts:
    127
    Hey there!
    I have been trying to use your script to create render textures to render to, but after applying it to the Camera and setting the number of colortextures to 4 like in your example, I get a list of empty texture slots.
    My C# script is identical to yours, except that I added the 4 extra lines from your last post to it.
    What could I be missing? Is there a Unity include that I need to add or something?
    Thanks!
    Ulf

    Edit: I am dumb! It only works at runtime. LOL
     
    Last edited: Aug 17, 2021