Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the relationship between AmbientColor::brightness and Blender's background color strength? #12280

Open
janhohenheim opened this issue Mar 3, 2024 · 6 comments
Labels
A-Rendering Drawing game state to the screen C-Docs An addition or correction to our documentation

Comments

@janhohenheim
Copy link
Member

janhohenheim commented Mar 3, 2024

How can Bevy's documentation be improved?

During Bevy 0.13's development, lots of attention went to PointLight, DirectionalLight and Spotlight. However, I failed to find any significant discussion of AmbientLight either on GitHub nor Discord. I'd be glad to be proved wrong if anyone's got a link though :)

The reason I care about this because the general consensus has been "let's try to have some kind of conformance with Blender", using Blender's EV100 and render outputs as direct references for how Bevy should behave. This worked out (mostly, there's still talk about Blender itself being wrong in places) for the lights mentioned, but AmbientLight kind of got left behind.

In Blender, under the tab "World", you can find the background light (aka environment light). The meaning behind its strength param is a bit elusive to me, and the docs are not helping.

This is how Blender renders a scene with no lights and only a background light of strength 1:

image

This is how Bevy renders the same scene with no lights and an AmbientLight of the same color with brightness 1:
image

As you can see, Bevy is much darker. (Ignore the procedural sky and the glowing orb, I just modified Foxtrot for the screenshots because it was handy)

Let's bump the brightness to the slightly magic constant 683:
image

Better, but very blue.

google/filament#1667 says that using Blender's exposure settings (which are Bevy's standard settings), the background strength should be the same as their IBL intensity, which I believe corresponds to Bevy's EnvironmentMapLight::intensity. I would love to test this, but I fail to create a valid environment map from a simple Color using Image::new since I keep getting an error like "Texture binding 13 expects dimension = Cube, but given a view with dimension = D(1, 2 or 3)" no matter what I do. I am not an expert in the Image API, so this is probably possible in some way.

Until someone confirms or denies this, my working hypothesis is that Blender's background shader strength corresponds to the intensity of an environment map with a single color.

@janhohenheim janhohenheim added C-Docs An addition or correction to our documentation S-Needs-Triage This issue needs to be labelled labels Mar 3, 2024
@fintelia
Copy link
Contributor

fintelia commented Mar 3, 2024

Related: #11933

@alice-i-cecile alice-i-cecile added A-Rendering Drawing game state to the screen and removed S-Needs-Triage This issue needs to be labelled labels Mar 3, 2024
@janhohenheim
Copy link
Member Author

@superdump do you have some thoughts on this? I'm not expecting a full answer, I'd just like to know what you think about my hunch.

@superdump
Copy link
Contributor

So I think @fintelia ’s answer here: #11933 (comment) defines the physical units. Basically the ambient colour multiplied by the ambient brightness gives luminance in cd/m^2. Then exposure is applied to that. As for how to match that in blender, I don’t know without digging deeper.

@janhohenheim
Copy link
Member Author

janhohenheim commented Mar 23, 2024

@superdump am I right in my assumption that this works differently when using a monochrome EnvironmentLightMap?
If so, I'd like to test if this is the same behavior as in Blender. Do you have some tips on how I could construct an Image for such a lightmap? Every time I tried to create an image manually for it, I ran into problems like "Texture binding 13 expects dimension = Cube, but given a view with dimension = D(1, 2 or 3)"

@superdump
Copy link
Contributor

superdump commented Mar 23, 2024

Yup, you need a cubemap texture, which is a texture with 6 cube faces ordered in bevy conventions like looking along +x, -x, +y, -y, -z, +z. Note that the order of z is swapped to be minus first then plus. This is because cubemap textures in graphics APIs are left-handed. Left-handed y-up has positive z going into the screen. Right-handed y-up that bevy uses has positive z coming out of the screen. Hence we need to swap the order of the z faces.

The skybox example uses cubemap textures and specifically a PNG that doesn’t have the metadata to communicate to the asset loaders that it is a cubemap, where the ktx2 textures do. You can see how that bit is handled here:

bevy/examples/3d/skybox.rs

Lines 152 to 160 in 85b488b

// NOTE: PNGs do not have any metadata that could indicate they contain a cubemap texture,
// so they appear as one texture. The following code reconfigures the texture as necessary.
if image.texture_descriptor.array_layer_count() == 1 {
image.reinterpret_stacked_2d_as_array(image.height() / image.width());
image.texture_view_descriptor = Some(TextureViewDescriptor {
dimension: Some(TextureViewDimension::Cube),
..default()
});
}
. If you take a look at the PNG you can also see how they’re laid out. I think the faces are stacked vertically, and the faces are square, so we divide the height by the width to know how many faces there are.

@janhohenheim
Copy link
Member Author

janhohenheim commented Mar 23, 2024

Update: it seems like using the environment map leads to more desirable effects.

Blender:
image

AmbientLight = background color * background strength * 400:
image

No AmbientLight, but a lightmap with 6 sides, each containing just one pixel = background color * background strength * 400:
image

It's weird to me that I needed to multiply the strength by a big constant, otherwise everything is still very dark. Bevy also seems less saturated than Blender for some reason.

Note that things get better when I multiply by the watts to lumens ratio 683.0, but I don't know if that is a coincidence or not:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Rendering Drawing game state to the screen C-Docs An addition or correction to our documentation
Projects
None yet
Development

No branches or pull requests

4 participants