Render too bright?

Hello Armory community,

I just noticed lately by playing with the last SDK, the objects seem to be rendered a bit too bright since the lasts SDK…

Here’s a simple sphere in the viewport looking like this:
viewport

Looked like this in the SDK2105
SDK2105

And look like this since the SDK2106
( Here rendered with SDK2108 )
SDK2108

I thought that something changed with the way the “occlusion” or the “world_environement” work, but I couldn’t find any notification… Is this supposed to look like this ?

I found that by reducing the “world strength” to 0.1 ( in Blender or by editing this file ) I could make it look like the previous version, but it’s a bit odd having to do that…

Has anybody found this strange too, or knows why the render changed?
Thanks a lot.

(Tested on Linux and Windows with Blender 2.93.2)

2 Likes

Could you please share the blend file you tested it with. That way the lighting, materials and settings are also same when we test.

Best,
QC

Hi QuantumCoderQC, thanks for the reply.

It’s the default scene from Blender. I just replaced the cube with a sphere and turned the viewport mode to “Rendered”, but I didn’t touch anything else.

Untitled.blend (1.0 MB)

Hi, I just installed Armory again from itch.io (so no funky stuff that could break my results), did not mess with any settings, and even my default cube is too bright


So yeah I definitely think this is an issue, it looks like there are no shadows and no light falloff (?).

When using a Sun Lamp the results are as follows:


Enabling Shadow Map Atlasing does not change anything.
Updating to the latest git version shows the same results.

1 Like

Thanks Simonrazer for checking on your side,

I wanted to add some details.
It seems like the Object is too much affected by the “World”, making it looks like it’s emitting light. Which makes the light falloff difficult to see.

Here’s a test with NO “Light”, but a “World”:
(Blender LEFT / Armory RIGHT)
World_ON_light_OFF WorldON_LightOFF

Here’s a test with a “Light”, but NO “World”:
(Blender LEFT / Armory RIGHT)
WorldOFF_LightON World_OFF_Light_ON

Maybe I search at the wrong place but, I tried to compare the code of the two versions, and I noticed some changes were made in the “make_world.py”, but it’s a bit beyond my skills to understand how it affects the code…

1 Like

Yes, that is most probably the issue, the problematic commit seems to be https://github.com/armory3d/armory/commit/656b018e5f73240074f7bbf08514617f6d95f94b.

Originally, (ir)radiance probes were only correctly exported for environment maps, the hosek/wilkie sky model and color-only worlds. This became problematic when Armory got support for more complex world shaders, so now the probes are quickly rendered with cycles in the background and then exported and converted with cmft. There were issues with the brightness and I already made it a bit darker so that it looked correct for colorful world shaders. But it’s still too bright.

I’m not entirely sure how to solve this as I don’t understand much of the spherical harmonics math that is used for the environment probes (thankfully cmft does most of it), but we can probably tweak the brightness here. The old code is still around and I think is even used in some cases. For Hosek/Wilkie skies the coefficients are also divided by 2, for color-only worlds the floats are even multiplied with 1.13. A bit more background information can probably be found in the 2.9 update thread.

But maybe it’s not that easy to just multiply every coefficient by some value, maybe the brightness is not linear at all, I don’t know unfortunately.

The shader code for irradiance can be found here and IIRC it’s directly implementing formulas from some scientific paper. So I don’t think we should do adjustments there.

Edit: According to this vizualization and this blog article it could actually be sufficient enough to multiply band 0 with the wanted brightness.

1 Like

Whoa, Thank you very much timodriaan for this very detailed reponse and explanation :slight_smile:
It’s a lot of info to digest, but I will study those links very carefully.
It’s much complexier than what I was imagining, and way beyond my comprehension yet…

That’s what I thought. I just hoped I could find a value to play with in order to tweak the brightness.
Seems like you found it :slight_smile:

I’m looking forward to see the results.

1 Like

Feel free to play around with the brightness yourself in the code, as I wrote in the “edit” part above it is probably much simpler than I thought at first. There’s also a small chance that something is wrong with the gamma values that are passed to cmft. Unfortunately I don’t have much time until next wednesday but then I can also give it a try :slight_smile:

1 Like

Sure I will.
I don’t have much time either, but I’ll play with it this weekend.
I would like to understand what I’m playing with instead of multiplying band 0 with random values.

Thanks a lot for your help. :slight_smile:

1 Like

Hello, I come back to share what I’ve found so far:

I tested a bit playing with the “band 0”, but it’s way too complex to deal with and I didn’t find good results…
So instead I tried to see what I could do with the nodes.

I found that the background radiance strength is always set to full power even when the background color is set to a much darker value.

So by playing with the “Strength” value of the “Background” node I could adjust the intensity to something that’s look more like the Eevee’s render.

Normal Strength value, is too bright in Armory.

Lowering the Strength value makes it better in Armory.

Comparing normal value in blender with lower in Armory.

I made a simple scene to test it, with checker in the backgroud:
Radiance_tweak.blend (713 KB)
The color 1 is a very bright Red, and the color 2 is a very dark Blue.

Here in the default setup, the sphere looks purple as if the blue color was as bright as the red color.

And here in this setup with the brightness of the color is linked to the strength of the “Background” node, making the blue color much darker, and concurding with Eevee’s render. ( or closer )

For the math I tested and tweaked until results seemed to be good enough.
So I thought I would just need to add this math expression somewhere in the code and it would be fixed, but the thing is that this math expression is not correct…

Indeed, if you unplug the math node from the Background’s Strength input, change the Strength value manually and re-link the math node, the result will be different.
It’s like if the strength value wasn’t properly override by the node input.

I think there is something broken with this node…
Also I’ve had some random prompt quit but, as I saw other people having this issue, I think this is an other problem.

3 Likes

Hey! Is this supposed to be fixed by now? It is still just bright for me, no matter if I turn the World to clear or (ir)radiance off.

Hi, sorry for my late answer, I didn’t see in September that there was a new post in this thread :sweat_smile:

I tested a bit playing with the “band 0”, but it’s way too complex to deal with and I didn’t find good results…

Yeah, it was similar for me. I got results that looked quite close to Blender in some situations, but then in other situations it looked way off. So I guess that a simple linear change in brightness is not what we’re after, but rather something gamma or colorspace related.

It’s like if the strength value wasn’t properly override by the node input.

Yes. The strength input socket is kind of an exception in Armory… As you can see here, only the default (=unconnected) value of the socket is taken into account because the strength is not evaluated in the shader but instead exported to the game as a single scalar variable (so there is only one uniform value and thus we can’t correctly parse the node tree from that socket). The variable is then sent as a uniform to the shader (source).

I guess that this is a relic from the time when Armory didn’t support complex shader trees for world shaders, and I will try to find a solution for that soon :slight_smile: Shouldn’t be too difficult if that value isn’t used elsewhere.

Also I’ve had some random prompt quit but, as I saw other people having this issue, I think this is an other problem.

There is a chance that this issue is now fixed as the Kha and Krom versions were updated again :slight_smile: Please let me know if you’re still experiencing this.


My post regarding this brightness issue on the Discord channel today, were I talked about the places in the code where I suspect the issue is:

One [place] is the part where the SH (spherical harmonics) coefficients are parsed and there we could manually change the brightness of the irradiance, however that would be trial and error. I did some tests back in August and by simply multiplying the base band of the SH coefficients with a certain factor I was able to get close to how Blender looks, but in certain situations it still looked way off. So that wasn’t a good solution.

The other place is the interaction with cmft, which is the tool that we use to generate the SH coefficients from the environment render done in Cycles. Cmft has two different gamma parameters, one for input and one for its output. I don’t know what’s the difference between them and there is not much documentation, but that’s certainly something to look into. Also the Cycles render might be off (or Blender manually manipulates the irradiance somewhere?), but upon inspection it looks pretty close to what you get with Eevee. My current plan is to temporarily allow to change gamma correction parameters for the irradiance calculation in the shaders during runtime. Then it’s easier to see how likely it is that the wrong brightness is caused by the gamma values.


Edit: I think I have found the issue, but I need to verify it first. More on that tomorrow :slight_smile:

2 Likes

Hi, thank for the feed back!

Alright! Looking forward to see it :slight_smile:

Edit: About trial and error and made some tests to see the relation between “color value” and “world strength”.
Might be useful to somebody so I’ll share the results( X = Colorvalue; Y=World Strength):


This is how I found the math formulla I used with the nodes.

1 Like

Edit : I think I have found the issue, but I need to verify it first. More on that tomorrow

Turns out I didn’t find it yet :frowning: There are two calls to cmft, one for radiance and one for irradiance. I realized that the brightness gets lower when you also add the gamma parameters to the irradiance call, currently they are only passed to the radiance call. Yesterday I got some good results but I tested it with more files and it still looks off in some especially darker situations.

Then I found this commit from Lubos which further confused me. He actively removed the gamma parameters from the irradiance cmft call, but from the commit alone I couldn’t find out why. Also, comments in the cmft code provide some small example configurations, and the one for irradiance also does not do any gamma correction. So I guess I have to do some research when to apply what correction in which direction and what Armory exactly does in the shaders.

Btw, the idea to use Desmos to compare measured brightness is really clever! Thanks for sharing the results, they might come in handy… Did you do these tests with color grading/tonemapping active (Blender and Armory)?

2 Likes

Hi, thanks !

I tried both tonemaps :
( Armory = filmic / Blender = filmic)
( Armory = off / Blender = raw )
With a colorvalue from 0.0 to 1.0 the curves were similar ( or very very close ).
But beyond 1.0 the curves seem to diverge a little…

I think I’ll try to test it again, more accurately and with more values.

2 Likes

I’m back with a few more findings that I want to share as they might be helpful for this or even future issues:

  • The /= 2 for sh coefficients in write_probes.py can be used for controlling the exposure, this visualization widget uses the same logic for it’s exposure parameter (source code).

  • After reading a bit about gamma correction I think that we need to apply input gamma correction when calculating SH coefficients for .jpg environment renders (the currently used format), because Blender writes non-linear values (sRGB) into .jpg files.

    Jpg files from other sources might be different though, I still have to do some research in that regard as jpg files seem to use the YCbCr color space internally, which doesn’t use the classic rgb components at all.

    Also, converting to linear from sRGB is technically slightly different from simply applying a x^2.2 gamma correction, so this might be another issue to solve…

  • I tried to use .hdr for the environment render instead (which should give better results) and it seems that Blender is really broken when saving hdr files. Negative values (in either component) will result in visible artifacts in the HDR and a much brighter HDR in general as if there would be overflow errors.

    This is a regular equirectangular hdr file rendered by Blender for a world shader where the world normals are directly connected to the output:

    And this is the same shader but with applied clamping between 0 and 1 on each component (clamping between 0 and any other positive value > 1 works as well, it’s really the negative values which normal vectors can have):

    Blender itself displays both renders exactly the same, but in every external HDR viewer you can see the difference. Both images are in linear color space, and you can clearly see that the upper one looks way too bright. I then passed both these images to cmft for testing and the bottom image actually gave very good results, even without any gamma correction or exposure adjustments. So if we could find a way to fix the Blender output (maybe it’s worth a bug report?) I guess we can solve the issue by using HDR instead of JPG…

2 Likes

Hi!
I tested the .hdr environment background too. Indeed it works great :slight_smile:
Irradiance_HDR
But I’m concern how much heavier .hdr is compared to .jpeg.
I guess it was the reason why .jpeg format was chosen in the first place.

But also, I think I found a way to export .jpeg files in linear colorspace:
In the “render properties” tab, under “Color Management”, there is a “Display Device” option, set it to “None”.

I made a test with the HDR Environment Map below:
EnvTexture_ColorManagement

Then I rendered/exported it as a .jpeg and re-import it as an Environment Map.
Of course this makes a very dark environment map from the Blender point of view, but it looks nice in Armory

Here’s the comparison:


I don’t know if it is possible to switch the “Display Device” option to “None” when Armory creates the “envmaps”?
But I think this could be a solution.

2 Likes

It really does, the problem is that the colors are wrong if the world shader outputs negative values. In most cases this is not an issue but it can happen. I opened a Blender bug report here, hopefully there will be a solution soon. In my opinion the user should ideally be able to choose between hdr or jpg.

If I remember correctly, the format did always depend on the kind of environment texture before arbitrarily complex world shaders were implemented last year. If no environment texture was used, the irradiance or radiance was calculated from the environment color and in case of skies the radiance was precomputed. I made the decision back then to use jpg because I wasn’t sure about possible performance implications (and maybe there were some other issues with HDR, I don’t know anymore).

Oh, that actually makes a difference in the output file? I tried that option but it didn’t seem to have an effect for me, but probably I did something wrong then. The documentation says that it’s for display purposes and I then went on to try other things, but it is possible to set it via Python. I will test this again in the next days and compare it to the gamma-corrected output and if everything looks more or less correct I can open a pull request :slight_smile:

2 Likes

I had the same problem until i found that i can even fine tune the brightness by simply adjusting the background strength.

1 Like

Yes I saw that, I reproduced your setup and got the same result.

I found the code for it :slight_smile:

scene.display_settings.display_device = ‘None’

I added this line in the write_probes.py in the setup_envmap_render() function.
It is just a first step as it works well with simple color background but it doesn’t work with .jpeg environment texture yet. And the Background Strength Node doesn’t work fully either, but I’ll work on it.

Note: I found that setting the “Gamma” value to 0.45 in Blender gives the same results as changing the “Display Device” to “None”… This might be good to know…

2 Likes