Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Meshlet GLTF processor #13431

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
3fbc508
Misc asset code quality and docs
JMS55 May 15, 2024
6cf0bee
Merge branch 'main' of https://github.com/bevyengine/bevy
JMS55 May 16, 2024
b267e0c
WIP
JMS55 May 16, 2024
f6e6554
Add TODO
JMS55 May 16, 2024
cfaa541
More WIP
JMS55 May 18, 2024
d428c3c
WIP
JMS55 May 18, 2024
ab34446
WIP
JMS55 May 18, 2024
8915c32
WIP
JMS55 May 18, 2024
d4e6567
WIP
JMS55 May 18, 2024
6ee5f47
WIP
JMS55 May 19, 2024
896eae8
WIP
JMS55 May 20, 2024
bd258c2
Merge commit '2aed777435d26c357ed71cdb8c7b858de35e582e' into meshlet-…
JMS55 May 20, 2024
70ea4a6
Misc merge fix
JMS55 May 20, 2024
7d9b3d7
Load meshlet meshes when loading entire gltf scene
JMS55 May 22, 2024
842291a
Fmt
JMS55 May 22, 2024
8857188
Fix scene loading
JMS55 May 23, 2024
b7e684f
Switch to embedded GLB buffer
JMS55 May 24, 2024
920bbdd
Add processor alias
JMS55 May 24, 2024
87fe640
Merge commit 'ec01c2dc4562adb979cf5497a48b53efa8250901' into meshlet-…
JMS55 May 24, 2024
dca38b8
Rename meshlet module
JMS55 May 24, 2024
21105cb
Documentation
JMS55 May 24, 2024
f630f1d
Use serde default for GltfLoaderSettings
JMS55 May 24, 2024
8ab47d3
Clippy
JMS55 May 24, 2024
2892523
Add doc comment to GltfLoader
JMS55 May 24, 2024
275e3f2
Fix missing cfg
JMS55 May 24, 2024
baf783c
Fix compile
JMS55 May 24, 2024
faa0b79
Make some meshlet stuff private
JMS55 May 25, 2024
a7034cd
Change some docs
JMS55 May 28, 2024
9e96e0b
Doc tweak
JMS55 May 29, 2024
0d99c8b
Use full path for alias
JMS55 May 29, 2024
234a5a0
Fix bug with buffer slices
JMS55 May 29, 2024
dd17657
Add docs about release mode
JMS55 May 29, 2024
34e08ef
Merge commit '29d6575e222abbe4bdb4f5cec79377bc8a1c4cf5' into meshlet-…
JMS55 May 29, 2024
9035d4d
Add doc comment after rebase
JMS55 May 29, 2024
179822a
Box large variant
JMS55 May 29, 2024
b360a3b
Update crates/bevy_gltf/src/loader.rs
JMS55 May 29, 2024
cf7595d
Sharper shadows
JMS55 May 29, 2024
4557879
Use glb bunny asset
JMS55 May 29, 2024
c746a5f
Dynamic shadow config in example
JMS55 May 29, 2024
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
10 changes: 1 addition & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -1022,21 +1022,13 @@ wasm = false
name = "meshlet"
path = "examples/3d/meshlet.rs"
doc-scrape-examples = true
required-features = ["meshlet"]
required-features = ["meshlet_processor", "asset_processor"]

[package.metadata.example.meshlet]
name = "Meshlet"
description = "Meshlet rendering for dense high-poly scenes (experimental)"
category = "3D Rendering"
wasm = false
setup = [
[
"curl",
"-o",
"assets/models/bunny.meshlet_mesh",
"https://raw.githubusercontent.com/JMS55/bevy_meshlet_asset/bd869887bc5c9c6e74e353f657d342bef84bacd8/bunny.meshlet_mesh",
],
]

[[example]]
name = "lightmaps"
Expand Down
121 changes: 121 additions & 0 deletions assets/models/bunny.gltf

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions assets/models/bunny.gltf.meta
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
(
meta_format_version: "1.0",
asset: Process(
processor: "MeshletMeshProcessor",
settings: (
loader_settings: (),
saver_settings: (),
),
),
)
19 changes: 19 additions & 0 deletions crates/bevy_asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,14 @@ pub trait AssetApp {
fn register_asset_loader<L: AssetLoader>(&mut self, loader: L) -> &mut Self;
/// Registers the given `processor` in the [`App`]'s [`AssetProcessor`].
fn register_asset_processor<P: Process>(&mut self, processor: P) -> &mut Self;
/// Registers the given `processor` in the [`App`]'s [`AssetProcessor`] along with an extra alias.
///
/// This alias can be used in meta files to refer to this asset processor without using the full type name.
fn register_asset_processor_with_alias<P: Process>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to not have an extra method here, and instead require asset processors to implement TypePath? (Probably not a now thing.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't think about TypePath, that might be a decent alternative.

Copy link
Member

@cart cart May 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still on vacation so this is just a quick review: I think this approach is solid, especially in the short term. I do think migrating to TypePath + supporting short names is the right long term move (this code was written in a pre-TypePath-merge world), but even in that case, it doesn't fully solve the "generic flattening / LoadAndSave erasure problem". We'd need to use that in combination with something like what @JMS55 suggested awhile back on discord (define a new short type name that shims LoadAndSave<X, Y>). Rather than discuss whether or not that is the "right" final approach here, we should just merge "aliases" as they are simple and they get the job done.

Random musings: to support the more general "one to many asset transformations" space, we'll need to make meta serialization more type erased + dynamic than it currently is. That might also allow us to rethink how things like LoadAndSave are expressed.

&mut self,
processor: P,
alias: &'static str,
) -> &mut Self;
/// Registers the given [`AssetSourceBuilder`] with the given `id`.
///
/// Note that asset sources must be registered before adding [`AssetPlugin`] to your application,
Expand Down Expand Up @@ -331,6 +339,17 @@ impl AssetApp for App {
self
}

fn register_asset_processor_with_alias<P: Process>(
&mut self,
processor: P,
alias: &'static str,
) -> &mut Self {
if let Some(asset_processor) = self.world().get_resource::<AssetProcessor>() {
asset_processor.register_processor_with_alias(processor, alias);
}
self
}

fn register_asset_source(
&mut self,
id: impl Into<AssetSourceId<'static>>,
Expand Down
12 changes: 11 additions & 1 deletion crates/bevy_asset/src/processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ use crate::io::{AssetReader, AssetWriter};
/// [`AssetProcessor`] can be run in the background while a Bevy App is running. Changes to assets will be automatically detected and hot-reloaded.
///
/// Assets will only be re-processed if they have been changed. A hash of each asset source is stored in the metadata of the processed version of the
/// asset, which is used to determine if the asset source has actually changed.
/// asset, which is used to determine if the asset source has actually changed.
///
/// A [`ProcessorTransactionLog`] is produced, which uses "write-ahead logging" to make the [`AssetProcessor`] crash and failure resistant. If a failed/unfinished
/// transaction from a previous run is detected, the affected asset(s) will be re-processed.
Expand Down Expand Up @@ -489,6 +489,16 @@ impl AssetProcessor {
process_plans.insert(std::any::type_name::<P>(), Arc::new(processor));
}

/// Register a new asset processor with an alias.
pub fn register_processor_with_alias<P: Process>(&self, processor: P, alias: &'static str) {
let mut process_plans = self.data.processors.write();
#[cfg(feature = "trace")]
let processor = InstrumentedAssetProcessor(processor);
let processor = Arc::new(processor);
process_plans.insert(alias, processor.clone());
process_plans.insert(std::any::type_name::<P>(), processor);
}

/// Set the default processor for the given `extension`. Make sure `P` is registered with [`AssetProcessor::register_processor`].
pub fn set_default_processor<P: Process>(&self, extension: &str) {
let mut default_processors = self.data.default_processors.write();
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_gltf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ keywords = ["bevy"]
dds = ["bevy_render/dds"]
pbr_transmission_textures = ["bevy_pbr/pbr_transmission_textures"]
pbr_multi_layer_material_textures = []
# Enables the meshlet renderer for dense high-poly scenes (experimental)
meshlet = ["bevy_pbr/meshlet"]
# Enables processing meshes into meshlet meshes
meshlet_processor = ["meshlet", "bevy_pbr/meshlet_processor"]

[dependencies]
# bevy
Expand Down
27 changes: 26 additions & 1 deletion crates/bevy_gltf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use bevy_animation::AnimationClip;
use bevy_utils::HashMap;

mod loader;
#[cfg(feature = "meshlet")]
mod meshlet_saver;
mod vertex_attributes;
pub use loader::*;

Expand Down Expand Up @@ -55,26 +57,44 @@ impl GltfPlugin {
impl Plugin for GltfPlugin {
fn build(&self, app: &mut App) {
app.register_type::<GltfExtras>()
.init_asset::<RawGltf>()
.init_asset::<Gltf>()
.init_asset::<GltfNode>()
.init_asset::<GltfPrimitive>()
.init_asset::<GltfMesh>()
.preregister_asset_loader::<GltfLoader>(&["gltf", "glb"]);

#[cfg(feature = "meshlet")]
app.register_asset_processor_with_alias::<bevy_asset::processor::LoadAndSave<RawGltfLoader, meshlet_saver::MeshletMeshGltfSaver>>(
meshlet_saver::MeshletMeshGltfSaver.into(),
"MeshletMeshProcessor"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be a good idea to still include Gltf & the bevy namespace here (maybe like bevy::asset::GltfMeshletMeshProcessor?) - it's still going to be a lot shorter than the 3 type paths without the alias.

Copy link
Contributor Author

@JMS55 JMS55 May 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically bevy::asset would be inconsistent with the other auto generated processor names which use bevy_asset due to using std::any::type_name(), but I get what you're saying.

);
}

fn finish(&self, app: &mut App) {
let supported_compressed_formats = match app.world().get_resource::<RenderDevice>() {
Some(render_device) => CompressedImageFormats::from_features(render_device.features()),
None => CompressedImageFormats::NONE,
};

app.register_asset_loader(RawGltfLoader);
app.register_asset_loader(GltfLoader {
supported_compressed_formats,
custom_vertex_attributes: self.custom_vertex_attributes.clone(),
});
}
}

/// Representation of a loaded glTF file.
/// Underlying JSON Representation of a loaded glTF file.
#[derive(Asset, Debug, TypePath)]
pub struct RawGltf {
/// The JSON section of a glTF file.
pub gltf: gltf::Gltf,
/// The buffers of a glTF file, whether from the GLB BIN section, or from external bin files.
pub buffer_data: Vec<Vec<u8>>,
}

/// Bevy representation of a loaded glTF file.
#[derive(Asset, Debug, TypePath)]
pub struct Gltf {
/// All scenes loaded from the glTF file.
Expand Down Expand Up @@ -140,6 +160,11 @@ pub struct GltfMesh {
pub struct GltfPrimitive {
/// Topology to be rendered.
pub mesh: Handle<Mesh>,
/// Meshlet topology to be rendered.
///
/// If this is Some, then `mesh` is [`Handle::default()`].
#[cfg(feature = "meshlet")]
pub meshlet_mesh: Option<Handle<bevy_pbr::experimental::meshlet::MeshletMesh>>,
/// Material to apply to the `mesh`.
pub material: Option<Handle<StandardMaterial>>,
/// Additional data.
Expand Down
Loading
Loading