Skip to content

Commit

Permalink
Indirect.
Browse files Browse the repository at this point in the history
  • Loading branch information
tychedelia committed Sep 10, 2024
1 parent bba3032 commit b42f7dc
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 61 deletions.
77 changes: 47 additions & 30 deletions bevy_nannou_draw/src/draw/indirect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,19 @@ use crate::draw::primitive::Primitive;
use crate::draw::{Draw, DrawCommand};
use crate::render::{PreparedShaderModel, ShaderModel};
use bevy::core_pipeline::core_3d::Opaque3dBinKey;
use bevy::pbr::{MaterialPipeline, MaterialPipelineKey, PreparedMaterial, RenderMaterialInstances, SetMaterialBindGroup};
use bevy::pbr::{
MaterialPipeline, MaterialPipelineKey, PreparedMaterial, RenderMaterialInstances,
SetMaterialBindGroup,
};
use bevy::render::extract_component::ExtractComponentPlugin;
use bevy::render::extract_instances::ExtractedInstances;
use bevy::render::mesh::allocator::MeshAllocator;
use bevy::render::mesh::RenderMeshBufferInfo;
use bevy::render::render_asset::{prepare_assets, RenderAsset};
use bevy::render::render_phase::{BinnedRenderPhaseType, ViewBinnedRenderPhases};
use bevy::render::storage::{GpuShaderStorageBuffer, ShaderStorageBuffer};
use bevy::render::view;
use bevy::render::view::VisibilitySystems;
use bevy::{
core_pipeline::core_3d::Opaque3d,
ecs::system::{lifetimeless::*, SystemParamItem},
Expand All @@ -37,7 +43,6 @@ use rayon::prelude::*;
use std::hash::Hash;
use std::marker::PhantomData;
use std::ops::Range;
use bevy::render::extract_instances::ExtractedInstances;

pub struct Indirect<'a, M>
where
Expand Down Expand Up @@ -126,7 +131,14 @@ where
SM::Data: PartialEq + Eq + Hash + Clone,
{
fn build(&self, app: &mut App) {
app.add_plugins(ExtractComponentPlugin::<IndirectMesh>::default());
app.add_plugins((
ExtractComponentPlugin::<IndirectMesh>::default(),
ExtractComponentPlugin::<Handle<ShaderStorageBuffer>>::default(),
))
.add_systems(
PostUpdate,
view::check_visibility::<With<IndirectMesh>>.in_set(VisibilitySystems::CheckVisibility),
);

app.sub_app_mut(RenderApp)
.add_render_command::<Opaque3d, DrawIndirectMaterial<SM>>()
Expand All @@ -152,7 +164,14 @@ fn queue_indirect<SM>(
mut pipelines: ResMut<SpecializedMeshPipelines<IndirectPipeline<SM>>>,
pipeline_cache: Res<PipelineCache>,
meshes: Res<RenderAssets<RenderMesh>>,
(render_mesh_instances, indirect_meshes, mut phases, mut views, shader_models, extracted_instances): (
(
render_mesh_instances,
indirect_meshes,
mut phases,
mut views,
shader_models,
extracted_instances,
): (
Res<RenderMeshInstances>,
Query<Entity, With<IndirectMesh>>,
ResMut<ViewBinnedRenderPhases<Opaque3d>>,
Expand Down Expand Up @@ -241,7 +260,8 @@ impl<SM: ShaderModel> FromWorld for IndirectPipeline<SM> {
}

impl<SM: ShaderModel> SpecializedMeshPipeline for IndirectPipeline<SM>
where SM::Data: PartialEq + Eq + Hash + Clone
where
SM::Data: PartialEq + Eq + Hash + Clone,
{
type Key = MaterialPipelineKey<SM>;

Expand All @@ -259,7 +279,9 @@ impl<SM: ShaderModel> SpecializedMeshPipeline for IndirectPipeline<SM>
descriptor.fragment.as_mut().unwrap().shader = fragment_shader.clone();
}

descriptor.layout.insert(2, self.shader_model_layout.clone());
descriptor
.layout
.insert(2, self.shader_model_layout.clone());

let pipeline = MaterialPipeline {
mesh_pipeline: self.mesh_pipeline.clone(),
Expand All @@ -273,14 +295,17 @@ impl<SM: ShaderModel> SpecializedMeshPipeline for IndirectPipeline<SM>
}
}

type DrawIndirectMaterial<M> = (
type DrawIndirectMaterial<SM> = (
SetItemPipeline,
SetShaderModelBindGroup<M, 2>,
SetMeshViewBindGroup<0>,
SetShaderModelBindGroup<SM, 2>,
DrawMeshIndirect,
);

pub struct SetShaderModelBindGroup<M: ShaderModel, const I: usize>(PhantomData<M>);
impl<P: PhaseItem, SM: ShaderModel, const I: usize> RenderCommand<P> for SetShaderModelBindGroup<SM, I> {
struct SetShaderModelBindGroup<M: ShaderModel, const I: usize>(PhantomData<M>);
impl<P: PhaseItem, SM: ShaderModel, const I: usize> RenderCommand<P>
for SetShaderModelBindGroup<SM, I>
{
type Param = (
SRes<RenderAssets<PreparedShaderModel<SM>>>,
SRes<ExtractedInstances<AssetId<SM>>>,
Expand All @@ -296,14 +321,13 @@ impl<P: PhaseItem, SM: ShaderModel, const I: usize> RenderCommand<P> for SetShad
(models, instances): SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
info!("SetShaderModelBindGroup");
let materials = models.into_inner();
let material_instances = instances.into_inner();
let models = models.into_inner();
let instances = instances.into_inner();

let Some(asset_id) = material_instances.get(&item.entity()) else {
let Some(asset_id) = instances.get(&item.entity()) else {
return RenderCommandResult::Skip;
};
let Some(material) = materials.get(*asset_id) else {
let Some(material) = models.get(*asset_id) else {
return RenderCommandResult::Skip;
};
pass.set_bind_group(I, &material.bind_group, &[]);
Expand All @@ -312,7 +336,6 @@ impl<P: PhaseItem, SM: ShaderModel, const I: usize> RenderCommand<P> for SetShad
}

struct DrawMeshIndirect;

impl<P: PhaseItem> RenderCommand<P> for DrawMeshIndirect {
type Param = (
SRes<RenderAssets<RenderMesh>>,
Expand All @@ -328,7 +351,11 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMeshIndirect {
item: &P,
_view: (),
indirect_buffer: Option<&'w Handle<ShaderStorageBuffer>>,
(meshes, render_mesh_instances, mesh_allocator, ssbos): SystemParamItem<'w, '_, Self::Param>,
(meshes, render_mesh_instances, mesh_allocator, ssbos): SystemParamItem<
'w,
'_,
Self::Param,
>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
let mesh_allocator = mesh_allocator.into_inner();
Expand All @@ -355,28 +382,18 @@ impl<P: PhaseItem> RenderCommand<P> for DrawMeshIndirect {
pass.set_vertex_buffer(0, vertex_buffer_slice.buffer.slice(..));

match &gpu_mesh.buffer_info {
RenderMeshBufferInfo::Indexed {
index_format,
..
} => {
RenderMeshBufferInfo::Indexed { index_format, .. } => {
let Some(index_buffer_slice) =
mesh_allocator.mesh_index_slice(&mesh_instance.mesh_asset_id)
else {
return RenderCommandResult::Skip;
};

pass.set_index_buffer(index_buffer_slice.buffer.slice(..), 0, *index_format);
info!("Index count: {}", index_buffer_slice.range.len());
pass.draw_indexed_indirect(
&indirect_buffer.buffer,
0,
);
pass.draw_indexed_indirect(&indirect_buffer.buffer, 0);
}
RenderMeshBufferInfo::NonIndexed => {
pass.draw_indirect(
&indirect_buffer.buffer,
0,
);
pass.draw_indirect(&indirect_buffer.buffer, 0);
}
}
RenderCommandResult::Success
Expand Down
2 changes: 1 addition & 1 deletion bevy_nannou_draw/src/draw/instanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,4 @@ where
.draw_commands
.push(Some(DrawCommand::Instanced(primitive, range)));
}
}
}
18 changes: 9 additions & 9 deletions bevy_nannou_draw/src/draw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ use std::marker::PhantomData;
use std::ops::{Deref, Range};
use std::sync::{Arc, RwLock};

pub use self::background::Background;
pub use self::drawing::{Drawing, DrawingContext};
use self::primitive::Primitive;
pub use self::theme::Theme;
use crate::draw::indirect::Indirect;
use crate::draw::instanced::Instanced;
use crate::draw::mesh::MeshExt;
use crate::render::DefaultNannouMaterial;
use bevy::asset::UntypedAssetId;
use bevy::prelude::*;
use bevy::render::render_resource as wgpu;
Expand All @@ -15,24 +23,16 @@ use bevy::render::storage::ShaderStorageBuffer;
use bevy::utils::{HashMap, HashSet};
use lyon::path::PathEvent;
use uuid::Uuid;
use crate::draw::indirect::Indirect;
pub use self::background::Background;
pub use self::drawing::{Drawing, DrawingContext};
use self::primitive::Primitive;
pub use self::theme::Theme;
use crate::draw::instanced::Instanced;
use crate::draw::mesh::MeshExt;
use crate::render::DefaultNannouMaterial;

pub mod background;
mod drawing;
pub mod indirect;
pub mod instanced;
pub mod mesh;
pub mod primitive;
pub mod properties;
pub(crate) mod render;
pub mod theme;
pub mod indirect;

/// A simple API for drawing 2D and 3D graphics.
///
Expand Down
19 changes: 11 additions & 8 deletions bevy_nannou_draw/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ use bevy::render::{render_resource as wgpu, RenderApp};
use bevy::window::WindowRef;
use lyon::lyon_tessellation::{FillTessellator, StrokeTessellator};

use crate::draw::indirect::{IndirectMaterialPlugin, IndirectMesh};
use crate::draw::mesh::MeshExt;
use crate::draw::render::{RenderContext, RenderPrimitive};
use crate::draw::{DrawCommand, DrawContext};
use crate::draw::indirect::{IndirectMaterialPlugin, IndirectMesh};
use crate::DrawHolder;

pub trait ShaderModel:
Expand All @@ -57,9 +57,7 @@ pub struct NannouRenderPlugin;
impl Plugin for NannouRenderPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, setup_default_texture)
.add_plugins((
ExtractComponentPlugin::<NannouTextureHandle>::default(),
))
.add_plugins((ExtractComponentPlugin::<NannouTextureHandle>::default(),))
.add_plugins(ExtractResourcePlugin::<DefaultTextureHandle>::default())
.add_systems(Update, texture_event_handler)
.add_systems(PostUpdate, update_draw_mesh);
Expand All @@ -75,10 +73,8 @@ where
M::Data: PartialEq + Eq + Hash + Clone,
{
fn build(&self, app: &mut App) {
app.add_plugins((
MaterialPlugin::<M>::default(),
))
.add_systems(PostUpdate, update_material::<M>.after(update_draw_mesh));
app.add_plugins((MaterialPlugin::<M>::default(),))
.add_systems(PostUpdate, update_material::<M>.after(update_draw_mesh));
}
}

Expand Down Expand Up @@ -360,9 +356,16 @@ fn update_draw_mesh(
let mat_id = last_mat.expect("No material set for instanced draw command");
commands.spawn((
IndirectMesh,
indirect_buffer,
UntypedMaterialId(mat_id),
mesh.clone(),
Transform::default(),
GlobalTransform::default(),
Visibility::default(),
InheritedVisibility::default(),
ViewVisibility::default(),
NannouMesh,
NoFrustumCulling,
window_layers.clone(),
));
}
Expand Down
10 changes: 5 additions & 5 deletions examples/assets/shaders/particle_sdf_compute.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct Particle {
};

@group(0) @binding(0) var<storage, read_write> particles: array<Particle>;
@group(0) @binding(1) var<uniform> sphere_center: vec3<f32>;
@group(0) @binding(1) var<uniform> sphere_center: vec4<f32>;
@group(0) @binding(2) var<uniform> sphere_radius: f32;
@group(0) @binding(3) var<uniform> particle_count: u32;
@group(0) @binding(4) var<uniform> resolution: vec2<u32>;
Expand All @@ -25,7 +25,7 @@ fn raymarch(ro: vec3<f32>, rd: vec3<f32>, max_steps: u32, max_dist: f32) -> f32
var total_distance = 0.0;
for (var i: u32 = 0u; i < max_steps; i++) {
let p = ro + total_distance * rd;
let distance = sdf_sphere(p, sphere_center, sphere_radius);
let distance = sdf_sphere(p, sphere_center.xyz, sphere_radius);
if distance < 0.001 {
return total_distance;
}
Expand All @@ -41,8 +41,8 @@ fn closest_point_on_sphere(point: vec2<f32>) -> vec3<f32> {
let aspect = f32(resolution.x) / f32(resolution.y);
// Adjust for the new coordinate system
let point3d = vec3(point.x * aspect, point.y, 0.0);
let to_sphere = normalize(point3d - sphere_center);
let surface_point = sphere_center + to_sphere * sphere_radius;
let to_sphere = normalize(point3d - sphere_center.xyz);
let surface_point = sphere_center.xyz + to_sphere * sphere_radius;
return vec3(surface_point.x / surface_point.z / aspect, surface_point.y / surface_point.z, surface_point.z);
}

Expand Down Expand Up @@ -132,7 +132,7 @@ fn update(@builtin(global_invocation_id) global_id: vec3<u32>) {
let particle_3d = vec3(particle.position.x * aspect, particle.position.y, p.z);

// Calculate the vector from sphere center to the particle on the sphere surface
let to_particle = particle_3d - sphere_center;
let to_particle = particle_3d - sphere_center.xyz;

// Calculate the view direction (assuming camera is looking along negative z-axis)
let view_direction = vec3(0.0, 0.0, -1.0);
Expand Down
7 changes: 6 additions & 1 deletion examples/assets/shaders/particle_sdf_material.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ fn vertex(vertex: Vertex) -> VertexOutput {
let particle = particles[vertex.instance_index];
var out: VertexOutput;
out.clip_position = mesh_position_local_to_clip(
get_world_from_local(vertex.instance_index),
mat4x4<f32>(
vec4(1.0, 0.0, 0.0, 0.0),
vec4(0.0, 1.0, 0.0, 0.0),
vec4(0.0, 0.0, 1.0, 0.0),
vec4(0.0, 0.0, 0.0, 1.0)
),
vec4(vertex.position, 1.0)
) + vec4(particle.position, 0.0, 0.0);
out.color = particle.color;
Expand Down
5 changes: 4 additions & 1 deletion examples/compute/particle_mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ impl Compute for ComputeModel {
}
}

#[shader_model(fragment = "shaders/particle_mouse_material.wgsl", vertex = "shaders/particle_mouse_material.wgsl")]
#[shader_model(
fragment = "shaders/particle_mouse_material.wgsl",
vertex = "shaders/particle_mouse_material.wgsl"
)]
struct ShaderModel {
#[storage(0, read_only, visibility(vertex))]
particles: Handle<ShaderStorageBuffer>,
Expand Down
Loading

0 comments on commit b42f7dc

Please sign in to comment.