Port to Bevy 0.12 (#25)
This commit is contained in:
parent
6dcf604b93
commit
ddb40d0c2a
@ -11,7 +11,7 @@ keywords = ["gamedev", "bevy", "outline"]
|
|||||||
categories = ["game-engines", "rendering"]
|
categories = ["game-engines", "rendering"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = { version = "0.11", default-features = false, features = [
|
bevy = { version = "0.12", default-features = false, features = [
|
||||||
"bevy_asset",
|
"bevy_asset",
|
||||||
"bevy_render",
|
"bevy_render",
|
||||||
"bevy_pbr",
|
"bevy_pbr",
|
||||||
@ -23,10 +23,10 @@ bevy = { version = "0.11", default-features = false, features = [
|
|||||||
bitfield = "0.14"
|
bitfield = "0.14"
|
||||||
interpolation = "0.2"
|
interpolation = "0.2"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
wgpu-types = "0.16.1"
|
wgpu-types = "0.17"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy = { version = "0.11", default-features = false, features = [
|
bevy = { version = "0.12", default-features = false, features = [
|
||||||
"animation",
|
"animation",
|
||||||
"bevy_gltf",
|
"bevy_gltf",
|
||||||
"bevy_pbr",
|
"bevy_pbr",
|
||||||
|
10
src/draw.rs
10
src/draw.rs
@ -59,7 +59,7 @@ pub(crate) fn queue_outline_stencil_mesh(
|
|||||||
if !view_mask.intersects(outline_mask) {
|
if !view_mask.intersects(outline_mask) {
|
||||||
continue; // Layer not enabled
|
continue; // Layer not enabled
|
||||||
}
|
}
|
||||||
let Some(mesh) = render_meshes.get(&outline.mesh) else {
|
let Some(mesh) = render_meshes.get(outline.mesh_id) else {
|
||||||
continue; // No mesh
|
continue; // No mesh
|
||||||
};
|
};
|
||||||
let key = base_key
|
let key = base_key
|
||||||
@ -78,6 +78,8 @@ pub(crate) fn queue_outline_stencil_mesh(
|
|||||||
pipeline,
|
pipeline,
|
||||||
draw_function: draw_stencil,
|
draw_function: draw_stencil,
|
||||||
distance,
|
distance,
|
||||||
|
batch_range: 0..0,
|
||||||
|
dynamic_offset: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,7 +137,7 @@ pub(crate) fn queue_outline_volume_mesh(
|
|||||||
if !view_mask.intersects(outline_mask) {
|
if !view_mask.intersects(outline_mask) {
|
||||||
continue; // Layer not enabled
|
continue; // Layer not enabled
|
||||||
}
|
}
|
||||||
let Some(mesh) = render_meshes.get(&outline.mesh) else {
|
let Some(mesh) = render_meshes.get(outline.mesh_id) else {
|
||||||
continue; // No mesh
|
continue; // No mesh
|
||||||
};
|
};
|
||||||
let transparent = fragment_uniform.colour[3] < 1.0;
|
let transparent = fragment_uniform.colour[3] < 1.0;
|
||||||
@ -162,6 +164,8 @@ pub(crate) fn queue_outline_volume_mesh(
|
|||||||
pipeline,
|
pipeline,
|
||||||
draw_function: draw_transparent_outline,
|
draw_function: draw_transparent_outline,
|
||||||
distance,
|
distance,
|
||||||
|
batch_range: 0..0,
|
||||||
|
dynamic_offset: None,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
opaque_phase.add(OpaqueOutline {
|
opaque_phase.add(OpaqueOutline {
|
||||||
@ -169,6 +173,8 @@ pub(crate) fn queue_outline_volume_mesh(
|
|||||||
pipeline,
|
pipeline,
|
||||||
draw_function: draw_opaque_outline,
|
draw_function: draw_opaque_outline,
|
||||||
distance,
|
distance,
|
||||||
|
batch_range: 0..0,
|
||||||
|
dynamic_offset: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,22 +138,23 @@ impl OutlineMeshExt for Mesh {
|
|||||||
fn auto_generate_outline_normals(
|
fn auto_generate_outline_normals(
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
mut events: EventReader<'_, '_, AssetEvent<Mesh>>,
|
mut events: EventReader<'_, '_, AssetEvent<Mesh>>,
|
||||||
mut squelch: Local<HashSet<Handle<Mesh>>>,
|
mut squelch: Local<HashSet<AssetId<Mesh>>>,
|
||||||
) {
|
) {
|
||||||
for event in events.iter() {
|
for event in events.read() {
|
||||||
match event {
|
match event {
|
||||||
AssetEvent::Created { handle } | AssetEvent::Modified { handle } => {
|
AssetEvent::Added { id } | AssetEvent::Modified { id } => {
|
||||||
if squelch.contains(handle) {
|
if squelch.contains(id) {
|
||||||
// Suppress modification events created by this system
|
// Suppress modification events created by this system
|
||||||
squelch.remove(handle);
|
squelch.remove(id);
|
||||||
} else if let Some(mesh) = meshes.get_mut(handle) {
|
} else if let Some(mesh) = meshes.get_mut(*id) {
|
||||||
let _ = mesh.generate_outline_normals();
|
let _ = mesh.generate_outline_normals();
|
||||||
squelch.insert(handle.clone_weak());
|
squelch.insert(*id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AssetEvent::Removed { handle } => {
|
AssetEvent::Removed { id } => {
|
||||||
squelch.remove(handle);
|
squelch.remove(id);
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
33
src/lib.rs
33
src/lib.rs
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
use bevy::asset::load_internal_asset;
|
use bevy::asset::load_internal_asset;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use bevy::render::batching::{batch_and_prepare_render_phase, write_batched_instance_buffer};
|
||||||
use bevy::render::extract_component::{
|
use bevy::render::extract_component::{
|
||||||
ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
|
ExtractComponent, ExtractComponentPlugin, UniformComponentPlugin,
|
||||||
};
|
};
|
||||||
@ -42,11 +43,12 @@ use crate::draw::{
|
|||||||
use crate::node::{OpaqueOutline, OutlineNode, StencilOutline, TransparentOutline};
|
use crate::node::{OpaqueOutline, OutlineNode, StencilOutline, TransparentOutline};
|
||||||
use crate::pipeline::{OutlinePipeline, FRAGMENT_SHADER_HANDLE, OUTLINE_SHADER_HANDLE};
|
use crate::pipeline::{OutlinePipeline, FRAGMENT_SHADER_HANDLE, OUTLINE_SHADER_HANDLE};
|
||||||
use crate::uniforms::{
|
use crate::uniforms::{
|
||||||
extract_outline_uniforms, queue_outline_stencil_bind_group, queue_outline_volume_bind_group,
|
extract_outline_uniforms, prepare_outline_stencil_bind_group,
|
||||||
set_outline_visibility, OutlineFragmentUniform, OutlineStencilUniform, OutlineVolumeUniform,
|
prepare_outline_volume_bind_group, set_outline_visibility, OutlineFragmentUniform,
|
||||||
|
OutlineStencilUniform, OutlineVolumeUniform,
|
||||||
};
|
};
|
||||||
use crate::view_uniforms::{
|
use crate::view_uniforms::{
|
||||||
extract_outline_view_uniforms, queue_outline_view_bind_group, OutlineViewUniform,
|
extract_outline_view_uniforms, prepare_outline_view_bind_group, OutlineViewUniform,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod computed;
|
mod computed;
|
||||||
@ -258,6 +260,20 @@ impl Plugin for OutlinePlugin {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
Render,
|
Render,
|
||||||
(
|
(
|
||||||
|
prepare_outline_view_bind_group,
|
||||||
|
prepare_outline_stencil_bind_group,
|
||||||
|
prepare_outline_volume_bind_group,
|
||||||
|
)
|
||||||
|
.in_set(RenderSet::PrepareBindGroups),
|
||||||
|
)
|
||||||
|
.add_systems(
|
||||||
|
Render,
|
||||||
|
(queue_outline_stencil_mesh, queue_outline_volume_mesh).in_set(RenderSet::QueueMeshes),
|
||||||
|
)
|
||||||
|
.add_systems(
|
||||||
|
Render,
|
||||||
|
(
|
||||||
|
sort_phase_system::<StencilOutline>,
|
||||||
sort_phase_system::<OpaqueOutline>,
|
sort_phase_system::<OpaqueOutline>,
|
||||||
sort_phase_system::<TransparentOutline>,
|
sort_phase_system::<TransparentOutline>,
|
||||||
)
|
)
|
||||||
@ -266,15 +282,16 @@ impl Plugin for OutlinePlugin {
|
|||||||
.add_systems(
|
.add_systems(
|
||||||
Render,
|
Render,
|
||||||
(
|
(
|
||||||
queue_outline_view_bind_group,
|
batch_and_prepare_render_phase::<StencilOutline, OutlinePipeline>,
|
||||||
queue_outline_stencil_bind_group,
|
batch_and_prepare_render_phase::<OpaqueOutline, OutlinePipeline>,
|
||||||
queue_outline_volume_bind_group,
|
batch_and_prepare_render_phase::<TransparentOutline, OutlinePipeline>,
|
||||||
)
|
)
|
||||||
.in_set(RenderSet::Queue),
|
.in_set(RenderSet::PrepareResources),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Render,
|
Render,
|
||||||
(queue_outline_stencil_mesh, queue_outline_volume_mesh).in_set(RenderSet::Queue),
|
write_batched_instance_buffer::<OutlinePipeline>
|
||||||
|
.in_set(RenderSet::PrepareResourcesFlush),
|
||||||
);
|
);
|
||||||
|
|
||||||
let world = &mut app.sub_app_mut(RenderApp).world;
|
let world = &mut app.sub_app_mut(RenderApp).world;
|
||||||
|
56
src/node.rs
56
src/node.rs
@ -1,4 +1,5 @@
|
|||||||
use std::cmp::Reverse;
|
use std::cmp::Reverse;
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
use bevy::ecs::system::lifetimeless::Read;
|
use bevy::ecs::system::lifetimeless::Read;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
@ -16,6 +17,7 @@ use bevy::render::{
|
|||||||
render_graph::{Node, RenderGraphContext},
|
render_graph::{Node, RenderGraphContext},
|
||||||
renderer::RenderContext,
|
renderer::RenderContext,
|
||||||
};
|
};
|
||||||
|
use bevy::utils::nonmax::NonMaxU32;
|
||||||
use bevy::utils::FloatOrd;
|
use bevy::utils::FloatOrd;
|
||||||
|
|
||||||
pub(crate) struct StencilOutline {
|
pub(crate) struct StencilOutline {
|
||||||
@ -23,6 +25,8 @@ pub(crate) struct StencilOutline {
|
|||||||
pub pipeline: CachedRenderPipelineId,
|
pub pipeline: CachedRenderPipelineId,
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
pub draw_function: DrawFunctionId,
|
pub draw_function: DrawFunctionId,
|
||||||
|
pub batch_range: Range<u32>,
|
||||||
|
pub dynamic_offset: Option<NonMaxU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhaseItem for StencilOutline {
|
impl PhaseItem for StencilOutline {
|
||||||
@ -40,6 +44,22 @@ impl PhaseItem for StencilOutline {
|
|||||||
fn draw_function(&self) -> bevy::render::render_phase::DrawFunctionId {
|
fn draw_function(&self) -> bevy::render::render_phase::DrawFunctionId {
|
||||||
self.draw_function
|
self.draw_function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn batch_range(&self) -> &std::ops::Range<u32> {
|
||||||
|
&self.batch_range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn batch_range_mut(&mut self) -> &mut std::ops::Range<u32> {
|
||||||
|
&mut self.batch_range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dynamic_offset(&self) -> Option<bevy::utils::nonmax::NonMaxU32> {
|
||||||
|
self.dynamic_offset
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dynamic_offset_mut(&mut self) -> &mut Option<bevy::utils::nonmax::NonMaxU32> {
|
||||||
|
&mut self.dynamic_offset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedRenderPipelinePhaseItem for StencilOutline {
|
impl CachedRenderPipelinePhaseItem for StencilOutline {
|
||||||
@ -54,6 +74,8 @@ pub(crate) struct OpaqueOutline {
|
|||||||
pub pipeline: CachedRenderPipelineId,
|
pub pipeline: CachedRenderPipelineId,
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
pub draw_function: DrawFunctionId,
|
pub draw_function: DrawFunctionId,
|
||||||
|
pub batch_range: Range<u32>,
|
||||||
|
pub dynamic_offset: Option<NonMaxU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhaseItem for OpaqueOutline {
|
impl PhaseItem for OpaqueOutline {
|
||||||
@ -71,6 +93,22 @@ impl PhaseItem for OpaqueOutline {
|
|||||||
fn draw_function(&self) -> bevy::render::render_phase::DrawFunctionId {
|
fn draw_function(&self) -> bevy::render::render_phase::DrawFunctionId {
|
||||||
self.draw_function
|
self.draw_function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn batch_range(&self) -> &Range<u32> {
|
||||||
|
&self.batch_range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn batch_range_mut(&mut self) -> &mut Range<u32> {
|
||||||
|
&mut self.batch_range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dynamic_offset(&self) -> Option<NonMaxU32> {
|
||||||
|
self.dynamic_offset
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dynamic_offset_mut(&mut self) -> &mut Option<NonMaxU32> {
|
||||||
|
&mut self.dynamic_offset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedRenderPipelinePhaseItem for OpaqueOutline {
|
impl CachedRenderPipelinePhaseItem for OpaqueOutline {
|
||||||
@ -85,6 +123,8 @@ pub(crate) struct TransparentOutline {
|
|||||||
pub pipeline: CachedRenderPipelineId,
|
pub pipeline: CachedRenderPipelineId,
|
||||||
pub entity: Entity,
|
pub entity: Entity,
|
||||||
pub draw_function: DrawFunctionId,
|
pub draw_function: DrawFunctionId,
|
||||||
|
pub batch_range: Range<u32>,
|
||||||
|
pub dynamic_offset: Option<NonMaxU32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PhaseItem for TransparentOutline {
|
impl PhaseItem for TransparentOutline {
|
||||||
@ -102,6 +142,22 @@ impl PhaseItem for TransparentOutline {
|
|||||||
fn draw_function(&self) -> bevy::render::render_phase::DrawFunctionId {
|
fn draw_function(&self) -> bevy::render::render_phase::DrawFunctionId {
|
||||||
self.draw_function
|
self.draw_function
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn batch_range(&self) -> &Range<u32> {
|
||||||
|
&self.batch_range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn batch_range_mut(&mut self) -> &mut Range<u32> {
|
||||||
|
&mut self.batch_range
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dynamic_offset(&self) -> Option<NonMaxU32> {
|
||||||
|
self.dynamic_offset
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dynamic_offset_mut(&mut self) -> &mut Option<NonMaxU32> {
|
||||||
|
&mut self.dynamic_offset
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedRenderPipelinePhaseItem for TransparentOutline {
|
impl CachedRenderPipelinePhaseItem for TransparentOutline {
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
#import bevy_render::view View
|
#import bevy_render::view::View
|
||||||
#import bevy_pbr::mesh_types Mesh
|
#import bevy_render::maths
|
||||||
#import bevy_pbr::mesh_types SkinnedMesh
|
#import bevy_pbr::mesh_types::Mesh
|
||||||
|
#import bevy_pbr::mesh_types::SkinnedMesh
|
||||||
|
#import bevy_pbr::mesh_functions
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
#ifdef VERTEX_POSITIONS
|
#ifdef VERTEX_POSITIONS
|
||||||
@location(0) position: vec3<f32>,
|
@location(0) position: vec3<f32>,
|
||||||
|
@builtin(instance_index) instance_index: u32,
|
||||||
#endif
|
#endif
|
||||||
#ifndef OFFSET_ZERO
|
#ifndef OFFSET_ZERO
|
||||||
@location(1) outline_normal: vec3<f32>,
|
@location(1) outline_normal: vec3<f32>,
|
||||||
@ -39,9 +42,7 @@ struct OutlineVertexUniform {
|
|||||||
@group(0) @binding(0)
|
@group(0) @binding(0)
|
||||||
var<uniform> view: View;
|
var<uniform> view: View;
|
||||||
|
|
||||||
@group(1) @binding(0)
|
#import bevy_pbr::mesh_bindings
|
||||||
var<uniform> mesh: Mesh;
|
|
||||||
|
|
||||||
#import bevy_pbr::skinning
|
#import bevy_pbr::skinning
|
||||||
#import bevy_pbr::morph
|
#import bevy_pbr::morph
|
||||||
|
|
||||||
@ -90,7 +91,7 @@ fn vertex(vertex_no_morph: Vertex) -> VertexOutput {
|
|||||||
#ifdef SKINNED
|
#ifdef SKINNED
|
||||||
let model = bevy_pbr::skinning::skin_model(vertex.joint_indices, vertex.joint_weights);
|
let model = bevy_pbr::skinning::skin_model(vertex.joint_indices, vertex.joint_weights);
|
||||||
#else
|
#else
|
||||||
let model = mesh.model;
|
let model = bevy_pbr::mesh_functions::get_model_matrix(vertex_no_morph.instance_index);
|
||||||
#endif
|
#endif
|
||||||
let clip_pos = view.view_proj * (model * vec4<f32>(vertex.position, 1.0));
|
let clip_pos = view.view_proj * (model * vec4<f32>(vertex.position, 1.0));
|
||||||
#ifdef OFFSET_ZERO
|
#ifdef OFFSET_ZERO
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use bevy::pbr::{setup_morph_and_skinning_defs, MeshPipelineKey};
|
use bevy::ecs::query::QueryItem;
|
||||||
|
use bevy::ecs::system::lifetimeless::Read;
|
||||||
|
use bevy::ecs::system::SystemParamItem;
|
||||||
|
use bevy::pbr::{
|
||||||
|
setup_morph_and_skinning_defs, MeshFlags, MeshPipelineKey, MeshPipelineViewLayoutKey,
|
||||||
|
MeshTransforms, MeshUniform,
|
||||||
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::reflect::TypeUuid;
|
use bevy::render::batching::GetBatchData;
|
||||||
use bevy::render::render_resource::{
|
use bevy::render::render_resource::{
|
||||||
BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState,
|
BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, BindingType, BlendState,
|
||||||
BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
|
BufferBindingType, BufferSize, ColorTargetState, ColorWrites, CompareFunction, DepthBiasState,
|
||||||
@ -11,6 +17,7 @@ use bevy::render::render_resource::{
|
|||||||
TextureFormat, VertexState,
|
TextureFormat, VertexState,
|
||||||
};
|
};
|
||||||
use bevy::render::renderer::RenderDevice;
|
use bevy::render::renderer::RenderDevice;
|
||||||
|
use bevy::render::settings::WgpuSettings;
|
||||||
use bevy::render::texture::BevyDefault;
|
use bevy::render::texture::BevyDefault;
|
||||||
use bevy::render::view::ViewTarget;
|
use bevy::render::view::ViewTarget;
|
||||||
use bevy::{
|
use bevy::{
|
||||||
@ -23,18 +30,20 @@ use bevy::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bitfield::{bitfield_bitrange, bitfield_fields};
|
use bitfield::{bitfield_bitrange, bitfield_fields};
|
||||||
|
use wgpu_types::{Backends, PushConstantRange};
|
||||||
|
|
||||||
use crate::uniforms::{
|
use crate::uniforms::{
|
||||||
DepthMode, OutlineFragmentUniform, OutlineStencilUniform, OutlineVolumeUniform,
|
DepthMode, ExtractedOutline, OutlineFragmentUniform, OutlineStencilUniform,
|
||||||
|
OutlineVolumeUniform,
|
||||||
};
|
};
|
||||||
use crate::view_uniforms::OutlineViewUniform;
|
use crate::view_uniforms::OutlineViewUniform;
|
||||||
use crate::ATTRIBUTE_OUTLINE_NORMAL;
|
use crate::ATTRIBUTE_OUTLINE_NORMAL;
|
||||||
|
|
||||||
pub(crate) const OUTLINE_SHADER_HANDLE: HandleUntyped =
|
pub(crate) const OUTLINE_SHADER_HANDLE: Handle<Shader> =
|
||||||
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 2101625026478770097);
|
Handle::weak_from_u128(2101625026478770097);
|
||||||
|
|
||||||
pub(crate) const FRAGMENT_SHADER_HANDLE: HandleUntyped =
|
pub(crate) const FRAGMENT_SHADER_HANDLE: Handle<Shader> =
|
||||||
HandleUntyped::weak_from_u64(Shader::TYPE_UUID, 12033806834125368121);
|
Handle::weak_from_u128(12033806834125368121);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
pub(crate) enum PassType {
|
pub(crate) enum PassType {
|
||||||
@ -245,11 +254,14 @@ impl SpecializedMeshPipeline for OutlinePipeline {
|
|||||||
buffer_attrs.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
|
buffer_attrs.push(Mesh::ATTRIBUTE_POSITION.at_shader_location(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut bind_layouts = vec![if key.msaa() == Msaa::Off {
|
let mut bind_layouts = vec![self
|
||||||
self.mesh_pipeline.view_layout.clone()
|
.mesh_pipeline
|
||||||
|
.get_view_layout(if key.msaa() == Msaa::Off {
|
||||||
|
MeshPipelineViewLayoutKey::empty()
|
||||||
} else {
|
} else {
|
||||||
self.mesh_pipeline.view_layout_multisampled.clone()
|
MeshPipelineViewLayoutKey::MULTISAMPLED
|
||||||
}];
|
})
|
||||||
|
.clone()];
|
||||||
|
|
||||||
bind_layouts.push(setup_morph_and_skinning_defs(
|
bind_layouts.push(setup_morph_and_skinning_defs(
|
||||||
&self.mesh_pipeline.mesh_layouts,
|
&self.mesh_pipeline.mesh_layouts,
|
||||||
@ -308,15 +320,23 @@ impl SpecializedMeshPipeline for OutlinePipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let buffers = vec![layout.get_layout(&buffer_attrs)?];
|
let buffers = vec![layout.get_layout(&buffer_attrs)?];
|
||||||
|
let mut push_constant_ranges = Vec::with_capacity(1);
|
||||||
|
// Proxy for webgl feature flag in bevy
|
||||||
|
if WgpuSettings::default().backends == Some(Backends::GL) {
|
||||||
|
push_constant_ranges.push(PushConstantRange {
|
||||||
|
stages: ShaderStages::VERTEX,
|
||||||
|
range: 0..4,
|
||||||
|
});
|
||||||
|
}
|
||||||
Ok(RenderPipelineDescriptor {
|
Ok(RenderPipelineDescriptor {
|
||||||
vertex: VertexState {
|
vertex: VertexState {
|
||||||
shader: OUTLINE_SHADER_HANDLE.typed::<Shader>(),
|
shader: OUTLINE_SHADER_HANDLE,
|
||||||
entry_point: "vertex".into(),
|
entry_point: "vertex".into(),
|
||||||
shader_defs: vertex_defs,
|
shader_defs: vertex_defs,
|
||||||
buffers,
|
buffers,
|
||||||
},
|
},
|
||||||
fragment: Some(FragmentState {
|
fragment: Some(FragmentState {
|
||||||
shader: FRAGMENT_SHADER_HANDLE.typed::<Shader>(),
|
shader: FRAGMENT_SHADER_HANDLE,
|
||||||
shader_defs: fragment_defs,
|
shader_defs: fragment_defs,
|
||||||
entry_point: "fragment".into(),
|
entry_point: "fragment".into(),
|
||||||
targets,
|
targets,
|
||||||
@ -343,8 +363,28 @@ impl SpecializedMeshPipeline for OutlinePipeline {
|
|||||||
mask: !0,
|
mask: !0,
|
||||||
alpha_to_coverage_enabled: false,
|
alpha_to_coverage_enabled: false,
|
||||||
},
|
},
|
||||||
push_constant_ranges: default(),
|
push_constant_ranges,
|
||||||
label: Some(Cow::Borrowed("outline_pipeline")),
|
label: Some(Cow::Borrowed("outline_pipeline")),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GetBatchData for OutlinePipeline {
|
||||||
|
type Param = ();
|
||||||
|
type Query = Read<ExtractedOutline>;
|
||||||
|
type QueryFilter = ();
|
||||||
|
type CompareData = ();
|
||||||
|
type BufferData = MeshUniform;
|
||||||
|
|
||||||
|
fn get_batch_data(
|
||||||
|
_: &SystemParamItem<Self::Param>,
|
||||||
|
outline: &QueryItem<Self::Query>,
|
||||||
|
) -> (Self::BufferData, Option<Self::CompareData>) {
|
||||||
|
let ts = MeshTransforms {
|
||||||
|
transform: (&outline.transform).into(),
|
||||||
|
previous_transform: (&outline.transform).into(),
|
||||||
|
flags: MeshFlags::NONE.bits(),
|
||||||
|
};
|
||||||
|
((&ts).into(), None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,11 +3,12 @@ use bevy::{
|
|||||||
lifetimeless::{Read, SRes},
|
lifetimeless::{Read, SRes},
|
||||||
SystemParamItem,
|
SystemParamItem,
|
||||||
},
|
},
|
||||||
|
math::Affine3A,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
render::{
|
render::{
|
||||||
extract_component::{ComponentUniforms, DynamicUniformIndex},
|
extract_component::{ComponentUniforms, DynamicUniformIndex},
|
||||||
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
|
render_phase::{PhaseItem, RenderCommand, RenderCommandResult, TrackedRenderPass},
|
||||||
render_resource::{BindGroup, BindGroupDescriptor, BindGroupEntry, ShaderType},
|
render_resource::{BindGroup, BindGroupEntry, ShaderType},
|
||||||
renderer::RenderDevice,
|
renderer::RenderDevice,
|
||||||
Extract,
|
Extract,
|
||||||
},
|
},
|
||||||
@ -18,7 +19,8 @@ use crate::{node::StencilOutline, pipeline::OutlinePipeline, ComputedOutline};
|
|||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
pub(crate) struct ExtractedOutline {
|
pub(crate) struct ExtractedOutline {
|
||||||
pub depth_mode: DepthMode,
|
pub depth_mode: DepthMode,
|
||||||
pub mesh: Handle<Mesh>,
|
pub transform: Affine3A,
|
||||||
|
pub mesh_id: AssetId<Mesh>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Component, ShaderType)]
|
#[derive(Clone, Component, ShaderType)]
|
||||||
@ -57,13 +59,11 @@ pub(crate) struct OutlineVolumeBindGroup {
|
|||||||
pub bind_group: BindGroup,
|
pub bind_group: BindGroup,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_outline_visibility(
|
pub(crate) fn set_outline_visibility(mut query: Query<(&mut ViewVisibility, &ComputedOutline)>) {
|
||||||
mut query: Query<(&mut ComputedVisibility, &ComputedOutline)>,
|
|
||||||
) {
|
|
||||||
for (mut visibility, computed) in query.iter_mut() {
|
for (mut visibility, computed) in query.iter_mut() {
|
||||||
if let ComputedOutline(Some(computed)) = computed {
|
if let ComputedOutline(Some(computed)) = computed {
|
||||||
if computed.volume.value.enabled || computed.stencil.value.enabled {
|
if computed.volume.value.enabled || computed.stencil.value.enabled {
|
||||||
visibility.set_visible_in_view();
|
visibility.set();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,14 +72,15 @@ pub(crate) fn set_outline_visibility(
|
|||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
pub(crate) fn extract_outline_uniforms(
|
pub(crate) fn extract_outline_uniforms(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
query: Extract<Query<(Entity, &ComputedOutline, &Handle<Mesh>)>>,
|
query: Extract<Query<(Entity, &ComputedOutline, &GlobalTransform, &Handle<Mesh>)>>,
|
||||||
) {
|
) {
|
||||||
for (entity, computed, mesh) in query.iter() {
|
for (entity, computed, transform, mesh) in query.iter() {
|
||||||
let cmds = &mut commands.get_or_spawn(entity);
|
let cmds = &mut commands.get_or_spawn(entity);
|
||||||
if let ComputedOutline(Some(computed)) = computed {
|
if let ComputedOutline(Some(computed)) = computed {
|
||||||
cmds.insert(ExtractedOutline {
|
cmds.insert(ExtractedOutline {
|
||||||
depth_mode: computed.mode.value.depth_mode,
|
depth_mode: computed.mode.value.depth_mode,
|
||||||
mesh: mesh.clone_weak(),
|
transform: transform.affine(),
|
||||||
|
mesh_id: mesh.id(),
|
||||||
});
|
});
|
||||||
if computed.volume.value.enabled {
|
if computed.volume.value.enabled {
|
||||||
cmds.insert(OutlineVolumeUniform {
|
cmds.insert(OutlineVolumeUniform {
|
||||||
@ -100,26 +101,26 @@ pub(crate) fn extract_outline_uniforms(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn queue_outline_stencil_bind_group(
|
pub(crate) fn prepare_outline_stencil_bind_group(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
outline_pipeline: Res<OutlinePipeline>,
|
outline_pipeline: Res<OutlinePipeline>,
|
||||||
vertex: Res<ComponentUniforms<OutlineStencilUniform>>,
|
vertex: Res<ComponentUniforms<OutlineStencilUniform>>,
|
||||||
) {
|
) {
|
||||||
if let Some(vertex_binding) = vertex.binding() {
|
if let Some(vertex_binding) = vertex.binding() {
|
||||||
let bind_group = render_device.create_bind_group(&BindGroupDescriptor {
|
let bind_group = render_device.create_bind_group(
|
||||||
entries: &[BindGroupEntry {
|
Some("outline_stencil_bind_group"),
|
||||||
|
&outline_pipeline.outline_stencil_bind_group_layout,
|
||||||
|
&[BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource: vertex_binding.clone(),
|
resource: vertex_binding.clone(),
|
||||||
}],
|
}],
|
||||||
label: Some("outline_stencil_bind_group"),
|
);
|
||||||
layout: &outline_pipeline.outline_stencil_bind_group_layout,
|
|
||||||
});
|
|
||||||
commands.insert_resource(OutlineStencilBindGroup { bind_group });
|
commands.insert_resource(OutlineStencilBindGroup { bind_group });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn queue_outline_volume_bind_group(
|
pub(crate) fn prepare_outline_volume_bind_group(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
outline_pipeline: Res<OutlinePipeline>,
|
outline_pipeline: Res<OutlinePipeline>,
|
||||||
@ -127,8 +128,10 @@ pub(crate) fn queue_outline_volume_bind_group(
|
|||||||
fragment: Res<ComponentUniforms<OutlineFragmentUniform>>,
|
fragment: Res<ComponentUniforms<OutlineFragmentUniform>>,
|
||||||
) {
|
) {
|
||||||
if let (Some(vertex_binding), Some(fragment_binding)) = (vertex.binding(), fragment.binding()) {
|
if let (Some(vertex_binding), Some(fragment_binding)) = (vertex.binding(), fragment.binding()) {
|
||||||
let bind_group = render_device.create_bind_group(&BindGroupDescriptor {
|
let bind_group = render_device.create_bind_group(
|
||||||
entries: &[
|
"outline_volume_bind_group",
|
||||||
|
&outline_pipeline.outline_volume_bind_group_layout,
|
||||||
|
&[
|
||||||
BindGroupEntry {
|
BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource: vertex_binding.clone(),
|
resource: vertex_binding.clone(),
|
||||||
@ -138,9 +141,7 @@ pub(crate) fn queue_outline_volume_bind_group(
|
|||||||
resource: fragment_binding.clone(),
|
resource: fragment_binding.clone(),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
label: Some("outline_volume_bind_group"),
|
);
|
||||||
layout: &outline_pipeline.outline_volume_bind_group_layout,
|
|
||||||
});
|
|
||||||
commands.insert_resource(OutlineVolumeBindGroup { bind_group });
|
commands.insert_resource(OutlineVolumeBindGroup { bind_group });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use bevy::render::render_phase::{
|
|||||||
PhaseItem, RenderCommand, RenderCommandResult, RenderPhase, TrackedRenderPass,
|
PhaseItem, RenderCommand, RenderCommandResult, RenderPhase, TrackedRenderPass,
|
||||||
};
|
};
|
||||||
use bevy::render::render_resource::ShaderType;
|
use bevy::render::render_resource::ShaderType;
|
||||||
use bevy::render::render_resource::{BindGroup, BindGroupDescriptor, BindGroupEntry};
|
use bevy::render::render_resource::{BindGroup, BindGroupEntry};
|
||||||
use bevy::render::renderer::RenderDevice;
|
use bevy::render::renderer::RenderDevice;
|
||||||
use bevy::render::view::RenderLayers;
|
use bevy::render::view::RenderLayers;
|
||||||
use bevy::render::Extract;
|
use bevy::render::Extract;
|
||||||
@ -49,21 +49,21 @@ pub(crate) fn extract_outline_view_uniforms(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn queue_outline_view_bind_group(
|
pub(crate) fn prepare_outline_view_bind_group(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
render_device: Res<RenderDevice>,
|
render_device: Res<RenderDevice>,
|
||||||
outline_pipeline: Res<OutlinePipeline>,
|
outline_pipeline: Res<OutlinePipeline>,
|
||||||
view_uniforms: Res<ComponentUniforms<OutlineViewUniform>>,
|
view_uniforms: Res<ComponentUniforms<OutlineViewUniform>>,
|
||||||
) {
|
) {
|
||||||
if let Some(view_binding) = view_uniforms.binding() {
|
if let Some(view_binding) = view_uniforms.binding() {
|
||||||
let bind_group = render_device.create_bind_group(&BindGroupDescriptor {
|
let bind_group = render_device.create_bind_group(
|
||||||
entries: &[BindGroupEntry {
|
"outline_view_bind_group",
|
||||||
|
&outline_pipeline.outline_view_bind_group_layout,
|
||||||
|
&[BindGroupEntry {
|
||||||
binding: 0,
|
binding: 0,
|
||||||
resource: view_binding.clone(),
|
resource: view_binding.clone(),
|
||||||
}],
|
}],
|
||||||
label: Some("outline_view_bind_group"),
|
);
|
||||||
layout: &outline_pipeline.outline_view_bind_group_layout,
|
|
||||||
});
|
|
||||||
commands.insert_resource(OutlineViewBindGroup { bind_group });
|
commands.insert_resource(OutlineViewBindGroup { bind_group });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user