Search Unity

HDRP: How to render anything custom

Discussion in 'Graphics Experimental Previews' started by KnightPista, Dec 3, 2018.

  1. KnightPista

    KnightPista

    Joined:
    May 18, 2015
    Posts:
    37
    Hi,

    I'm using HD render pipeline. When I use provided stuff (hd-lit shader, Shader Graph), all works nice...

    Now I want to do some custom rendering:
    • adding Command Buffer to the main camera, or
    • render some objects using ortho camera into render texture with simple HLSL-unlit shader (to render object masks for custom effects etc.)

    However, it seems that in SRP we cannot insert custom Command Buffer into camera...
    HDRP: https://forum.unity.com/threads/hdrp-how-to-add-command-buffer-to-camera.568870/
    LWRP: https://forum.unity.com/threads/lwrp-and-camera-command-buffers.537682/

    Is it even possible with SRP? I've not found anything about that on the forums, and if someone even asked, the thread was unanswered. Not even on github examples. I know I can make my custom SRP, but that would be just too much work so reverting back to the default pipeline would be much easier.

    Anyone got the Command Buffers or rendering masks using the HDRP working? Thanks!
     
  2. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,515
    Peter77 and Nyarlathothep like this.
  3. KnightPista

    KnightPista

    Joined:
    May 18, 2015
    Posts:
    37
    Is it also possible with the HDRP?
     
    Nyarlathothep likes this.
  4. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    1,515
    AFAIK - no
     
  5. SebLagarde

    SebLagarde

    Unity Technologies

    Joined:
    Dec 30, 2015
    Posts:
    450
    Hi,

    Currently HD don't support any command buffer insertion or callback.
    We will try to provide other customization way in the future.
     
    Nyarlathothep likes this.
  6. drcrck

    drcrck

    Joined:
    May 23, 2017
    Posts:
    279
    any news? I'd prefer good ones, like "will be available in the next release"
     
    yinyinh and Nyarlathothep like this.
  7. kelloh

    kelloh

    Joined:
    Mar 2, 2015
    Posts:
    29
    I'm also very curious to know if the HDRP will be gaining hook points for custom object rendering in the near future.
     
    Nyarlathothep likes this.
  8. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    7,687
    Any news on this ?
     
  9. QuadraticForm

    QuadraticForm

    Joined:
    Oct 13, 2016
    Posts:
    2
    Hey everyone, I'm working on a hairworks integration project,
    today I upgraded my project to HDRP, and I found out that
    there is a HDAdditionalCameraData component on the camera,
    and it has a customRender event you can use to override default rendering logic,
    you can do anything there with ScriptableRenderContext and CommandBuffer.

    Don't know about you guys, but I only need to set render targets and issue my plugin event there,
    the rest is up to my native plugin, so It worked perfectly for me.
     
    Nyarlathothep, nasos_333 and Artherl like this.
  10. darkydoodle

    darkydoodle

    Joined:
    Oct 27, 2018
    Posts:
    45
    Yes, that's what I use also (shadow camera and fx camera). But careful if your cameras are not all at the same place, unity matrixes are not reliable. Also, if you manage to render something with drawrenderer, it would be very nice of you to put an example code :p
    I had to modify mine twice already to make it work and now it's not working (again) since the last update (2019.2 a8 HDRP 5.9).
     
  11. Artherl

    Artherl

    Joined:
    Oct 29, 2018
    Posts:
    1
    that is awesome!
     
  12. Nyarlathothep

    Nyarlathothep

    Joined:
    Jun 13, 2013
    Posts:
    251
    What stage of the render pipeline does the customRender event render to? We have an asset that directly modifies the GBuffer using Camera.AddCommandBuffer with the correct CameraEvent, but customRender doesn't seem to have an equivalent (I don't know HDRP very well, so maybe that's wrapped up somewhere in the ScriptableRenderContext).
     
  13. darkydoodle

    darkydoodle

    Joined:
    Oct 27, 2018
    Posts:
    45
    It completly bypasses the render pipeline. It's not like an injection at a specific stage. If you look at the code of the HDRP, you'll see that if there's a customRender, it executes it and skip the rest of the rendering for this camera.
    I use it to calculate a shadowmap (that I use later on the main cam) and some other kind of depth maps (that I used later in post process, but I'm blocked with the PPV3 right now)
     
    QuadraticForm and Nyarlathothep like this.
  14. Nyarlathothep

    Nyarlathothep

    Joined:
    Jun 13, 2013
    Posts:
    251
    Ah that's unfortunate, definitely not what we need! Thanks anyway :)
     
  15. Partha_online

    Partha_online

    Joined:
    Aug 24, 2013
    Posts:
    8
    Hi,
    How can I extract Shadow Map data in HDRP, using a custom HDRP shader.
    Can any one help me on this
     
  16. kripto289

    kripto289

    Joined:
    Feb 21, 2013
    Posts:
    303
    After 1.5+ year HDRP still does not have command buffers or some functional and LWRP removed some feature like a "IAfterTransparentPass" etc....
    Good job!
     
    Nyarlathothep likes this.
  17. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    7,687
    It is amazing how these pipelines are the most advertised thing in Unity and they simply not work yet.

    Frankly is hard to believe what is happening to Unity and to Asset Store lately, is like a very very bad nightmare.
     
  18. Raul_MadGoat

    Raul_MadGoat

    Joined:
    Jan 10, 2015
    Posts:
    182
    Is there any update on this?
     
  19. neekoh

    neekoh

    Joined:
    Nov 16, 2012
    Posts:
    4
    For what it's worth darkydoodle's approach works to an extent to replace image effects done previously with OnRenderImage() callback. I scratched my head a good while for this, so I thought I'd share a basic duct tape solution until the next update. It probably won't help the OP though. I referred to keijiro's github for this: https://github.com/keijiro/HdrpBlitter
    I'm using Unity 2019.2.0f1 with HDRP 6.9.1. The effect is the VHS scrambling seen here: https://twitter.com/niko_stenberg/status/1161896916076154880

    - Set up a target render texture on your main camera, I do this in Update()
    Code (CSharp):
    1.  
    2. RenderTexture rt = mainCamera.targetTexture;
    3. if (rt == null)
    4. {
    5.     rt = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.Default, 0);
    6.     mainCamera.targetTexture = rt;
    7. }
    8. else if (rt.width != Screen.width || rt.height != Screen.height)
    9. {
    10.     rt.Release();
    11.     rt = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.Default, 0);
    12.     mainCamera.targetTexture = rt;
    13. }
    14.  
    - Set up a second camera to render after the main camera
    - On a script on the second camera subscribe to the customRender event, I do this in OnEnable()
    Code (CSharp):
    1.  
    2. var HDData = GetComponent<HDAdditionalCameraData>();
    3. if (HDData != null)
    4.     HDData.customRender += CustomRender;
    5.  
    - In the CustomRender function pass the render texture to your shader and execute a command buffer to render a full screen triangle
    Code (CSharp):
    1.  
    2. void CustomRender(ScriptableRenderContext context, HDCamera camera)
    3. {
    4.     if (camera == null || camera.camera == null) return;
    5.  
    6.     RenderTexture RT = Camera.main.targetTexture;
    7.  
    8.     if (RT == null)
    9.         return;
    10.  
    11.     // Target ID
    12.     var rt = camera.camera.targetTexture;
    13.     var rtid = rt != null ?
    14.         new RenderTargetIdentifier(rt) :
    15.         new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
    16.  
    17.     // Shader uniforms
    18.     rewindEffectMaterial.SetFloat(globalIntensityId, imageEffectIntensity);
    19.     rewindEffectMaterial.SetTexture(mainTexId, RT);
    20.     passthroughMaterial.SetTexture(mainTexId, RT);
    21.  
    22.     // Blit
    23.     if (effectCB == null)
    24.     {
    25.         effectCB = new CommandBuffer();
    26.         effectCB.name = "Rewind effect";
    27.         CoreUtils.DrawFullScreen(effectCB, rewindEffectMaterial, rtid);
    28.     }
    29.     if (passthroughCB == null)
    30.     {
    31.         passthroughCB = new CommandBuffer();
    32.         passthroughCB.name = "Rewind effect passthrough";
    33.         CoreUtils.DrawFullScreen(passthroughCB, passthroughMaterial, rtid);
    34.     }
    35.     if (imageEffectIntensity == 0f)
    36.         context.ExecuteCommandBuffer(passthroughCB);
    37.     else
    38.         context.ExecuteCommandBuffer(effectCB);
    39. }
    40.  
    This function should always blit something. I'm using two materials to just blit the RT as is, if there's no effect to be done. You may need other managing in your particular case.

    Here's the passthrough shader for reference. Modify to suit your image effect needs.
    Code (CSharp):
    1.  
    2. Shader "reLive/BlitPassthroughHDRP"
    3. {
    4.     Properties
    5.     {
    6.         [HideInInspector]_MainTex("Base (RGB)", 2D) = "white" {}
    7.     }
    8.  
    9.     HLSLINCLUDE
    10.  
    11. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
    12. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
    13. #include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
    14.  
    15.     float2 FixVFlip(float2 texcoord)
    16.     {
    17. #if UNITY_UV_STARTS_AT_TOP
    18.         bool flip = _ProjectionParams.x > 0;
    19. #else
    20.         bool flip = _ProjectionParams.x < 0;
    21. #endif
    22.         if (flip) texcoord.y = _RTHandleScale.y - texcoord.y;
    23.         return texcoord;
    24.     }
    25.  
    26.     TEXTURE2D(_MainTex);
    27.     SAMPLER(sampler_MainTex);
    28.  
    29.     // Vertex shader (procedural fullscreen triangle)
    30.     void Vertex(
    31.         uint vertexID : SV_VertexID,
    32.         out float4 positionCS : SV_POSITION,
    33.         out float2 texcoord : TEXCOORD0
    34.     )
    35.     {
    36.         positionCS = GetFullScreenTriangleVertexPosition(vertexID);
    37.         texcoord = FixVFlip(GetFullScreenTriangleTexCoord(vertexID));
    38.     }
    39.  
    40.     // Fragment shader
    41.     float4 Fragment(
    42.         float4 positionCS : SV_POSITION,
    43.         float2 texcoord : TEXCOORD0
    44.     ) : SV_Target
    45.     {
    46.         // just output the texture
    47.         return SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, texcoord);
    48.     }
    49.     ENDHLSL
    50.  
    51.     SubShader
    52.     {
    53.         Cull Off ZWrite Off ZTest Always
    54.         Pass
    55.         {
    56.             HLSLPROGRAM
    57.             #pragma vertex Vertex
    58.             #pragma fragment Fragment
    59.             ENDHLSL
    60.         }
    61.     }
    62. }
    63.  
     
    Olmi, Raul_MadGoat and darkydoodle like this.
  20. iamarugin

    iamarugin

    Joined:
    Dec 17, 2014
    Posts:
    170
  21. glbranimir

    glbranimir

    Joined:
    Jun 18, 2019
    Posts:
    4
    Can I use this method to generate a
    _CameraNormalsTexture
    and make a custom shader graph node that samples that texture? I won't to achieve the internal edge detection shader, but every article points to something legacy or non-HDRP...