Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug Viewport is incorrect in a custom pass running in AfterPostProcess when using dynamic resolution

Discussion in 'High Definition Render Pipeline' started by half_voxel, Nov 18, 2020.

  1. half_voxel

    half_voxel

    Joined:
    Oct 20, 2007
    Posts:
    977
    I have a script that needs to render things in world space *after* post-processing effects.
    This works perfectly using a custom HDRP pass with CustomPassInjectionPoint.AfterPostProcess, but not when using dynamic resolution. When dynamic resolution is enabled the render target is scaled up at some point in the post-processing effects stack, which is expected. However, my custom pass still gets a viewport which is only a fraction of the full size.
    I believe this is a bug as at this point the viewport should cover the whole screen (or at least the whole part of the screen the camera should render to after being scaled up).

    1. Use a custom pass with CustomPassInjectionPoint.AfterPostProcess
    2. Use dynamic resolution
    3. Render something in the custom pass.
    4. The things will be rendered in a scaled down way in a corner of the screen.

    upload_2020-11-18_16-24-24.png
     
  2. Yavvn

    Yavvn

    Joined:
    May 8, 2019
    Posts:
    18
    Bumping this thread for a response, this issue is also preventing us from using dynamic resolution in HDRP.
     
  3. DeadNinja

    DeadNinja

    Joined:
    Jun 3, 2013
    Posts:
    39
    Confirm, totally block my project - tested on all 2020.1-2020.2 versions with HDRP 9 - 10
     
  4. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
  5. olavrv

    olavrv

    Joined:
    May 26, 2015
    Posts:
    511
    This issue has re-appeared, identified in 2021.2.4f1 up until 2021.10f1
     
  6. MS80

    MS80

    Joined:
    Mar 7, 2014
    Posts:
    346
    It seems this bug is still existing in Unity 2022.0.1f1 and HDRP 13.1.8.
    How could I add a "pass that resets the camera size"?
     
  7. gewl

    gewl

    Joined:
    May 19, 2016
    Posts:
    95
    I've been encountering this as well on 2021.3.5, though I think I'm only getting it when I use FSR (DLSS disabled) and am forcing a specific screen percentage.
     
  8. nasos_333

    nasos_333

    Joined:
    Feb 13, 2013
    Posts:
    13,212
    hi, is this still an issue, was it resolved in some of the latest versions ?

    Thanks
     
  9. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    Still seems broken in latest LTS. And it still does not appear under "known issues". Not sure what's going wrong here.
     
  10. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    718
    This is a major issue for me, since I don't want to post-process my UI!

    I tried to check if the prior fix for the bug was running, but I was unable to embed HDRP in my project without massive breakage. The code is still there, though.
     
  11. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    I guess we should keep this topic alive and on top of the HDRP board, until there is an official response from Unity.
    This is a heavy bug, which makes it impossible to combine Dynamic Scaling / DLSS / FSR / TAAU with any custom post processor, or with world space UI (which is also affected, if you use the necessary Custom Pass to avoid blur of fonts).

    Funny also that the issue is marked fixed:
    https://issuetracker.unity3d.com/is...sion-when-both-at-active-drs-plus-custom-pass

    and that a PR (which seems to correspond to this issue) is waiting since April in the Graphics repo.
     
    Genebris likes this.
  12. LumaPxxx

    LumaPxxx

    Joined:
    Oct 3, 2010
    Posts:
    340
    They've fixed it in 2022.2.
    try the beta version you will see it.
     
    Genebris likes this.
  13. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    This does not help much, as we use LTS for production. As this is a clear and major bug, it should be listed as known issues on LTS release notes and fixed with high priority. Not sure why this is not the case, as the bug is known since release of LTS (and earlier)
     
  14. pwka

    pwka

    Joined:
    Sep 19, 2012
    Posts:
    49
    This gets "fixed" when you only see the scene or game view at a time. This bug has been around for a very long time. This plus jittering makes custom pass not very usable in production.
     
  15. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    *bump* we need an official response from someone at Unity.
     
  16. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    Another bump. New version (2021.3.11), still no mentioning of this major bug, and no resolution. Instead new bugs in the release, leading to instant crash :(
     
  17. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    *bump* I don't know what to tell our users anymore about why we don't fix the bugs with DLSS & co. We are at 2021.3 LTS, DLSS was introduced as a key feature a year ago or more, still not working correctly.
     
  18. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    time for a *bump*. Someone @Unity, please respond.
     
  19. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    718
    I've been doing some testing on this.

    The original problem -- where the custom pass would appear scaled-down -- is not happening for me in 2021.3.9f1. If I get rid of the fixes introduced here, then the scaled-down rendering returns.

    What is happening is that the custom pass is getting clipped based on the render scale. So, if the render scale is at 50%, only the bottom quarter of the custom pass gets drawn at all. The part that is drawn does get drawn at the correct scale.

    Custom post-processing volumes that run in the After Post Process step are not affected. I am only seeing problems with custom passes set to run in the After Post Process step.

    I'm tinkering around with the pipeline, but I haven't had any luck making this work correctly yet. If I find a gross hack that makes it work, I'll post it :)
     
    Qleenie likes this.
  20. chemicalcrux

    chemicalcrux

    Joined:
    Mar 16, 2017
    Posts:
    718
    This remains broken in 2022.2.2 with HDRP 14.0.4. I have not been able to figure out a workaround.

    I guess a new bug report needs to be filed for this? I'll make a project for it.

    Edit: whilst working on a bug report, I've gotten some confusing results!

    I started by using the Outline shader from this HDRP documentation: https://docs.unity3d.com/Packages/c...stom-Pass.html#scripting-example-outline-pass

    Notice how this is from HDRP 7.1. I had to tweak the script a bit to make it work right.

    upload_2023-1-18_15-58-20.png

    This resulted in the custom pass getting clipped to a fraction of the screen and getting scaled up. So, at 50% resolution, only the bottom quarter was visible, and the outlines that were getting drawn were doubled in size.

    I then switched to one from HDRP 12.0: https://docs.unity3d.com/Packages/c...nition@12.0/manual/Custom-Pass-Scripting.html

    upload_2023-1-18_15-54-4.png

    This one resulted in scaling of the effect, but not clipping.

    Notice how the outlines are visible all the way to the edge of the screen.

    The problem I have been having is not like either of these! Instead, I'm seeing the custom pass getting clipped to the bottom corner of the screen, but it is showing up at the right scale.

    This makes me wonder if there is no bug, and that this is just a problem with the custom pass shaders. I do not understand the shaders well enough to say much there, unfortunately.
     
    Last edited: Jan 18, 2023
  21. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    303
    Was this ever fixed? My world space UI (via custom pass after post process) gets clipped like crazy with either FSR enabled or DLSS on 2021.3.30f1 HDRP.
     
  22. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    No, it’s not fixed. I did another bug report 2 weeks ago. QA seems to be struggling with reproducing, as they don’t seem to be able to enable DLSS on their test machines. Still awaiting reply from them.
     
  23. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    303
    ugh :(. Please do share if and when you get a case number so I send a vote that way. This has been plaguing my project for a long while.
     
    Qleenie likes this.
  24. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
    Hello, sorry for the delay.

    Regarding this scaling issue in the outline shader, you can fix this by using Load instead of Samples in the shader. Load works by using pixel coordinates instead of UVs so there is no scaling needed to fetch the texture data. Here's an example with the outline shader:

    Code (CSharp):
    1. Shader "Hidden/Outline"
    2. {
    3.     HLSLINCLUDE
    4.  
    5.     #pragma vertex Vert
    6.  
    7.     #pragma target 4.5
    8.     #pragma only_renderers d3d11 playstation xboxone xboxseries vulkan metal switch
    9.  
    10.     #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
    11.  
    12.     TEXTURE2D_X(_OutlineBuffer);
    13.     float4 _OutlineColor;
    14.     float _Threshold;
    15.  
    16.     #define v2 1.41421
    17.     #define c45 0.707107
    18.     #define c225 0.9238795
    19.     #define s225 0.3826834
    20.  
    21.     #define MAXSAMPLES 8
    22.     // Neighbour pixel positions
    23.     static float2 samplingPositions[MAXSAMPLES] =
    24.     {
    25.         float2( 1,  1),
    26.         float2( 0,  1),
    27.         float2(-1,  1),
    28.         float2(-1,  0),
    29.         float2(-1, -1),
    30.         float2( 0, -1),
    31.         float2( 1, -1),
    32.         float2( 1, 0),
    33.     };
    34.  
    35.     float4 FullScreenPass(Varyings varyings) : SV_Target
    36.     {
    37.         UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(varyings);
    38.  
    39.         float depth = LoadCameraDepth(varyings.positionCS.xy);
    40.         uint2 screenPosition = uint2(varyings.positionCS.xy);
    41.         PositionInputs posInput = GetPositionInput(varyings.positionCS.xy, _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
    42.         float4 color = float4(0.0, 0.0, 0.0, 0.0);
    43.         float luminanceThreshold = max(0.000001, _Threshold * 0.01);
    44.  
    45.         // Load the camera color buffer at the mip 0 if we're not at the before rendering injection point
    46.         if (_CustomPassInjectionPoint != CUSTOMPASSINJECTIONPOINT_BEFORE_RENDERING)
    47.             color = float4(CustomPassSampleCameraColor(posInput.positionNDC.xy, 0), 1);
    48.  
    49.         // When sampling RTHandle texture, always use _RTHandleScale.xy to scale your UVs first.
    50.         float4 outline = LOAD_TEXTURE2D_X_LOD(_OutlineBuffer, screenPosition, 0);
    51.         outline.a = 0;
    52.  
    53.         if (Luminance(outline.rgb) < luminanceThreshold)
    54.         {
    55.             for (int i = 0; i < MAXSAMPLES; i++)
    56.             {
    57.                 float4 neighbour = LOAD_TEXTURE2D_X_LOD(_OutlineBuffer, screenPosition + samplingPositions[i], 0);
    58.  
    59.                 if (Luminance(neighbour) > luminanceThreshold)
    60.                 {
    61.                     outline.rgb = _OutlineColor.rgb;
    62.                     outline.a = 1;
    63.                     break;
    64.                 }
    65.             }
    66.         }
    67.  
    68.         return outline;
    69.     }
    70.  
    71.     ENDHLSL
    72.  
    73.     SubShader
    74.     {
    75.         Pass
    76.         {
    77.             Name "Custom Pass 0"
    78.  
    79.             ZWrite Off
    80.             ZTest Always
    81.             Blend SrcAlpha OneMinusSrcAlpha
    82.             Cull Off
    83.  
    84.             HLSLPROGRAM
    85.                 #pragma fragment FullScreenPass
    86.             ENDHLSL
    87.         }
    88.     }
    89.     Fallback Off
    90. }
    91.  
    If you still want to use Sample(), then the issue becomes more complex as it's related to the way RTHandle scaling system works. Fixing this requires an understanding of the content of the texture you're sampling the the outline shader and where in the pipeline this texture was generated.

    The outline texture is written in the outline pass, which means that if the outline pass is executed during the "after post process" injection point, the texture will contain data that is not scaled (as after post process is located after the upscaling pass of DLSS / FSR, see the diagram at the end of this page). The problem is that by default the RTHandle system expects you to sample textures that are scaled with DRS (dynamic resolution scaling), which is not the case for the outline object texture.

    This means that you need to remove the DRS scaling from the _RTHandleScale.xy in the shader to be able to sample texture that doesn't have this scaling. This can be done with these lines of code:

    Code (CSharp):
    1.  
    2. float2 scaling = _RTHandleScale.xy;
    3. if (_CustomPassInjectionPoint == CUSTOMPASSINJECTIONPOINT_AFTER_POST_PROCESS)
    4.     scaling *= rcp(_DynamicResolutionFullscreenScale.xy);
    5.  
    We're aware that this is not a good solution and I hope we'll be able to improve the situation in the future using texture aliasing, this will essentially allow us to remove all these different scaling factors from the shader and greatly simplify the number of combinations we have (before/after post, DLSS, Upscaling before/after post, muli-camera with different resolution, hardcoded scale in RTHandles, etc.). One of the blocking problems right now is DX11 which doesn't support texture aliasing.
     
  25. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    is there any way to have a custom pass volume (DrawRenderersCustomPass) to render world space UI without aliasing in DLSS without artifacts? The tricks here are not applicable for this case, I guess.
     
    mons00n likes this.
  26. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
    For World Space UI it's complicated as you typically want it to be rendered after the upscale pass so that text/images don't appear blurry or have ghosting.

    I think there are two main cases here:
    - World space UI that doesn't use depth.
    - World space UI that uses depth information (either for depth test to hide your UI when it's behind objects or make it fade)


    If you don't use depth, it's actually simple as you can just use a regular DrawRenderers pass with the injection point "After Post Process".

    If you need depth, then you need to know which kind of upscaler/Anti-aliasing you're using because depending on this you may not be able to read the depth information correctly.
    The first thing to know is that when TAA, DLSS, TAAU, or path tracing is enabled, the depth texture will be jittered (each frame will contain slightly shifted depth data). We do this jittering by applying a slight shift in the camera projection matrix, this shift is applied at the start of the frame up to the "resolve" (where we stabilize the image using the previous jittered frames) which is usually done during the post processes.
    jittered depth is very hard to use after the resolve happens because we also reset the matrices to non-jittered ones after the post process (so that objects rendered after the resolve don't jitter) which means that rendering a depth-tested objects at this point will cause flickering around the depth-tested values of the objects.

    Technically it's possible to mitigate this visual issue by either accumulating samples over multiple frames like TAA (which introduce ghosting) or trying to "stabilize" the depth value by reading multiple depth pixel and doing the depth test manually. But all these workarounds have downsides, there is no silver bullet.

    The only perfect solution is to re-render the depth of your scene to have a correct depth buffer for your world space UI after the post process, but usually that's way too expensive so not really a solution.
     
  27. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    Not sure if I can follow 100%; does this mean that depth tested world space UI with Dynamic Resolution is currently not possible, at least not with writing a very complicated custom shader which basically implements denoising of jittery depth textures?
     
  28. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
    That is only if you want to manually render your world space UI after the post process and the depth information is jittered (TAA, DLSS, etc.).

    Regular world space UI should work exactly like transparent objects in the world and dynamic resolution is applied to them which introduces blur, etc.

    We currently do not have a solution to render world space UI without dynamic resolution if your depth buffer is jittered.
     
  29. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    Is it planned to implement something like this? Not sure how to do UI properly in XR using dynamic resolution without a way to leave the UI out (it becomes unreadable if e.g. scaling factor is high).
     
  30. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
    Nothing is planned right now because the issue is inherent to the jittering techniques used by most upsamplers. These two things are just incompatible from what I understand.

    You could still rely on a non-jittered dynamic resolution algorithm like FSR, CAS, or Catmull Rom but they have lower quality than DLSS / TAAU.
     
  31. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    would it be possible to use the new Shader Graph feature "exclude material from upscalers" to avoid the issue with world space UI getting either blurred by DLSS or having z / depth issues, by using material for UI (including TMPro) which uses this feature? I briefly tried, but did not see any effect.
     
  32. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
    This option disables temporal effects (anti-aliasing and upscaling) on the pixels rendered with this material, depending on your use case it could work.

    I'd still expect some jittering to happen when your world space UI clips into the depth of the scene though. Maybe that is not that much of a problem, it depends on the content of the scene and you can probably make it less visible by fading the UI when it gets close to the scene depth too.
     
    Qleenie likes this.
  33. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    308
    When it comes to "Screen Space - Camera" and "World Space" UIs used in conjunction with DLSS and FSR2/3 (store package), there really is only one solid solution to deal with jittering and other issues, and that is the lightweight HDRP UI camera:

    GitHub - alelievr/HDRP-UI-Camera-Stacking: Optimized implementation of camera stacking for UI only in HDRP.

    Even though DLSS was working OK overall, as soon as you use a custom Shader Graph for any UI element, the jittering is out of control. On the FSR2 side, it was just jittering regardless of built-in UI shaders vs. custom shader graphs.
     
  34. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    Hey, thanks for the tip! Are you sure this works with world space UI? Al examples in the project seem to be screen space, I wouldn't know how to adapt this to world space UI.
     
  35. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    308
    It works OK for us - you attach the UI Camera script to a second camera in the scene - set the layer to UI. Then set your various canvasses that you want to render, to the UI layer and make sure your main camera does not render UI.

    Of course this is rendered using a different camera, so your UI will appear over everything else - if you want a true world UI such as an interactive UI on a computer monitor in the world, that would just be a regular world UI rendered using the main camera.
     
  36. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    We are using interactable world space UI in HDRP in VR; screen space is not possible to be used in VR at all.

    The issue we are having is that world space UI is being blurred by DLSS or TAA. Using a custom pass volume for UI solves this, but brings new issues, as the depth buffer is not preserved, so world space UI renders above everything else.
    Seems unsolvable with Unity, unless the mentioned exclude material from Upscale helps.

    The UI camera stacking seems to be screen space only, there is a closed discussion about VR support, which got implemented as experimental, but this seems to be more for HUD like display (no interactive UI, as interacting with screen space UI in VR is not possible).
     
  37. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    308
    It's not just screen space UI - like I mention we use it for world space UI and for screen-space camera UI. The catch is, it renders over everything because it is done in a second camera - so this solution won't work for you where the UI is part of the world itself and needs to be obscured correctly.
     
  38. Genebris

    Genebris

    Joined:
    Mar 18, 2013
    Posts:
    141
    Why is that not preserved? It definitely should be available in custom pass.
     
  39. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    see discussion above; DLSS and TAAU are introducing jitter into the depth texture.
     
  40. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    the "rendering above everything" issue is exactly what I want to solve;) Out of curiosity, how would the setup for world space UI look like with the UI Camera from this project; even if I switch the canvas to world space, it's still being rendered in screen space on the main camera; in fact it's rendered double in this case, a second time in world space, but non interactable.
     
  41. mgeorgedeveloper

    mgeorgedeveloper

    Joined:
    Jul 10, 2012
    Posts:
    308
    You may be right about the world-space UI behaviour. I will look into it from scratch again soon.
     
    Qleenie likes this.
  42. Qleenie

    Qleenie

    Joined:
    Jan 27, 2019
    Posts:
    832
    this did not seem to work; if I understand the behavior correctly, it means the material will still be scaled down, just not scaled up by the upscaler. So at DLSS fastest setting you get basically a pixel mess, nearly impossible to read.

    There must be a solution for using an upscaler with world space UI and correct depth rendering, I cannot believe that this is impossible to do....And no, upscalers like FSR 1 won't work with XR, the quality is just too bad. TAAU is barely acceptable, DLSS looks really good.
     
  43. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
    Yes.

    The problem with recent upscaler tech is that you need to jitter the whole frame for them to reconstruct a better image (more sampling points = better quality), which has the side effect that everything rendered post-resolve won't be able to use data that were not resolved by temporal accumulation to remove the jittering.
    Currently, we only resolve the color buffer, so it's the only thing that is in a usable state after the post process, everything else like depth, normals, or any other buffer cannot be used as is without artifacts.

    I see 3 possible solutions for this problem, I didn't experiment with them but I think they have a good chance of fixing this:
    - Do a resolve pass on the depth buffer, essentially this would be the same as applying TAA or TAAU on the depth instead of the color. The algorithm would need tweaking as it's not the same information type and it'll not work with DLSS as it's a black box that only outputs the resolved color. This option would be pretty hard to implement but it'll solve most of the jittering issue and would be performant.
    - Render the whole depth buffer again after the post-process. This will 100% work and it's easy to do but it's very costly.
    - Deal with the jittering by hiding it "artistically" for example it'd be possible to blur the UI when it gets close to the depth values or do multiple samples in the depth buffer to have a more stable depth test overall, etc.
     
  44. Genebris

    Genebris

    Joined:
    Mar 18, 2013
    Posts:
    141
    Can you copy original low res depth buffer into a separate buffer before jittering happens and use that?
    edit: no, I realize now the jittering starts from the first draw call, there's no clean version of it
     
    Last edited: Feb 17, 2024
    Qleenie likes this.
  45. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    249
    Indeed, the jittering is inside the projection matrix of the camera, so every object rendered is jittered.