bevy/crates/bevy_pbr/src/meshlet/persistent_buffer_impls.rs
JMS55 9cc7e7c080
Meshlet screenspace-derived tangents (#15084)
* Save 16 bytes per vertex by calculating tangents in the shader at
runtime, rather than storing them in the vertex data.
* Based on https://jcgt.org/published/0009/03/04,
https://www.jeremyong.com/graphics/2023/12/16/surface-gradient-bump-mapping.
* Fixed visbuffer resolve to use the updated algorithm that flips ddy
correctly
* Added some more docs about meshlet material limitations, and some
TODOs about transforming UV coordinates for the future.


![image](https://github.com/user-attachments/assets/222d8192-8c82-4d77-945d-53670a503761)

For testing add a normal map to the bunnies with StandardMaterial like
below, and then test that on both main and this PR (make sure to
download the correct bunny for each). Results should be mostly
identical.

```rust
normal_map_texture: Some(asset_server.load_with_settings(
    "textures/BlueNoise-Normal.png",
    |settings: &mut ImageLoaderSettings| settings.is_srgb = false,
)),
```
2024-09-29 18:39:25 +00:00

79 lines
2.3 KiB
Rust

use super::{
asset::{Meshlet, MeshletBoundingSpheres},
persistent_buffer::PersistentGpuBufferable,
};
use alloc::sync::Arc;
const MESHLET_VERTEX_SIZE_IN_BYTES: u32 = 32;
impl PersistentGpuBufferable for Arc<[u8]> {
type Metadata = ();
fn size_in_bytes(&self) -> usize {
self.len()
}
fn write_bytes_le(&self, _: Self::Metadata, buffer_slice: &mut [u8]) {
buffer_slice.clone_from_slice(self);
}
}
impl PersistentGpuBufferable for Arc<[u32]> {
type Metadata = u64;
fn size_in_bytes(&self) -> usize {
self.len() * size_of::<u32>()
}
fn write_bytes_le(&self, offset: Self::Metadata, buffer_slice: &mut [u8]) {
let offset = offset as u32 / MESHLET_VERTEX_SIZE_IN_BYTES;
for (i, index) in self.iter().enumerate() {
let size = size_of::<u32>();
let i = i * size;
let bytes = (*index + offset).to_le_bytes();
buffer_slice[i..(i + size)].clone_from_slice(&bytes);
}
}
}
impl PersistentGpuBufferable for Arc<[Meshlet]> {
type Metadata = (u64, u64);
fn size_in_bytes(&self) -> usize {
self.len() * size_of::<Meshlet>()
}
fn write_bytes_le(
&self,
(vertex_offset, index_offset): Self::Metadata,
buffer_slice: &mut [u8],
) {
let vertex_offset = (vertex_offset as usize / size_of::<u32>()) as u32;
let index_offset = index_offset as u32;
for (i, meshlet) in self.iter().enumerate() {
let size = size_of::<Meshlet>();
let i = i * size;
let bytes = bytemuck::cast::<_, [u8; size_of::<Meshlet>()]>(Meshlet {
start_vertex_id: meshlet.start_vertex_id + vertex_offset,
start_index_id: meshlet.start_index_id + index_offset,
vertex_count: meshlet.vertex_count,
triangle_count: meshlet.triangle_count,
});
buffer_slice[i..(i + size)].clone_from_slice(&bytes);
}
}
}
impl PersistentGpuBufferable for Arc<[MeshletBoundingSpheres]> {
type Metadata = ();
fn size_in_bytes(&self) -> usize {
self.len() * size_of::<MeshletBoundingSpheres>()
}
fn write_bytes_le(&self, _: Self::Metadata, buffer_slice: &mut [u8]) {
buffer_slice.clone_from_slice(bytemuck::cast_slice(self));
}
}