bevy/crates/bevy_render/src/wireframe/mod.rs
Simon Guillot 785aad92f4 Fix pipeline initialisation of wireframe mode (fixes #1609) (#1623)
More details are in the associated issue #1609.

While looking for the source of this issue, I've noticed that the `set` and `set_untracked` methods aren't really DRY:
68606934e3/crates/bevy_asset/src/assets.rs (L76-L85)

68606934e3/crates/bevy_asset/src/assets.rs (L91-L99)

Shouldn't `set` call `set_untracked`? Also, given the bug that arose from a misusage of these functions, maybe some refactoring is needed?
2021-03-12 22:12:07 +00:00

130 lines
4.0 KiB
Rust

use crate::{
draw::DrawContext,
mesh::Indices,
pipeline::{PipelineDescriptor, PipelineSpecialization, RenderPipeline},
prelude::*,
shader::Shader,
};
use bevy_app::prelude::*;
use bevy_asset::{Assets, Handle, HandleUntyped};
use bevy_ecs::{
query::With,
reflect::ReflectComponent,
system::{IntoSystem, Query, QuerySet, Res},
world::Mut,
};
use bevy_reflect::{Reflect, TypeUuid};
use bevy_utils::HashSet;
mod pipeline;
pub const WIREFRAME_PIPELINE_HANDLE: HandleUntyped =
HandleUntyped::weak_from_u64(PipelineDescriptor::TYPE_UUID, 0x137c75ab7e9ad7f5);
#[derive(Debug, Default)]
pub struct WireframePlugin;
impl Plugin for WireframePlugin {
fn build(&self, app: &mut AppBuilder) {
app.init_resource::<WireframeConfig>()
.add_system_to_stage(crate::RenderStage::Draw, draw_wireframes_system.system());
let world = app.world_mut().cell();
let mut shaders = world.get_resource_mut::<Assets<Shader>>().unwrap();
let mut pipelines = world
.get_resource_mut::<Assets<PipelineDescriptor>>()
.unwrap();
pipelines.set_untracked(
WIREFRAME_PIPELINE_HANDLE,
pipeline::build_wireframe_pipeline(&mut shaders),
);
}
}
#[derive(Debug, Clone, Reflect, Default)]
#[reflect(Component)]
pub struct Wireframe;
#[derive(Debug, Clone)]
pub struct WireframeConfig {
pub global: bool,
}
impl Default for WireframeConfig {
fn default() -> Self {
WireframeConfig { global: false }
}
}
pub fn draw_wireframes_system(
mut draw_context: DrawContext,
msaa: Res<Msaa>,
meshes: Res<Assets<Mesh>>,
wireframe_config: Res<WireframeConfig>,
mut query: QuerySet<(
Query<(&mut Draw, &mut RenderPipelines, &Handle<Mesh>, &Visible)>,
Query<(&mut Draw, &mut RenderPipelines, &Handle<Mesh>, &Visible), With<Wireframe>>,
)>,
) {
let iterator = |(mut draw, mut render_pipelines, mesh_handle, visible): (
Mut<Draw>,
Mut<RenderPipelines>,
&Handle<Mesh>,
&Visible,
)| {
if !visible.is_visible {
return;
}
// don't render if the mesh isn't loaded yet
let mesh = if let Some(mesh) = meshes.get(mesh_handle) {
mesh
} else {
return;
};
let mut render_pipeline = RenderPipeline::specialized(
WIREFRAME_PIPELINE_HANDLE.typed(),
PipelineSpecialization {
sample_count: msaa.samples,
strip_index_format: None,
shader_specialization: Default::default(),
primitive_topology: mesh.primitive_topology(),
dynamic_bindings: render_pipelines
.bindings
.iter_dynamic_bindings()
.map(|name| name.to_string())
.collect::<HashSet<String>>(),
vertex_buffer_layout: mesh.get_vertex_buffer_layout(),
},
);
render_pipeline.dynamic_bindings_generation =
render_pipelines.bindings.dynamic_bindings_generation();
draw_context
.set_pipeline(
&mut draw,
&render_pipeline.pipeline,
&render_pipeline.specialization,
)
.unwrap();
draw_context
.set_bind_groups_from_bindings(&mut draw, &mut [&mut render_pipelines.bindings])
.unwrap();
draw_context
.set_vertex_buffers_from_bindings(&mut draw, &[&render_pipelines.bindings])
.unwrap();
match mesh.indices() {
Some(Indices::U32(indices)) => draw.draw_indexed(0..indices.len() as u32, 0, 0..1),
Some(Indices::U16(indices)) => draw.draw_indexed(0..indices.len() as u32, 0, 0..1),
None => draw.draw(0..mesh.count_vertices() as u32, 0..1),
};
};
if wireframe_config.global {
query.q0_mut().iter_mut().for_each(iterator);
} else {
query.q1_mut().iter_mut().for_each(iterator);
}
}