Search Unity

Feature Request VFX Collide With Depth Buffer in URP?

Discussion in 'Visual Effect Graph' started by naelstrof, Feb 17, 2021.

  1. naelstrof

    naelstrof

    Joined:
    Sep 12, 2017
    Posts:
    22
    I spent some time trying to get the node to work within the LTS version of URP and the Visual Effects Graph (7.5.3). It didn't work, but it seems like it should work.

    I started writing a VFX binder that tried to inject the camera information it needed, simply converting the HDRP version-- but I got stuck and decided to try upgrading.

    After upgrade I now get this handy message that it's simply not supported! Well crap!


    Though it seems like it should be possible for it to work provided that the depth buffer is bound properly. Is there anything I could do to get it to work? Or is it something in the works that I could wait for? It'd be really handy for weather effects!
     
    OccaSoftware and PutridEx like this.
  2. VladVNeykov

    VladVNeykov

    Unity Technologies

    Joined:
    Sep 16, 2016
    Posts:
    550
    Hey @naelstrof ,

    I believe if you switch the Camera field to a custom one, and you manually supply a depth texture (by exposing a Texture2D in blackboard), you should be able to make it work.

    The implementation of automatically binding the camera buffers in URP is missing at the moment, but if you set everything else to match your camera and manually supply a depth texture, it should work.
     
    MagiJedi likes this.
  3. naelstrof

    naelstrof

    Joined:
    Sep 12, 2017
    Posts:
    22
    Thanks so much! Right now it seems like it requires a Texture2DArrray, and I'm struggling to figure out why. Though I'll poke around with trying to pass my depth texture as a variety of different Texture2DArrays and see what happens.
     
    Last edited: Feb 17, 2021
  4. naelstrof

    naelstrof

    Joined:
    Sep 12, 2017
    Posts:
    22
    I figured it out! I just made the following edits to the Visual Effects package:
    com.unity.visualeffectgraph@7.5.3/Editor/Types/VFXTypes.cs:
    Code (CSharp):
    1. // Line 300, switched this
    2.         [Tooltip("The depth buffer of the camera, containing the rendered depth information.")]
    3.         public Texture2DArray depthBuffer;
    4.         [Tooltip("The color buffer of the camera, containing the rendered color information.")]
    5.         public Texture2DArray colorBuffer;
    6. // With this:
    7.         [Tooltip("The depth buffer of the camera, containing the rendered depth information.")]
    8.         public Texture2D depthBuffer;
    9.         [Tooltip("The color buffer of the camera, containing the rendered color information.")]
    10.         public Texture2D colorBuffer;
    11.  
    com.unity.visualeffectgraph@7.5.3/Editor/Expressions/VFXExpressionCamera.cs:
    Code (CSharp):
    1. // Line 158, I switched this:
    2. sealed protected override VFXExpression Evaluate(VFXExpression[] constParents) { return VFXValue.Constant<Texture2DArray>(null); }
    3. // With this:
    4. sealed protected override VFXExpression Evaluate(VFXExpression[] constParents) { return VFXValue.Constant<Texture2D>(null); }
    5.  
    com.unity.visualeffectgraph@7.5.3/Editor/Models/Blocks/Implementations/Collision/CollisionDepth.cs:
    Code (CSharp):
    1. // Basically replaced all texture array lookups with standard ones.
    2. // I'll go over each line and its replacement anyway for clarity:
    3. // Line 97, switched
    4. float depth = LoadTexture(Camera_depthBuffer,int4(uv*Camera_pixelDimensions, 0, 0)).r;
    5. // with
    6. float depth = LoadTexture(Camera_depthBuffer,int3(uv*Camera_pixelDimensions, 0)).r;
    7.  
    8. // ...
    9.  
    10. // Line 123, switched
    11. float depth10 = LoadTexture(Camera_depthBuffer, int4(depthPos10, 0, 0)).r;
    12.         float depth01 = LoadTexture(Camera_depthBuffer, int4(depthPos01, 0, 0)).r;
    13. // With
    14. float depth10 = LoadTexture(Camera_depthBuffer, int3(depthPos10, 0)).r;
    15.         float depth01 = LoadTexture(Camera_depthBuffer, int3(depthPos01, 0)).r;
    16.  
    17.  
    Then I created a default VFX graph with these settings:


    And used a custom binder to just-- set a property to the _CameraDepthTexture global:
    VFXDepthBinder.cs
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Rendering;
    5.  
    6. namespace UnityEngine.VFX.Utility
    7. {
    8.     [AddComponentMenu("VFX/Property Binders/Depth Binder")]
    9.     [VFXBinder("Depth/Depth")]
    10.     class VFXDepthBinder : VFXBinderBase {
    11.         public string Property { get { return (string)m_Property; } set { m_Property = value; UpdateSubProperties(); } }
    12.         [VFXPropertyBinding("UnityEditor.VFX.Depth"), SerializeField, UnityEngine.Serialization.FormerlySerializedAs("m_Parameter")]
    13.         protected ExposedProperty m_Property = "DepthTexture";
    14.         private ExposedProperty DepthBuffer;
    15.         private Texture depthTexture;
    16.         protected override void OnEnable() {
    17.             base.OnEnable();
    18.             UpdateSubProperties();
    19.         }
    20.  
    21.         void OnValidate() {
    22.             UpdateSubProperties();
    23.         }
    24.  
    25.         void UpdateSubProperties() {
    26.             DepthBuffer = m_Property;
    27.         }
    28.  
    29.         public override bool IsValid(VisualEffect component) {
    30.             return component.HasTexture((int)DepthBuffer);
    31.         }
    32.  
    33.         public override void UpdateBinding(VisualEffect component) {
    34.             if (depthTexture == null) {
    35.                 depthTexture = Shader.GetGlobalTexture("_CameraDepthTexture");
    36.             }
    37.             component.SetTexture((int)DepthBuffer, depthTexture);
    38.         }
    39.  
    40.         public override string ToString() {
    41.             return string.Format("Depth : '{0}' -> {1}", m_Property, depthTexture == null ? "(null)" : depthTexture.ToString());
    42.         }
    43.     }
    44. }
    And it works!

    There was only a couple of gotchas:
    1. it doesn't work in the editor (unless you're playing).
    2. The camera(s) needs to be tagged as "MainCamera".
    3. And finally the Camera portion of the CollideDepth node needs to be set to worldspace (W instead of L, easy to miss).

    I've also published my changes to a fork on github here: https://github.com/naelstrof/com.unity.visualeffectgraph/tree/7.5.3-cwdb-urp
     
    Last edited: Feb 18, 2021
  5. jonas0jacobsen

    jonas0jacobsen

    Joined:
    Apr 30, 2019
    Posts:
    1
    Holy moly thank you so mutch!
     
    naelstrof likes this.
  6. naelstrof

    naelstrof

    Joined:
    Sep 12, 2017
    Posts:
    22
    As a follow up, if you need a camera that isn't the main camera. I wrote an extra CameraBinder here:

    https://github.com/naelstrof/com.un...ertyBinding/Implementation/URPCameraBinder.cs

    It requires you to set the Camera to output to a RenderTexture, and to specify it to the binder, but it works! The gotchas for this one is that the Camera MUST be in perspective mode, and the RenderTexture needs to be outputting depth.
     
    lilacsky824 and laurentlavigne like this.
  7. Kwahusss

    Kwahusss

    Joined:
    Sep 21, 2015
    Posts:
    13
    In new Unity input Depth buffer have grey input, when output 2d Sampler have red input. Anybody knows how to connect them now?
     
    Glutax likes this.
  8. Ervo

    Ervo

    Joined:
    May 26, 2016
    Posts:
    8
  9. naelstrof

    naelstrof

    Joined:
    Sep 12, 2017
    Posts:
    22
    I stopped maintaining the branch because it was such a hassle. I did describe all the changes that need to happen in post #4 though! Sorry!
     
  10. Ohmnivore

    Ohmnivore

    Joined:
    Dec 16, 2013
    Posts:
    5