Is it possible to have transparents using the 2D renderer in URP?

Hi! I started using the URP for the 2D lights package and it’s been really enjoyable so far. However, I’m unable to make a screen-space distortion effect (which utilizes a custom shader on a hopefully transparent object) with the 2D renderer that’s necessary to use if you want the 2D lights & shadows. I want to know if it’s possible, which it really seems like it should be, but I can’t figure it out.

My main question is, how do I mark an object as transparent for the 2D renderer in URP?

I’m able to get the screen-space distortion effect with a Forward Renderer instead by following this tutorial. With a Forward Renderer you can make a new layer and then specify that layer to render after the others inside the “Render Features” settings, which doesn’t appear to exist with a 2D renderer. But the problem with using a Forward Renderer is that 2D lights & shadows don’t work anymore.

As a different workaround for getting the same effect while using the 2D renderer, I’ve also tried to have the shader run directly on the camera by using this script attached to the camera, but it doesn’t seem to do anything:

public class ScreenWideEffect : MonoBehaviour
{
    public Material material;

    public void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Graphics.Blit(source, destination, material);
    }
}

Here’s the shader graph I’m using, if it helps:
1 - the shader for an object I wanted to make transparent and put in the scene on top of other stuff
2 - slightly modified to take in the _CameraOpaqueTexture, so it can distort that and blit to screen

I also tried setting up both a 2d renderer and a forward renderer but I can’t seem to get the 2d renderer to render my should-be-transparent object as a big grey square. Which makes sense because I couldn’t find a setting that looked like it should tell the renderer that object is different and should be rendered afterwards.

So my questions are, in order of importance,
A) Is it possible to make a transparent object with the 2d renderer?
B) Is there some other way to get a screen space distortion effect while using a 2d renderer?
C) Alternately, is it possible to get 2D lights & shadows without using the 2d renderer?
D) What am I doing wrong with my OnRenderImage() script above, or with my multiple-renderer setup?

A) No. What you need for these effects is the opaque texture feature available in the Forward Renderer. 2D Renderer doesn’t support this currently, but we have plans to implement it.

B) Use multiple cameras. The first camera renders the scene to a render texture, then in the second camera sample the render texture and do the distortion. Our new 2D demo project uses this technique for water reflections: https://assetstore.unity.com/packages/essentials/tutorial-projects/lost-crypt-2d-sample-project-158673

C) No.

D) OnRenderImage() is not supported by any SRP.

1 Like

Awesome, thank you so much! The only thing I had found was this: Multiple questions about the 2D Renderer. Been researching for weeks and can't find info / solution where the suggestion was to fork the 2d tenderer and write your own thing which seems WAY harder.

Sorry to hijack I’m just confused by the answer to A). It’s not possible to make a transparent object with the 2D renderer? Aren’t all sprites by default on the transparent render queue, or am I misunderstanding the question?

If I understand correctly, you’re right that all sprites are on the transparent render queue by default.

What my question should’ve been is something like “is it possible to make a sprite that will render after the other sprites” to which the answer is no.

1 Like

Ah yeah. I was hoping with SRP we’d be able to basically script it so we’d basically be able to make our own version of _CameraOpaqueTexture at a custom moment in the pipeline. Essentially like grabpass in the built-in render pipeline except not as devastating performancewise.

Hello!
Any news by any chance on this?
Currently on 2019.3.5f1 and marvelled at how well 2D Renderer works with composite shadow casters and all even in low-ish end devices.

However, was interested in this very same feature, wondering if it is coming soon or already implemented in further versions.

Would rather go with A. and be done with it (if it is to be implemented anytime soon) or go the Scriptable Renderer Features (if it is to be implemented also) and have control on ‘when’ to create the opaque (or equivalent) texture for the sprites.

B. would work, however it requires a bit of a dual camera setup to make the post processing effects work on a final rendered texture (the mix of a first camera RT base fullscreen sprite, the distortion effects overlaid, let the pipeline work post effects like bloom and vignette and others). Certainly not that complicated and on the easy side to do but would be the last option.

Thanks a lot in advance.

We still haven’t implemented the opaque texture feature for the 2D Renderer, but we are very close to starting.

1 Like

The “opaque texture” feature is now implemented as it’s being tested, though the final name of this feature might be something else.

I’m extremely interested about this, that last message really made my heart beat (I have been googling regularly to see if this will be implemented for a very long time now), I just checked and I assume that it didn’t make it through yet? Anyone knows anything about this? @Chris_Chu ?

Nothing about it in the 2020.1 or 2020.2 release notes.

Its in 2021.1. There is a new variable called _CameraSortingLayersTexture. This can be enabled by going to the 2D Renderer Data. You can get it in the latest beta.

I would definitely appreciate hearing any feedback.

Why is it called _CameraSortingLayersTexture if it’s just the opaque render target? It probably should get called whatever it’s largest use-case might be, or by what it actually is… that name doesn’t really leap out to developers wanting an opaque texture if skimming any (eventual) docs.

“There are no plans to support _CameraOpaqueTexture. We have instead created a new shader variable called _CameraSortingLayersTexture which will contain layers rendered from back to front, up until a specified layer. The upcoming release of URP 11 should have it.” -Chris_Chu from another thread.

1 Like

Yeah I get that, but it is also compatible with just the one layer, so it’s basically describing potential usage instead of what it actually is as an object.

Not an issue for me, was just feeding back.

_CameraSortingLayerTextures was added to allow more flexibility with the 2D rendering workflow, by allowing users to render from the back-most layer to a selected layer and saving that into a texture.

This was needed because sprites are by default all transparent and overwriting the _CameraOpaqueTexture after rendering transparency, would be confusing to users, unless they already know what _CameraOpaqueTexture does.

Additionally, overwriting the _CameraOpaqueTexture could cause potential problems in the future if we plan to support mixed 2D/3D rendering.

1 Like

Thanks for the explanation, I guess it’s no problem if it’s documented.

Would this mean it would be possible to emulate the current GrabPass functionality for transparents by using _CameraSortingLayerTexture?

As in would it be possible to specify multiple sorting layers during the rendering process and saving each into a texture? Or is it limited to only 1 specific sorting layer using only that 1 built-in texture variable?

thanks for the info @Chris_Chu , super happy to see Unity giving this some love, unfortunately I don’t see to be able to make it work, This is literally the only thing that shows up on google when searching for this new variable so I’m sure that a little step by step guide will benefit the whole community for years to come as it is likely to stay up there.

I have a test project that is working with CameraOpaque and Forward renderer, when I replace the CameraOpaque variable for the one you mentioned and change my forward renderer for the 2D renderer I can see the effect working in the preview window of shader graph (just like I could see the effect of _CameraOpaqueTexture) but in game I get the same result that _CameraOpaqueTexture were giving me with the 2D renderer (working fine with the other renderers), only the colour changes (just a semi-transparent black sprite), any chance of getting a little git sample where this node is up and running? This is how I have this set up:

in my shader graph (which seems to display the correct effect), I just put this variable in the node as a texture where I use to have the camera opaque one (tried with both, and ‘s’ and without an ‘s’ at the end, noticed that you mentioned both):

6813245--791198--upload_2021-2-7_22-28-10.png

then in the renderer I turn it on, pointing to a default layer:

6813245--791201--upload_2021-2-7_22-29-43.png

my background is opaque (in the default layer):

6813245--791204--upload_2021-2-7_22-30-59.png

the sprite with the _CameraSortingLayerTextures material is transparent (it is also in the default layer):

6813245--791207--upload_2021-2-7_22-31-50.png

tried experimenting with different values but nothing seems to bring it back to live, am I missing something?

thanks for your time!

You choose a range of layers starting from the back and they are rendered into a built-in texture variable. The functionality is similar to how _CameraOpaqueTexture works for 3D.