Will Camera Depth Normal Textures be added fto urp?

I’m curious if the built in pipeline’s Camera Normals Texture feature will be added later to the universal render pipeline. I’m mostly using it for a Sobel filter but I know its also useful for an number of other post processing effects.

I found an solution for a renderer feature that adds one here Redirecting… ,
But Going through the trouble of setting up a global texture using a shader in hidden/internal seems like an awkward solution to a problem that should probably have built in solution considering how useful Camera normal textures seem to be.

Also if any one had a more elegant solution for retrieving the normals of a pixel on camera I’d really appreciate it

1 Like

Still, there are so many missing features in URP.

1 Like

Normals got added with SSAO to 10.x.

If you have a renderer feature you can call
ConfigureInput(ScriptableRenderPassInput.Normal);

And it will generate a prepass providing you with the texture. And then in your shader have this include:
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareNormalsTexture.hlsl"

that will give you access to

LoadSceneNormals(uint2 uv)```
8 Likes

Good news! Thank you!

forward only uh, does it cost 2x drawcall like in built in?

@Elvar_Orn sorry for the dumb question, but how to use the normal texture in custom shader without renderer feature?

In documentation says

I looked at sources of urp 10.x but unfortunately, I’m not so good to understand how to make it works similar to _CameraDepthTexture.

UOD: I tried to add pass like in Lit.shader but it doesn’t change anything.

1 Like

How do you use it without scripts? I have custom shader, I added “DepthNormals” pass from Lit to my custom shader. Then in another shader I sample from _CameraNormalsTexture using SampleSceneNormals, but I allways get empty data, no sceen normals (red color). Also when I use Lit shader on objects I still cant get anithing from SampleSceneNormals. Am I should enable it somewhere?

So. IF I add SSAO then it works. How do I enable render to _CameraNormalsTexture without adding SSAO to renderer?

3 Likes

I am very happy that I found this thread. I needed access to the CameraNormalsTexture for the normal direction masking of some amplify decal projectors. I duplicated the SSAO renderer feature and stripped everything away except for the ConfigureInput line which results in a renderer feature that triggers rendering to the CameraNormalsTexture and absolutely nothing else (and does not add more draw calls or sth similar if SSAO is used).

using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;


[DisallowMultipleRendererFeature]
[Tooltip("The Scene Normals pass enables rendering to the CameraNormalsTexture if no other pass does it already.")]
internal class SceneNormals : ScriptableRendererFeature
{
    private SceneNormalsPass m_SceneNormalsPass = null;

    public override void Create()
    {
        if (m_SceneNormalsPass == null)
        {
            m_SceneNormalsPass = new SceneNormalsPass();
        }
    }

    public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
    {
        m_SceneNormalsPass.Setup();
        renderer.EnqueuePass(m_SceneNormalsPass);
    }


    // The Scene Normals Pass
    private class SceneNormalsPass : ScriptableRenderPass
    {
        public void Setup()
        {
            ConfigureInput(ScriptableRenderPassInput.Normal); // all of this to just call this one line
            return;
        }

        public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData) { }
    }
}
5 Likes

Thanks!

One issue I’m having is that when I use this, terrain has issues with the depth buffer. This is how it should look like (water shader accesses depth buffer to render foam)

8111312--1050572--upload_2022-5-8_15-3-15.jpg

But with that feature added, the foam is gone. Would you have any idea why this happens? (only happens for terrain)

@alexanderameye

So I tried figuring that out but I think I really only have like a semi 80% ish good answer unfortunately.
I made that script based on the urp version in unity 2021.2 and I believe the depth normals texture is not really considered production ready outside of the ssao effect and maybe decals (which in that version were not final either).

I rewrote the following part 3 times now because everytime I thought “this is the reason” I realized it was something else.
Good news it does work. Bad news it’s a bit annoying.

As I noticed that the Stylized Water Asset does not support 2021 yet I hence checked this in 2020.3.34f1 in the “Water Demo” scene. First of all _CameraDepthTexture seems to be renamed to _CameraDepthAttachment in 2021.2, fine.
But switchting between Depth and DepthNormals as source for SSAO either renders a DepthPrePass or has no specific draw calls for depth normals at all… at first… until I enabled shadows on the Directional Light once and set the Floor Material to URP/Lit (instead of Unlit), since then the DepthNormalsPrePass gets executed correctly and foam and other depth effects show up.


The shadow part is probably irrelevant what isn’t is that Unlit shaders don’t have a depthNormals pass and since no shader has one the draw calls don’t show up at all. So if you want to use the depthNormals Texture all shaders that would write to it have to support it as well, there is no fallback to depthOnly.

This part in implementation details led me somewhat in the right direction: Ambient Occlusion | Universal RP | 10.9.0

Random side note: DepthNormals texture is not getting MSAA in 2021.2 if you don’t have Depth Priming enabled but that is by default on in lower versions it seems.

By way huge fan of the asset, very nice work.

These people renaming things in urp need to be dealt with. It’s so exhausting tracking stuff like this down!

3 Likes

So what does Sample URP Buffer node do in ShaderGraph do we have to do anything for that to work ? Theres no docmentation on it at all…

How do we use this in shader graph so we can sample scene normals ? Been trying to work that out for ages…

You add the renderer feature and then in your shader graph you need to sample the globally declared _CameraNormalsTexture (the name and reference needs to match this exactly).
Edit: Oh an be aware that the _CameraNormalsTexture contains worldspace normals, you might need to transform those into object / tangent space depending on what you want to do.
8647917--1163418--upload_2022-12-9_10-29-7.png

8647917--1163421--upload_2022-12-9_10-31-50.png

Omg thank you so much, spent all day reading the documentation and couldn’t figure out how to do any of this.

I must be missing something because everyone else seems to know what they are doing except me lol

ehhh I know the feeling very well, hits me every day too. I guess thats normal if you work on something you haven’t done exactly like this before.

The camera normals texture stuff behaves very similarly like you would access this in the built in pipeline, having some knowledge from when I mainly used that helps. Although I always expect SRP to do everything differently.

I never really touched built in sadly.

But why shader graph has a scene depth node but no scene normal node, and in order to enable scene normals we have to write C#. This stuff should just be in there for us so we don’t have to write boiler plate code just to use a texture. And I would’ve never figured out the C# code I would have had to write to enable depth normals either. It was lucky I found this thread.

I agree in so far that generating the camera normals texture should be a toggle in the urp asset, same as depth texture.
They probably wanted to omit a normals texture from urp in the beginning (because creating it somewhat expensive because you render every object again to a separate buffer). Afaik it appeared first with the SSAO effect which absolutely needed it.

Edit: Uhh just found your post about the undocumented sample buffer node. If it works that obviously is an option as well (but still needs to renderer feature to populate the buffer first)