Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/bevy_pbr/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ derive_more = { version = "2", default-features = false, features = ["from"] }
lz4_flex = { version = "0.11", default-features = false, features = [
"frame",
], optional = true }
range-alloc = { version = "0.1.3", optional = true }
meshopt = { version = "0.4.1", optional = true }
metis = { version = "0.2", optional = true }
range-alloc = { version = "0.1", optional = true }
meshopt = { version = "0.6.2", optional = true }
metis = { version = "0.2.2", optional = true }
itertools = { version = "0.14", optional = true }
bitvec = { version = "1", optional = true }
# direct dependency required for derive macro
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_pbr/src/meshlet/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use thiserror::Error;
const MESHLET_MESH_ASSET_MAGIC: u64 = 1717551717668;

/// The current version of the [`MeshletMesh`] asset format.
pub const MESHLET_MESH_ASSET_VERSION: u64 = 2;
pub const MESHLET_MESH_ASSET_VERSION: u64 = 3;

/// A mesh that has been pre-processed into multiple small clusters of triangles called meshlets.
///
Expand Down Expand Up @@ -86,8 +86,8 @@ pub struct Meshlet {
pub start_vertex_attribute_id: u32,
/// The offset within the parent mesh's [`MeshletMesh::indices`] buffer where the indices for this meshlet begin.
pub start_index_id: u32,
/// The amount of vertices in this meshlet.
pub vertex_count: u8,
/// The amount of vertices in this meshlet (minus one to fit 256 in a u8).
pub vertex_count_minus_one: u8,
/// The amount of triangles in this meshlet.
pub triangle_count: u8,
/// Unused.
Expand Down
40 changes: 11 additions & 29 deletions crates/bevy_pbr/src/meshlet/from_mesh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use bitvec::{order::Lsb0, vec::BitVec, view::BitView};
use core::{f32, ops::Range};
use itertools::Itertools;
use meshopt::{
build_meshlets, ffi::meshopt_Meshlet, generate_vertex_remap_multi,
simplify_with_attributes_and_locks, Meshlets, SimplifyOptions, VertexDataAdapter, VertexStream,
build_meshlets, ffi::meshopt_Meshlet, generate_position_remap,
simplify_with_attributes_and_locks, Meshlets, SimplifyOptions, VertexDataAdapter,
};
use metis::{option::Opt, Graph};
use smallvec::SmallVec;
Expand Down Expand Up @@ -81,23 +81,11 @@ impl MeshletMesh {
let vertex_normals = bytemuck::cast_slice(&vertex_buffer[12..16]);

// Generate a position-only vertex buffer for determining triangle/meshlet connectivity
let (position_only_vertex_count, position_only_vertex_remap) = generate_vertex_remap_multi(
vertices.vertex_count,
&[VertexStream::new_with_stride::<Vec3, _>(
vertex_buffer.as_ptr(),
vertex_stride,
)],
Some(&indices),
);
let position_only_vertex_remap = generate_position_remap(&vertices);

// Split the mesh into an initial list of meshlets (LOD 0)
let (mut meshlets, mut cull_data) = compute_meshlets(
&indices,
&vertices,
&position_only_vertex_remap,
position_only_vertex_count,
None,
);
let (mut meshlets, mut cull_data) =
compute_meshlets(&indices, &vertices, &position_only_vertex_remap, None);

let mut vertex_locks = vec![false; vertices.vertex_count];

Expand All @@ -115,7 +103,6 @@ impl MeshletMesh {
&simplification_queue,
&meshlets,
&position_only_vertex_remap,
position_only_vertex_count,
);

// Group meshlets into roughly groups of size TARGET_MESHLETS_PER_GROUP,
Expand All @@ -133,7 +120,6 @@ impl MeshletMesh {
&groups,
&meshlets,
&position_only_vertex_remap,
position_only_vertex_count,
);

let simplified = groups.par_chunk_map(AsyncComputeTaskPool::get(), 1, |_, groups| {
Expand Down Expand Up @@ -172,7 +158,6 @@ impl MeshletMesh {
&simplified_group_indices,
&vertices,
&position_only_vertex_remap,
position_only_vertex_count,
Some((group.lod_bounds, group.parent_error)),
);

Expand Down Expand Up @@ -295,11 +280,10 @@ fn compute_meshlets(
indices: &[u32],
vertices: &VertexDataAdapter,
position_only_vertex_remap: &[u32],
position_only_vertex_count: usize,
prev_lod_data: Option<(BoundingSphere, f32)>,
) -> (Meshlets, Vec<TempMeshletCullData>) {
// For each vertex, build a list of all triangles that use it
let mut vertices_to_triangles = vec![Vec::new(); position_only_vertex_count];
let mut vertices_to_triangles = vec![Vec::new(); position_only_vertex_remap.len()];
for (i, index) in indices.iter().enumerate() {
let vertex_id = position_only_vertex_remap[*index as usize];
let vertex_to_triangles = &mut vertices_to_triangles[vertex_id as usize];
Expand Down Expand Up @@ -383,7 +367,7 @@ fn compute_meshlets(
)
};
for meshlet_indices in &indices_per_meshlet {
let meshlet = build_meshlets(meshlet_indices, vertices, 255, 128, 0.0);
let meshlet = build_meshlets(meshlet_indices, vertices, 256, 128, 0.0);
for meshlet in meshlet.iter() {
let (lod_group_sphere, error) = prev_lod_data.unwrap_or_else(|| {
let bounds = meshopt::compute_meshlet_bounds(meshlet, vertices);
Expand All @@ -408,10 +392,9 @@ fn find_connected_meshlets(
simplification_queue: &[u32],
meshlets: &Meshlets,
position_only_vertex_remap: &[u32],
position_only_vertex_count: usize,
) -> Vec<Vec<(usize, usize)>> {
// For each vertex, build a list of all meshlets that use it
let mut vertices_to_meshlets = vec![Vec::new(); position_only_vertex_count];
let mut vertices_to_meshlets = vec![Vec::new(); position_only_vertex_remap.len()];
for (id_index, &meshlet_id) in simplification_queue.iter().enumerate() {
let meshlet = meshlets.get(meshlet_id as _);
for index in meshlet.triangles {
Expand Down Expand Up @@ -505,9 +488,8 @@ fn lock_group_borders(
groups: &[TempMeshletGroup],
meshlets: &Meshlets,
position_only_vertex_remap: &[u32],
position_only_vertex_count: usize,
) {
let mut position_only_locks = vec![-1; position_only_vertex_count];
let mut position_only_locks = vec![-1; position_only_vertex_remap.len()];

// Iterate over position-only based vertices of all meshlets in all groups
for (group_id, group) in groups.iter().enumerate() {
Expand Down Expand Up @@ -617,7 +599,7 @@ fn build_and_compress_per_meshlet_vertex_data(
let mut max_quantized_position_channels = IVec3::MIN;

// Lossy vertex compression
let mut quantized_positions = [IVec3::ZERO; 255];
let mut quantized_positions = [IVec3::ZERO; 256];
for (i, vertex_id) in meshlet_vertex_ids.iter().enumerate() {
// Load source vertex attributes
let vertex_id_byte = *vertex_id as usize * vertex_stride;
Expand Down Expand Up @@ -668,7 +650,7 @@ fn build_and_compress_per_meshlet_vertex_data(
start_vertex_position_bit,
start_vertex_attribute_id,
start_index_id: meshlet.triangle_offset,
vertex_count: meshlet.vertex_count as u8,
vertex_count_minus_one: (meshlet.vertex_count - 1) as u8,
triangle_count: meshlet.triangle_count as u8,
padding: 0,
bits_per_vertex_position_channel_x,
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_pbr/src/meshlet/meshlet_bindings.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct Meshlet {
}

fn get_meshlet_vertex_count(meshlet: ptr<function, Meshlet>) -> u32 {
return extractBits((*meshlet).packed_a, 0u, 8u);
return extractBits((*meshlet).packed_a, 0u, 8u) + 1u;
}

fn get_meshlet_triangle_count(meshlet: ptr<function, Meshlet>) -> u32 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

// TODO: Fixed-point math and top-left rule

var<workgroup> viewport_vertices: array<vec3f, 255>;
var<workgroup> viewport_vertices: array<vec3f, 256>;

@compute
@workgroup_size(128, 1, 1) // 128 threads per workgroup, 1-2 vertices per thread, 1 triangle per thread, 1 cluster per workgroup
Expand Down