Skip to content

Commit

Permalink
Update for Bevy 0.14. (#63)
Browse files Browse the repository at this point in the history
* Update for Bevy 0.14.

* Update src/material.rs

---------

Co-authored-by: IceSentry <[email protected]>
  • Loading branch information
yrns and IceSentry committed Jul 9, 2024
1 parent a68fbd3 commit 236257b
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 104 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,18 @@ authors = [

[dependencies]
bitflags = "2.3"
bevy = { version = "0.13", default-features = false, features = [
bevy = { version = "0.14", default-features = false, features = [
"bevy_core_pipeline",
"bevy_render",
"bevy_asset",
] }
bytemuck = "1.16.1"

[dev-dependencies]
lazy_static = "1.4.0"
rand = "0.8.4"
ringbuffer = "0.15"
bevy = { version = "0.13", default-features = false, features = [
bevy = { version = "0.14", default-features = false, features = [
"bevy_winit",
"bevy_pbr",
"x11",
Expand Down
4 changes: 2 additions & 2 deletions examples/depth_bias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ fn setup(
}),
material: materials.add(PolylineMaterial {
width: 5.0,
color: Color::RED,
color: bevy::color::palettes::css::RED.into(),
depth_bias: -1.0,
perspective: false,
}),
Expand All @@ -97,7 +97,7 @@ fn setup(
}),
material: materials.add(PolylineMaterial {
width: 1.0,
color: Color::hsl((bias + 1.0) / 2.0 * 270.0, 1.0, 0.5),
color: Color::hsl((bias + 1.0) / 2.0 * 270.0, 1.0, 0.5).to_linear(),
depth_bias: bias,
perspective: false,
}),
Expand Down
4 changes: 2 additions & 2 deletions examples/linestrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn setup(
}),
material: polyline_materials.add(PolylineMaterial {
width: 2.0,
color: Color::RED,
color: bevy::color::palettes::css::RED.into(),
perspective: false,
// Bias the line toward the camera so the line at the cube-plane intersection is visible
depth_bias: -0.0002,
Expand All @@ -52,7 +52,7 @@ fn setup(
// cube
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::from_size(Vec3::ONE)),
material: standard_materials.add(Color::rgb_u8(124, 144, 255)),
material: standard_materials.add(Color::srgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.0, 0.0),
..default()
});
Expand Down
2 changes: 1 addition & 1 deletion examples/minimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn setup(
}),
material: polyline_materials.add(PolylineMaterial {
width: 10.0,
color: Color::RED,
color: bevy::color::palettes::css::RED.into(),
perspective: false,
..default()
}),
Expand Down
3 changes: 2 additions & 1 deletion examples/nbody.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ fn setup(
}),
material: polyline_materials.add(PolylineMaterial {
width: (size * 0.1).powf(1.8),
color: Color::hsl(rng.gen_range(0.0..360.0), 1.0, rng.gen_range(1.2..3.0)),
color: Color::hsl(rng.gen_range(0.0..360.0), 1.0, rng.gen_range(1.2..3.0))
.to_linear(),
perspective: true,
..Default::default()
}),
Expand Down
2 changes: 1 addition & 1 deletion examples/perspective.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn setup(
}),
material: polyline_materials.add(PolylineMaterial {
width: 10.0,
color: Color::RED,
color: bevy::color::palettes::css::RED.into(),
perspective: true,
..default()
}),
Expand Down
157 changes: 85 additions & 72 deletions src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use crate::polyline::{
};

use bevy::{
core_pipeline::core_3d::{AlphaMask3d, Opaque3d, Transparent3d},
core_pipeline::{
core_3d::{AlphaMask3d, Opaque3d, Opaque3dBinKey, Transparent3d},
prepass::OpaqueNoLightmap3dBinKey,
},
ecs::{
query::ROQueryItem,
system::{
Expand All @@ -16,13 +19,13 @@ use bevy::{
reflect::TypePath,
render::{
extract_component::ExtractComponentPlugin,
render_asset::{
PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssetUsages, RenderAssets,
},
render_asset::{PrepareAssetError, RenderAsset, RenderAssetPlugin, RenderAssets},
render_phase::*,
render_resource::{binding_types::uniform_buffer, *},
renderer::{RenderDevice, RenderQueue},
view::{ExtractedView, ViewUniformOffset, VisibleEntities},
view::{
check_visibility, ExtractedView, ViewUniformOffset, VisibilitySystems, VisibleEntities,
},
Render, RenderApp, RenderSet,
},
};
Expand All @@ -35,7 +38,7 @@ pub struct PolylineMaterial {
/// Corresponds to screen pixels when line is positioned nearest the
/// camera.
pub width: f32,
pub color: Color,
pub color: LinearRgba,
/// How closer to the camera than real geometry the line should be.
///
/// Value between -1 and 1 (inclusive).
Expand Down Expand Up @@ -64,7 +67,7 @@ impl Default for PolylineMaterial {
fn default() -> Self {
Self {
width: 10.0,
color: Color::WHITE,
color: Color::WHITE.to_linear(),
depth_bias: 0.0,
perspective: false,
}
Expand All @@ -83,13 +86,13 @@ impl PolylineMaterial {
}

#[inline]
fn bind_group(render_asset: &<Self as RenderAsset>::PreparedAsset) -> &BindGroup {
fn bind_group(render_asset: &GpuPolylineMaterial) -> &BindGroup {
&render_asset.bind_group
}

#[allow(unused_variables)]
#[inline]
fn dynamic_uniform_indices(material: &<Self as RenderAsset>::PreparedAsset) -> &[u32] {
fn dynamic_uniform_indices(material: &GpuPolylineMaterial) -> &[u32] {
&[]
}
}
Expand All @@ -108,33 +111,29 @@ pub struct GpuPolylineMaterial {
pub alpha_mode: AlphaMode,
}

impl RenderAsset for PolylineMaterial {
type PreparedAsset = GpuPolylineMaterial;
impl RenderAsset for GpuPolylineMaterial {
type SourceAsset = PolylineMaterial;
type Param = (
SRes<RenderDevice>,
SRes<RenderQueue>,
SRes<PolylineMaterialPipeline>,
);

fn asset_usage(&self) -> RenderAssetUsages {
RenderAssetUsages::default()
}

fn prepare_asset(
self,
polyline_material: Self::SourceAsset,
(device, queue, polyline_pipeline): &mut bevy::ecs::system::SystemParamItem<Self::Param>,
) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
) -> Result<Self, PrepareAssetError<Self::SourceAsset>> {
let value = PolylineMaterialUniform {
width: self.width,
depth_bias: self.depth_bias,
color: self.color.as_linear_rgba_f32().into(),
width: polyline_material.width,
depth_bias: polyline_material.depth_bias,
color: polyline_material.color.to_f32_array().into(),
};

let mut buffer = UniformBuffer::from(value);
buffer.write_buffer(device, queue);

let Some(buffer_binding) = buffer.binding() else {
return Err(PrepareAssetError::RetryNextUpdate(self));
return Err(PrepareAssetError::RetryNextUpdate(polyline_material));
};

let bind_group = device.create_bind_group(
Expand All @@ -143,21 +142,23 @@ impl RenderAsset for PolylineMaterial {
&BindGroupEntries::single(buffer_binding),
);

let alpha_mode = if self.color.a() < 1.0 {
let alpha_mode = if polyline_material.color.alpha() < 1.0 {
AlphaMode::Blend
} else {
AlphaMode::Opaque
};

Ok(GpuPolylineMaterial {
buffer,
perspective: self.perspective,
perspective: polyline_material.perspective,
alpha_mode,
bind_group,
})
}
}

pub type WithPolyline = With<Handle<PolylineMaterial>>;

/// Adds the necessary ECS resources and render logic to enable rendering entities using ['PolylineMaterial']
#[derive(Default)]
pub struct PolylineMaterialPlugin;
Expand All @@ -166,11 +167,15 @@ impl Plugin for PolylineMaterialPlugin {
fn build(&self, app: &mut App) {
app.init_asset::<PolylineMaterial>()
.add_plugins(ExtractComponentPlugin::<Handle<PolylineMaterial>>::default())
.add_plugins(RenderAssetPlugin::<PolylineMaterial>::default());
.add_plugins(RenderAssetPlugin::<GpuPolylineMaterial>::default())
.add_systems(
PostUpdate,
check_visibility::<WithPolyline>.in_set(VisibilitySystems::CheckVisibility),
);
}

fn finish(&self, app: &mut App) {
if let Ok(render_app) = app.get_sub_app_mut(RenderApp) {
if let Some(render_app) = app.get_sub_app_mut(RenderApp) {
render_app
.add_render_command::<Transparent3d, DrawPolylineMaterial>()
.add_render_command::<Opaque3d, DrawPolylineMaterial>()
Expand Down Expand Up @@ -250,7 +255,7 @@ pub struct SetMaterialBindGroup<const I: usize>;
impl<const I: usize, P: PhaseItem> RenderCommand<P> for SetMaterialBindGroup<I> {
type ViewQuery = ();
type ItemQuery = Read<Handle<PolylineMaterial>>;
type Param = SRes<RenderAssets<PolylineMaterial>>;
type Param = SRes<RenderAssets<GpuPolylineMaterial>>;

fn render<'w>(
_item: &P,
Expand Down Expand Up @@ -280,15 +285,12 @@ pub fn queue_material_polylines(
mut pipelines: ResMut<SpecializedRenderPipelines<PolylineMaterialPipeline>>,
pipeline_cache: Res<PipelineCache>,
msaa: Res<Msaa>,
render_materials: Res<RenderAssets<PolylineMaterial>>,
render_materials: Res<RenderAssets<GpuPolylineMaterial>>,
material_meshes: Query<(&Handle<PolylineMaterial>, &PolylineUniform)>,
mut views: Query<(
&ExtractedView,
&VisibleEntities,
&mut RenderPhase<Opaque3d>,
&mut RenderPhase<AlphaMask3d>,
&mut RenderPhase<Transparent3d>,
)>,
views: Query<(Entity, &ExtractedView, &VisibleEntities)>,
mut opaque_phases: ResMut<ViewBinnedRenderPhases<Opaque3d>>,
mut alpha_mask_phases: ResMut<ViewBinnedRenderPhases<AlphaMask3d>>,
mut transparent_phases: ResMut<ViewSortedRenderPhases<Transparent3d>>,
) {
let draw_opaque = opaque_draw_functions
.read()
Expand All @@ -303,16 +305,14 @@ pub fn queue_material_polylines(
.get_id::<DrawPolylineMaterial>()
.unwrap();

for (view, visible_entities, mut opaque_phase, mut alpha_mask_phase, mut transparent_phase) in
views.iter_mut()
{
let inverse_view_matrix = view.transform.compute_matrix().inverse();
for (view_entity, view, visible_entities) in &views {
let inverse_view_matrix = view.world_from_view.compute_matrix().inverse();
let inverse_view_row_2 = inverse_view_matrix.row(2);

let mut polyline_key = PolylinePipelineKey::from_msaa_samples(msaa.samples());
polyline_key |= PolylinePipelineKey::from_hdr(view.hdr);

for visible_entity in &visible_entities.entities {
for visible_entity in visible_entities.get::<WithPolyline>() {
let Ok((material_handle, polyline_uniform)) = material_meshes.get(*visible_entity)
else {
continue;
Expand All @@ -329,51 +329,64 @@ pub fn queue_material_polylines(
let pipeline_id =
pipelines.specialize(&pipeline_cache, &material_pipeline, polyline_key);

let (mut opaque_phase, mut alpha_mask_phase, mut transparent_phase) = (
opaque_phases.get_mut(&view_entity),
alpha_mask_phases.get_mut(&view_entity),
transparent_phases.get_mut(&view_entity),
);

// NOTE: row 2 of the inverse view matrix dotted with column 3 of the model matrix
// gives the z component of translation of the mesh in view space
let polyline_z = inverse_view_row_2.dot(polyline_uniform.transform.col(3));
match material.alpha_mode {
AlphaMode::Opaque => {
opaque_phase.add(Opaque3d {
entity: *visible_entity,
draw_function: draw_opaque,
pipeline: pipeline_id,
batch_range: 0..1,
dynamic_offset: None,
// The draw command doesn't use a mesh handle so we don't need an `asset_id`
asset_id: AssetId::invalid(),
});
if let Some(opaque_phase) = opaque_phase.as_mut() {
opaque_phase.add(
Opaque3dBinKey {
pipeline: pipeline_id,
draw_function: draw_opaque,
// The draw command doesn't use a mesh handle so we don't need an `asset_id`
asset_id: AssetId::<Mesh>::invalid().untyped(),
material_bind_group_id: Some(material.bind_group.id()),
lightmap_image: None,
},
*visible_entity,
BinnedRenderPhaseType::NonMesh,
);
}
}
AlphaMode::Mask(_) => {
alpha_mask_phase.add(AlphaMask3d {
entity: *visible_entity,
draw_function: draw_alpha_mask,
pipeline: pipeline_id,
// NOTE: Front-to-back ordering for alpha mask with ascending sort means near should have the
// lowest sort key and getting further away should increase. As we have
// -z in front of the camera, values in view space decrease away from the
// camera. Flipping the sign of mesh_z results in the correct front-to-back ordering
distance: -polyline_z,
batch_range: 0..1,
dynamic_offset: None,
});
if let Some(alpha_mask_phase) = alpha_mask_phase.as_mut() {
alpha_mask_phase.add(
OpaqueNoLightmap3dBinKey {
draw_function: draw_alpha_mask,
pipeline: pipeline_id,
asset_id: AssetId::<Mesh>::invalid().untyped(),
material_bind_group_id: Some(material.bind_group.id()),
},
*visible_entity,
BinnedRenderPhaseType::NonMesh,
);
}
}
AlphaMode::Blend
| AlphaMode::Premultiplied
| AlphaMode::Add
| AlphaMode::Multiply => {
transparent_phase.add(Transparent3d {
entity: *visible_entity,
draw_function: draw_transparent,
pipeline: pipeline_id,
// NOTE: Back-to-front ordering for transparent with ascending sort means far should have the
// lowest sort key and getting closer should increase. As we have
// -z in front of the camera, the largest distance is -far with values increasing toward the
// camera. As such we can just use mesh_z as the distance
distance: polyline_z,
batch_range: 0..1,
dynamic_offset: None,
});
if let Some(transparent_phase) = transparent_phase.as_mut() {
transparent_phase.add(Transparent3d {
entity: *visible_entity,
draw_function: draw_transparent,
pipeline: pipeline_id,
// NOTE: Back-to-front ordering for transparent with ascending sort means far should have the
// lowest sort key and getting closer should increase. As we have
// -z in front of the camera, the largest distance is -far with values increasing toward the
// camera. As such we can just use mesh_z as the distance
distance: polyline_z,
batch_range: 0..1,
extra_index: PhaseItemExtraIndex::NONE,
});
}
}
}
}
Expand Down
Loading

0 comments on commit 236257b

Please sign in to comment.