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

light renderlayers #10742

Merged
merged 1 commit into from
Dec 12, 2023
Merged

Conversation

robtfm
Copy link
Contributor

@robtfm robtfm commented Nov 26, 2023

Objective

add RenderLayers awareness to lights. lights default to RenderLayers::layer(0), and must intersect the camera entity's RenderLayers in order to affect the camera's output.

note that lights already use renderlayers to filter meshes for shadow casting. this adds filtering lights per view based on intersection of camera layers and light layers.

fixes #3462

Solution

PointLights and SpotLights are assigned to individual views in assign_lights_to_clusters, so we simply cull the lights which don't match the view layers in that function.

DirectionalLights are global, so we

  • add the light layers to the DirectionalLight struct
  • add the view layers to the ViewUniform struct
  • check for intersection before processing the light in apply_pbr_lighting

potential issue: when mesh/light layers are smaller than the view layers weird results can occur. e.g:
camera = layers 1+2
light = layers 1
mesh = layers 2

the mesh does not cast shadows wrt the light as (1 & 2) == 0.
the light affects the view as (1+2 & 1) != 0.
the view renders the mesh as (1+2 & 2) != 0.

so the mesh is rendered and lit, but does not cast a shadow.

this could be fixed (so that the light would not affect the mesh in that view) by adding the light layers to the point and spot light structs, but i think the setup is pretty unusual, and space is at a premium in those structs (adding 4 bytes more would reduce the webgl point+spot light max count to 240 from 256).

I think typical usage is for cameras to have a single layer, and meshes/lights to maybe have multiple layers to render to e.g. minimaps as well as primary views.

if there is a good use case for the above setup and we should support it, please let me know.


Migration Guide

Lights no longer affect all RenderLayers by default, now like cameras and meshes they default to RenderLayers::layer(0). To recover the previous behaviour and have all lights affect all views, add a RenderLayers::all() component to the light entity.

@robtfm
Copy link
Contributor Author

robtfm commented Nov 26, 2023

to test, i was changing the light layers in the render_to_texture.rs. you can replace the PointLightBundle with something like

    commands.spawn((
        DirectionalLightBundle {
            transform: Transform::default().looking_at(-Vec3::Y + Vec3::X, Vec3::Z),
            ..Default::default()
        },
        RenderLayers::all(), // or RenderLayers::layer(0) etc
    ));

or

    commands.spawn((
        SpotLightBundle {
            transform: Transform::from_translation(Vec3::new(0.0, 0.0, 10.0)).looking_at(Vec3::ZERO, Vec3::Y),
            ..Default::default()
        },
        RenderLayers::all(),
    ));

@robtfm robtfm added C-Feature A new feature, making something new possible A-Rendering Drawing game state to the screen labels Nov 26, 2023
@alice-i-cecile alice-i-cecile added this to the 0.13 milestone Nov 26, 2023
Copy link

@TheBiochemic TheBiochemic left a comment

Choose a reason for hiding this comment

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

Changes look good to me,
additionally what i did locally, is adding some additional LightSources into the render_to_texture example using different layers and casting shadows plus a plane on the main layer to catch them, and they don't interfere with eachother anymore. Feature works as intended.

image
In the front left corner there is a orange_red light on the main layer, and in a similar position there is a lime_green light, on the first pass layer (RenderLayers::layer(1))

@robtfm robtfm added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Dec 5, 2023
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Dec 12, 2023
Merged via the queue into bevyengine:main with commit 67d92e9 Dec 12, 2023
26 checks passed
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-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Lights don't respect RenderLayer
4 participants