Skip to content

Commit

Permalink
Add vertex buffer attribute descriptors to resolve sorting issues
Browse files Browse the repository at this point in the history
- Vertex attribute buffer descriptors can be set as a resource (typed
  with `Mesh` and `SpriteBatch`, for 3D and 2D renderers respectively) to
  override the vertex attribute buffer layout at runtime. Defaults to
  sane layouts provided by `Mesh` and `SpriteBatch`.
- `SpecializedPipeline` has a new associated type for the vertex
  attribute buffer descriptor accepted by the `specialize` method.
- Discussion: https://discord.com/channels/691052431525675048/743663924229963868/908484759833960489

Fix vertex buffer layout overrides for `Sprite`
  • Loading branch information
parasyte committed Nov 13, 2021
1 parent 9a4cc42 commit 8e15297
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 202 deletions.
12 changes: 9 additions & 3 deletions examples/shader/custom_shader_pipelined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,14 @@ pub struct CustomPipeline {

impl SpecializedPipeline for CustomPipeline {
type Key = PbrPipelineKey;

fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
let mut descriptor = self.pbr_pipeline.specialize(key);
type VertexSpecialization = Mesh;

fn specialize(
&self,
key: Self::Key,
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
) -> RenderPipelineDescriptor {
let mut descriptor = self.pbr_pipeline.specialize(key, vbd);
descriptor.vertex.shader = self.shader.clone();
descriptor.fragment.as_mut().unwrap().shader = self.shader.clone();
descriptor.layout = Some(vec![
Expand Down Expand Up @@ -201,6 +206,7 @@ pub fn queue_custom(
&mut pipeline_cache,
&custom_pipeline,
key,
&Mesh::get_default_vertex_buffer_descriptor(),
),
draw_function: draw_custom,
distance: view_row_2.dot(mesh_uniform.transform.col(3)),
Expand Down
17 changes: 13 additions & 4 deletions examples/shader/shader_defs_pipelined.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,18 @@ impl FromWorld for IsRedPipeline {

impl SpecializedPipeline for IsRedPipeline {
type Key = (IsRed, PbrPipelineKey);
type VertexSpecialization = Mesh;

fn specialize(&self, (is_red, pbr_pipeline_key): Self::Key) -> RenderPipelineDescriptor {
fn specialize(
&self,
(is_red, pbr_pipeline_key): Self::Key,
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
) -> RenderPipelineDescriptor {
let mut shader_defs = Vec::new();
if is_red.0 {
shader_defs.push("IS_RED".to_string());
}
let mut descriptor = self.pbr_pipeline.specialize(pbr_pipeline_key);
let mut descriptor = self.pbr_pipeline.specialize(pbr_pipeline_key, vbd);
descriptor.vertex.shader = self.shader.clone();
descriptor.vertex.shader_defs = shader_defs.clone();
let fragment = descriptor.fragment.as_mut().unwrap();
Expand Down Expand Up @@ -149,8 +154,12 @@ fn queue_custom(
let view_matrix = view.transform.compute_matrix();
let view_row_2 = view_matrix.row(2);
for (entity, mesh_uniform, is_red) in material_meshes.iter() {
let pipeline =
pipelines.specialize(&mut pipeline_cache, &custom_pipeline, (*is_red, key));
let pipeline = pipelines.specialize(
&mut pipeline_cache,
&custom_pipeline,
(*is_red, key),
&Mesh::get_default_vertex_buffer_descriptor(),
);
transparent_phase.add(Transparent3d {
entity,
pipeline,
Expand Down
87 changes: 24 additions & 63 deletions pipelined/bevy_pbr2/src/render/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,73 +179,22 @@ bitflags::bitflags! {

impl SpecializedPipeline for ShadowPipeline {
type Key = ShadowPipelineKey;
type VertexSpecialization = Mesh;

fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
let (vertex_array_stride, vertex_attributes) =
if key.contains(ShadowPipelineKey::VERTEX_TANGENTS) {
(
48,
vec![
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 12,
shader_location: 0,
},
// Normal
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 0,
shader_location: 1,
},
// Uv (GOTCHA! uv is no longer third in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute {
format: VertexFormat::Float32x2,
offset: 40,
shader_location: 2,
},
// Tangent
VertexAttribute {
format: VertexFormat::Float32x4,
offset: 24,
shader_location: 3,
},
],
)
} else {
(
32,
vec![
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 12,
shader_location: 0,
},
// Normal
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 0,
shader_location: 1,
},
// Uv
VertexAttribute {
format: VertexFormat::Float32x2,
offset: 24,
shader_location: 2,
},
],
)
};
fn specialize(
&self,
_key: Self::Key,
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
) -> RenderPipelineDescriptor {
RenderPipelineDescriptor {
vertex: VertexState {
shader: SHADOW_SHADER_HANDLE.typed::<Shader>(),
entry_point: "vertex".into(),
shader_defs: vec![],
buffers: vec![VertexBufferLayout {
array_stride: vertex_array_stride,
array_stride: vbd.stride(),
step_mode: VertexStepMode::Vertex,
attributes: vertex_attributes,
attributes: vbd.to_raw(),
}],
},
fragment: None,
Expand Down Expand Up @@ -755,13 +704,25 @@ pub fn queue_shadows(
for VisibleEntity { entity, .. } in visible_entities.iter() {
let mut key = ShadowPipelineKey::empty();
if let Ok(mesh_handle) = casting_meshes.get(*entity) {
if let Some(mesh) = render_meshes.get(mesh_handle) {
let pipeline_id = if let Some(mesh) = render_meshes.get(mesh_handle) {
if mesh.has_tangents {
key |= ShadowPipelineKey::VERTEX_TANGENTS;
}
}
let pipeline_id =
pipelines.specialize(&mut pipeline_cache, &shadow_pipeline, key);

pipelines.specialize(
&mut pipeline_cache,
&shadow_pipeline,
key,
&mesh.vertex_buffer_descriptor,
)
} else {
pipelines.specialize(
&mut pipeline_cache,
&shadow_pipeline,
key,
&Mesh::get_default_vertex_buffer_descriptor(),
)
};

shadow_phase.add(Shadow {
draw_function: draw_shadow_mesh,
Expand Down
86 changes: 24 additions & 62 deletions pipelined/bevy_pbr2/src/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -446,64 +446,13 @@ impl PbrPipelineKey {

impl SpecializedPipeline for PbrPipeline {
type Key = PbrPipelineKey;
type VertexSpecialization = Mesh;

fn specialize(&self, key: Self::Key) -> RenderPipelineDescriptor {
let (vertex_array_stride, vertex_attributes) =
if key.contains(PbrPipelineKey::VERTEX_TANGENTS) {
(
48,
vec![
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 12,
shader_location: 0,
},
// Normal
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 0,
shader_location: 1,
},
// Uv (GOTCHA! uv is no longer third in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute {
format: VertexFormat::Float32x2,
offset: 40,
shader_location: 2,
},
// Tangent
VertexAttribute {
format: VertexFormat::Float32x4,
offset: 24,
shader_location: 3,
},
],
)
} else {
(
32,
vec![
// Position (GOTCHA! Vertex_Position isn't first in the buffer due to how Mesh sorts attributes (alphabetically))
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 12,
shader_location: 0,
},
// Normal
VertexAttribute {
format: VertexFormat::Float32x3,
offset: 0,
shader_location: 1,
},
// Uv
VertexAttribute {
format: VertexFormat::Float32x2,
offset: 24,
shader_location: 2,
},
],
)
};
fn specialize(
&self,
key: Self::Key,
vbd: &VertexBufferDescriptor<Self::VertexSpecialization>,
) -> RenderPipelineDescriptor {
let mut shader_defs = Vec::new();
if key.contains(PbrPipelineKey::VERTEX_TANGENTS) {
shader_defs.push(String::from("VERTEX_TANGENTS"));
Expand All @@ -517,9 +466,9 @@ impl SpecializedPipeline for PbrPipeline {
entry_point: "vertex".into(),
shader_defs: shader_defs.clone(),
buffers: vec![VertexBufferLayout {
array_stride: vertex_array_stride,
array_stride: vbd.stride(),
step_mode: VertexStepMode::Vertex,
attributes: vertex_attributes,
attributes: vbd.to_raw(),
}],
},
fragment: Some(FragmentState {
Expand Down Expand Up @@ -704,12 +653,25 @@ pub fn queue_meshes(
} else {
continue;
}
if let Some(mesh) = render_meshes.get(mesh_handle) {
let pipeline_id = if let Some(mesh) = render_meshes.get(mesh_handle) {
if mesh.has_tangents {
key |= PbrPipelineKey::VERTEX_TANGENTS;
}
}
let pipeline_id = pipelines.specialize(&mut pipeline_cache, &pbr_pipeline, key);

pipelines.specialize(
&mut pipeline_cache,
&pbr_pipeline,
key,
&mesh.vertex_buffer_descriptor,
)
} else {
pipelines.specialize(
&mut pipeline_cache,
&pbr_pipeline,
key,
&Mesh::get_default_vertex_buffer_descriptor(),
)
};

// NOTE: row 2 of the view matrix dotted with column 3 of the model matrix
// gives the z component of translation of the mesh in view space
Expand Down
Loading

0 comments on commit 8e15297

Please sign in to comment.