mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
Fix lightmaps break when deferred rendering is enabled (#14599)
# Objective - Fixes https://github.com/bevyengine/bevy/issues/13552 ## Solution - Thanks for the guidance from @DGriffin91, the current solution is to transmit the light_map through the emissive channel to avoid increasing the bandwidth of deferred shading. - <del>Store lightmap sample result into G-Buffer and pass them into the `Deferred Lighting Pipeline`, therefore we can get the correct indirect lighting via the `apply_pbr_lighting` function.</del> - <del>The original G-Buffer lacks storage for lightmap data, therefore a new buffer is added. We can only use Rgba16Uint here due to the 32-byte limit on the render targets.</del> ## Testing - Need to test all the examples that contains a prepass, with both the forward and deferred rendering mode. - I have tested the ones below. - `lightmaps` (adjust the code based on the issue and check the rendering result) - `transmission` (it contains a prepass) - `ssr` (it also uses the G-Bufffer) - `meshlet` (forward and deferred) - `pbr` ## Showcase By updating the `lightmaps` example to use deferred rendering, this pull request enables correct rendering result of the Cornell Box. ``` diff --git a/examples/3d/lightmaps.rs b/examples/3d/lightmaps.rs index 564a3162b..11a748fba 100644 --- a/examples/3d/lightmaps.rs +++ b/examples/3d/lightmaps.rs @@ -1,12 +1,14 @@ //! Rendering a scene with baked lightmaps. -use bevy::pbr::Lightmap; +use bevy::core_pipeline::prepass::DeferredPrepass; +use bevy::pbr::{DefaultOpaqueRendererMethod, Lightmap}; use bevy::prelude::*; fn main() { App::new() .add_plugins(DefaultPlugins) .insert_resource(AmbientLight::NONE) + .insert_resource(DefaultOpaqueRendererMethod::deferred()) .add_systems(Startup, setup) .add_systems(Update, add_lightmaps_to_meshes) .run(); @@ -19,10 +21,12 @@ fn setup(mut commands: Commands, asset_server: Res<AssetServer>) { ..default() }); - commands.spawn(Camera3dBundle { - transform: Transform::from_xyz(-278.0, 273.0, 800.0), - ..default() - }); + commands + .spawn(Camera3dBundle { + transform: Transform::from_xyz(-278.0, 273.0, 800.0), + ..default() + }) + .insert(DeferredPrepass); } fn add_lightmaps_to_meshes( ``` <img width="1280" alt="image" src="https://github.com/user-attachments/assets/17fd3367-61cc-4c23-b956-e7cfc751af3c"> ## Emissive Issue **The emissive light object appears incorrectly rendered because the alpha channel of emission is set to 1 in deferred rendering and 0 in forward rendering, leading to different emissive light result. Could this be a bug?** ```wgsl // pbr_deferred_functions.wgsl - pbr_input_from_deferred_gbuffer let emissive = rgb9e5::rgb9e5_to_vec3_(gbuffer.g); if ((pbr.material.flags & STANDARD_MATERIAL_FLAGS_UNLIT_BIT) != 0u) { pbr.material.base_color = vec4(emissive, 1.0); pbr.material.emissive = vec4(vec3(0.0), 1.0); } else { pbr.material.base_color = vec4(pow(base_rough.rgb, vec3(2.2)), 1.0); pbr.material.emissive = vec4(emissive, 1.0); } // pbr_functions.wgsl - apply_pbr_lighting emissive_light = emissive_light * mix(1.0, view_bindings::view.exposure, emissive.a); ``` --------- Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>
This commit is contained in:
parent
015f2c69ca
commit
3a478ad5c1
2 changed files with 20 additions and 0 deletions
|
@ -53,6 +53,22 @@ fn deferred_gbuffer_from_pbr_input(in: PbrInput) -> vec4<u32> {
|
||||||
} else {
|
} else {
|
||||||
base_color_srgb = pow(in.material.base_color.rgb, vec3(1.0 / 2.2));
|
base_color_srgb = pow(in.material.base_color.rgb, vec3(1.0 / 2.2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Utilize the emissive channel to transmit the lightmap data. To ensure
|
||||||
|
// it matches the output in forward shading, pre-multiply it with the
|
||||||
|
// calculated diffuse color.
|
||||||
|
let base_color = in.material.base_color.rgb;
|
||||||
|
let metallic = in.material.metallic;
|
||||||
|
let specular_transmission = in.material.specular_transmission;
|
||||||
|
let diffuse_transmission = in.material.diffuse_transmission;
|
||||||
|
let diffuse_color = pbr_functions::calculate_diffuse_color(
|
||||||
|
base_color,
|
||||||
|
metallic,
|
||||||
|
specular_transmission,
|
||||||
|
diffuse_transmission
|
||||||
|
);
|
||||||
|
emissive += in.lightmap_light * diffuse_color * view.exposure;
|
||||||
|
|
||||||
let deferred = vec4(
|
let deferred = vec4(
|
||||||
deferred_types::pack_unorm4x8_(vec4(base_color_srgb, in.material.perceptual_roughness)),
|
deferred_types::pack_unorm4x8_(vec4(base_color_srgb, in.material.perceptual_roughness)),
|
||||||
rgb9e5::vec3_to_rgb9e5_(emissive),
|
rgb9e5::vec3_to_rgb9e5_(emissive),
|
||||||
|
|
|
@ -429,6 +429,10 @@ where
|
||||||
shader_defs.push("DEFERRED_PREPASS".into());
|
shader_defs.push("DEFERRED_PREPASS".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if key.mesh_key.contains(MeshPipelineKey::LIGHTMAPPED) {
|
||||||
|
shader_defs.push("LIGHTMAP".into());
|
||||||
|
}
|
||||||
|
|
||||||
if layout.0.contains(Mesh::ATTRIBUTE_COLOR) {
|
if layout.0.contains(Mesh::ATTRIBUTE_COLOR) {
|
||||||
shader_defs.push("VERTEX_COLORS".into());
|
shader_defs.push("VERTEX_COLORS".into());
|
||||||
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(7));
|
vertex_attributes.push(Mesh::ATTRIBUTE_COLOR.at_shader_location(7));
|
||||||
|
|
Loading…
Reference in a new issue