RenderTarget not being saved with enough precision

I am trying to use a render target as displacement for my ocean but I am having precision problems. Specifically, despite having a material that should be producing values varying from 0-512 on a 512x512 texture, I am only getting 160 unique values. Where is the precision being lost and what can I do to avoid it?

Setup

Firstly, I have the following material:

The texture coordinate X is scaled up by 512 and then used as the blue channel of an emissive colour. Therefore, the values should vary from 0-512. Note FFloat16 is perfectly accurate enough to store every whole number in this range accurately and certainly 512 unique values in this range.

This material is then applied to a material billboard component where the BaseSizeX/BaseSizeY are set to 512.

Then a SceneCaptureComponent, positioned 512 units away with a 90 degree FOV (so it captures the whole billboard and nothing else). This renders to a render target in HDR (with otherwise default settings). The render target is HDR and 512x512 in size.

Results

At this point, I’d expect the target to contain 512 unique values ({~0, ~1,…~512}). However, using the following test code it can be seen to have only 160 unique colours. Further, saving it out to a bitmap (after scaling down to fit in the 0-1 range required of a non-HDR image) reveals bands of the same colour (should get 255 different colours):

Test code

FTextureRenderTarget2DResource* textureResource = (FTextureRenderTarget2DResource*)RenderTarget->Resource;
TArray<FFloat16Color> Pixels;
bool bDidRead = textureResource->ReadFloat16Pixels(Pixels)    
TSet<float> UniqueColours;

for (FFloat16Color& Colour : Pixels)
{
	float Height = Colour.B.GetFloat();
	UniqueColours.Add(Height);
}

UE_LOG(LogTemp, Log, TEXT("Unique colours: %i"), UniqueColours.Num());

[Numbers from the UniqueColours set][3]

Hate to do this but: bump…

Hi -

The RenderTarget Texture that you have assigned to the Scene Capture Component, what is the compression settings? If it is set to TC_Default, try TC_HDR or TC_HDR Compressed.

Thank You

Eric Ketchum

Changing to TC_HDR in the RenderTarget didn’t help (still 160 colours). There wasn’t a TC_HDR Compressed in the drop down, though I tried ticking the “Defer Compression” option (again to no avail).

I also tried changing the TextureGroup in LOD to ColorLookupTable which also didn’t help.

Finally, I reduced the size of the texture to 256, reduced the multiple in the material to 256 and the number of unique colours still dropped (down to 128)

The problem appears to be a performance improvement one. I noticed in the distro build it was working correctly. Changing Project Editor Settings > Engine Scalability Settings>Effects to Epic resolved the issue.

It would be useful to know of a way to override this setting on whatever needs overriding to store the texture correctly. I’m not sure where the data is being lost, as I’m not sure what changing the effects affects.