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

refactor: core pipeline changes #73

Merged
merged 8 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe
- There is now a `default_font` feature that uses the same `FiraMono-subset.ttf` font used in the bevy/default_font feature.
- There is now a `render_layers` example.
- There is now a `cube_3d` example.
- You may now choose the render layers for the Vello canvas. This can be configured through the `VelloPlugin`.
- You may now choose to use CPU rendering with Vello and configure anti-aliasing. This can be configured through the `VelloPlugin`.

### Changed

- `VelloPlugin` now has configuration. To retain previous behavior, use `VelloPlugin::default()`.
- `VelloRenderer` is now a resource.
- The `VelloRenderer` will attempt CPU fallback if it cannot obtain a GPU.
- The font API has changed significantly. Please visit `examples/text` for further usage. This is to prepare for additional text features such as linebreak behavior, bounded text, and text justification.
- `VelloText` has been renamed to `VelloTextSection`.
- `VelloText.content` has been renamed to `VelloText.value`.
Expand All @@ -27,11 +31,13 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe
- The field `VelloAssetBundle.vector` was renamed to `VelloAssetBundle.asset`.
- Renamed `VelloAssetAlignment` to `VelloAssetAnchor`. Fields were renamed `alignment` were renamed to `asset_anchor`.
- Renamed `VelloTextAlignment` to `VelloTextAnchor`. Fields were renamed `alignment` were renamed to `text_anchor`.
- The `SSRenderTarget` (fullscreen quad that renders your frame) no longer renders at a zepth of `-0.001`. This was a legacy hack used to ensure Gizmos rendered on-top.
- The `SSRenderTarget` (fullscreen quad that renders your frame) no longer renders at a zepth of `-0.001`. This was a legacy hack used to ensure Gizmos rendered on-top. `RenderLayers` should be used now (there's an example).

### Removed

- Removed `ZFunction`s from the render pipeline. Now ordering is based solely on the `Transform`'s z component. If you dependeded on this behavior, you'll need to adjust the transform Z in a system prior to render.
- `VelloRenderPlugin` is now private, as it is not helpful for downstream developers to add manually.
- Removed `VelloCanvasMaterial` from prelude, as it is not typical to use.

### Fixed

Expand Down
15 changes: 10 additions & 5 deletions examples/cube3d/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ fn main() {
let mut app = App::new();

app.add_plugins(DefaultPlugins)
.add_plugins(VelloPlugin::default())
.add_plugins(VelloPlugin {
use_cpu: false,
antialiasing: vello::AaConfig::Msaa8,
..default()
})
.add_systems(Startup, setup)
.add_systems(Update, cube_rotator_system)
.add_plugins(ExtractComponentPlugin::<VelloTarget>::default());
Expand Down Expand Up @@ -115,15 +119,14 @@ fn setup(
}

fn render_texture(
mut vello_renderer: Local<Option<VelloRenderer>>,
renderer: Res<VelloRenderer>,
render_settings: Res<VelloRenderSettings>,
target: Query<&VelloTarget>,
device: Res<RenderDevice>,
gpu_images: Res<RenderAssets<GpuImage>>,
queue: Res<RenderQueue>,
time: Res<Time>,
) {
let renderer =
vello_renderer.get_or_insert_with(|| VelloRenderer::from_device(device.wgpu_device()));
let target = target.single();

let mut scene = VelloScene::default();
Expand All @@ -147,9 +150,11 @@ fn render_texture(
base_color: vello::peniko::Color::WHITE,
width: gpu_image.size.x,
height: gpu_image.size.y,
antialiasing_method: vello::AaConfig::Area,
antialiasing_method: render_settings.antialiasing,
};
renderer
.lock()
.unwrap()
.render_to_texture(
device.wgpu_device(),
&queue,
Expand Down
48 changes: 12 additions & 36 deletions examples/render_layers/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@ use bevy_vello::{prelude::*, VelloPlugin};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(VelloPlugin::default())
.add_systems(
Startup,
(
setup_canvas,
setup_gizmos,
setup_animation,
setup_background,
),
)
.add_plugins(VelloPlugin {
canvas_render_layers: RenderLayers::layer(1).with(2),
..default()
})
.add_systems(Startup, (setup_gizmos, setup_scene))
.add_systems(Update, (animation, background, run_gizmos))
.run();
}
Expand All @@ -28,11 +23,6 @@ struct AnimationScene;
#[derive(Component)]
struct BackgroundScene;

fn setup_canvas(mut settings: ResMut<VelloRenderSettings>) {
// There's only 1 Vello canvas, so as long as you use a layer that has a camera, you're good!
settings.canvas_render_layers = RenderLayers::layer(3); // the gizmo camera layer
}

fn setup_gizmos(mut commands: Commands, mut config_store: ResMut<GizmoConfigStore>) {
// This camera can only see Gizmos.
commands.spawn((
Expand All @@ -50,42 +40,28 @@ fn setup_gizmos(mut commands: Commands, mut config_store: ResMut<GizmoConfigStor
config.render_layers = RenderLayers::layer(3);
}

fn setup_animation(mut commands: Commands) {
fn setup_scene(mut commands: Commands) {
commands.spawn((
Camera2dBundle {
camera: Camera {
// This camera will render AFTER the blue background camera!
order: 0,
// This camera will render first.
order: -1,
..default()
},
..default()
},
RenderLayers::layer(2),
RenderLayers::layer(1).with(2),
));

commands.spawn((
VelloSceneBundle::default(),
AnimationScene,
RenderLayers::layer(2),
));
}

fn setup_background(mut commands: Commands) {
commands.spawn((
Camera2dBundle {
camera: Camera {
// Render first
order: -1,
..default()
},
..default()
},
BackgroundScene,
RenderLayers::layer(1),
));
commands.spawn((
VelloSceneBundle::default(),
BackgroundScene,
RenderLayers::layer(1),
AnimationScene,
RenderLayers::layer(2),
));
}

Expand Down
18 changes: 2 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub mod prelude {
pub use crate::{
debug::DebugVisualizations,
integrations::{VectorFile, VelloAsset, VelloAssetAnchor},
render::{VelloCanvasMaterial, VelloRenderSettings},
render::VelloRenderSettings,
text::{VelloFont, VelloTextAnchor, VelloTextSection, VelloTextStyle},
CoordinateSpace, VelloAssetBundle, VelloScene, VelloSceneBundle, VelloTextBundle,
};
Expand Down Expand Up @@ -113,23 +113,9 @@ pub struct VelloTextBundle {
}

/// A simple newtype component wrapper for [`vello::Scene`] for rendering.
#[derive(Component, Default, Clone)]
#[derive(Component, Default, Clone, Deref, DerefMut)]
pub struct VelloScene(vello::Scene);

impl std::ops::Deref for VelloScene {
type Target = vello::Scene;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl std::ops::DerefMut for VelloScene {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl VelloScene {
pub fn new() -> Self {
Self::default()
Expand Down
49 changes: 38 additions & 11 deletions src/plugin.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,51 @@
use crate::{
debug::DebugVisualizationsPlugin, render::VelloRenderPlugin, text::VelloFontLoader, VelloAsset,
VelloFont, VelloRenderSettings,
debug::DebugVisualizationsPlugin,
render::{VelloCanvasSettings, VelloRenderPlugin},
text::VelloFontLoader,
VelloAsset, VelloFont, VelloRenderSettings,
};
use bevy::{asset::load_internal_binary_asset, prelude::*, render::view::RenderLayers};
use vello::AaConfig;

#[derive(Resource, Default, Debug)]
#[derive(Clone)]
pub struct VelloPlugin {
/// The render layers that will be used for the Vello canvas mesh.
pub canvas_render_layers: RenderLayers,

/// Use CPU instead of GPU
pub use_cpu: bool,

/// Which antialiasing strategy to use
pub antialiasing: AaConfig,
}

impl Default for VelloPlugin {
fn default() -> Self {
let default_canvas_settings = VelloCanvasSettings::default();
let default_render_settings = VelloRenderSettings::default();
Self {
canvas_render_layers: default_canvas_settings.render_layers,
use_cpu: default_render_settings.use_cpu,
antialiasing: default_render_settings.antialiasing,
}
}
}

impl Plugin for VelloPlugin {
fn build(&self, app: &mut App) {
app.add_plugins(VelloRenderPlugin)
.insert_resource(VelloRenderSettings {
canvas_render_layers: self.canvas_render_layers.clone(),
})
.add_plugins(DebugVisualizationsPlugin)
.init_asset::<VelloAsset>()
.init_asset::<VelloFont>()
.init_asset_loader::<VelloFontLoader>();
app.add_plugins(VelloRenderPlugin {
canvas_settings: VelloCanvasSettings {
render_layers: self.canvas_render_layers.clone(),
},
render_settings: VelloRenderSettings {
use_cpu: self.use_cpu,
antialiasing: self.antialiasing,
},
})
.add_plugins(DebugVisualizationsPlugin)
.init_asset::<VelloAsset>()
.init_asset::<VelloFont>()
.init_asset_loader::<VelloFontLoader>();
#[cfg(feature = "svg")]
app.add_plugins(crate::integrations::svg::SvgIntegrationPlugin);
#[cfg(feature = "lottie")]
Expand Down
81 changes: 70 additions & 11 deletions src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@ use bevy::{
AsBindGroup, RenderPipelineDescriptor, ShaderRef, SpecializedMeshPipelineError,
VertexBufferLayout, VertexFormat, VertexStepMode,
},
renderer::RenderDevice,
view::RenderLayers,
},
sprite::{Material2d, Material2dKey},
};
use std::sync::{Arc, Mutex};
use vello::{AaConfig, AaSupport};

mod extract;
mod plugin;
mod prepare;
mod systems;

pub use plugin::VelloRenderPlugin;
pub use plugin::VelloRenderSettings;
pub(crate) use plugin::VelloRenderPlugin;

/// A handle to the screen space render target shader.
pub const SSRT_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(2314894693238056781);
Expand Down Expand Up @@ -60,26 +63,82 @@ impl Material2d for VelloCanvasMaterial {
}
}

#[derive(Deref, DerefMut)]
pub struct VelloRenderer(vello::Renderer);
#[derive(Resource, Deref, DerefMut)]
pub struct VelloRenderer(Arc<Mutex<vello::Renderer>>);

impl VelloRenderer {
pub fn from_device(device: &vello::wgpu::Device) -> Self {
let renderer = vello::Renderer::new(
pub fn try_new(
device: &vello::wgpu::Device,
settings: &VelloRenderSettings,
) -> Result<Self, vello::Error> {
vello::Renderer::new(
device,
vello::RendererOptions {
surface_format: None,
use_cpu: false,
antialiasing_support: vello::AaSupport::area_only(),
use_cpu: settings.use_cpu,
// TODO: Vello doesn't currently allow adding additional AA support after initialization, so we need to use all support modes here instead.
antialiasing_support: AaSupport::all(),
num_init_threads: None,
},
)
// TODO: Attempt CPU fallback. Support changing antialias settings.
.expect("No GPU Device");
VelloRenderer(renderer)
.map(Mutex::new)
.map(Arc::new)
.map(VelloRenderer)
}
}

impl FromWorld for VelloRenderer {
fn from_world(world: &mut World) -> Self {
match VelloRenderer::try_new(
world.get_resource::<RenderDevice>().unwrap().wgpu_device(),
world.get_resource::<VelloRenderSettings>().unwrap(),
) {
Ok(r) => r,
Err(e) => {
error!("Attempting safe-mode fallback, failed to initialize renderer: {e:}");
{
let mut settings = world.get_resource_mut::<VelloRenderSettings>().unwrap();
settings.use_cpu = true;
settings.antialiasing = AaConfig::Area;
}
match VelloRenderer::try_new(
world.get_resource::<RenderDevice>().unwrap().wgpu_device(),
world.get_resource::<VelloRenderSettings>().unwrap(),
) {
Ok(r) => r,
Err(e) => panic!("Failed to start vello: {e}"),
}
}
}
}
}

#[derive(Resource, Deref, DerefMut, Default)]
#[cfg(feature = "lottie")]
pub struct VelatoRenderer(velato::Renderer);

/// Render settings for Vello.
#[derive(Resource, Clone)]
pub struct VelloRenderSettings {
/// Use CPU instead of GPU
pub use_cpu: bool,

/// Which antialiasing strategy to use
pub antialiasing: AaConfig,
}

impl Default for VelloRenderSettings {
fn default() -> Self {
Self {
use_cpu: false,
antialiasing: AaConfig::Area,
}
}
}

/// Canvas settings for Vello.
#[derive(Resource, Clone, Debug, Default, PartialEq)]
pub(crate) struct VelloCanvasSettings {
/// The render layers that will be used for the Vello canvas mesh.
pub render_layers: RenderLayers,
}
Loading
Loading