Search Unity

Question Overwriting the camera projection and worldToCamera matrix in a custom pass

Discussion in 'High Definition Render Pipeline' started by larsbertram1, Feb 17, 2020.

  1. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    i have successfully overwritten both - the camera projection and worldToCamera matrix - in URP using a
    ScriptableRendererFeature to render with an orthographic camera top down without having to use a second camera.
    just using cmd.SetViewProjectionMatrices(MyworldToCameraMatrix, MyprojectionMatrix); did the trick.
    then using:
    context.ExecuteCommandBuffer(cmd);
    context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings);

    was all i needed to get the things rendered into my render texture a virtually no costs.

    so i wonder if this is possible in HDRP somehow as well.
    my first test using a CustomPass and more or less the same setup and finally:
    HDUtils.DrawRendererList(renderContext, cmd, RendererList.Create(result));
    unfortunally failed.

    it would be great to render out a top down projected rt for anything like displacement just using the default camera and its culling results.
     
    Egad_McDad likes this.
  2. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    I apologize for necroing this thread but I've run into this same problem just today. Is there any chance you've gotten this working?

    I first tried using
    SetProjectionMatrix()
    without luck. After checking the custom passes repository I found that CameraDepthBake.cs uses
    SetProjectionMatrix()
    so I tried it but found that it did not work either, it only mirrored the final result down the middle with the objects still being drawn in a non-orthographic manner. Lastly, I tried additionally setting the view projection matrix along with a few others (included in the code below).

    The code:
    Code (CSharp):
    1. protected override void Execute(CustomPassContext ctx)
    2. {
    3.     // cache the camera's previous matrices
    4.     var prevProjectionMatrix = ctx.hdCamera.camera.projectionMatrix;
    5.     var viewMatrix = ctx.hdCamera.camera.worldToCameraMatrix;
    6.     var prevViewProjectionMatrix = prevPMatrix * viewMatrix;
    7.  
    8.     var orthographicProjectionMatrix = GL.GetGPUProjectionMatrix( Matrix4x4.Ortho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 100.0f), true);
    9.  
    10.     var viewProjectionMatrix = orthographicProjectionMatrix * viewMatrix;
    11.  
    12.     ctx.cmd.SetGlobalMatrix("_ProjMatrix", orthographicProjectionMatrix );
    13.     ctx.cmd.SetGlobalMatrix("_ViewProjMatrix", viewProjectionMatrix );
    14.     ctx.cmd.SetGlobalMatrix("_InvProjMatrix", orthographicProjectionMatrix.inverse );
    15.     ctx.cmd.SetGlobalMatrix("_InvViewProjMatrix", viewProjectionMatrix.inverse );    
    16.     ctx.cmd.SetGlobalMatrix("_CameraViewProjMatrix", viewProjectionMatrix );
    17.  
    18.  
    19.  
    20.     ctx.cmd.DrawMeshInstanced(
    21.         myMesh,
    22.         0,
    23.         myMaterial,
    24.         0,
    25.         myMatrices,
    26.         myMatrices.Length-1
    27.     );
    28.  
    29.     // reset the matrices
    30.     ctx.cmd.SetGlobalMatrix("_ViewProjMatrix", prevProjectionMatrix );
    31.     ctx.cmd.SetGlobalMatrix("_InvProjMatrix", prevProjectionMatrix .inverse);
    32.     ctx.cmd.SetGlobalMatrix("_InvViewProjMatrix", prevViewProjectionMatrix .inverse);
    33.     ctx.cmd.SetGlobalMatrix("_CameraViewProjMatrix", prevViewProjectionMatrix );
    34. }
    35.  
    Any help at all would be immensely appreciated! I've lost a few hours to this problem already and hopefully this will help others from falling down this same hole

    Edit: I've also tested the code with

    HDUtils.DrawRendererList()
    with similar results so I don't believe that
    DrawMeshInstanced()
    is the culprit
     
    Last edited: Nov 12, 2020
  3. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    262
    Hello,

    I see that you're using the new custom pass API (with the CustomPassContext), so I guess you're using HDRP 10.x?

    If that's the case, we landed a change where all our camera settings are uploaded to a big constant buffer, which means that you can't modify them with the `SetGlobal` API.

    To allow the camera settings to be overwritten, we added the CustomPassUtils.RenderFrom* functions, that allows you to render objects from a different camera.

    For reference here's the updated CameraDepthBake script as it would be in 10.x bBtw, I'll soon update all the passes in the sample repository to 10.x)

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Rendering.HighDefinition;
    3. using UnityEngine.Rendering;
    4. using System.Reflection;
    5.  
    6. class DepthCapturePass : CustomPass
    7. {
    8.     public RenderTexture depthFromCam;
    9.     public Material depthMaterial;
    10.     public Camera bakeCamera;
    11.     public bool render;
    12.  
    13.     FieldInfo cullingResultField;
    14.  
    15.     protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
    16.     {
    17.         cullingResultField = typeof(CustomPassContext).GetField(nameof(CustomPassContext.cullingResults));
    18.     }
    19.  
    20.     protected override void Execute(CustomPassContext ctx)
    21.     {
    22.         if (!render || depthMaterial == null || bakeCamera == null || depthFromCam == null)
    23.             return;
    24.  
    25.         if (ctx.hdCamera.camera == bakeCamera || ctx.hdCamera.camera.cameraType != CameraType.Game)
    26.             return;
    27.  
    28.         bakeCamera.TryGetCullingParameters(out var cullingParams);
    29.         cullingParams.cullingOptions = CullingOptions.ShadowCasters;
    30.         // Make sure to pass the reference of the struct and not it's value as we'd end up modifying it's copy instead of the one we have in this function
    31.         cullingResultField.SetValueDirect(__makeref(ctx), ctx.renderContext.Cull(ref cullingParams));
    32.  
    33.         RenderStateBlock lessEqualStateBlock = new RenderStateBlock(RenderStateMask.Depth) { depthState = new DepthState(true, CompareFunction.LessEqual) };
    34.  
    35.         CoreUtils.SetRenderTarget(ctx.cmd, depthFromCam.colorBuffer, depthFromCam.depthBuffer, ClearFlag.All);
    36.         CustomPassUtils.RenderFromCamera(ctx, bakeCamera, -1, RenderQueueType.AllOpaque, depthMaterial, depthMaterial.FindPass("ForwardOnly"), lessEqualStateBlock);
    37.     }
    38. }
    39.  
     
    Egad_McDad likes this.
  4. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    i set a custom global worldtoview matrix and custom shaders. this works fine in hdrp 7 and 9. i haven't checked it in hdrp 10 tho.
     
    Egad_McDad likes this.
  5. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    Ah, I'm sorry, I forgot to include the version - I'm using the 9.0.0-preview.33 package version. Also, I'm on 2020.1.10f1 if that helps at all either.

    So after checking the docs it looks like
    CustomPassUtils.DrawFromCamera()
    isn't available in version 9.0. I'll take a peak in the hdrp package repo page for the CustomPassUtils to see if I can just reproduce the functionality in 9.0.

    Also, does the SetGlobal API also not work in 9.0?
     
  6. Egad_McDad

    Egad_McDad

    Joined:
    Feb 5, 2020
    Posts:
    39
    Thanks you! By custom do you mean a matrix which is a property of a those shaders?

    I've looked into trying to replace the transformation by the projection matrix using a custom shader but I'm not sure exactly where it happens in the hdrp shaders, or rather I haven't yet tracked down which file and line it happens on. As of now I've just made a copy of the unlit shader with some of the bells and whistles removed and its working. If you could point me to where to find the transformation I'd be extremely grateful!

    Edit: Looks like I found it,
    VertMesh()
    in VertMesh.hlsl
     
    Last edited: Nov 12, 2020
  7. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    262
    Egad_McDad likes this.
  8. xHammy

    xHammy

    Joined:
    Aug 11, 2017
    Posts:
    27
    Sorry hyjacking this thread a bit. I'm having trouble wrapping my head around render passes a bit. This is the exact thing I want to do right now, well almost anyway, do you mind sharing the code for this?
     
  9. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    nowadays CustomPassUtils.DrawFromCamera() should make your life easier already.
     
    hippocoder and Egad_McDad like this.