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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

HDRP and GBuffer

Discussion in 'Shaders' started by Kamael, Jan 4, 2019.

  1. Kamael

    Kamael

    Joined:
    Mar 11, 2013
    Posts:
    15
    I want to write outline post process shader, but I have problem. When I want to use normals from GBuffer textures, I got just grey output.
    Code (CSharp):
    1. Shader "Hidden/SotR/Outline"
    2. {
    3.     HLSLINCLUDE
    4.  
    5.         #include "Packages/com.unity.postprocessing/PostProcessing/Shaders/StdLib.hlsl"
    6.  
    7.         //TEXTURE2D_SAMPLER2D(_MainTex, sampler_MainTex);
    8.         TEXTURE2D_SAMPLER2D(_CameraGBufferTexture2, sampler_CameraGBufferTexture2);
    9.        
    10.         float _Blend;
    11.  
    12.         float4 Frag(VaryingsDefault i) : SV_Target
    13.         {
    14.             //float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.texcoord);
    15.             float4 color = SAMPLE_TEXTURE2D(_CameraGBufferTexture2, sampler_CameraGBufferTexture2, i.texcoord);
    16.             //float luminance = dot(color.rgb, float3(0.2126729, 0.7151522, 0.0721750));
    17.             //color.rgb = lerp(color.rgb, luminance.xxx, _Blend.xxx);
    18.             return color;
    19.         }
    20.  
    21.     ENDHLSL
    22.  
    23.     SubShader
    24.     {
    25.         Cull Off ZWrite Off ZTest Always
    26.  
    27.         Pass
    28.         {
    29.             HLSLPROGRAM
    30.  
    31.                 #pragma vertex VertDefault
    32.                 #pragma fragment Frag
    33.  
    34.             ENDHLSL
    35.         }
    36.     }
    37. }
     
  2. arnaud-carre

    arnaud-carre

    Unity Technologies

    Joined:
    Jun 23, 2016
    Posts:
    97
    Hi!
    HDRP encodes data in GBUFFER to maximize space storage. So you have to use helper function to retrieve various GBUFFER component. Regarding normal you could do that:

    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"

    // Load normal and roughness.
    NormalData normalData;
    DecodeFromNormalBuffer(positionSS, normalData);
    float3 N = normalData.normalWS;
    float roughness = normalData.perceptualRoughness;
     
  3. Kamael

    Kamael

    Joined:
    Mar 11, 2013
    Posts:
    15
    Thanks! Ok, I got this. I had some problems with library, but in the end i handled that. Unfortunately I have two problems now:
    1. The texture does not clear on the sky.
    Normals.png
    2. The second problem i that, when I change window size, outline based on normal texture is not refreshing.
    Outline.png
     
  4. arnaud-carre

    arnaud-carre

    Unity Technologies

    Joined:
    Jun 23, 2016
    Posts:
    97
    The first issue is by design. By default, HDRP didn't clear GBUFFER and some other buffers to get some GPU perf. It suppose that complete screen is always rendered. Did you disable the skybox or something?
    Regarding the second issue, HDRP internally use some heuristic to not resize buffers in some case. So at the end, a fullscreen quad could have different UV than (1,1) ( maybe 0.8, 0.8 )
    To properly handle that you could use that kind of code to render your fullscreen quad :

    cmd.DrawProcedural(Matrix4x4.identity, m_AOResolveMaterial, 0, MeshTopology.Triangles, 3, 1, m_AOPropertyBlock);

    ( taken from HDRenderPipeline.cs )

    As it's drawProcedural using one big triangle ( faster than a quad ), your vertex shader should use some math to correctly set UV. You have an exemple of that in DebugColorPicker.shader

    Code (CSharp):
    1.             Varyings Vert(Attributes input)
    2.             {
    3.                 Varyings output;
    4.                 output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
    5.                 output.texcoord = GetNormalizedFullScreenTriangleTexCoord(input.vertexID);
    6.  
    7.                 return output;
    8.             }
    9.  
     
  5. Kamael

    Kamael

    Joined:
    Mar 11, 2013
    Posts:
    15
    First problem: I didn't disable anything. Camera settings are from the template.
    Second problem: I handled the second issue using ratio of _MainTex_TexelSize and _NormalBufferTexture_TexelSize.
     
  6. arnaud-carre

    arnaud-carre

    Unity Technologies

    Joined:
    Jun 23, 2016
    Posts:
    97
    ok first problem is because we don't clear GBUFFER (as we expect to redraw complete screen each frame). When HDRP is doing lighting pass, we use stencil buffer to "not fetch" normal for the sky.

    an easy work around for you is to clear the GBUFFER each frame. You can do that in ClearBuffers function in HDRP. At the end of the func there is that kind of code:
    Code (CSharp):
    1. // This is to save some performance
    2.                if (hdCamera.frameSettings.litShaderMode == LitShaderMode.Deferred)
    3.                {
    4.                    // We still clear in case of debug mode
    5.                    if (m_CurrentDebugDisplaySettings.IsDebugDisplayEnabled())
    6.                    {
    7.                        using (new ProfilingSample(cmd, "Clear GBuffer", CustomSamplerId.ClearGBuffer.GetSampler()))
    8.                        {
    9.                            HDUtils.SetRenderTarget(cmd, hdCamera, m_GbufferManager.GetBuffersRTI(), m_SharedRTManager.GetDepthStencilBuffer(), ClearFlag.Color, CoreUtils.clearColorAllBlack);
    10.                        }
    11.                    }
    12.                }
    You can comment those "if" to always perform GBUFFER clear.
     
  7. cecarlsen

    cecarlsen

    Joined:
    Jun 30, 2006
    Posts:
    848
    @arnaud-carre I am looking for an example of a shader that renderes to the HDRP Gbuffer when executed with DrawProcedural on a CommandBuffer. I haven't seen that work without actually altering the HDRP. Is it possible in the current version of HDRP?
     
  8. superjayman

    superjayman

    Joined:
    May 31, 2013
    Posts:
    185
    Can someone show a working method of just getting the Normals, the line below gives me an error!!!!

    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"

    HDRP is terrible to work with, nothing is documented and constantly changing, what the hell is going on Unity>>>>>????
     
  9. LIVENDA_LABS

    LIVENDA_LABS

    Joined:
    Sep 23, 2013
    Posts:
    377
    Any update on this, help would be appreciated, we need access to the Normal buffer in HDRP / LWRP latest version.
     
    ModLunar and ScaniX like this.
  10. arnaud-carre

    arnaud-carre

    Unity Technologies

    Joined:
    Jun 23, 2016
    Posts:
    97
    In HDRP GBUFFER use data encoding to save some memory. So you have to use decoding functions to get data ( ie normal ). @superjayman you may have include ordering issue.
    My advice is to look at com.unity.render-pipelines.high-definition\Runtime\Lighting\ScreenSpaceLighting\ScreenSpaceReflections.compute file. Look for GetNormalAndPerceptualRoughness function in this file, you should find everything you need.
     
  11. antoinefortin95

    antoinefortin95

    Joined:
    Jan 25, 2019
    Posts:
    3
    Hello,
    Sorry to be a little bit late on the answer and also english is not my first langage :) But I felt on this post when I wanted to about the same thing in HDRP.
    I found that into HDRP the function to read information from related textures are defined with this macro:
    In the file GLCore.hlsl
    Code (CSharp):
    1. #define LOAD_TEXTURE2D_ARRAY(textureName, unCoord2, index)                      textureName.Load(int4(unCoord2, index, 0))
    The parameters from LOAD_TEXTURE... they require a Pixel coordinate, this is why in the PostProcess the code is like this:
    Code (CSharp):
    1.     float4 CustomPostProcess(Varyings input) : SV_Target
    2.  
    3.     {
    4.         UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
    5.         uint2 positionSSRegular = input.texcoord* _ScreenSize.xy;...
    We can use the positionSSRegular to find the informations example the world normals.
    The G Buffer is not cleared into HDRP as Arnaud mentionned :)

    So in a post process.
    What I did is make three functions to explain how I dealt with the required informations I needed to get in my post-process.
    Exemple to get the Depth I use this as a function
    Code (CSharp):
    1. float GetDepth(int2 SSRegular)
    2. {
    3.     return LOAD_TEXTURE2D_X(_CameraDepthTexture, SSRegular).x;
    4. }
    It gives this:
    upload_2020-6-15_16-36-31.png

    Exemple to get the Normal WorldSpace. I use this:
    Code (CSharp):
    1.     float3 normalWS = GetNormalWorldSpace(positionSSRegular, depth);


    The function is like this:
    Code (CSharp):
    1. /* Use this to clear GBuffer like...*/
    2. float3 GetNormalWorldSpace(float2 uv, float depth)
    3. {
    4.     float3 normalWS = 0.0f;
    5.    
    6.     if (depth > 0.0f)
    7.     {
    8.         NormalData normalData;
    9.         const float4 normalBuffer = LOAD_TEXTURE2D_X(_NormalBufferTexture, uv);
    10.         DecodeFromNormalBuffer(normalBuffer, uv, normalData);
    11.         normalWS = normalData.normalWS;
    12.     }
    13.    
    14.     return normalWS;
    15. }
    16.  
    Which gives:
    upload_2020-6-15_16-40-5.png

    The problem you have with the normalWS are because the Gbuffer is not cleared, so a simple trick you can do is to simple check if the Depth is > 0.0f




     
    lilacsky824, Delphic_ and Egad_McDad like this.
  12. antoinefortin95

    antoinefortin95

    Joined:
    Jan 25, 2019
    Posts:
    3
    This should solve the NormalWS problem.
    Code (CSharp):
    1.     if (depth > 0.0f)
    2.     {
    3.         NormalData normalData;
    4.         const float4 normalBuffer = LOAD_TEXTURE2D_X(_NormalBufferTexture, uv);
    5.         DecodeFromNormalBuffer(normalBuffer, uv, normalData);
    6.         normalWS = normalData.normalWS;
    7.     }
     
    Egad_McDad and cecarlsen like this.
  13. Delphic_

    Delphic_

    Joined:
    Apr 23, 2018
    Posts:
    39
    nice, is there also a way to get the basecolor and other layers too like specular, diffuse and so on ?
     
    ModLunar likes this.
  14. TOES2

    TOES2

    Joined:
    May 20, 2013
    Posts:
    135
    Bump this, I also want to know how to get albedo/diffuse
     
    ModLunar likes this.
  15. ModLunar

    ModLunar

    Joined:
    Oct 16, 2016
    Posts:
    372
    Bump, and very surprised something important like this wouldn't be documented for HDRP?
    (Please correct me if I'm wrong though!)
     
  16. JuanCecchetto

    JuanCecchetto

    Joined:
    May 18, 2015
    Posts:
    6
    Bumping this, I would also like to know if there is a way to decode the Albedo.
     
  17. a300mind

    a300mind

    Joined:
    Sep 24, 2021
    Posts:
    1
    Same Here. I also want to know how to get albedo/diffuse in HDRP.
     
  18. Gooren

    Gooren

    Joined:
    Nov 20, 2015
    Posts:
    324
    I would also be interested in knowing how to get albedo/diffuse