bevy/crates/bevy_pbr/src/lightmap/lightmap.wgsl
Patrick Walton dd14f3a477
Implement lightmaps. (#10231)
![Screenshot](https://i.imgur.com/A4KzWFq.png)

# Objective

Lightmaps, textures that store baked global illumination, have been a
mainstay of real-time graphics for decades. Bevy currently has no
support for them, so this pull request implements them.

## Solution

The new `Lightmap` component can be attached to any entity that contains
a `Handle<Mesh>` and a `StandardMaterial`. When present, it will be
applied in the PBR shader. Because multiple lightmaps are frequently
packed into atlases, each lightmap may have its own UV boundaries within
its texture. An `exposure` field is also provided, to control the
brightness of the lightmap.

Note that this PR doesn't provide any way to bake the lightmaps. That
can be done with [The Lightmapper] or another solution, such as Unity's
Bakery.

---

## Changelog

### Added
* A new component, `Lightmap`, is available, for baked global
illumination. If your mesh has a second UV channel (UV1), and you attach
this component to the entity with that mesh, Bevy will apply the texture
referenced in the lightmap.

[The Lightmapper]: https://github.com/Naxela/The_Lightmapper

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2024-01-02 20:38:47 +00:00

29 lines
1 KiB
WebGPU Shading Language

#define_import_path bevy_pbr::lightmap
#import bevy_pbr::mesh_bindings::mesh
@group(1) @binding(4) var lightmaps_texture: texture_2d<f32>;
@group(1) @binding(5) var lightmaps_sampler: sampler;
// Samples the lightmap, if any, and returns indirect illumination from it.
fn lightmap(uv: vec2<f32>, exposure: f32, instance_index: u32) -> vec3<f32> {
let packed_uv_rect = mesh[instance_index].lightmap_uv_rect;
let uv_rect = vec4<f32>(vec4<u32>(
packed_uv_rect.x & 0xffffu,
packed_uv_rect.x >> 16u,
packed_uv_rect.y & 0xffffu,
packed_uv_rect.y >> 16u)) / 65535.0;
let lightmap_uv = mix(uv_rect.xy, uv_rect.zw, uv);
// Mipmapping lightmaps is usually a bad idea due to leaking across UV
// islands, so there's no harm in using mip level 0 and it lets us avoid
// control flow uniformity problems.
//
// TODO(pcwalton): Consider bicubic filtering.
return textureSampleLevel(
lightmaps_texture,
lightmaps_sampler,
lightmap_uv,
0.0).rgb * exposure;
}