Skip to content

Commit

Permalink
chore: upgrade to bevy 0.12 (#20)
Browse files Browse the repository at this point in the history
* chore: build for bevy 0.12

* chore: upgrade bevy_panorbit_camera

* fix: gate phase item addition on uniform availability

* docs: bevy 0.12 support

* chore: bump version to 0.4.0
  • Loading branch information
mosure authored Nov 6, 2023
1 parent 67570b2 commit 51bdd5d
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 77 deletions.
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "bevy_gaussian_splatting"
description = "bevy gaussian splatting render pipeline plugin"
version = "0.3.0"
version = "0.4.0"
edition = "2021"
authors = ["mosure <[email protected]>"]
license = "MIT"
Expand All @@ -14,15 +14,15 @@ exclude = [".devcontainer", ".github", "docs", "dist", "build", "assets", "credi
default-run = "viewer"

[dependencies]
bevy-inspector-egui = "0.20.0"
bevy_panorbit_camera = "0.8.0"
bevy-inspector-egui = "0.21"
bevy_panorbit_camera = "0.9.0"
bincode2 = "2.0.1"
bytemuck = "1.14.0"
flate2 = "1.0.28"
ply-rs = "0.1.3"
rand = "0.8.5"
serde = "1.0.189"
wgpu = "0.16.0"
wgpu = "0.17.1"


[target.'cfg(target_arch = "wasm32")'.dependencies]
Expand All @@ -32,7 +32,7 @@ wasm-bindgen = "0.2.87"

# TODO: use minimal bevy features
[dependencies.bevy]
version = "0.11.3"
version = "0.12"
default-features = true


Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ bevy gaussian splatting render pipeline plugin
![Alt text](docs/notferris.png)
![Alt text](docs/bike.png)

`cargo run -- {path to ply or gcloud file}`
`cargo run -- scenes/icecream.gcloud`

## capabilities

Expand Down Expand Up @@ -70,6 +70,7 @@ to build wasm run:

| `bevy_gaussian_splatting` | `bevy` |
| :-- | :-- |
| `0.4` | `0.12` |
| `0.1 - 0.3` | `0.11` |


Expand Down
30 changes: 19 additions & 11 deletions src/gaussian.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
io::{
BufReader,
Cursor,
ErrorKind,
},
marker::Copy,
};
Expand All @@ -11,8 +12,9 @@ use bevy::{
prelude::*,
asset::{
AssetLoader,
AsyncReadExt,
LoadContext,
LoadedAsset,
io::Reader,
},
reflect::TypeUuid,
render::render_resource::ShaderType,
Expand Down Expand Up @@ -136,6 +138,7 @@ pub struct Gaussian {
}

#[derive(
Asset,
Clone,
Debug,
Reflect,
Expand Down Expand Up @@ -233,12 +236,21 @@ impl Default for GaussianCloudSettings {
pub struct GaussianCloudLoader;

impl AssetLoader for GaussianCloudLoader {
type Asset = GaussianCloud;
type Settings = ();
type Error = std::io::Error;

fn load<'a>(
&'a self,
bytes: &'a [u8],
reader: &'a mut Reader,
_settings: &'a Self::Settings,
load_context: &'a mut LoadContext,
) -> BoxedFuture<'a, Result<(), bevy::asset::Error>> {
) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {

Box::pin(async move {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;

match load_context.path().extension() {
Some(ext) if ext == "ply" => {
let cursor = Cursor::new(bytes);
Expand All @@ -247,19 +259,15 @@ impl AssetLoader for GaussianCloudLoader {
let ply_cloud = parse_ply(&mut f)?;
let cloud = GaussianCloud(ply_cloud);

load_context.set_default_asset(LoadedAsset::new(cloud));

Ok(())
Ok(cloud)
},
Some(ext) if ext == "gcloud" => {
let decompressed = GzDecoder::new(bytes);
let decompressed = GzDecoder::new(bytes.as_slice());
let cloud: GaussianCloud = deserialize_from(decompressed).expect("failed to decode cloud");

load_context.set_default_asset(LoadedAsset::new(cloud));

Ok(())
Ok(cloud)
},
_ => Ok(()),
_ => Err(std::io::Error::new(ErrorKind::Other, "only .ply and .gcloud supported")),
}
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Plugin for GaussianSplattingPlugin {
// TODO: allow hot reloading of GaussianCloud handle through inspector UI
app.register_type::<SphericalHarmonicCoefficients>();
app.register_type::<GaussianCloud>();
app.add_asset::<GaussianCloud>();
app.init_asset::<GaussianCloud>();
app.register_asset_reflect::<GaussianCloud>();

app.init_asset_loader::<GaussianCloudLoader>();
Expand Down
3 changes: 1 addition & 2 deletions src/ply.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::io::BufRead;

use bevy::asset::Error;
use ply_rs::{
ply::{
Property,
Expand Down Expand Up @@ -53,7 +52,7 @@ impl PropertyAccess for Gaussian {
}
}

pub fn parse_ply(mut reader: &mut dyn BufRead) -> Result<Vec<Gaussian>, Error> {
pub fn parse_ply(mut reader: &mut dyn BufRead) -> Result<Vec<Gaussian>, std::io::Error> {
let gaussian_parser = Parser::<Gaussian>::new();
let header = gaussian_parser.read_header(&mut reader)?;

Expand Down
6 changes: 3 additions & 3 deletions src/render/gaussian.wgsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#import bevy_render::globals Globals
#import bevy_render::view View
#import bevy_render::globals::Globals
#import bevy_render::view::View

#import bevy_gaussian_splatting::spherical_harmonics spherical_harmonics_lookup
#import bevy_gaussian_splatting::spherical_harmonics::spherical_harmonics_lookup


struct GaussianInput {
Expand Down
82 changes: 46 additions & 36 deletions src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use bevy::{
prelude::*,
asset::{
load_internal_asset,
HandleUntyped,
LoadState,
},
core_pipeline::core_3d::{
Expand All @@ -18,7 +17,6 @@ use bevy::{
},
query::ROQueryItem,
},
reflect::TypeUuid,
render::{
Extract,
extract_component::{
Expand Down Expand Up @@ -75,8 +73,8 @@ use crate::gaussian::{
};


const GAUSSIAN_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 68294581);
const SPHERICAL_HARMONICS_SHADER_HANDLE: HandleUntyped = HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 834667312);
const GAUSSIAN_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(68294581);
const SPHERICAL_HARMONICS_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(834667312);

pub mod node {
pub const RADIX_SORT: &str = "radix_sort";
Expand Down Expand Up @@ -124,9 +122,9 @@ impl Plugin for RenderPipelinePlugin {
.add_systems(
Render,
(
queue_gaussian_bind_group.in_set(RenderSet::Queue),
queue_gaussian_view_bind_groups.in_set(RenderSet::Queue),
queue_gaussians.in_set(RenderSet::Queue),
queue_gaussian_bind_group.in_set(RenderSet::QueueMeshes),
queue_gaussian_view_bind_groups.in_set(RenderSet::QueueMeshes),
queue_gaussians.in_set(RenderSet::QueueMeshes),
),
);
}
Expand Down Expand Up @@ -237,6 +235,7 @@ impl RenderAsset for GaussianCloud {

#[allow(clippy::too_many_arguments)]
fn queue_gaussians(
gaussian_cloud_uniform: Res<ComponentUniforms<GaussianCloudUniform>>,
transparent_3d_draw_functions: Res<DrawFunctions<Transparent3d>>,
custom_pipeline: Res<GaussianCloudPipeline>,
mut pipelines: ResMut<SpecializedRenderPipelines<GaussianCloudPipeline>>,
Expand All @@ -252,6 +251,11 @@ fn queue_gaussians(
&mut RenderPhase<Transparent3d>,
)>,
) {
// TODO: condition this system based on GaussianCloudBindGroup attachment
if gaussian_cloud_uniform.buffer().is_none() {
return;
};

let draw_custom = transparent_3d_draw_functions.read().id::<DrawGaussians>();

for (_view, mut transparent_phase) in &mut views {
Expand All @@ -264,11 +268,18 @@ fn queue_gaussians(

let pipeline = pipelines.specialize(&pipeline_cache, &custom_pipeline, key);

// // TODO: distance to gaussian cloud centroid
// let rangefinder = view.rangefinder3d();

transparent_phase.add(Transparent3d {
entity,
draw_function: draw_custom,
distance: 0.0,
// distance: rangefinder
// .distance_translation(&mesh_instance.transforms.transform.translation),
pipeline,
batch_range: 0..1,
dynamic_offset: None,
});
}
}
Expand Down Expand Up @@ -436,7 +447,7 @@ impl FromWorld for GaussianCloudPipeline {
gaussian_cloud_layout.clone(),
radix_sort_layout.clone(),
];
let shader = GAUSSIAN_SHADER_HANDLE.typed();
let shader = GAUSSIAN_SHADER_HANDLE;
let shader_defs = shader_defs(false, false);

let pipeline_cache = render_world.resource::<PipelineCache>();
Expand Down Expand Up @@ -754,10 +765,10 @@ pub fn queue_gaussian_bind_group(
return;
};

assert!(model.size() == std::mem::size_of::<GaussianCloudUniform>() as u64);

groups.base_bind_group = Some(render_device.create_bind_group(&BindGroupDescriptor {
entries: &[
groups.base_bind_group = Some(render_device.create_bind_group(
"gaussian_uniform_bind_group",
&gaussian_cloud_pipeline.gaussian_uniform_layout,
&[
BindGroupEntry {
binding: 0,
resource: BindingResource::Buffer(BufferBinding {
Expand All @@ -767,16 +778,15 @@ pub fn queue_gaussian_bind_group(
}),
},
],
layout: &gaussian_cloud_pipeline.gaussian_uniform_layout,
label: Some("gaussian_uniform_bind_group"),
}));
));

for (entity, cloud_handle) in gaussian_clouds.iter() {
if asset_server.get_load_state(cloud_handle) == LoadState::Loading {
// TODO: add asset loading indicator (and maybe streamed loading)
if Some(LoadState::Loading) == asset_server.get_load_state(cloud_handle) {
continue;
}

if !gaussian_cloud_res.contains_key(cloud_handle) {
if gaussian_cloud_res.get(cloud_handle).is_none() {
continue;
}

Expand All @@ -802,10 +812,10 @@ pub fn queue_gaussian_bind_group(

let radix_sort_bind_groups: [BindGroup; 4] = (0..4)
.map(|idx| {
render_device.create_bind_group(&BindGroupDescriptor {
label: format!("radix_sort_bind_group {}", idx).as_str().into(),
layout: &gaussian_cloud_pipeline.radix_sort_layout,
entries: &[
render_device.create_bind_group(
format!("radix_sort_bind_group {}", idx).as_str(),
&gaussian_cloud_pipeline.radix_sort_layout,
&[
BindGroupEntry {
binding: 0,
resource: BindingResource::Buffer(BufferBinding {
Expand Down Expand Up @@ -841,15 +851,17 @@ pub fn queue_gaussian_bind_group(
}),
},
],
})
)
})
.collect::<Vec<BindGroup>>()
.try_into()
.unwrap();

commands.entity(entity).insert(GaussianCloudBindGroup {
cloud_bind_group: render_device.create_bind_group(&BindGroupDescriptor {
entries: &[
cloud_bind_group: render_device.create_bind_group(
"gaussian_cloud_bind_group",
&gaussian_cloud_pipeline.gaussian_cloud_layout,
&[
BindGroupEntry {
binding: 0,
resource: BindingResource::Buffer(BufferBinding {
Expand All @@ -859,12 +871,12 @@ pub fn queue_gaussian_bind_group(
}),
},
],
layout: &gaussian_cloud_pipeline.gaussian_cloud_layout,
label: Some("gaussian_cloud_bind_group"),
}),
),
radix_sort_bind_groups,
sorted_bind_group: render_device.create_bind_group(&BindGroupDescriptor {
entries: &[
sorted_bind_group: render_device.create_bind_group(
"render_sorted_bind_group",
&gaussian_cloud_pipeline.sorted_layout,
&[
BindGroupEntry {
binding: 5,
resource: BindingResource::Buffer(BufferBinding {
Expand All @@ -874,9 +886,7 @@ pub fn queue_gaussian_bind_group(
}),
},
],
layout: &gaussian_cloud_pipeline.sorted_layout,
label: Some("render_sorted_bind_group"),
}),
),
});
}
}
Expand Down Expand Up @@ -925,11 +935,11 @@ pub fn queue_gaussian_view_bind_groups(
},
];

let view_bind_group = render_device.create_bind_group(&BindGroupDescriptor {
entries: &entries,
label: Some("gaussian_view_bind_group"),
let view_bind_group = render_device.create_bind_group(
"gaussian_view_bind_group",
layout,
});
&entries,
);


commands.entity(entity).insert(GaussianViewBindGroup {
Expand Down
Loading

0 comments on commit 51bdd5d

Please sign in to comment.