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.

Question Extracting G-buffers for URP deferred shader

Discussion in 'Universal Render Pipeline' started by RogueStargun, Nov 22, 2021.

  1. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    272
    I'm interested in using Unity's Barracuda Machine learning platform, and one of the first steps to my project is extracting G-buffers to textures (for passing to a machine learning algorithm).

    I was wondering what the best way to do this with URP would be.
     
  2. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    272
    Perhaps it would be better to simplify the question. How do I write G-buffers to texture in URP or HDRP? I'd like to do this for every frame.
     
  3. amirebrahimi_unity

    amirebrahimi_unity

    Unity Technologies

    Joined:
    Aug 12, 2015
    Posts:
    400
    Others may chime in here, but I'll take a stab.

    IANAGP (I am not a graphics programmer), but I'd say you could probably create a deferred pass with multiple render targets to unpack any data you want. This will likely be helpful.

    I also came across this old post and sample code.
     
    daneobyrd likes this.
  4. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    272
    Thank you so much for your response amirebrahmini!
    It looks like every single one of the old posts you linked is for the legacy render pipeline. The new SRP based rendering pipelines presumably have slightly different interfaces for extracting these data. I am going to start much simpler and see if I can figure out how to extract render buffers ala this blog post: https://alexanderameye.github.io/notes/edge-detection-outlines/

    Edit: If you have examples of G-buffer extraction using SRPs in URP or HDRP, that would be extremely useful!
     
    Last edited: Nov 24, 2021
  5. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    272
    The more I dive into doing this in URP the more difficult this is seeming.
    So far I can vaguely ascertain that
    com.unity.render-piplines.universal/shaders/utils/StencilDeferred.shader
    pulls the GBuffers, extracts BRDFData and Surface data from these buffers then caclulates the final color.

    I don't know anything about programming shaders, but as far as I can tell, one way to do this is to make a custom shader for each Buffer, figure out the correct operation for each buffer, then output that to a texture within the shader?????

    The following (admittedly crappy) attempt at doing this results in glitchy output.

    Code (CSharp):
    1.  
    2. Shader "CustomDeferred/GBuffer0"
    3. {
    4.     SubShader
    5.     {
    6.         Tags
    7.         {
    8.             "RenderType"="Opaque" "RenderPipeline" = "UniversalPipeline" "LightMode" = "UniversalGBuffer" "UniversalMaterialType" = "Lit"
    9.         }
    10.  
    11.         HLSLINCLUDE
    12.         #pragma vertex vert
    13.         #pragma fragment frag
    14.  
    15.         #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    16.         #include "Packages/com.unity.render-pipelines.universal/Shaders/Utils/Deferred.hlsl"
    17.         #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
    18.  
    19.         struct Attributes
    20.         {
    21.             float4 positionOS : POSITION;
    22.             float2 uv : TEXCOORD0;
    23.         };
    24.  
    25.         struct Varyings
    26.         {
    27.  
    28.             float4 positionHCS : SV_POSITION;
    29.             float2 uv : TEXCOORD0;
    30.         };
    31.      
    32.         #define GBUFFER0 0
    33.  
    34.  
    35.         FRAMEBUFFER_INPUT_HALF(GBUFFER0);
    36.  
    37.  
    38.         Varyings vert(Attributes IN)
    39.         {
    40.             Varyings OUT;
    41.             OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
    42.             return OUT;
    43.         }
    44.         ENDHLSL
    45.  
    46.         Pass
    47.         {
    48.             Name "GBUFFER EXTRACTION"
    49.  
    50.             HLSLPROGRAM
    51.             half4 frag(Varyings IN) : SV_TARGET
    52.             {
    53.                 half4 gbuffer0 = LOAD_FRAMEBUFFER_INPUT(GBUFFER0, IN.positionHCS.xyz);
    54.  
    55.  
    56.                 return gbuffer0;
    57.             }
    58.             ENDHLSL
    59.         }
    60.     }  
    61. }
    62. }

    Applying this shader to a material results in some seriously glitchy behavior. Omitting the tag
    "LightMode" = "UniversalGBuffer", also seemed to result in a completely black render. Anyone with better shader programming knowledge want to chime in?
     
    Last edited: Nov 25, 2021
  6. funkyCoty

    funkyCoty

    Joined:
    May 22, 2018
    Posts:
    655
    Bump - I just needed to do the same thing and I'm seeing that it's not yet possible???

    In the URP source, I see that GBufferPass.cs has a OnCameraCleanup which seems to be ran right after gbuffer stuff is handled, which releases the rendertextures for the gbuffers? What if I want to access them?? I'm trying to access them to both read and then write to (for screen-space reflections) - but it seems like it's just not possible?

    It's so close! Can anyone at Unity chime in?
    Unity_9zTEy7kZEy.png
     
    Last edited: Jun 2, 2022
  7. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    272
    Bump. It's stuff like this that will make tools like Barracuda actually more useful, imo
     
  8. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    12,206
    Bump, is the an easy way to have access to _CameraGBufferTexture2, like in previous Standard Pipeline ?

    This is a nightmare so far, i have spent a day to do the simplest of thing with zero success
     
  9. daneobyrd

    daneobyrd

    Joined:
    Mar 29, 2018
    Posts:
    100
    Have you tried with BuiltinRenderTextureType.GBuffer2?

     
    nasos_333 likes this.
  10. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    12,206
    Hi, thanks :). this worked and without do anything else :)
     
  11. crybirb

    crybirb

    Joined:
    Jun 13, 2022
    Posts:
    5
    So if anyone stumbles through this like I did and still can't make it work, try this:

    Code (CSharp):
    1.             CommandBuffer cmd = new CommandBuffer();
    2.             cmd.name = "TESTING GBuffer TESTING";
    3.             var gBuff = Shader.PropertyToID("GetBuff0");
    4.  
    5.             RenderTargetIdentifier rti = new RenderTargetIdentifier("_GBuffer1");
    6.             cmd.GetTemporaryRT(gBuff, Screen.width, Screen.height, 0, FilterMode.Bilinear, RenderTextureFormat.ARGB32);
    7.             cmd.Blit(rti, gBuff);
    8.             cmd.SetGlobalTexture(ShaderIDs.CommandBuffer0, gBuff);
    9.             cmd.ReleaseTemporaryRT(gBuff);
    10.             context.ExecuteCommandBuffer(cmd);
    11.             CommandBufferPool.Release(cmd);
    For some reason
                cmd.Blit(BuiltinRenderTextureType.GBuffer0, gBuff); 
    DOES NOT WORK. I had to go into the Deferred pass .cs, find these identifiers and do that by hand.
     
    bajja and daneobyrd like this.
  12. bajja

    bajja

    Joined:
    Feb 3, 2013
    Posts:
    5
    For me this didn't work as they have renamed _GBuffer1 etc. to include the screen resolution and buffer format etc.. Personally, I ended up having to use reflection to unpack the internal GbufferAttachments array from inside URP... I imagine this is potentially problematic though.. Praying that unity give us an official way to access the Gbuffers, like in the built in pipeline...
     
  13. ViCoX

    ViCoX

    Joined:
    Nov 22, 2013
    Posts:
    37
    Wow this almost comical except it makes me cry.