|
| 1 | +use crate::{ |
| 2 | + draw::DrawContext, |
| 3 | + mesh::Indices, |
| 4 | + pipeline::{PipelineDescriptor, PipelineSpecialization, RenderPipeline}, |
| 5 | + prelude::*, |
| 6 | + shader::Shader, |
| 7 | +}; |
| 8 | +use bevy_app::prelude::*; |
| 9 | +use bevy_asset::{Assets, Handle, HandleUntyped}; |
| 10 | +use bevy_ecs::{IntoSystem, Mut, Query, QuerySet, Res, With}; |
| 11 | +use bevy_reflect::{Reflect, ReflectComponent, TypeUuid}; |
| 12 | +use bevy_utils::HashSet; |
| 13 | + |
| 14 | +mod pipeline; |
| 15 | + |
| 16 | +pub const WIREFRAME_PIPELINE_HANDLE: HandleUntyped = |
| 17 | + HandleUntyped::weak_from_u64(PipelineDescriptor::TYPE_UUID, 0x137c75ab7e9ad7f5); |
| 18 | + |
| 19 | +#[derive(Debug, Default)] |
| 20 | +pub struct WireframePlugin; |
| 21 | + |
| 22 | +impl Plugin for WireframePlugin { |
| 23 | + fn build(&self, app: &mut AppBuilder) { |
| 24 | + app.init_resource::<WireframeConfig>() |
| 25 | + .add_system_to_stage(crate::RenderStage::Draw, draw_wireframes_system.system()); |
| 26 | + let resources = app.resources(); |
| 27 | + let mut shaders = resources.get_mut::<Assets<Shader>>().unwrap(); |
| 28 | + let mut pipelines = resources.get_mut::<Assets<PipelineDescriptor>>().unwrap(); |
| 29 | + pipelines.set( |
| 30 | + WIREFRAME_PIPELINE_HANDLE, |
| 31 | + pipeline::build_wireframe_pipeline(&mut shaders), |
| 32 | + ); |
| 33 | + } |
| 34 | +} |
| 35 | + |
| 36 | +#[derive(Debug, Clone, Reflect, Default)] |
| 37 | +#[reflect(Component)] |
| 38 | +pub struct Wireframe; |
| 39 | + |
| 40 | +#[derive(Debug, Clone)] |
| 41 | +pub struct WireframeConfig { |
| 42 | + pub global: bool, |
| 43 | +} |
| 44 | + |
| 45 | +impl Default for WireframeConfig { |
| 46 | + fn default() -> Self { |
| 47 | + WireframeConfig { global: false } |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +pub fn draw_wireframes_system( |
| 52 | + mut draw_context: DrawContext, |
| 53 | + msaa: Res<Msaa>, |
| 54 | + meshes: Res<Assets<Mesh>>, |
| 55 | + wireframe_config: Res<WireframeConfig>, |
| 56 | + mut query: QuerySet<( |
| 57 | + Query<(&mut Draw, &mut RenderPipelines, &Handle<Mesh>, &Visible)>, |
| 58 | + Query<(&mut Draw, &mut RenderPipelines, &Handle<Mesh>, &Visible), With<Wireframe>>, |
| 59 | + )>, |
| 60 | +) { |
| 61 | + let iterator = |(mut draw, mut render_pipelines, mesh_handle, visible): ( |
| 62 | + Mut<Draw>, |
| 63 | + Mut<RenderPipelines>, |
| 64 | + &Handle<Mesh>, |
| 65 | + &Visible, |
| 66 | + )| { |
| 67 | + if !visible.is_visible { |
| 68 | + return; |
| 69 | + } |
| 70 | + |
| 71 | + // don't render if the mesh isn't loaded yet |
| 72 | + let mesh = if let Some(mesh) = meshes.get(mesh_handle) { |
| 73 | + mesh |
| 74 | + } else { |
| 75 | + return; |
| 76 | + }; |
| 77 | + |
| 78 | + let mut render_pipeline = RenderPipeline::specialized( |
| 79 | + WIREFRAME_PIPELINE_HANDLE.typed(), |
| 80 | + PipelineSpecialization { |
| 81 | + sample_count: msaa.samples, |
| 82 | + strip_index_format: None, |
| 83 | + shader_specialization: Default::default(), |
| 84 | + primitive_topology: mesh.primitive_topology(), |
| 85 | + dynamic_bindings: render_pipelines |
| 86 | + .bindings |
| 87 | + .iter_dynamic_bindings() |
| 88 | + .map(|name| name.to_string()) |
| 89 | + .collect::<HashSet<String>>(), |
| 90 | + vertex_buffer_layout: mesh.get_vertex_buffer_layout(), |
| 91 | + }, |
| 92 | + ); |
| 93 | + render_pipeline.dynamic_bindings_generation = |
| 94 | + render_pipelines.bindings.dynamic_bindings_generation(); |
| 95 | + |
| 96 | + draw_context |
| 97 | + .set_pipeline( |
| 98 | + &mut draw, |
| 99 | + &render_pipeline.pipeline, |
| 100 | + &render_pipeline.specialization, |
| 101 | + ) |
| 102 | + .unwrap(); |
| 103 | + draw_context |
| 104 | + .set_bind_groups_from_bindings(&mut draw, &mut [&mut render_pipelines.bindings]) |
| 105 | + .unwrap(); |
| 106 | + draw_context |
| 107 | + .set_vertex_buffers_from_bindings(&mut draw, &[&render_pipelines.bindings]) |
| 108 | + .unwrap(); |
| 109 | + |
| 110 | + match mesh.indices() { |
| 111 | + Some(Indices::U32(indices)) => draw.draw_indexed(0..indices.len() as u32, 0, 0..1), |
| 112 | + Some(Indices::U16(indices)) => draw.draw_indexed(0..indices.len() as u32, 0, 0..1), |
| 113 | + None => draw.draw(0..mesh.count_vertices() as u32, 0..1), |
| 114 | + }; |
| 115 | + }; |
| 116 | + |
| 117 | + if wireframe_config.global { |
| 118 | + query.q0_mut().iter_mut().for_each(iterator); |
| 119 | + } else { |
| 120 | + query.q1_mut().iter_mut().for_each(iterator); |
| 121 | + } |
| 122 | +} |
0 commit comments