# bevy_spark
SPZ Gaussian splat rendering for Bevy.
The crate provides:
- `SparkPlugin` for loading and rendering `.spz` assets.
- `SplatCloud` for spawning a splat asset as a normal Bevy entity.
- SPZ v1/v2/v3 parsing with spherical harmonics, anti-alias flags, and LOD payloads.
- Per-view CPU sorting, experimental GPU radix sorting, LOD traversal, and typed quality settings.
## Installation
```toml
[dependencies]
bevy = "0.18"
bevy_spark = "0.2"
```
## Basic Usage
```rust
use bevy::prelude::*;
use bevy_spark::{SparkPlugin, SplatCloud, SplatCoordinateConvention, Splats};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(SparkPlugin)
.add_systems(Startup, setup)
.run();
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let handle: Handle<Splats> = asset_server.load("butterfly.spz");
commands.spawn((
SplatCloud { handle },
SplatCoordinateConvention::YDown,
Transform::from_xyz(0.0, 0.0, -3.0),
));
commands.spawn((Camera3d::default(), Transform::default()));
}
```
`SplatCoordinateConvention::YDown` is useful for SPZ files authored in the common 3DGS/SparkJS convention. Marble exports from World Labs use an OpenCV-style coordinate system; see the [World Labs export specs](https://docs.worldlabs.ai/marble/export/specs) for their SPZ and PLY export options and example scenes.
## Examples
This repository does not bundle large splat assets. Download or copy an `.spz` file into your Bevy asset root first:
```bash
mkdir -p assets
# copy your file to assets/butterfly.spz, assets/kitchen_500k.spz, etc.
```
Run the object example:
```bash
cargo run --release --example butterfly
```
Run the interior navigation example with any SPZ file under `assets/`:
```bash
cargo run --release --example kitchen -- kitchen_500k.spz
```
For fullscreen testing with lower fragment cost:
```bash
BEVY_SPARK_UPSCALE=2 BEVY_SPARK_FULLSCREEN=1 cargo run --release --example kitchen -- kitchen_2m.spz
```
The kitchen example pins its window scale factor to 1x by default so `1280x720` means physical render size. Set `BEVY_SPARK_WINDOW_SCALE=native` to use the OS HiDPI scale instead.
## Configuration
Use `SparkSettings` for global quality, sorting, LOD, upload, and multi-cloud defaults. The default preset is `SparkQualityPreset::Balanced`, which keeps the renderer practical for interactive scenes; use `SparkQualityPreset::Reference` for SparkJS-style capture comparisons. Add `SplatCloudSettings` to override quality, sorting, or LOD for one cloud.
Set `SparkConfigSource::ResourceOnly` if an application should ignore `BEVY_SPARK_*` environment overrides.
For Bevy's WebGL2 backend, enable the crate's `webgl2` feature. It forwards Bevy's WebGL2 support and switches splat, SH, and sorted-index data to integer textures while leaving the storage-buffer path as the default for native and WebGPU-capable adapters.
## Mixing splats with other transparents
Splat clouds are queued as a single `Transparent3d` entry with sort distance `f32::NEG_INFINITY` so they always draw first in the transparent phase. Opaque geometry inside the splat volume occludes correctly via depth test. Other transparent materials (lighting overlays, decals, glass) draw on top of the splat unconditionally — convenient for splat-as-environment but means transparent objects can't be partially occluded by closer splats.
## Attribution
SPZ parser behavior and splat shader parity were implemented with reference to SparkJS (`@sparkjsdev/spark`), MIT licensed by WORLD LABS TECHNOLOGIES, INC. The reference commit used during parity work is recorded in `NOTICE.md`.