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

Introduce support for mixed lighting by allowing lights to opt out of contributing diffuse light to lightmapped objects. #16761

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

pcwalton
Copy link
Contributor

@pcwalton pcwalton commented Dec 11, 2024

This PR adds support for mixed lighting to Bevy, whereby some parts of the scene are lightmapped, while others take part in real-time lighting. (Here real-time lighting means lighting at runtime via the PBR shader, as opposed to precomputed light using lightmaps.) It does so by adding a new field, affects_lightmapped_meshes to IrradianceVolume and AmbientLight, and a corresponding field affects_lightmapped_mesh_diffuse to DirectionalLight, PointLight, SpotLight, and EnvironmentMapLight. By default, this value is set to true; when set to false, the light contributes nothing to the diffuse irradiance component to meshes with lightmaps.

Note that specular light is unaffected. This is because the correct way to bake specular lighting is directional lightmaps, which we have no support for yet.

There are two general ways I expect this field to be used:

  1. When diffuse indirect light is baked into lightmaps, irradiance volumes and reflection probes shouldn't contribute any diffuse light to the static geometry that has a lightmap. That's because the baking tool should have already accounted for it, and in a higher-quality fashion, as lightmaps typically offer a higher effective texture resolution than the light probe does.

  2. When direct diffuse light is baked into a lightmap, punctual lights shouldn't contribute any diffuse light to static geometry with a lightmap, to avoid double-counting. It may seem odd to bake direct light into a lightmap, as opposed to indirect light. But there is a use case: in a scene with many lights, avoiding light leaks requires shadow mapping, which quickly becomes prohibitive when many lights are involved. Baking lightmaps allows light leaks to be eliminated on static geometry.

A new example, mixed_lighting, has been added. It demonstrates a sofa (model from the glTF Sample Assets) that has been lightmapped offline using Bakery. It has four modes:

  1. In baked mode, all objects are locked in place, and all the diffuse direct and indirect light has been calculated ahead of time. Note that the bottom of the sphere has a red tint from the sofa, illustrating that the baking tool captured indirect light for it.

  2. In mixed direct mode, lightmaps capturing diffuse direct and indirect light have been pre-calculated for the static objects, but the dynamic sphere has real-time lighting. Note that, because the diffuse lighting has been entirely pre-calculated for the scenery, the dynamic sphere casts no shadow. In a real app, you would typically use real-time lighting for the most important light so that dynamic objects can shadow the scenery and relegate baked lighting to the less important lights for which shadows aren't as important. Also note that there is no red tint on the sphere, because there is no global illumination applied to it. In an actual game, you could fix this problem by supplementing the lightmapped objects with an irradiance volume.

  3. In mixed indirect mode, all direct light is calculated in real-time, and the static objects have pre-calculated indirect lighting. This corresponds to the mode that most applications are expected to use. Because direct light on the scenery is computed dynamically, shadows are fully supported. As in mixed direct mode, there is no global illumination on the sphere; in a real application, irradiance volumes could be used to supplement the lightmaps.

  4. In real-time mode, no lightmaps are used at all, and all punctual lights are rendered in real-time. No global illumination exists.

In the example, you can click around to move the sphere, unless you're in baked mode, in which case the sphere must be locked in place to be lit correctly.

Showcase

Baked mode:
Screenshot 2024-12-13 112926

Mixed direct mode:
Screenshot 2024-12-13 112933

Mixed indirect mode (default):
Screenshot 2024-12-13 112939

Real-time mode:
Screenshot 2024-12-13 112944

Migration guide

  • The AmbientLight resource, the IrradianceVolume component, and the EnvironmentMapLight component now have affects_lightmapped_meshes fields. If you don't need to use that field (for example, if you aren't using lightmaps), you can safely set the field to true.
  • DirectionalLight, PointLight, and SpotLight now have affects_lightmapped_mesh_diffuse fields. If you don't need to use that field (for example, if you aren't using lightmaps), you can safely set the field to true.

illuminating lightmapped objects.

This should be fully working, but it needs some better documentation and
a little polish on the example, so I'm marking it as a draft for now.
@pcwalton pcwalton added S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged A-Rendering Drawing game state to the screen C-Feature A new feature, making something new possible labels Dec 11, 2024
@pcwalton pcwalton added this to the 0.16 milestone Dec 11, 2024
Copy link
Contributor

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

Copy link
Contributor

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

@pcwalton pcwalton changed the title Introduce support for mixed lighting by allowing lights to opt out of illuminating lightmapped objects. Introduce support for mixed lighting by allowing lights to opt out of contributing diffuse light to lightmapped objects. Dec 11, 2024
@pcwalton pcwalton marked this pull request as ready for review December 11, 2024 23:38
@pcwalton pcwalton added S-Needs-Review Needs reviewer attention (from anyone!) to move forward and removed S-Waiting-on-Author The author needs to make changes or address concerns before this can be merged labels Dec 12, 2024
@pcwalton pcwalton requested a review from kristoff3r December 12, 2024 00:07
@JMS55
Copy link
Contributor

JMS55 commented Dec 13, 2024

To summarize the discord conversation of what's needed:

  1. Making example have a mode with baked indirect + realtime direct lighting
  2. Updating the migration guide

Copy link
Contributor

@IceSentry IceSentry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code LGTM. I haven't tested anything locally yet, but I'm happy with the implementation.

@pcwalton
Copy link
Contributor Author

@JMS55 I made the requested changes.

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-Feature A new feature, making something new possible S-Needs-Review Needs reviewer attention (from anyone!) to move forward
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

3 participants