How to render texture pixels "as are" with no post-processing (UE4 4.23)

In my 2D C++ game I want my sprites rendered as they are. For example I have a pure white background and all pixels are (RGB) {255, 255, 255}. I have turned off as much post-processing as I can. The best I get now is the background is rendered as a mixture of {254, 254, 254} and {253, 253, 253} pixels. Others examples is a light-grey coloured pixel {192, 192, 192} is rendered as {197, 197, 197} and red can become {253, 0, 0} or {254, 0, 0} instead of {255, 0, 0}.

I’m getting close to full re-production. The 4 main things I did was turn off anti-aliasing, set vignette intensity to 0, set r.TonemapperFilm=0 and set r.DefaultFeature.AutoExposure.ExtendDefaultLuminanceRange=False.

Can anyone think of what final step I need to take?

Create a post process material that does nothing but pass-thru the prost process input, set it to “replace tonemapper” and add it to your post process volume or camera blendables array. It’s so raw you’ll receive linear color values, so you’ll have to convert to sRGB (gamma convert) yourself.

“As are” is not a thing, its “As is”

Thank you Manoel.Neto for your advice. It really got me searching. You have given me hope!

I forgot to mention I am coding my game in C++.

My textures have sRGB set.

So far I have created a post process material in the editor and set the shading model to unlit and replace tonemapper.

I have added it to my camera blendables (as you can see I can also add it to the post process settings):

UMaterial* parentMaterial = LoadObject<UMaterial>(nullptr, TEXT(“Material’/Game/Materials/NewMaterial.NewMaterial’”));
UMaterialInstanceDynamic* MaterialInstance = UMaterialInstanceDynamic::Create(parentMaterial, nullptr);
// Camera->PostProcessSettings.AddBlendable(MaterialInstance, 1.0f);

When I run the game, all I get is black {0, 0, 0} pixels for my sprites. So I guess like you say, I need to do a conversion.

To do the linear to sRGB conversion I don’t know is how to get access to SceneTexture:PostProcessInput0 in C++ that I have seen used in Blueprint.

Any ideas where this is located? How would I do the conversion?

Ok, phew! I have worked out that I can add blueprint nodes to the material.

So I have added SceneTexture:PostProcessInput0 and joined Color to Emissive Color. This has worked wonders, but not quite right for all my pixels.

White, yellow, red, cyan, black pixels are perfect.

The problem is pixel {128, 0, 0} comes out as {55, 0, 0}, similarly {0, 128, 128} comes out as {0, 55, 55} and {128, 0, 128} becomes {55, 0, 55}.

Also {192, 192, 192} comes out as {134, 134, 134}

I need to know now what node I insert to do a correct gamma conversion.

I tried the Power(X, 2.2) node joining Color to Base to Emissive Color, but those pixels I mentioned become worse. The {128, 0, 0} becomes {9, 0, 0} (basically 128 becomes 9) and {192, 192, 192 becomes {62, 62, 62}.

Check this thread, I think it describes your problem - Washed out Colors from Tone Mapping: How bad it really is, and how to fix it - Unreal Engine Forums tho its quite old and probably fixed, but it could give you just some ideas… probably.

Thank you NasteX. I have discovered that I can do a gamma correction using Power(X, 1/2.2), which is very close.

Actually, for now, I have turned off sRGB on my textures, and I do not need to do any gamma correction (no Power node needed). This reproduces my pixels 100%!

So, doing this, I believe that replacing the tonemapper seems to completely turn off post-processing.