Getting the texture for screen space shadows [URP]

Hello, I am kind of new to shaders (my most advanced effect is a wiggly sobel outline effect)

Anyways, I wanted to add some cool effects to my shadows and there’s a texture in Unity called _ScreenSpaceShadowmapTexture. From my understanding, I can create lots of cool effects by multiplying my texture to this.

However I am not sure how to access this. Preferably I’d like this texture in a shader graph. So I have been trying to get it in RenderTexture somewhere.

My past attempts:

First, I tried to access the texture in my shader graph itself by using Texture2D Asset and referecing it as _ScreenSpaceShadowmapTexture (it didn’t work, I was getting an error that my texture was already defined.

Next, I came across some posts that directly reference the texture itself and copy it using Blit. But it seems like it stopped working based on this post.

In the end, I was able to use the following code to write some cameraColor information to my render texture.

        RTHandle camColorhandle = renderingData.cameraData.renderer.cameraColorTargetHandle;

Is there a way to get screen space shadow texture in this renderingData stage? I also tried to write some low level shaders but I am not that familiar with them, and my attempts gave me gray textures. Is there an easy way to get this texture? Sorry if some of the things that I said didn’t make too much sense! I learned about Blit, CommandBuffer and everything by trying to solve this issue haha

Thanks

Some additional links:

  1. Someone suggests cmd.SetGlobalTexture method
  2. Someone suggests Blit method (it gave me gray texture)
  3. Someone trying to use that texture as a reference in Shader Graph

There you go. This will copy _ScreenSpaceShadowmapTexture into your RenderTexture. In my case it’s called shadowMapCopy, as you can see. :

    [RequireComponent(typeof(Camera))]
    public class ShadowMapper : MonoBehaviour
    {
        #region ❐  Properties and fields
        
        public RenderTexture shadowMapCopy;
        private Camera _camera;
        private static readonly int ScreenSpaceShadowmapTexture = Shader.PropertyToID("_ScreenSpaceShadowmapTexture");

        #endregion
        private void OnEnable()
        {
            RenderPipelineManager.endCameraRendering += CameraRender;
            _camera = GetComponent<Camera>();
        }

        // Unity calls this method automatically when it disables this component
        private void OnDisable()
        {
            RenderPipelineManager.endCameraRendering -= CameraRender;
        }
        
        void CameraRender(ScriptableRenderContext context, Camera renderingCamera)
        {
            if (renderingCamera != _camera) return;

            var rt = (RenderTexture) Shader.GetGlobalTexture(ScreenSpaceShadowmapTexture);
            if (!rt) return;
            
            var myCommandBuffer = new CommandBuffer();
            myCommandBuffer.Blit(rt, shadowMapCopy);
            
            context.ExecuteCommandBuffer(myCommandBuffer);
        }
    }
2 Likes

Thank you for your response, I really appreciate it. I linked your answer in my original question too. However this seems to give me a completely blank render texture :frowning: Are you on unity version 2022?

The steps to create render texture are following, correct?

Project → Right Click → Render Texture → Attach to property

Interestingly, there seems to be correct data in the rt variable if you look over here

So I am not sure why it’s giving me a black render texture. Either I am setting something incorrectly, or Blit isn’t working. I messed around with my render texture settings too but it seems to not change anything. I appreciate your help :slight_smile:

I’m on 2022.3.24f1 and this works.

To create a render texture, use context menu in your project Create -> Render Texture then assign it to the shadowMapCopy property of this script in inspector by drag & dropping.

This script must be attached to your camera which does the rendering.

You also have to add the ScreenSpaceShadows in your renderer feature list, in your assigned URP renderer, which also has to be chosen as the renderer within your camera.

Read this Screen Space Shadows Renderer Feature | Universal RP | 13.1.9

Yep,

  1. I created Render Texture
  2. I attached script to my main camera
  3. I assigned Render Texture property properly
  4. My camera’s renderer is set properly
  5. ScreenSpaceShadows is added to my renderer as a feature
  6. I’m on Unity 2022.3.17f1
  7. I am using forward renderer

And to confirm everything, it seems like I can see the texture in my frame debugger as well.

The only things that I can think of:

  1. Could it be because RenderTexture properties are different? Do these seem right to you?

  1. Do my renderer settings seem correct?

  1. Finally, here are my camera settings:

I think if all that seems correct to you, I might try to change Unity versions as this one seems to be cursed and I want my textured shadows haha. Thank you for helping me

It all indeed seems correct. Did you try settings a breakpoint in CameraRender method to check that it actually runs? It seems like nothing gets blitted in your case.

Also, do you see the unnamed command buffer in your frame debugger?

To answer your first question, yep CameraRender() function seems to be running per-frame because my logs that I showed you earlier are inside it

About your second question, I don’t see any command buffers in my frame debugger.

Could it be that our command buffer isn’t executing? I wish I knew more about Blits and CommandBuffers to debug this :face_with_spiral_eyes:

Edit: Here are some of the variables when I put a debug point near the end of CameraRender() function

It seems like that command buffer is created with correct info. The only thing which jumps at me is that rt’s ‘active’ variable is set to null

Yep, seems like that’s exactly the problem. Your command buffer isn’t being executed. That’s a good direction to dig into further.

You have the proper state within the rendering pipeline, you get the data because your RT isn’t null and we see no unnammed command buffer with your render texture in the frame debugger.

1 Like

@HikeOnARainyDay I did some research and the only difference I see is that I render with multiple cameras, while you have only one camera and my camera with shadow map copy blit command is not the last one. So maybe it gets automatically submitted. Maybe you need to explicitly submit the command buffer? Look at this example

Here’s how my rendering with multiple cameras happens

It’s really AFTER the camera is done with all its passes.

2 Likes

You sir are absolutely goated!!! If I add any cool shadow effects in my game, you’ll be in the credits!!

Adding a simple context.Submit() fixed it for me, thanks a lot!

On a slightly unrelated note, how do I get into CommandBuffers, RenderTextures and ScriptableRenderPipeline side of things in Unity? It seems like the API is constantly changing and I can’t find many tutorials on them. I tend to learn best through tutorials/courses, do you recommend any?

Thanks again :slight_smile:

Nice! Glad that it worked for ye :slight_smile:

To be honest, all the courses and answers online date so fast, it’s hard to find something that’s gonna work right out of the box most of the time, unless it’s super trivial. And you’re already kinda in it, if you’re working on this stuff.

One of my favorite tutorials is probably Unity C# and Shader Tutorials I usually skim through his stuff and ofc package docs themselves, because they’re versioned and also have a lot of good examples as well Universal Render Pipeline overview | Universal RP | 11.0.0

Cheers!

2 Likes