Custom global shader -- can I control where my passes are injected into the post process chain?

I’ll preface this by stating: I’m not a graphics programmer by background, so my question may be a foolish one. :slight_smile:

I need to create functionality somewhat similar to eye adaptation, but different. I need to be able to, at the press of a button, determine the min and max intensities of a grayscale scene, and then apply gain (multiplicative) and bias (additive) to the scene to adjust the scene into a 0.0-1.0 range.

My scene materials render values potentially much greater than 1.0.

I currently have a (global) compute shader that constantly calculates the min and max intensities and reads them back from the GPU for the CPU to access. When a button is pushed, I calculate new gain and bias values on the CPU. Those are handed to a global fragment shader that applies these to the scene. A SceneViewExtension manages all of this in an override of PrePostProcessPass_RenderThread(). I read and write to (*Inputs.SceneTextures)->SceneColorTexture.

Everything works fine except that translucent items (glass and particles) don’t contribute to the min/max and are unaffected by my fragment shader.

I understand now that translucency is done in a separate pass and combined together (typically) later in the post process chain. I’m trying to make my shaders work with translucency. They also need to run before tonemapping (so I can read values > 1.0) and before bloom (so I can clamp values to 1.0 after I’ve read them).

So far, the solutions I’ve stumbled upon are:

  1. Change all of our translucent materials to render before DOF. This seems to combine them into the base pass early enough that my shaders catch them.
  2. Grab the main translucency buffer (there appear to be several, and that concerns me) and separately run the shaders on both the main scene color and the translucency buffer.
  3. Post Process materials seem to give me the ability to exert some control over where in the chain my custom shaders run (e.g. BeforeTonemapping). I could perhaps convert my compute shader to a pixel shader (change to reading back through a texture?). I would presume tonemapping happens after translucency is combined. >_> I’m used to gaining more control of things when I move from visual tools in Unreal to C++, but I’m just not seeing where I have any way to get at the kinds of things the Post Process Material management code uses in my SceneViewExtension.

Is there some other trick I’m missing? I believe I saw a way to request specific textures from the RDG by name, but I don’t immediately see how that would even help me.

Thanks for your time and assistance!

Hello,

Thank you for reaching out.

I’ve been assigned this issue, and we will be looking into this use-case of a custom global shader and the SceneViewExtension for you.

Hello,

Translucent passes are rasterized to three different textures, and composited at different times. All of them render before bloom and tonemapping.

You can read more about how that works with TSR in this documentation:

https://dev.epicgames.com/documentation/en\-us/unreal\-engine/temporal\-super\-resolution\-in\-unreal\-engine\#tsrandtranslucency

To help see the order of events, I recommend using the console command “DumpGPU”.

With regards to SceneViewExtensions, they have a function you can override called “SubscribeToPostProcessingPass(…)”. The first parameter is which pass it currently is processing, so you can run custom shaders at that stage. The pass before bloom and tonemapping, but after all translucency is blended is “EPostProcessingPass::MotionBlur”

An example of a SceneViewExtension that uses the SubscribeToPostProcessingPass feature is “FDisplayClusterViewportFrameStatsViewExtension::SubscribeToPostProcessingPass(…)” from DisplayClusterViewportFrameStatsViewExtension.cpp in the nDisplay plugin. Keep in mind that this subscribes to the Tonemap pass, not MotionBlur.

Please let us know if this helps.

Thank you so much for the response!

I was able to return to this task late last week, and this is exactly what I needed. Translucency is now influencing my compute shader and is affected by my fragment shader.

I think I had noticed that function as I was initially skimming the SceneViewExtension class, but I forgot about it and didn’t re-discover it on following perusals.

Thanks for your time and help!

Hello,

Thank you for the reply.

Can we close your case? You can always re-open it if you need additional assistance for the same issue.

Absolutely! I don’t see an option for me to do that, so feel free! :slight_smile: Thanks again!