We’ve just switched our project from the built-in rendering to URP because our artist needs it to use Shader Graph. After fixing all the materials and the camera settings, everything seems to be working fine except for the full-screen blur we were using.
This is our setup before the transition:
Background Camera
Main 3D Camera
Main UI Camera
Blur Camera
Foreground UI Camera
Tooltip Camera
Blur Camera didn’t render any objects, it just had the following script on it:
This way everything except for the foreground UI and the tooltips was blurred when we enabled this camera.
Now, as I understand, OnRenderImage will not work with URP. So how do I achieve the same effect? I’ve very little experience working with graphics but as I see it I just need a place to plug the old blur shader. Could you please help me or at least point me in the right direction?
I’ve created a ScriptableRenderPass script and I guess I’m supposed to implement the Execute method and use ScriptableRenderContext somehow but I don’t exactly understand what I should do with it. Is there a code example somewhere maybe?
Thanks. I’ve been able to apply it to full screen but I still can’t figure out how to make it apply to the camera I need. It seems that depending on renderPassEvent it is applied either before the last camera or after all the cameras but I need it specifically between Main UI Camera and Foreground UI Camera. It’s still all very confusing and I can’t find any documentation aside from the API reference which doesn’t really explain anything.
I still haven’t been able to figure out how to do it.
Also, I tried using Bloom as described here: Bloom | Universal RP | 7.3.1
But it seems to only apply to the base camera. What am I missing here?
Edit: Nevermind the bloom issue. I had to check “Post Processing” in the other cameras’ settings. Now it works. Blur still doesn’t, though.
Another issue is that it wont apply on UI, as all canvas UI element are come with a transparent shader, and this urp_kawase_blur doesn’t work with transparent objects. Anybody can show us a right direction? There is no any documentation how these things work. I’m searching a workable blur shader/shadergraph which can work with transparent UI objects over a year from now, and there is none. (URP or LWRP not built in renderer)
I don’t want anybody gives me a full working code here, but I’m lack of shader hlsl coding, or maybe I (as many others it seems) miss some options with SRP forward renderer options… also there are stencil override option, which I could find any proper docu what are those things and how it works. Is there anything to do with transparent elements (UGUI)? Or these whole approach are bed?
I found this thread as I was searching for a solution to this as well. I managed to find a way that worked for me, based on the URP_Kawase_Blur example posted here. So I’ll share it in case it is useful for others as well:
I made it easier to work with on UIs. You only have to switch the material of a UI element to give it a blurred background. Otherwise it should match all the features of a normal Unity UI element. This approach also allows for all scene elements to be blurred and as such can include transparent objects.
It however does not support blurring of other UI layers yet. If you don’t care about transparent objects this can be achieved though: switch the render feature itself to before transparency and using two canvases. One in the default overlay mode for the non-blurred elements and one in the in-world mode for the blurred elements underneath. (If you need both blurred UI and transparent object to show up it’ll become significantly harder though)
Is it possible to acess the RenderFeatures via script? For example, In case I want to animate it to gradually blur (increase value of blurPasses in runtime), is it possible? Thanks!
Haven’t had the need to do that yet, so I’m not sure, though I expect that should be possible.
One limitation that will be there though is that the way the blurring is implemented, means that blur size scales in integer steps, so you’ll either have to animate it pretty fast to not make that obvious or you might see steps in the animation progress.
We can see that the blur shader and forward renderer script will not allow to show transparent objects (alpha-channel).
Not only behind UI element (this is a UI panel with a “Behind Text”) but any transparent game object. (blue transparent cube).
This shader and SRP script will get through only opaque pixels. So in this terms of subject, it’s useless. I’m sorry.
However, as I said, a more expert programmer or Unity dev help needed!
How can we alter this shader to allow to show transparent objects?
It seems like you just looked at the original Kawase Blur example instead of my edited version. The whole point of those edits was to support the changes you are asking for. Here’s a recreation of your example to show this:
@Arnage_nl Thanks a bunch for making this work with transparent objects, I’ve been trying to wrap my head around this for some time now. Do you know of a solution that would work on world space 3D objects, like a simple plane?
That should work, assuming your UI is rendered in screenspace on your second camera. Overlay UI is always rendered on top and can only read the blur texture and not influence it. See below for an example of using stacked camera’s with this effect. Can you elaborate on your specific setup? (Also sorry for the late reply, I missed this message and only noticed it due to Gandarufu’s reply)
The main problem is the limited control Renderer Features give over the rendering order. You can either activate it before translucency and thus miss out on anything transparent or after, but then the object that you want to render with is is already rendered so it can’t access a rendertarget that isn’t there yet. Ideally Unity would make this order more granular as it is in materials, but I guess that is a limitation of the way they implemented them.
The only solution that I know of is to use camera stacking now that that is available in URP. A second camera can render a 3D object that samples the blur texture form the base camera. Note however that, as this is an overlay camera, these objects don’t occlude behind objects rendered by the base camera. An advantage of this approach is that it also allows multiple layers of blurring, allowing you to put another blur layer on the overlay camera.
Here’s an example of this: The third cube is rendered with an overlay camera and blurs everything rendered by the base camera (including screenspace UI) and it is itself blurred again by the second blur pass on the overlay camera to get the blurred background for the final UI rendering.
Note: to do this you have to upgrade the project to 2019.4 as the branch I posted was made with 2019.3 which did not yet support camera stacking.
Hi @Arnage_nl
Thanks a bunch for your input on this That sounds exactly like what I’m looking for. I have an overlay camera that renders objects that are being examined. I was looking for a way to blur the entire screen in the background with a simple plane (also including transparent objects).
Now, your screenshot proves that it’s possible. I only need to figure the setup out. Is there any way you could include your 3 cube scene in your repository, if you have a minute?
I’d appreciate it very much! Thanks a lot for putting so much effort into this common problem a lot of people seem to have.
Edit: Never mind, I figured it out Hooray!! You’re a lifesaver!
This is one good looking blur. Now for the performance: is this bluring the entire frame and putting the entire frame inside a global texture?
Or, when used in UI, does it only blur the portion that’s covered by the blur UI?
Judging from the kawase blur render feature, it does a full screen blur and the UIBlur shader just samples _blurTexture made from kawase blur. So, nope.
Arguably, performance would be poor if only a small part uses blur, very good if there a multiple ui components that uses blur. Traditional grabpass blur method grabs texture and blurs it per item which allows fine tuned blurs that can differ per item but at a cost.
It already has built in downsample option so downsizing it to 1/4 and running 2 passes should be performant. ( honestly downsampling and upsampling is blur itself, just not as good ).