MRT's and surface shaders

Discussion in 'Developer Preview' started by Chickenlord, Jan 22, 2012.

  1. Chickenlord

    Chickenlord Member


    i've got a simple and quick question. As 3.5 comes with MRT support, how can one write to the other render targets in surface shaders? Is it possible at all?

  2. Chickenlord

    Chickenlord Member

  3. jemast

    jemast Member

    Theoretically, I think you cannot switch or pick render targets from shaders (I'm no expert on the subject at all so take that with a grain of salt).

    Though you can do this from script with methods such as:

    Code (csharp):

    Calling these methods before rendering passes that require separate/additional render targets should do the trick (for cameras, I'd try calling this in OnPreRender and OnPostRender methods but that's just a shot in the dark, haven't tried at all).

    By the way, they're both documented in the offline beta scripting reference (you can access it from Unity's Help menu).

    Edit: Actually, the Graphics.SetRenderTarget allows settings multiple render targets in one pass and the docs mention that "The function call with colorBuffers array enables techniques that use Multiple Render Targets (MRT), where fragment shader can output more than one final color.". If you cannot get these multiple outputs from surface shader, a last resort method may be to use "open compiled shader" method from one of your surface shaders where you want to use MRT and start from there.

    Edit2: Okay, after educating myself on the subject, it seems there are no documented feature for what you're looking for in surface shaders. Looks like you could file a feature request.
    Last edited: Jan 28, 2012
  4. Cameron.

    Cameron. Member

    Having MRT output for surface shaders would be nice, coupled with the newly included GL MIN/MAX blend modes would allow for some really nice methods of building info about the scene for much more complex post effects.
  5. brianasu

    brianasu Member

    Probably use Graphics.SetRenderTarget(RenderBuffer[] ...
    Then in your shader besides outputting a single Color you would output a custom struct
    struct COL_OUTPUT
    float4 Col0 : COLOR0;
    float4 Col1 : COLOR1;
    float4 Cor2 : COLOR2;

    and in your shader

    COL_OUTPUT frag(v2f i)
    ... shader stuff
    o.col1 = something;
    o.col2 = something;
    o.col3 = something;
    return o;
  6. Chickenlord

    Chickenlord Member

    Well, if i haven't missed anything this is not possible to achieve with surface shaders. Of course it's possible to return multiple results in standard cg vert/frag shaders, but i don't think anybody wants to convert all the surface shaders to standard ones using debug and in addition this would kill all the nice things surface shaders have to offer...
  7. ole

    ole Unity programmer

    as far as i know there is no easy way to make it work with surface shaders atm. but there is a way: uncollapse them via #pragma debug and then write for the various passes to the different buffers, just as brianasu suggested.

    EDIT: saw your post too late, but yes, for the time being MRT support mostly addresses possible post and custom FX speed-ups.
  8. romeo_ftv

    romeo_ftv Member

    you plan to implement the builtin imagespace motion blur effect?