bevy/examples/3d/lightmaps.rs
JMS55 bb0a82b9a7
Higher quality bicubic lightmap sampling (#16740)
# Objective
- Closes https://github.com/bevyengine/bevy/issues/14322.

## Solution
- Implement fast 4-sample bicubic filtering based on this shader toy
https://www.shadertoy.com/view/4df3Dn, with a small speedup from a ghost
of tushima presentation.

## Testing

- Did you test these changes? If so, how?
  - Ran on lightmapped example. Practically no difference in that scene.
- Are there any parts that need more testing?
  - Lightmapping a better scene.

## Changelog
- Lightmaps now have a higher quality bicubic sampling method (off by
default).

---------

Co-authored-by: Patrick Walton <pcwalton@mimiga.net>
2025-01-12 05:40:30 +00:00

104 lines
3.0 KiB
Rust

//! Rendering a scene with baked lightmaps.
use argh::FromArgs;
use bevy::{
core_pipeline::prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass},
pbr::{DefaultOpaqueRendererMethod, Lightmap},
prelude::*,
};
/// Demonstrates lightmaps
#[derive(FromArgs, Resource)]
struct Args {
/// enables deferred shading
#[argh(switch)]
deferred: bool,
/// enables bicubic filtering
#[argh(switch)]
bicubic: bool,
}
fn main() {
#[cfg(not(target_arch = "wasm32"))]
let args: Args = argh::from_env();
#[cfg(target_arch = "wasm32")]
let args: Args = Args::from_args(&[], &[]).unwrap();
let mut app = App::new();
app.add_plugins(DefaultPlugins)
.insert_resource(AmbientLight::NONE);
if args.deferred {
app.insert_resource(DefaultOpaqueRendererMethod::deferred());
}
app.insert_resource(args)
.add_systems(Startup, setup)
.add_systems(Update, add_lightmaps_to_meshes)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>, args: Res<Args>) {
commands.spawn(SceneRoot(asset_server.load(
GltfAssetLabel::Scene(0).from_asset("models/CornellBox/CornellBox.glb"),
)));
let mut camera = commands.spawn((
Camera3d::default(),
Transform::from_xyz(-278.0, 273.0, 800.0),
));
if args.deferred {
camera.insert((
DepthPrepass,
MotionVectorPrepass,
DeferredPrepass,
Msaa::Off,
));
}
}
fn add_lightmaps_to_meshes(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut materials: ResMut<Assets<StandardMaterial>>,
meshes: Query<
(Entity, &Name, &MeshMaterial3d<StandardMaterial>),
(With<Mesh3d>, Without<Lightmap>),
>,
args: Res<Args>,
) {
let exposure = 250.0;
for (entity, name, material) in meshes.iter() {
if &**name == "large_box" {
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
commands.entity(entity).insert(Lightmap {
image: asset_server.load("lightmaps/CornellBox-Large.zstd.ktx2"),
bicubic_sampling: args.bicubic,
..default()
});
continue;
}
if &**name == "small_box" {
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
commands.entity(entity).insert(Lightmap {
image: asset_server.load("lightmaps/CornellBox-Small.zstd.ktx2"),
bicubic_sampling: args.bicubic,
..default()
});
continue;
}
if name.starts_with("cornell_box") {
materials.get_mut(material).unwrap().lightmap_exposure = exposure;
commands.entity(entity).insert(Lightmap {
image: asset_server.load("lightmaps/CornellBox-Box.zstd.ktx2"),
bicubic_sampling: args.bicubic,
..default()
});
continue;
}
}
}