URP + custom Post process ... is it possible? (unity 2020.1.6f1 issue)

Hi guys!

I was wanderin if it is possible to create custom post processes with URP setup on unity 2020.1.6f1

I was able to do it with 2019.3 (using “render features” and injecting the shader) but since 3 days I’m struggling with the latest unity (2020) without being able to reach any result.

Of course I tried the same post-process system that was working on the previous unity version (2019) but it is not working now …quite annoying I must say

If you ask me… it looks like the “render features” are not working now.

does someone know something about this?

I’ve been using renderer features in 2020.1 and now in 2020.2 beta and they totally work. What exactly is not working for you?

Rendering a custom full screen postfx mainly.

Something like this for instance:

https://www.youtube.com/watch?v=77Lc43yTREo

On 2020 my result is a black screen (was working fine on 2019 like I said)
However as soon as I disable the renderfeature the game is “visible” again

I implemented a customizable post processing stack for URP 8.2.0 in 2020.1.4 using Renderer Features and Render Passes. It works for me.

I started the development on 2019.4.9 then moved to 2020.1.4. There was one change I noticed:
In 2020.1.4, there is an additional member “renderingData.cameraData.resolveFinalTarget” which determines if the camera renderer to the camera target or otherwise an internal temporary RT named “_AfterPostProcessTexture”.

I recommend that you check the render targets for each step in the frame debugger (with and without your renderer feature) to see flow of the data between the intermediate targets. You may be rendering to a render target that is not read by the subsequent passes.

For reference, here is my customizable PPS package: GitHub - yahiaetman/URPCustomPostProcessingStack: A Customizable Post-Processing Renderer Feature for Universal Render Pipeline

thanks! will do
really appreciated :smile:

No luck for the moment…
Still struggling without any positive result. :face_with_spiral_eyes:

@Yetman : Would it be possible for you to paste a section of the code so I understand how did you use the “renderingData.cameraData.resolveFinalTarget” that you mentioned.

thnx

BTW, something I forgot to mention before… I’m using shadergraph for the material shader (not sure if this could influence the result actually)

I use it inside the AddRenderPasses function of the CustomPostProcess renderer feature.

Link: URPCustomPostProcessingStack/Runtime/RenderFeatures/CustomPostProcess.cs at master · yahiaetman/URPCustomPostProcessingStack · GitHub

public override void AddRenderPasses(ScriptableRenderer renderer, ref RenderingData renderingData)
        {
            // Only inject passes if post processing is enabled
            if(renderingData.cameraData.postProcessEnabled) {
                // For each pass, only inject if there is at least one custom post-processing renderer class in it.
                if(m_AfterOpaqueAndSky.HasPostProcessRenderers && m_AfterOpaqueAndSky.PrepareRenderers(ref renderingData)){
                    m_AfterOpaqueAndSky.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget);
                    renderer.EnqueuePass(m_AfterOpaqueAndSky);
                }
                if(m_BeforePostProcess.HasPostProcessRenderers && m_BeforePostProcess.PrepareRenderers(ref renderingData)){
                    m_BeforePostProcess.Setup(renderer.cameraColorTarget, renderer.cameraColorTarget);
                    renderer.EnqueuePass(m_BeforePostProcess);
                }
                if(m_AfterPostProcess.HasPostProcessRenderers && m_AfterPostProcess.PrepareRenderers(ref renderingData)){
                    // If this camera resolve to the final target, then both the source & destination will be "_AfterPostProcessTexture" (Note: a final blit/post pass is added by the renderer).
                    var source = renderingData.cameraData.resolveFinalTarget ? m_AfterPostProcessColor.Identifier() : renderer.cameraColorTarget;
                    m_AfterPostProcess.Setup(source, source);
                    renderer.EnqueuePass(m_AfterPostProcess);
                }
            }
        }

I did that because while every pass before the built-in post-processing renders to the “_CameraColorTexture” (identified by the variable renderer.cameraColorTarget), the post processing pass renders to “_AfterPostProcessTexture” from which the final-blit pass reads.

Note: This is only important for passes added after the builtin post processing. If you use camera stacking, this is only important in the last camera, hence the renderingData.cameraData.resolveFinalTarget flag which seems to be only true for the last camera in the stack.

Also if you use a shader-graph with CommandBuffer.Blit, make sure that you specify the pass in the function argument (0 if you use an Unlit shader and plan to write the color result).
By default, CommandBuffer.Blit executes all the passes of the shader in sequence and shader graphs can have more than one pass. For example, Unlit shader graph has a depth-only pass after the first pass, this pass should draw black if a color target is bound (if I remember correctly).

Thanks @Yetman
I finally made it work!!

Ironically i was simply a matter of changing the shadergraph “shader template”
on Unity 2019 theshadergraph “sprite graph” was working like a charm but on “2020” for some reason you need to use a “graph unlit” …strange.

Anyway, thnks for your help a learned a ton with your posts :slight_smile:

cheers!

1 Like

Thank you @Yetman ! Your package seems awesome, however I am getting a black screen too - even with the grayscale example that is in the tutorial… I am using 2020.2.3

1 Like

Lol… it was a naming problem with my scripts… Didn’t get an error message from the shader first to catch that, but now it is working. :slight_smile:

1 Like