Another way to disable tonemapping

I’ve seen lots of posts asking how to disable tonemapping with a few people finding commands they can enter via blueprints to disable it.

I wanted to share another quick way I’ve found that appears to disable tonemapping: replace the tonemapper post process pass with a simple shader:

This shader takes in the post process input and pipes it straight to the output. It’s set to replace the tonemapper, and I gave it a priority of -1 so any other shaders we want to add at runtime that also replace the tonemapper can override it.

Because we’re doing singleplayer stuff, we have a function in our GameMode class, called by its PostBeginPlay(), that obtains or creates an unbound PostProcessVolume and adds this material to it:

        APostProcessVolume* VolumeActor = nullptr;
        for (TActorIterator<APostProcessVolume> PostProcessActor(GetWorld()); PostProcessActor; ++PostProcessActor)
            VolumeActor = *PostProcessActor;

        // spawn a post process material if one was not found in the scene.
        if (!VolumeActor)
            VolumeActor = GetWorld()->SpawnActor<APostProcessVolume>();
            VolumeActor->bUnbound = true;

        UMaterial* DisableTonemapperMat = LoadObject<UMaterial>(nullptr, TEXT("/Game/Seg/MaterialLibrary/PostProcess/PP_DisableTonemapping"));
        if (DisableTonemapperMat)
            VolumeActor->AddOrUpdateBlendable(DisableTonemapperMat, 1.0f);

If you’re doing a multiplayer game, you’d probably need to do this in your PlayerController or something like that. Alternatively, I’m sure there are good ways to do this in Blueprint as well.

Looking at “ProfileGPU”, this appears to do the trick. No tonemapping pass is done!

Thought I’d share.

Thanks! One little thing I’d like to add is that one might need to compensate gamma by adding a power(1/2.2) node between the SceneTexture and the Emissive Color input. The preview window in your screenshot looks too dark as well, this addition will make it look like it should.

Yep, you could even build out simple tonemappers like Hejl or Reinhard if you wanted. But, replacing the tonemapper means you lose a majority of the Post-Process Controls, including bloom, exposure, and color grading.

Instead of adding a Material to every PostProcess volumes in your scene (which can require a check every frame because of level streaming) just add it to the PostProcess settings of your Player/Main Camera instead. It will do the same and it will be easier to update and track.

Yeah, this sucks.
Is there any way around it? (Like replacing the tonemap in the shader itself)

Here are screenshots showcasing the difference we get when replacing the default Unreal tonemap with a more neutral custom one. (Unreal 4.23)

Problem is I lost control of the exposure in the post process volume. ;(

You should be able to replace the “Filmic Tonemapper” option directly in the shader with your own. I believe it would be in the PostProcessTonemap, but I haven’t dug into the actual location too much.

Also you may want to try modifying the default parameters built into the ACES tonemapper. You can adjust the toe, slope, and shoulder to reduce the roll off into blacks(or whites) and treat those as your new defaults.

Thank you! I am not sure I can achieve what I want with the Aces tonemapper (separate control of Luma and Chroma) so I will look into replacing the Filmic Tonemapper directly in the shader instead.

Why would you do that though? Linear output was never meant for human eye in the first place. And if the purpose is to replace unreal’s tone mapper with more neutral one, then why wouldn’t you just adjust the filmic settings to match yours closer? Unreal’s default tone mapper is not hardcoded at defaults, so if you don’t like the results it produces, just don’t stick to defaults, instead of going this full workaround circle with so many limitations.

Sorry if I was unclear, I am not looking for linear output. I am looking to do some operations in Luma only and the controls for the filmic tonemapper do not allow for that. At least its not exposed in the editor.

Hmm, if you need Luma only, you should be able to just do a dot product of your tonemapped image with 0.2126, 0.751, 0.0722 in a Post-Process Material set to “After Tonemapping.” If you need Luminance, do it “Before Tonemapping,” unless I’m also not understanding what you want to do correctly :slight_smile:

Yes, well, my question was why. What do you want to achieve? From the two comparison pictures above, it appears to me that you are looking for an overcomplicated way to achieve same thing as slightly reducing exposure and tone mapper slope. The process will be very different, but the result will be most likely near identical.

What I want to achieve:
To preserve color accuracy. I don’t want colors to change when switching between lit and basecolor buffer.

So you want linear output after all :slight_smile:

In that case we go back to my question why. I personally was thrown off by this as well, when I realized there’s no way in unreal to turn off tone mapping to a degree of seeing the clean linear output, but with time, I realized there are actually almost no valid reasons to desire that. Linear output was never really meant for human eye consumption.

There are indeed some of the issues, such as input texture already having some sort of perceptual color transform applied to the once inside the input image, and it being applied twice in the final engine, but in the grand scheme of things, it’s rather minor issue compared to the resulting gains in quality.

I was asking about what your end goal this. Let’s say you want to preserve the color accuracy, but why? This is just a workflow preference, not an end product. I suppose you are figuring out this piece of puzzle in order to achieve your final goal, which likely is producing a high visual quality game, cinematic or visualization. And this end goal can generally be achieved even without this piece of puzzle. Just different route to achieve same final level of quality.

That being said, the reasonable built in solution for this should be some bundled material editor node which would apply inverse of the tone mapping operations.

I know I get pissed, when I ask about something I want to achieve, and someone instead of providing an answer starts convincing me I don’t really want to do that, but in this case, I am afraid you will go a full circle before realizing you’ve been trying to do all this for nothing :slight_smile:

Thank you for trying to help me.
I am after a tonemap that retains the original colors as they are in the diffuse texture. (top image)

I tried your suggestion reducing the exposure (-0.25) and the tone mapper slope (-0.13) but since blacks were still very crushed a also had to lower the toe a bit (-0.15).
This gave the following result in the (middle image).

I still believe that the result from our custom neutral tonemap cannot be replicated with the standard tonemap. (bottom image)

Will definitely not give this up just yet. :slight_smile:

I would like to know why its called “Replace Tonemap” when in fact it is replacing the entire post process feature set.

Thank you, that is actually already a part of the custom tonemap. It wont matter if I would set it to run before or after the tonemap though as it is the tonemap in itself that is ruining my chroma. (Hence my desire to replace it altogether)

I only mentioned the before/after because Luma/Luminance are separate and based on gamma correction. There are 2 issues here affecting your color, one being the tone curve of the ACES RRT having a very soft rolloff into highlights, so any value >= 1 will be desaturated(to the point where true 1.0/white is hard to reach without over-exposure), and the other being the multiple color spaces ACES steps through to work in the proprietary color space AP1 before you get back to your final display-referred image.

If you like the contrast, and the curve parameters available in the Post-Process, you could remove the color space transforms in TonemapCommon.ush in the FilmToneMap() function to only work in the RGB color space, so the primaries won’t shift but you’ll still get the highlight desaturation. A little easier said than done though, or you could replace it all with an approximation of ACES from Krzysztof Narkowicz or Stephen Hill.

If you don’t like ACES at all, you could add in your own tonemapping operator in that same function. This was just a quick test but it looks like everything in the PostProcess stack still works as expected. You may want to comment out the rest of the ACES above it, but you might get issues if you’re outputting to other display spaces. Definitely comment out the “return max(0, ToneColor)” since that’s returning ACES.

You may also want to disable the Blue Correction(fixes ACES color space issue with saturated blues) and Expand Gamut in the Misc section of Color Grading in the Post-Process Volume.

Edit: Ironic that I used the wrong term in my code, since I’m getting *Luminance *of the linear color, not Luma. :o

Wow! Thanks! :eek:
This was just the kind of information I was looking for. I have a tonemap that I know works and that I like so I´ll try to replace it in the TonemapCommon.ush next week.
Have a nice weekend!

Very informational thread, subscribing

Btw In theory the EyeAdaptation node in the postprocess material should help with controlling the auto exposure, but for me it doesnt do anything. Any thoughts?