Skip to content

Commit

Permalink
Follow bevy example
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescarterbell committed Dec 20, 2023
1 parent 7ef94f4 commit be12323
Show file tree
Hide file tree
Showing 8 changed files with 156 additions and 136 deletions.
File renamed without changes.
42 changes: 27 additions & 15 deletions crates/bevy_tiles_render/src/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use bevy::{
ecs::{system::Resource, world::FromWorld},
math::{Mat3A, Mat4, Vec2},
render::{
mesh::{Mesh, MeshVertexAttribute},
render_resource::{
self, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, Buffer,
BufferInitDescriptor, BufferUsages, ShaderStages, VertexAttribute, VertexBufferLayout,
VertexFormat,
BufferInitDescriptor, BufferUsages, PrimitiveTopology, ShaderStages, VertexAttribute,
VertexBufferLayout, VertexFormat,
},
renderer::RenderDevice,
},
Expand Down Expand Up @@ -38,25 +39,36 @@ pub struct TriThingMeshBuffer(pub Buffer);

impl FromWorld for TriThingMeshBuffer {
fn from_world(world: &mut bevy::prelude::World) -> Self {
let device = world.get_resource_mut::<RenderDevice>().unwrap();
let mesh: [[f32; 2]; 6] = [
let device = world
.get_resource::<RenderDevice>()
.expect("No render device found!");

let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
let v_pos = vec![
[0.0, 0.0, 0.0],
[1.0, 0.0, 0.0],
[1.0, 1.0, 0.0],
[0.0, 0.0, 0.0],
[1.0, 1.0, 0.0],
[0.0, 1.0, 0.0],
];
let v_uv = vec![
[0.0, 0.0],
[1.0, 0.0],
[1.0, 1.0],
[0.0, 1.0],
[0.0, 0.0],
[1.0, 0.0],
[1.0, 1.0],
[0.0, 1.0],
];
let mesh: Vec<u8> = mesh
.iter()
.flat_map(|coord| coord.iter().flat_map(|val| val.to_be_bytes()))
.collect();
let mesh = device.create_buffer_with_data(&BufferInitDescriptor {
label: Some("tri_thing_default_mesh"),

mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, v_pos);
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, v_uv);

Self(device.create_buffer_with_data(&BufferInitDescriptor {
label: Some("Chunk Quad"),
contents: &mesh.get_vertex_buffer_data(),
usage: BufferUsages::VERTEX,
contents: &mesh,
});
Self(mesh)
}))
}
}

Expand Down
23 changes: 16 additions & 7 deletions crates/bevy_tiles_render/src/draw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,24 @@ use bevy::{
},
log::info,
render::{
render_phase::{RenderCommand, RenderCommandResult, TrackedRenderPass},
render_phase::{RenderCommand, RenderCommandResult, SetItemPipeline, TrackedRenderPass},
render_resource::PipelineCache,
},
sprite::{DrawMesh2d, SetMesh2dBindGroup, SetMesh2dViewBindGroup},
};

use crate::{bindings::TriThingMeshBuffer, tiles_render::TriThingBindGroups};

pub type DrawTiles = (SetPipeline, SetTilesBuffers);
pub type DrawTiles = (
// Set the pipeline
SetItemPipeline,
// Set the view uniform as bind group 0
SetMesh2dViewBindGroup<0>,
// Set the mesh uniform as bind group 1
SetMesh2dBindGroup<1>,
// Draw the mesh
DrawChunks,
);

pub struct SetPipeline;

Expand Down Expand Up @@ -47,24 +57,23 @@ impl RenderCommand<Transparent2d> for SetPipeline {
}
}

pub struct SetTilesBuffers;
impl RenderCommand<Transparent2d> for SetTilesBuffers {
pub struct DrawChunks;
impl RenderCommand<Transparent2d> for DrawChunks {
type Param = SRes<TriThingMeshBuffer>;

type ViewWorldQuery = ();

type ItemWorldQuery = Read<TriThingBindGroups>;
type ItemWorldQuery = ();

#[inline]
fn render<'w>(
_item: &Transparent2d,
_view: ROQueryItem<'w, Self::ViewWorldQuery>,
bind_groups: ROQueryItem<'w, Self::ItemWorldQuery>,
_: ROQueryItem<'w, Self::ItemWorldQuery>,
mesh: SystemParamItem<'w, '_, Self::Param>,
pass: &mut TrackedRenderPass<'w>,
) -> RenderCommandResult {
info!("Drawing!");
pass.set_bind_group(0, &bind_groups.transform_bind_group, &[]);
pass.set_vertex_buffer(0, mesh.into_inner().0.slice(..));
pass.draw(0..6, 0..1);
info!("Did draw call!");
Expand Down
85 changes: 50 additions & 35 deletions crates/bevy_tiles_render/src/pipeline.rs
Original file line number Diff line number Diff line change
@@ -1,89 +1,104 @@
use bevy::{
ecs::{system::Resource, world::FromWorld},
ecs::{
system::Resource,
world::{FromWorld, World},
},
render::{
render_resource::{
BindGroupLayout, BlendState, ColorTargetState, ColorWrites, Face, FragmentState,
FrontFace, MultisampleState, PolygonMode, PrimitiveState, PrimitiveTopology,
RenderPipelineDescriptor, SpecializedRenderPipeline, TextureFormat, VertexState,
RenderPipelineDescriptor, SpecializedRenderPipeline, TextureFormat, VertexBufferLayout,
VertexFormat, VertexState, VertexStepMode,
},
texture::BevyDefault,
view::ViewTarget,
},
sprite::Mesh2dPipeline,
sprite::{Mesh2dPipeline, Mesh2dPipelineKey},
};

use crate::{
bindings::{TilesBindGroupLayouts, TilesVertexBufferLayouts},
TILES_FRAG, TILES_VERT,
};
use crate::{TILES_FRAG, TILES_VERT};

#[derive(Resource)]
pub struct TilesPipeline {
vertex_layouts: TilesVertexBufferLayouts,
tile_layouts: TilesBindGroupLayouts,
view_layout: BindGroupLayout,
mesh2d_pipeline: Mesh2dPipeline,
}

#[derive(PartialEq, Eq, Hash, Clone)]
pub struct TilesPipelineKey;

impl FromWorld for TilesPipeline {
fn from_world(world: &mut bevy::prelude::World) -> Self {
let mesh_2d_pipeline = world.get_resource::<Mesh2dPipeline>().unwrap();
let tile_layouts = world.get_resource::<TilesBindGroupLayouts>().unwrap();
fn from_world(world: &mut World) -> Self {
Self {
vertex_layouts: TilesVertexBufferLayouts::default(),
view_layout: mesh_2d_pipeline.view_layout.clone(),
tile_layouts: tile_layouts.clone(),
mesh2d_pipeline: Mesh2dPipeline::from_world(world),
}
}
}

impl SpecializedRenderPipeline for TilesPipeline {
type Key = TilesPipelineKey;
type Key = Mesh2dPipelineKey;

fn specialize(
&self,
key: Self::Key,
) -> bevy::render::render_resource::RenderPipelineDescriptor {
// Customize how to store the meshes' vertex attributes in the vertex buffer
// Our meshes only have position and color
let formats = vec![
// Position
VertexFormat::Float32x3,
// Color
VertexFormat::Float32x2,
];

let vertex_layout =
VertexBufferLayout::from_vertex_formats(VertexStepMode::Vertex, formats);

let format = match key.contains(Mesh2dPipelineKey::HDR) {
true => ViewTarget::TEXTURE_FORMAT_HDR,
false => TextureFormat::bevy_default(),
};

RenderPipelineDescriptor {
label: Some("tiles_pipeline".into()),
layout: vec![
self.tile_layouts.transform_bind_group.clone(),
//self.view_layout.clone(),
],
vertex: VertexState {
// Use our custom shader
shader: TILES_VERT,
shader_defs: Vec::new(),
entry_point: "vs_main".into(),
buffers: vec![self.vertex_layouts.vertex_layout.clone()],
shader_defs: vec![],
// Use our custom vertex buffer
buffers: vec![vertex_layout],
},
fragment: Some(FragmentState {
// Use our custom shader
shader: TILES_FRAG,
shader_defs: Vec::new(),
shader_defs: vec![],
entry_point: "fs_main".into(),
targets: vec![Some(ColorTargetState {
format: TextureFormat::bevy_default(),
blend: Some(BlendState::PREMULTIPLIED_ALPHA_BLENDING),
format,
blend: Some(BlendState::ALPHA_BLENDING),
write_mask: ColorWrites::ALL,
})],
}),
// Use the two standard uniforms for 2d meshes
layout: vec![
// Bind group 0 is the view uniform
self.mesh2d_pipeline.view_layout.clone(),
// Bind group 1 is the mesh uniform
self.mesh2d_pipeline.mesh_layout.clone(),
],
push_constant_ranges: Vec::new(),
primitive: PrimitiveState {
topology: PrimitiveTopology::TriangleList,
strip_index_format: None,
front_face: FrontFace::Ccw,
cull_mode: Some(Face::Back),
unclipped_depth: false,
polygon_mode: PolygonMode::Fill,
conservative: false,
topology: PrimitiveTopology::TriangleList,
strip_index_format: None,
},
depth_stencil: None,
multisample: MultisampleState {
// TODO: MAKE THIS SPECIALIZED
count: 4,
count: key.msaa_samples(),
mask: !0,
alpha_to_coverage_enabled: false,
},
push_constant_ranges: vec![],
label: Some("tiles_pipeline".into()),
}
}
}
37 changes: 1 addition & 36 deletions crates/bevy_tiles_render/src/prepare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,40 +32,5 @@ pub fn prepare_tri_things(
bindgroup_layouts: Res<TilesBindGroupLayouts>,
tri_things: Query<(Entity, &GlobalTransform, &TriThing)>,
) {
for (entity, tri_thing_transform, _) in tri_things.iter() {
info!("Preparing!");

let transform_array: Vec<u8> = tri_thing_transform
.affine()
.matrix3
.to_cols_array_2d()
.iter()
.flat_map(|[x, y, z]| [*x, *y, *z, 0.0].into_iter())
.flat_map(|element| element.to_be_bytes())
.collect();

let transform_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
label: Some(format!("tri_thing_transform_buffer_{:?}", entity).as_str()),
usage: BufferUsages::UNIFORM,
contents: &transform_array,
});

let transform_bind_group = render_device.create_bind_group(
Some(format!("tri_thing_bindgroup_{:?}", entity).as_str()),
&bindgroup_layouts.transform_bind_group,
&[BindGroupEntry {
binding: 0,
resource: BindingResource::Buffer(BufferBinding {
buffer: &transform_buffer,
offset: 0,
size: NonZeroU64::new(48),
}),
}],
);
info!("{}", transform_buffer.size());

commands.entity(entity).insert(TriThingBindGroups {
transform_bind_group,
});
}
for (entity, tri_thing_transform, _) in tri_things.iter() {}
}
53 changes: 32 additions & 21 deletions crates/bevy_tiles_render/src/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,54 @@ use bevy::{
core_pipeline::core_2d::Transparent2d,
ecs::{
entity::Entity,
query::With,
system::{Query, Res, ResMut},
},
log::info,
log::{debug, info},
render::{
mesh::Mesh,
render_asset::RenderAssets,
render_phase::{DrawFunctions, RenderPhase},
render_resource::{PipelineCache, SpecializedRenderPipelines},
render_resource::{PipelineCache, PrimitiveTopology, SpecializedRenderPipelines},
view::{ExtractedView, Msaa, VisibleEntities},
},
sprite::{DrawMesh2d, Mesh2dPipelineKey, RenderMesh2dInstances},
utils::FloatOrd,
};

use crate::{
draw::DrawTiles,
pipeline::{TilesPipeline, TilesPipelineKey},
tiles::TriThing,
};
use crate::{draw::DrawTiles, pipeline::TilesPipeline, tiles::TriThing};

pub fn queue_tri_things(
mut sp_pipeline: ResMut<SpecializedRenderPipelines<TilesPipeline>>,
mut views_query: Query<(Entity, &mut RenderPhase<Transparent2d>)>,
draw_functions: Res<DrawFunctions<Transparent2d>>,
mut pipelines: ResMut<SpecializedRenderPipelines<TilesPipeline>>,
colored_mesh2d_pipeline: Res<TilesPipeline>,
transparent_draw_functions: Res<DrawFunctions<Transparent2d>>,
pipeline_cache: Res<PipelineCache>,
pipeline: Res<TilesPipeline>,
tri_things: Query<(Entity, &TriThing)>,
msaa: Res<Msaa>,
mut views: Query<(&mut RenderPhase<Transparent2d>, &ExtractedView)>,
chunks: Query<Entity, With<TriThing>>,
) {
for (view_entity, mut transparent_phase) in views_query.iter_mut() {
info!("Queuing!");
for (tri_entity, _) in tri_things.iter() {
let pipeline = sp_pipeline.specialize(&pipeline_cache, &pipeline, TilesPipelineKey);
let draw_function = draw_functions.read().get_id::<DrawTiles>().unwrap();
for (mut transparent_phase, view) in &mut views {
let mesh_key = Mesh2dPipelineKey::from_msaa_samples(msaa.samples())
| Mesh2dPipelineKey::from_hdr(view.hdr)
| Mesh2dPipelineKey::from_primitive_topology(PrimitiveTopology::TriangleList);
let pipeline_id = pipelines.specialize(&pipeline_cache, &colored_mesh2d_pipeline, mesh_key);

let draw_tiles = transparent_draw_functions.read().id::<DrawTiles>();

// Queue all entities visible to that view
for chunk_id in chunks.iter() {
debug!("Drawing chunk: {:?}", chunk_id);
transparent_phase.add(Transparent2d {
entity: chunk_id,
draw_function: draw_tiles,
pipeline: pipeline_id,
// The 2d render items are sorted according to their z value before rendering,
// in order to get correct transparency
sort_key: FloatOrd(0.0),
entity: tri_entity,
pipeline,
draw_function,
// This material is not batched
batch_range: 0..1,
dynamic_offset: None,
})
});
}
}
}
14 changes: 9 additions & 5 deletions crates/bevy_tiles_render/src/shaders/tiles_frag.wgsl
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#import bevy_tiles::vert::{VertOut}
// The input of the fragment shader must correspond to the output of the vertex shader for all `location`s
struct FragIn {
// The color is interpolated between vertices by default
@location(0) color: vec4<f32>,
};

/// Entry point for the fragment shader
@fragment
fn fs_main(in: VertOut) -> @location(0) vec4<f32> {
return vec4<f32>(1.0, 0.2, 0.1, 1.0);
}

fn fragment(in: FragIn) -> @location(0) vec4<f32> {
return in.color;
}
Loading

0 comments on commit be12323

Please sign in to comment.