Issues with HDRIs and render result pixel values that exceed half float limits #98575
Operating system: Windows-10-10.0.22000-SP0 64 Bits
Graphics card: NVIDIA GeForce RTX 3070/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 512.15
Broken: version: 3.1.2, branch: master, commit date: 2022-03-31 17:40, hash:
(Also tested in latest 3.3 Alpha)
Short description of error
Some lookdev HDRI's give the scene a colored tint, that also does not disappear after lowering the strength
Exact steps for others to reproduce the error
I imported this HDRI to preview lighting in my Eevee scene: https://polyhaven.com/a/lenong_2
I found a workaround by adjusting the exposure of the HDRi in advance by -1 in affinity photo. This makes the image only a tiny bit darker, but the end result is as you would expect it.
No yellow light, no sun.
I tried this with another HDRi from HDRIhaven (from another creator, this one specifically https://polyhaven.com/a/ehingen_hillside) and the issue also existed there.
I can confirm that "something" is wrong for both Eevee and Cycles, but not for version 3.1.2, and not exactly matching the problem described.
Operating system: Windows-10-10.0.19044-SP0 64 Bits
Graphics card: NVIDIA GeForce GTX 1070 with Max-Q Design/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 511.09
- I was not able to reproduce the "yellow" problem in any version using Strengths of 0.1, 0.01, or 0.
- However, I am observing black pixels for the overexposed portions of the sun in 3.2 and 3.3 that wasn't present in 3.1.2.
|.||3.1.2||3.2 beta||3.3 alpha|
Interesting that you found these black spots. I tested it again with both 3.1 and 3.3 (alpha) on my laptop, and there none of the issues were present.
For my own sanity i also tested it again on my main PC, this time with clean Blender installations of 3.1/3.3. Sadly the yellow glow issue was unchanged.
I can't reproduce the problem either.
It must be something specific on NVidia GPUs.
HDR/EXR makes no difference. Higher resolutions make the yellow glow slightly weaker, but at 4k it is still very clearly visible (So far i my tests were at 1k).
The black pixels have values exceeding 65504, which is the maximum that can be stored in half float. Render results are stored as half float textures for display, and the way such high values are treated may depend on the driver. We may need to manually clamp it, though it would be unfortunate to pay the performance cost for that.
For image textures, an option to use full float in Eevee was added in #73086 (Eevee: strange discrepancy in handling of 32 bit floating point textures). We should check if that still works, but it's intentional that this defaults to half float as that works and reduces memory for most textures.
Changed status from 'Needs Triage' to: 'Confirmed'
@brecht: would you consider this a TODO then?
Operating system: Windows-10-10.0.19043-SP0 64 Bits
Graphics card: NVIDIA GeForce GTX 1070/PCIe/SSE2 NVIDIA Corporation 4.5.0 NVIDIA 512.96
Blender version: 3.2.0, branch: master, commit date: 2022-06-08 10:22, hash:
Using the provided sample scene and HDRi, I cannot reproduce those two issues, the black spot on the Sun, and the yellow tint nor in Eevee neither in Cycles. Yes, there is some "yellowness" at lower exposure values but nothing comparable to the level experienced by those user.
Yes, there appear to be some differences in how the drivers or GPUs deal with half float clamping.
@pmoursnv, the NVIDIA OpenGL driver does not appear to clamp to the half float max value when uploading a float buffer to be stored as half float on the GPU, instead setting the value to zero. Other drivers do seem to clamp it. Do you know if that would be considered a driver bug?
We can do the clamping ourselves, but would prefer to avoid the performance impact of that. Or perhaps we can do the conversion to half float ourselves with SIMD optimizations, which maybe has similar performance to what the driver is doing, not sure if that conversion happens CPU or GPU side.
The driver does perform the usual float2half conversion, which for values exceeding the half maximum results in half infinity, and that is what is stored in the texture. During the gpu_shader_display_transform_frag shader that is translated to zero however (specifically inside "OCIO_to_display" function, where a 3D LUT is applied, which doesn't work for infinity since that doesn't translate into meaningful LUT coordinates) and so it ends up showing as zero on screen.
I wouldn't consider this a driver bug, since the OpenGL spec does not actually specify clamping behavior here (section 8.5 in the OpenGL 4.6 core spec specifies that clamping occurs when the data format is floating-point and the texture internalformat is an integer format or normalized fixed-point format, but nothing for when it is a floating-point format). So in my opinion the driver behaves correctly here.
To fix it is probably sufficient to simply filter out infinity values inside the gpu_shader_display_transform_frag shader.
Thanks, I should have figured out it ends up as infinity.
For displaying images with color management we can clamp in the shader quite easily. For Eevee/Workbench it may not be ideal to add clamping for every texture read, and since interpolation/mipmapping happens before we can clamp the results may not be good.
I cannot speak from cycles PoV, but from shaders perspective I would add clamping in the shaders as inf and nan triggers undefined behavior on OpenGL. Data pre-processing on the CPU might be less performant as it adds another data translation pass.
I don't think clamping in the shader will work well since it would happen after interopolation/mipmapping, so pixels that don't exceed the limit would be affected or there may be NaNs.
You’re right, think we could add clamping to the gpu texture creation image_gpu unit. Would also need a helper function in imbuf to clamp a part of rect_float.
In some cases additional buffer should be created to not modify the original data. Fe opener files that do not need any conversion to scene ref. Also for raw and data spaces….
This issue was referenced by
This issue was referenced by
could you check on the latest builds tomorrow if this issue has been fixed, or that we need some more tweaking?
The fix only affected the image engine used for display in the image editor, but this is also an issue for image textures.
I opened the files above in a build from today (14.10.2022) and the issue is still present
Thx @fclem ! (closing this was caused by the backporting to LTS)
I had this exact issue of the sun disc turning black at the end of a cycles render. After reading in this thread about certain values reaching infinity/NaN etc., I decided to lower the value of the sun intensity setting of the Nishita Sky Texture. I don't know why it works, but lowering the intensity setting until renders look right fixed it for me (a value of less than 2 in my case).
No due date set.
No dependencies set.
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?