这是indexloc提供的服务,不要输入任何密码
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
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 <mitchell@mosure.me>"]
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