Accessing normal texture in Shader Graph

I am trying to access and output camera normal texture. I have created a custom render pass feature to use it as a post-processing effect. I want to get camera normals texture in Shader Graph (not by writting a shader as “*.shader” file!). Earlier I was able to access “_CameraDepthTexture” in Shader Graph by creating a new property called “_CameraDepthTexture” and making it non-exposed. But when I try to get “_CameraDepthNormalsTexture” in the same way, it seems that “UnityDefault2D” is returned instead (at least according to Frame Debug window:8379114--1104759--1.png ).
I’ve used this code attached to my main camera:

 private void Start()
{
        Camera cam = GetComponent<Camera>();
        cam.depthTextureMode = cam.depthTextureMode | DepthTextureMode.DepthNormals;
}

It could be that my *.hlsl code that used inside a Custom Function Node to decode this texture is wrong as I was unable to import “UnityCG.cginc”. I’ve wrote DecodeDepthNormal function using this github link as reference: Unity-Built-in-Shaders/CGIncludes/UnityCG.cginc at master · TwoTailsGames/Unity-Built-in-Shaders · GitHub. Here is my HLSL file:

#ifndef NORMALS_INCLUDED
#define NORMALS_INCLUDED

inline float DecodeFloatRG( float2 enc )
{
    float2 kDecodeDot = float2(1.0, 1/255.0);
    return dot( enc, kDecodeDot );
}

inline float3 DecodeViewNormalStereo( float4 enc4 )
{
    float kScale = 1.7777;
    float3 nn = enc4.xyz*float3(2*kScale,2*kScale,0) + float3(-kScale,-kScale,1);
    float g = 2.0 / dot(nn.xyz,nn.xyz);
    float3 n;
    n.xy = g*nn.xy;
    n.z = g-1;
    return n;
}

inline void DecodeDepthNormal( float4 enc, out float depth, out float3 normal )
{
    depth = DecodeFloatRG (enc.zw);
    normal = DecodeViewNormalStereo (enc);
}

void DepthNormals_float(float2 uv, out float depth, out float3 normal)
{
    depth = 0.0f;
    normal = float3(0.0f, 0.0f, 0.0f);

    float4 depthnormal = _CameraDepthNormalsTexture.Sample(sampler_CameraDepthNormalsTexture, uv);
    DecodeDepthNormal(depthnormal, depth, normal);
}

#endif

Shader Graph implementation:

I am using Unity 2021.3.6f1 with default URP setup. Custom render pass feature seems to be implemented right as other post-processing effects work (as I mentioned I was able to output depth from “_CameraDepthTexture” earlier). I don’t get any Shader related errors in Unity, both “depth” and “normal” output black. Has anyone else tried to use “_CameraDepthNormalsTexture” in Shader Graph and output its normals texture to the camera? How should I do it? Any help and suggestions is appreciated.

Bump. Its a bit maddening how difficult it is to do this in URP. Does anyone have a working example for unity 2021.3?

Okay, I was able to finally get this working in Unity 2021.3.5f1 URP.

In your ScriptableRendererFeature:

public void Setup(ScriptableRenderer renderer) {
    ConfigureInput(ScriptableRenderPassInput.Normal);
}

And then in your custom function node:

#if !defined(SHADERGRAPH_PREVIEW)
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"
#endif

void SampleNormals_float(float2 UV, out float3 Out) {
  // Preview redefines _Time in a way that will throw a compile error on this import.
  #if !defined(SHADERGRAPH_PREVIEW)
    Out = SampleSceneNormals(UV);
  #else
    Out = float3(0, 0, 0);
  #endif
}

Note we have a different codepath for shadergraph preview as it throws a compile error due to a variable redefinition, not sure if there’s a way around that.

4 Likes