Reflect Vertex Buffer Attributes
Must follow VertexBufferDescriptorName_AttributeName format I_VertexBufferDescriptorName_AttributeName indicates that an attribute is instanced Currently all attributes must be defined in shaders or offsets will be incorrect.
This commit is contained in:
parent
62d1e710a5
commit
28fb0fdfc8
@ -25,7 +25,9 @@ fn main() {
|
|||||||
ShaderStage::Vertex,
|
ShaderStage::Vertex,
|
||||||
r#"
|
r#"
|
||||||
#version 450
|
#version 450
|
||||||
layout(location = 0) in vec4 a_Pos;
|
layout(location = 0) in vec4 Vertex_Position;
|
||||||
|
layout(location = 1) in vec4 Vertex_Normal;
|
||||||
|
layout(location = 2) in vec2 Vertex_Uv;
|
||||||
layout(location = 0) out vec4 v_Position;
|
layout(location = 0) out vec4 v_Position;
|
||||||
layout(set = 0, binding = 0) uniform Camera {
|
layout(set = 0, binding = 0) uniform Camera {
|
||||||
mat4 ViewProj;
|
mat4 ViewProj;
|
||||||
@ -34,7 +36,7 @@ fn main() {
|
|||||||
mat4 Model;
|
mat4 Model;
|
||||||
};
|
};
|
||||||
void main() {
|
void main() {
|
||||||
v_Position = Model * a_Pos;
|
v_Position = Model * Vertex_Position;
|
||||||
gl_Position = ViewProj * v_Position;
|
gl_Position = ViewProj * v_Position;
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
|
|||||||
@ -1,172 +1,107 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use rand::{random, rngs::StdRng, Rng, SeedableRng};
|
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||||
|
|
||||||
struct Person;
|
|
||||||
|
|
||||||
struct Velocity {
|
|
||||||
pub value: math::Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct NavigationPoint {
|
|
||||||
pub target: math::Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Wander {
|
|
||||||
pub duration_bounds: math::Vec2,
|
|
||||||
pub distance_bounds: math::Vec2,
|
|
||||||
pub duration: f32,
|
|
||||||
pub elapsed: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
AppBuilder::new()
|
AppBuilder::new()
|
||||||
.setup_world(setup)
|
.add_defaults()
|
||||||
.add_system(build_wander_system())
|
|
||||||
.add_system(build_navigate_system())
|
|
||||||
.add_system(build_move_system())
|
.add_system(build_move_system())
|
||||||
.add_system(bevy::diagnostics::build_fps_printer_system())
|
.add_system(bevy::diagnostics::build_fps_printer_system())
|
||||||
|
.setup_world(setup)
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(world: &mut World, resources: &mut Resources) {
|
|
||||||
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
|
||||||
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
|
|
||||||
|
|
||||||
world.insert(
|
|
||||||
(),
|
|
||||||
vec![
|
|
||||||
// lights
|
|
||||||
(
|
|
||||||
Light::default(),
|
|
||||||
LocalToWorld::identity(),
|
|
||||||
Translation::new(4.0, -4.0, 5.0),
|
|
||||||
Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
world.insert(
|
|
||||||
(),
|
|
||||||
vec![
|
|
||||||
// camera
|
|
||||||
(
|
|
||||||
Camera::new(CameraType::Projection {
|
|
||||||
fov: std::f32::consts::PI / 4.0,
|
|
||||||
near: 1.0,
|
|
||||||
far: 1000.0,
|
|
||||||
aspect_ratio: 1.0,
|
|
||||||
}),
|
|
||||||
ActiveCamera,
|
|
||||||
LocalToWorld(Mat4::look_at_rh(
|
|
||||||
Vec3::new(6.0, -40.0, 20.0),
|
|
||||||
Vec3::new(0.0, 0.0, 0.0),
|
|
||||||
Vec3::new(0.0, 0.0, 1.0),
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut rng = StdRng::from_entropy();
|
|
||||||
for _ in 0..70000 {
|
|
||||||
create_person(
|
|
||||||
world,
|
|
||||||
cube_handle,
|
|
||||||
Translation::new(rng.gen_range(-50.0, 50.0), 0.0, rng.gen_range(-50.0, 50.0)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_wander_system() -> Box<dyn Schedulable> {
|
|
||||||
let mut rng = StdRng::from_entropy();
|
|
||||||
|
|
||||||
SystemBuilder::new("Wander")
|
|
||||||
.read_resource::<Time>()
|
|
||||||
.with_query(<(
|
|
||||||
Read<Person>,
|
|
||||||
Read<Translation>,
|
|
||||||
Write<Wander>,
|
|
||||||
Write<NavigationPoint>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |_, world, time, person_query| {
|
|
||||||
for (_, translation, mut wander, mut navigation_point) in person_query.iter_mut(world) {
|
|
||||||
wander.elapsed += time.delta_seconds;
|
|
||||||
if wander.elapsed >= wander.duration {
|
|
||||||
let direction = math::vec3(
|
|
||||||
rng.gen_range(-1.0, 1.0),
|
|
||||||
rng.gen_range(-1.0, 1.0),
|
|
||||||
rng.gen_range(0.0, 0.001),
|
|
||||||
)
|
|
||||||
.normalize();
|
|
||||||
let distance =
|
|
||||||
rng.gen_range(wander.distance_bounds.x(), wander.distance_bounds.y());
|
|
||||||
navigation_point.target = translation.0 + direction * distance;
|
|
||||||
wander.elapsed = 0.0;
|
|
||||||
wander.duration =
|
|
||||||
rng.gen_range(wander.duration_bounds.x(), wander.duration_bounds.y());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_navigate_system() -> Box<dyn Schedulable> {
|
|
||||||
SystemBuilder::new("Navigate")
|
|
||||||
.with_query(<(
|
|
||||||
Read<Person>,
|
|
||||||
Write<Translation>,
|
|
||||||
Write<Velocity>,
|
|
||||||
Write<NavigationPoint>,
|
|
||||||
)>::query())
|
|
||||||
.build(move |_, world, _, person_query| {
|
|
||||||
for (_, translation, mut velocity, navigation_point) in person_query.iter_mut(world) {
|
|
||||||
let distance = navigation_point.target - translation.0;
|
|
||||||
if distance.length() > 0.01 {
|
|
||||||
let direction = distance.normalize();
|
|
||||||
velocity.value = direction * 2.0;
|
|
||||||
} else {
|
|
||||||
velocity.value = math::vec3(0.0, 0.0, 0.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_move_system() -> Box<dyn Schedulable> {
|
fn build_move_system() -> Box<dyn Schedulable> {
|
||||||
SystemBuilder::new("Move")
|
SystemBuilder::new("Move")
|
||||||
.read_resource::<Time>()
|
.read_resource::<Time>()
|
||||||
.with_query(<(Write<Translation>, Read<Velocity>)>::query())
|
.write_resource::<AssetStorage<StandardMaterial>>()
|
||||||
.build(move |_, world, time, person_query| {
|
.with_query(<(Write<Translation>, Read<Handle<StandardMaterial>>)>::query())
|
||||||
for (mut translation, velocity) in person_query.iter_mut(world) {
|
.build(move |_, world, (time, material_storage), person_query| {
|
||||||
translation.0 += velocity.value * time.delta_seconds;
|
for (mut translation, material_handle) in person_query.iter_mut(world) {
|
||||||
|
let material = material_storage.get_mut(&material_handle).unwrap();
|
||||||
|
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
|
||||||
|
if let ColorSource::Color(ref mut color) = material.albedo {
|
||||||
|
*color = *color
|
||||||
|
+ Color::rgb(-time.delta_seconds, -time.delta_seconds, time.delta_seconds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_person(world: &mut World, mesh_handle: Handle<Mesh>, translation: Translation) {
|
fn setup(world: &mut World, resources: &mut Resources) {
|
||||||
world.insert(
|
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||||
(),
|
let mut material_storage = resources
|
||||||
vec![(
|
.get_mut::<AssetStorage<StandardMaterial>>()
|
||||||
Person {},
|
.unwrap();
|
||||||
Wander {
|
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
|
||||||
duration_bounds: math::vec2(3.0, 10.0),
|
let plane_handle = mesh_storage.add(Mesh::load(MeshType::Plane { size: 10.0 }));
|
||||||
distance_bounds: math::vec2(-50.0, 50.0),
|
let cube_material_handle = material_storage.add(StandardMaterial {
|
||||||
elapsed: 0.0,
|
albedo: Color::rgb(0.5, 0.4, 0.3).into(),
|
||||||
duration: 0.0,
|
});
|
||||||
},
|
let plane_material_handle = material_storage.add(StandardMaterial {
|
||||||
NavigationPoint {
|
albedo: Color::rgb(0.1, 0.2, 0.1).into(),
|
||||||
target: math::vec3(0.0, 0.0, 0.0),
|
});
|
||||||
},
|
|
||||||
Velocity {
|
let mut builder = world
|
||||||
value: math::vec3(0.0, 0.0, 0.0),
|
.build()
|
||||||
},
|
// plane
|
||||||
StandardMaterial {
|
.add_entity(MeshEntity {
|
||||||
albedo: (math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()).into(),
|
mesh: plane_handle,
|
||||||
},
|
material: plane_material_handle,
|
||||||
Renderable {
|
..Default::default()
|
||||||
|
})
|
||||||
|
// cube
|
||||||
|
.add_entity(MeshEntity {
|
||||||
|
mesh: cube_handle,
|
||||||
|
material: cube_material_handle,
|
||||||
|
translation: Translation::new(0.0, 0.0, 1.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// light
|
||||||
|
.add_entity(LightEntity {
|
||||||
|
translation: Translation::new(4.0, -4.0, 5.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// camera
|
||||||
|
.add_entity(CameraEntity {
|
||||||
|
camera: Camera::new(CameraType::Projection {
|
||||||
|
fov: std::f32::consts::PI / 4.0,
|
||||||
|
near: 1.0,
|
||||||
|
far: 1000.0,
|
||||||
|
aspect_ratio: 1.0,
|
||||||
|
}),
|
||||||
|
active_camera: ActiveCamera,
|
||||||
|
local_to_world: LocalToWorld(Mat4::look_at_rh(
|
||||||
|
Vec3::new(3.0, 8.0, 5.0),
|
||||||
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
Vec3::new(0.0, 0.0, 1.0),
|
||||||
|
)),
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut rng = StdRng::from_entropy();
|
||||||
|
for _ in 0..500 {
|
||||||
|
let spawned_material_handle = material_storage.add(StandardMaterial {
|
||||||
|
albedo: Color::rgb(
|
||||||
|
rng.gen_range(0.0, 1.0),
|
||||||
|
rng.gen_range(0.0, 1.0),
|
||||||
|
rng.gen_range(0.0, 1.0),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
});
|
||||||
|
builder = builder.add_entity(MeshEntity {
|
||||||
|
mesh: cube_handle,
|
||||||
|
material: spawned_material_handle,
|
||||||
|
translation: Translation::new(
|
||||||
|
rng.gen_range(-50.0, 50.0),
|
||||||
|
rng.gen_range(-50.0, 50.0),
|
||||||
|
0.0,
|
||||||
|
),
|
||||||
|
renderable: Renderable {
|
||||||
instanced: true,
|
instanced: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
mesh_handle,
|
..Default::default()
|
||||||
LocalToWorld::identity(),
|
})
|
||||||
translation,
|
}
|
||||||
)],
|
|
||||||
);
|
builder.build();
|
||||||
}
|
}
|
||||||
|
|||||||
172
examples/instancing_old.rs
Normal file
172
examples/instancing_old.rs
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use rand::{random, rngs::StdRng, Rng, SeedableRng};
|
||||||
|
|
||||||
|
struct Person;
|
||||||
|
|
||||||
|
struct Velocity {
|
||||||
|
pub value: math::Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NavigationPoint {
|
||||||
|
pub target: math::Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Wander {
|
||||||
|
pub duration_bounds: math::Vec2,
|
||||||
|
pub distance_bounds: math::Vec2,
|
||||||
|
pub duration: f32,
|
||||||
|
pub elapsed: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
AppBuilder::new()
|
||||||
|
.setup_world(setup)
|
||||||
|
.add_system(build_wander_system())
|
||||||
|
.add_system(build_navigate_system())
|
||||||
|
.add_system(build_move_system())
|
||||||
|
.add_system(bevy::diagnostics::build_fps_printer_system())
|
||||||
|
.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(world: &mut World, resources: &mut Resources) {
|
||||||
|
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||||
|
let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube));
|
||||||
|
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![
|
||||||
|
// lights
|
||||||
|
(
|
||||||
|
Light::default(),
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
Translation::new(4.0, -4.0, 5.0),
|
||||||
|
Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![
|
||||||
|
// camera
|
||||||
|
(
|
||||||
|
Camera::new(CameraType::Projection {
|
||||||
|
fov: std::f32::consts::PI / 4.0,
|
||||||
|
near: 1.0,
|
||||||
|
far: 1000.0,
|
||||||
|
aspect_ratio: 1.0,
|
||||||
|
}),
|
||||||
|
ActiveCamera,
|
||||||
|
LocalToWorld(Mat4::look_at_rh(
|
||||||
|
Vec3::new(6.0, -40.0, 20.0),
|
||||||
|
Vec3::new(0.0, 0.0, 0.0),
|
||||||
|
Vec3::new(0.0, 0.0, 1.0),
|
||||||
|
)),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut rng = StdRng::from_entropy();
|
||||||
|
for _ in 0..70000 {
|
||||||
|
create_person(
|
||||||
|
world,
|
||||||
|
cube_handle,
|
||||||
|
Translation::new(rng.gen_range(-50.0, 50.0), 0.0, rng.gen_range(-50.0, 50.0)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_wander_system() -> Box<dyn Schedulable> {
|
||||||
|
let mut rng = StdRng::from_entropy();
|
||||||
|
|
||||||
|
SystemBuilder::new("Wander")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.with_query(<(
|
||||||
|
Read<Person>,
|
||||||
|
Read<Translation>,
|
||||||
|
Write<Wander>,
|
||||||
|
Write<NavigationPoint>,
|
||||||
|
)>::query())
|
||||||
|
.build(move |_, world, time, person_query| {
|
||||||
|
for (_, translation, mut wander, mut navigation_point) in person_query.iter_mut(world) {
|
||||||
|
wander.elapsed += time.delta_seconds;
|
||||||
|
if wander.elapsed >= wander.duration {
|
||||||
|
let direction = math::vec3(
|
||||||
|
rng.gen_range(-1.0, 1.0),
|
||||||
|
rng.gen_range(-1.0, 1.0),
|
||||||
|
rng.gen_range(0.0, 0.001),
|
||||||
|
)
|
||||||
|
.normalize();
|
||||||
|
let distance =
|
||||||
|
rng.gen_range(wander.distance_bounds.x(), wander.distance_bounds.y());
|
||||||
|
navigation_point.target = translation.0 + direction * distance;
|
||||||
|
wander.elapsed = 0.0;
|
||||||
|
wander.duration =
|
||||||
|
rng.gen_range(wander.duration_bounds.x(), wander.duration_bounds.y());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_navigate_system() -> Box<dyn Schedulable> {
|
||||||
|
SystemBuilder::new("Navigate")
|
||||||
|
.with_query(<(
|
||||||
|
Read<Person>,
|
||||||
|
Write<Translation>,
|
||||||
|
Write<Velocity>,
|
||||||
|
Write<NavigationPoint>,
|
||||||
|
)>::query())
|
||||||
|
.build(move |_, world, _, person_query| {
|
||||||
|
for (_, translation, mut velocity, navigation_point) in person_query.iter_mut(world) {
|
||||||
|
let distance = navigation_point.target - translation.0;
|
||||||
|
if distance.length() > 0.01 {
|
||||||
|
let direction = distance.normalize();
|
||||||
|
velocity.value = direction * 2.0;
|
||||||
|
} else {
|
||||||
|
velocity.value = math::vec3(0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_move_system() -> Box<dyn Schedulable> {
|
||||||
|
SystemBuilder::new("Move")
|
||||||
|
.read_resource::<Time>()
|
||||||
|
.with_query(<(Write<Translation>, Read<Velocity>)>::query())
|
||||||
|
.build(move |_, world, time, person_query| {
|
||||||
|
for (mut translation, velocity) in person_query.iter_mut(world) {
|
||||||
|
translation.0 += velocity.value * time.delta_seconds;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_person(world: &mut World, mesh_handle: Handle<Mesh>, translation: Translation) {
|
||||||
|
world.insert(
|
||||||
|
(),
|
||||||
|
vec![(
|
||||||
|
Person {},
|
||||||
|
Wander {
|
||||||
|
duration_bounds: math::vec2(3.0, 10.0),
|
||||||
|
distance_bounds: math::vec2(-50.0, 50.0),
|
||||||
|
elapsed: 0.0,
|
||||||
|
duration: 0.0,
|
||||||
|
},
|
||||||
|
NavigationPoint {
|
||||||
|
target: math::vec3(0.0, 0.0, 0.0),
|
||||||
|
},
|
||||||
|
Velocity {
|
||||||
|
value: math::vec3(0.0, 0.0, 0.0),
|
||||||
|
},
|
||||||
|
StandardMaterial {
|
||||||
|
albedo: (math::vec4(0.5, 0.3, 0.3, 1.0) * random::<f32>()).into(),
|
||||||
|
},
|
||||||
|
Renderable {
|
||||||
|
instanced: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
mesh_handle,
|
||||||
|
LocalToWorld::identity(),
|
||||||
|
translation,
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -12,7 +12,6 @@ use crate::{
|
|||||||
render_resource::resource_name,
|
render_resource::resource_name,
|
||||||
shader::{Shader, ShaderStages},
|
shader::{Shader, ShaderStages},
|
||||||
texture::TextureFormat,
|
texture::TextureFormat,
|
||||||
Vertex,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -22,12 +21,19 @@ pub enum PipelineLayoutType {
|
|||||||
Reflected(Option<PipelineLayout>),
|
Reflected(Option<PipelineLayout>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum DescriptorType<T> {
|
||||||
|
Manual(T),
|
||||||
|
Reflected(Option<T>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PipelineDescriptor {
|
pub struct PipelineDescriptor {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub draw_targets: Vec<String>,
|
pub draw_targets: Vec<String>,
|
||||||
pub layout: PipelineLayoutType,
|
pub layout: PipelineLayoutType,
|
||||||
pub shader_stages: ShaderStages,
|
pub shader_stages: ShaderStages,
|
||||||
|
pub reflect_vertex_buffer_descriptors: bool,
|
||||||
pub rasterization_state: Option<RasterizationStateDescriptor>,
|
pub rasterization_state: Option<RasterizationStateDescriptor>,
|
||||||
|
|
||||||
/// The primitive topology used to interpret vertices.
|
/// The primitive topology used to interpret vertices.
|
||||||
@ -76,6 +82,7 @@ impl PipelineDescriptor {
|
|||||||
depth_bias_slope_scale: 0.0,
|
depth_bias_slope_scale: 0.0,
|
||||||
depth_bias_clamp: 0.0,
|
depth_bias_clamp: 0.0,
|
||||||
}),
|
}),
|
||||||
|
reflect_vertex_buffer_descriptors: true,
|
||||||
primitive_topology: PrimitiveTopology::TriangleList,
|
primitive_topology: PrimitiveTopology::TriangleList,
|
||||||
index_format: IndexFormat::Uint16,
|
index_format: IndexFormat::Uint16,
|
||||||
sample_count: 1,
|
sample_count: 1,
|
||||||
@ -169,6 +176,7 @@ impl<'a> PipelineBuilder<'a> {
|
|||||||
mut self,
|
mut self,
|
||||||
vertex_buffer_descriptor: VertexBufferDescriptor,
|
vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
self.pipeline.reflect_vertex_buffer_descriptors = false;
|
||||||
self.pipeline
|
self.pipeline
|
||||||
.vertex_buffer_descriptors
|
.vertex_buffer_descriptors
|
||||||
.push(vertex_buffer_descriptor);
|
.push(vertex_buffer_descriptor);
|
||||||
@ -229,7 +237,6 @@ impl<'a> PipelineBuilder<'a> {
|
|||||||
alpha_blend: BlendDescriptor::REPLACE,
|
alpha_blend: BlendDescriptor::REPLACE,
|
||||||
write_mask: ColorWrite::ALL,
|
write_mask: ColorWrite::ALL,
|
||||||
})
|
})
|
||||||
.add_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
|
||||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec4 a_Pos;
|
layout(location = 0) in vec4 Vertex_Position;
|
||||||
layout(location = 1) in vec4 a_Normal;
|
layout(location = 1) in vec4 Vertex_Normal;
|
||||||
layout(location = 2) in vec2 a_Uv;
|
layout(location = 2) in vec2 Vertex_Uv;
|
||||||
|
|
||||||
|
# ifdef INSTANCING
|
||||||
|
layout(location = 3) in vec4 I_Object_Model_0;
|
||||||
|
layout(location = 4) in vec4 I_Object_Model_1;
|
||||||
|
layout(location = 5) in vec4 I_Object_Model_2;
|
||||||
|
layout(location = 6) in vec4 I_Object_Model_3;
|
||||||
|
# endif
|
||||||
|
|
||||||
layout(location = 0) out vec4 v_Position;
|
layout(location = 0) out vec4 v_Position;
|
||||||
layout(location = 1) out vec3 v_Normal;
|
layout(location = 1) out vec3 v_Normal;
|
||||||
@ -12,13 +19,24 @@ layout(set = 0, binding = 0) uniform Camera {
|
|||||||
mat4 ViewProj;
|
mat4 ViewProj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# ifndef INSTANCING
|
||||||
layout(set = 1, binding = 0) uniform Object {
|
layout(set = 1, binding = 0) uniform Object {
|
||||||
mat4 Model;
|
mat4 Model;
|
||||||
};
|
};
|
||||||
|
# endif
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
v_Normal = mat3(Model) * vec3(a_Normal.xyz);
|
# ifdef INSTANCING
|
||||||
v_Position = Model * a_Pos;
|
mat4 Model = mat4(
|
||||||
v_Uv = a_Uv;
|
I_Object_Model_0,
|
||||||
|
I_Object_Model_1,
|
||||||
|
I_Object_Model_2,
|
||||||
|
I_Object_Model_3
|
||||||
|
);
|
||||||
|
# endif
|
||||||
|
|
||||||
|
v_Normal = mat3(Model) * vec3(Vertex_Normal.xyz);
|
||||||
|
v_Position = Model * Vertex_Position;
|
||||||
|
v_Uv = Vertex_Uv;
|
||||||
gl_Position = ViewProj * v_Position;
|
gl_Position = ViewProj * v_Position;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,6 @@ use crate::{
|
|||||||
render_resource::resource_name,
|
render_resource::resource_name,
|
||||||
shader::{Shader, ShaderStage},
|
shader::{Shader, ShaderStage},
|
||||||
texture::TextureFormat,
|
texture::TextureFormat,
|
||||||
Vertex,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
pub trait ForwardPipelineBuilder {
|
pub trait ForwardPipelineBuilder {
|
||||||
@ -71,7 +70,6 @@ impl ForwardPipelineBuilder for RenderGraphBuilder {
|
|||||||
},
|
},
|
||||||
write_mask: ColorWrite::ALL,
|
write_mask: ColorWrite::ALL,
|
||||||
})
|
})
|
||||||
.add_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
|
||||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
||||||
.finish(),
|
.finish(),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -13,7 +13,6 @@ use crate::{
|
|||||||
render_resource::resource_name,
|
render_resource::resource_name,
|
||||||
shader::{Shader, ShaderStage},
|
shader::{Shader, ShaderStage},
|
||||||
texture::TextureFormat,
|
texture::TextureFormat,
|
||||||
Vertex,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -64,7 +63,6 @@ impl ForwardFlatPipelineBuilder for RenderGraphBuilder {
|
|||||||
alpha_blend: BlendDescriptor::REPLACE,
|
alpha_blend: BlendDescriptor::REPLACE,
|
||||||
write_mask: ColorWrite::ALL,
|
write_mask: ColorWrite::ALL,
|
||||||
})
|
})
|
||||||
.add_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
|
||||||
.add_draw_target(resource_name::draw_target::MESHES)
|
.add_draw_target(resource_name::draw_target::MESHES)
|
||||||
.finish(),
|
.finish(),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -6,15 +6,12 @@ use crate::{
|
|||||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
||||||
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||||
},
|
}, PipelineDescriptor,
|
||||||
InputStepMode, PipelineDescriptor, VertexAttributeDescriptor, VertexBufferDescriptor,
|
|
||||||
VertexFormat,
|
|
||||||
},
|
},
|
||||||
render_graph::RenderGraphBuilder,
|
render_graph::RenderGraphBuilder,
|
||||||
render_resource::{resource_name, resource_providers::RectData},
|
render_resource::{resource_name},
|
||||||
shader::{Shader, ShaderStage},
|
shader::{Shader, ShaderStage},
|
||||||
texture::TextureFormat,
|
texture::TextureFormat,
|
||||||
Vertex,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
pub trait UiPipelineBuilder {
|
pub trait UiPipelineBuilder {
|
||||||
@ -72,33 +69,6 @@ impl UiPipelineBuilder for RenderGraphBuilder {
|
|||||||
},
|
},
|
||||||
write_mask: ColorWrite::ALL,
|
write_mask: ColorWrite::ALL,
|
||||||
})
|
})
|
||||||
.add_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
|
||||||
.add_vertex_buffer_descriptor(VertexBufferDescriptor {
|
|
||||||
stride: std::mem::size_of::<RectData>() as u64,
|
|
||||||
step_mode: InputStepMode::Instance,
|
|
||||||
attributes: vec![
|
|
||||||
VertexAttributeDescriptor {
|
|
||||||
format: VertexFormat::Float2,
|
|
||||||
offset: 0,
|
|
||||||
shader_location: 3,
|
|
||||||
},
|
|
||||||
VertexAttributeDescriptor {
|
|
||||||
format: VertexFormat::Float2,
|
|
||||||
offset: 2 * 4,
|
|
||||||
shader_location: 4,
|
|
||||||
},
|
|
||||||
VertexAttributeDescriptor {
|
|
||||||
format: VertexFormat::Float4,
|
|
||||||
offset: 4 * 4,
|
|
||||||
shader_location: 5,
|
|
||||||
},
|
|
||||||
VertexAttributeDescriptor {
|
|
||||||
format: VertexFormat::Float,
|
|
||||||
offset: 8 * 4,
|
|
||||||
shader_location: 6,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
.add_draw_target(resource_name::draw_target::UI)
|
.add_draw_target(resource_name::draw_target::UI)
|
||||||
.finish(),
|
.finish(),
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,15 +1,13 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
// vertex attributes
|
layout(location = 0) in vec4 Vertex_Position;
|
||||||
layout(location = 0) in vec4 a_Pos;
|
layout(location = 1) in vec4 Vertex_Normal;
|
||||||
layout(location = 1) in vec4 a_Normal;
|
layout(location = 2) in vec2 Vertex_Uv;
|
||||||
layout(location = 2) in vec2 a_Uv;
|
|
||||||
|
|
||||||
// instanced attributes (RectData)
|
layout (location = 3) in vec2 I_Rect_Position;
|
||||||
layout (location = 3) in vec2 a_RectPosition;
|
layout (location = 4) in vec2 I_Rect_Size;
|
||||||
layout (location = 4) in vec2 a_RectSize;
|
layout (location = 5) in vec4 I_Rect_Color;
|
||||||
layout (location = 5) in vec4 a_RectColor;
|
layout (location = 6) in float I_Rect_ZIndex;
|
||||||
layout (location = 6) in float a_RectZIndex;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 v_Color;
|
layout(location = 0) out vec4 v_Color;
|
||||||
|
|
||||||
@ -18,8 +16,8 @@ layout(set = 0, binding = 0) uniform Camera2d {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
v_Color = a_RectColor;
|
v_Color = I_Rect_Color;
|
||||||
vec4 position = a_Pos * vec4(a_RectSize, 0.0, 1.0);
|
vec4 position = Vertex_Position * vec4(I_Rect_Size, 0.0, 1.0);
|
||||||
position = position + vec4(a_RectPosition + a_RectSize / 2.0, -a_RectZIndex, 0.0);
|
position = position + vec4(I_Rect_Position + I_Rect_Size / 2.0, -I_Rect_ZIndex, 0.0);
|
||||||
gl_Position = ViewProj * position;
|
gl_Position = ViewProj * position;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub struct VertexBufferDescriptor {
|
pub struct VertexBufferDescriptor {
|
||||||
|
pub name: String,
|
||||||
pub stride: u64,
|
pub stride: u64,
|
||||||
pub step_mode: InputStepMode,
|
pub step_mode: InputStepMode,
|
||||||
pub attributes: Vec<VertexAttributeDescriptor>,
|
pub attributes: Vec<VertexAttributeDescriptor>,
|
||||||
@ -39,14 +40,52 @@ pub enum VertexFormat {
|
|||||||
Int4 = 48,
|
Int4 = 48,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VertexFormat {
|
||||||
|
pub fn get_size(&self) -> u64 {
|
||||||
|
match *self {
|
||||||
|
VertexFormat::Uchar2 => 2,
|
||||||
|
VertexFormat::Uchar4 => 4,
|
||||||
|
VertexFormat::Char2 => 2,
|
||||||
|
VertexFormat::Char4 => 4,
|
||||||
|
VertexFormat::Uchar2Norm => 2,
|
||||||
|
VertexFormat::Uchar4Norm => 4,
|
||||||
|
VertexFormat::Char2Norm => 2,
|
||||||
|
VertexFormat::Char4Norm => 4,
|
||||||
|
VertexFormat::Ushort2 => 2 * 2,
|
||||||
|
VertexFormat::Ushort4 => 2 * 4,
|
||||||
|
VertexFormat::Short2 => 2 * 2,
|
||||||
|
VertexFormat::Short4 => 2 * 4,
|
||||||
|
VertexFormat::Ushort2Norm => 2 * 2,
|
||||||
|
VertexFormat::Ushort4Norm => 2 * 4,
|
||||||
|
VertexFormat::Short2Norm => 2 * 2,
|
||||||
|
VertexFormat::Short4Norm => 2 * 4,
|
||||||
|
VertexFormat::Half2 => 2 * 2,
|
||||||
|
VertexFormat::Half4 => 2 * 4,
|
||||||
|
VertexFormat::Float => 4,
|
||||||
|
VertexFormat::Float2 => 4 * 2,
|
||||||
|
VertexFormat::Float3 => 4 * 3,
|
||||||
|
VertexFormat::Float4 => 4 * 4,
|
||||||
|
VertexFormat::Uint => 4,
|
||||||
|
VertexFormat::Uint2 => 4 * 2,
|
||||||
|
VertexFormat::Uint3 => 4 * 3,
|
||||||
|
VertexFormat::Uint4 => 4 * 4,
|
||||||
|
VertexFormat::Int => 4,
|
||||||
|
VertexFormat::Int2 => 4 * 2,
|
||||||
|
VertexFormat::Int3 => 4 * 3,
|
||||||
|
VertexFormat::Int4 => 4 * 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub enum InputStepMode {
|
pub enum InputStepMode {
|
||||||
Vertex = 0,
|
Vertex = 0,
|
||||||
Instance = 1,
|
Instance = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
||||||
pub struct VertexAttributeDescriptor {
|
pub struct VertexAttributeDescriptor {
|
||||||
|
pub name: String,
|
||||||
pub offset: u64,
|
pub offset: u64,
|
||||||
pub format: VertexFormat,
|
pub format: VertexFormat,
|
||||||
pub shader_location: u32,
|
pub shader_location: u32,
|
||||||
|
|||||||
@ -16,6 +16,15 @@ pub struct Renderable {
|
|||||||
pub instanced: bool,
|
pub instanced: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Renderable {
|
||||||
|
pub fn instanced() -> Self {
|
||||||
|
Renderable {
|
||||||
|
instanced: false,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Renderable {
|
impl Default for Renderable {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Renderable {
|
Renderable {
|
||||||
@ -116,7 +125,12 @@ pub fn update_shader_assignments(
|
|||||||
// reset assignments so they are updated every frame
|
// reset assignments so they are updated every frame
|
||||||
shader_pipeline_assignments.assignments = HashMap::new();
|
shader_pipeline_assignments.assignments = HashMap::new();
|
||||||
|
|
||||||
for (entity, renderable) in <Read<Renderable>>::query().iter_entities(world) {
|
for (entity, mut renderable) in <Write<Renderable>>::query().iter_entities_mut(world) {
|
||||||
|
// if instancing is enabled, set the def here
|
||||||
|
if renderable.instanced {
|
||||||
|
renderable.shader_defs.insert("INSTANCING".to_string());
|
||||||
|
}
|
||||||
|
|
||||||
for pipeline_handle in renderable.pipelines.iter() {
|
for pipeline_handle in renderable.pipelines.iter() {
|
||||||
if let None = compiled_shader_map
|
if let None = compiled_shader_map
|
||||||
.pipeline_to_macro_pipelines
|
.pipeline_to_macro_pipelines
|
||||||
|
|||||||
@ -7,7 +7,9 @@ use crate::{
|
|||||||
PassDescriptor, RenderPassColorAttachmentDescriptor,
|
PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||||
RenderPassDepthStencilAttachmentDescriptor,
|
RenderPassDepthStencilAttachmentDescriptor,
|
||||||
},
|
},
|
||||||
pipeline::{BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType},
|
pipeline::{
|
||||||
|
BindType, PipelineDescriptor, PipelineLayout, PipelineLayoutType,
|
||||||
|
},
|
||||||
render_graph::RenderGraph,
|
render_graph::RenderGraph,
|
||||||
render_resource::{
|
render_resource::{
|
||||||
resource_name, BufferUsage, RenderResource, RenderResources, ResourceInfo,
|
resource_name, BufferUsage, RenderResource, RenderResources, ResourceInfo,
|
||||||
@ -161,8 +163,19 @@ impl WgpuRenderer {
|
|||||||
bind_group_layouts: bind_group_layouts.as_slice(),
|
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let owned_vertex_buffer_descriptors = pipeline_descriptor
|
let reflected_vertex_layout = if pipeline_descriptor.reflect_vertex_buffer_descriptors {
|
||||||
.vertex_buffer_descriptors
|
Some(vertex_spirv.reflect_layout().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let vertex_buffer_descriptors = if let Some(ref layout) = reflected_vertex_layout {
|
||||||
|
&layout.vertex_buffer_descriptors
|
||||||
|
} else {
|
||||||
|
&pipeline_descriptor.vertex_buffer_descriptors
|
||||||
|
};
|
||||||
|
|
||||||
|
let owned_vertex_buffer_descriptors = vertex_buffer_descriptors
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| v.into())
|
.map(|v| v.into())
|
||||||
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
.collect::<Vec<OwnedWgpuVertexBufferDescriptor>>();
|
||||||
|
|||||||
@ -1,14 +1,18 @@
|
|||||||
use crate::render::{
|
use crate::render::{
|
||||||
pipeline::{BindGroup, BindType, Binding, UniformProperty, UniformPropertyType},
|
pipeline::{
|
||||||
|
BindGroup, BindType, Binding, InputStepMode, UniformProperty, UniformPropertyType,
|
||||||
|
VertexAttributeDescriptor, VertexBufferDescriptor, VertexFormat,
|
||||||
|
},
|
||||||
texture::TextureViewDimension,
|
texture::TextureViewDimension,
|
||||||
};
|
};
|
||||||
use spirv_reflect::{
|
use spirv_reflect::{
|
||||||
types::{
|
types::{
|
||||||
ReflectDescriptorBinding, ReflectDescriptorSet, ReflectDescriptorType, ReflectDimension,
|
ReflectDescriptorBinding, ReflectDescriptorSet, ReflectDescriptorType, ReflectDimension,
|
||||||
ReflectTypeDescription, ReflectTypeFlags,
|
ReflectInterfaceVariable, ReflectTypeDescription, ReflectTypeFlags,
|
||||||
},
|
},
|
||||||
ShaderModule,
|
ShaderModule,
|
||||||
};
|
};
|
||||||
|
use std::collections::HashSet;
|
||||||
use zerocopy::AsBytes;
|
use zerocopy::AsBytes;
|
||||||
// use rspirv::{binary::Parser, dr::Loader, lift::LiftContext};
|
// use rspirv::{binary::Parser, dr::Loader, lift::LiftContext};
|
||||||
|
|
||||||
@ -27,6 +31,7 @@ use zerocopy::AsBytes;
|
|||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct ShaderLayout {
|
pub struct ShaderLayout {
|
||||||
pub bind_groups: Vec<BindGroup>,
|
pub bind_groups: Vec<BindGroup>,
|
||||||
|
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
|
||||||
pub entry_point: String,
|
pub entry_point: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,8 +46,80 @@ impl ShaderLayout {
|
|||||||
bind_groups.push(bind_group);
|
bind_groups.push(bind_group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut vertex_attribute_descriptors = Vec::new();
|
||||||
|
for input_variable in module.enumerate_input_variables(None).unwrap() {
|
||||||
|
let vertex_attribute_descriptor =
|
||||||
|
reflect_vertex_attribute_descriptor(&input_variable);
|
||||||
|
vertex_attribute_descriptors.push(vertex_attribute_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_attribute_descriptors
|
||||||
|
.sort_by(|a, b| a.shader_location.cmp(&b.shader_location));
|
||||||
|
|
||||||
|
let mut visited_buffer_descriptors = HashSet::new();
|
||||||
|
let mut vertex_buffer_descriptors = Vec::new();
|
||||||
|
let mut current_descriptor: Option<VertexBufferDescriptor> = None;
|
||||||
|
for vertex_attribute_descriptor in vertex_attribute_descriptors.drain(..) {
|
||||||
|
let mut instance = false;
|
||||||
|
let current_buffer_name = {
|
||||||
|
let parts = vertex_attribute_descriptor
|
||||||
|
.name
|
||||||
|
.splitn(3, "_")
|
||||||
|
.collect::<Vec<&str>>();
|
||||||
|
if parts.len() == 3 {
|
||||||
|
if parts[0] == "I" {
|
||||||
|
instance = true;
|
||||||
|
parts[1].to_string()
|
||||||
|
} else {
|
||||||
|
parts[0].to_string()
|
||||||
|
}
|
||||||
|
} else if parts.len() == 2 {
|
||||||
|
parts[0].to_string()
|
||||||
|
} else {
|
||||||
|
panic!("Vertex attributes must follow the form BUFFERNAME_PROPERTYNAME. For example: Vertex_Position");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(current) = current_descriptor.as_mut() {
|
||||||
|
if ¤t.name == ¤t_buffer_name {
|
||||||
|
current.attributes.push(vertex_attribute_descriptor);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if visited_buffer_descriptors.contains(¤t_buffer_name) {
|
||||||
|
panic!("Vertex attribute buffer names must be consecutive.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(current) = current_descriptor.take() {
|
||||||
|
visited_buffer_descriptors.insert(current.name.to_string());
|
||||||
|
vertex_buffer_descriptors.push(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_descriptor = Some(VertexBufferDescriptor {
|
||||||
|
attributes: vec![vertex_attribute_descriptor],
|
||||||
|
name: current_buffer_name,
|
||||||
|
step_mode: if instance {
|
||||||
|
InputStepMode::Instance
|
||||||
|
} else {
|
||||||
|
InputStepMode::Vertex
|
||||||
|
},
|
||||||
|
stride: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(current) = current_descriptor.take() {
|
||||||
|
visited_buffer_descriptors.insert(current.name.to_string());
|
||||||
|
vertex_buffer_descriptors.push(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
for vertex_buffer_descriptor in vertex_buffer_descriptors.iter_mut() {
|
||||||
|
calculate_offsets(vertex_buffer_descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
ShaderLayout {
|
ShaderLayout {
|
||||||
bind_groups,
|
bind_groups,
|
||||||
|
vertex_buffer_descriptors,
|
||||||
entry_point: entry_point_name,
|
entry_point: entry_point_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,6 +128,27 @@ impl ShaderLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn calculate_offsets(vertex_buffer_descriptor: &mut VertexBufferDescriptor) {
|
||||||
|
let mut offset = 0;
|
||||||
|
for attribute in vertex_buffer_descriptor.attributes.iter_mut() {
|
||||||
|
attribute.offset = offset;
|
||||||
|
offset += attribute.format.get_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
vertex_buffer_descriptor.stride = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_vertex_attribute_descriptor(
|
||||||
|
input_variable: &ReflectInterfaceVariable,
|
||||||
|
) -> VertexAttributeDescriptor {
|
||||||
|
VertexAttributeDescriptor {
|
||||||
|
name: input_variable.name.clone(),
|
||||||
|
format: reflect_vertex_format(input_variable.type_description.as_ref().unwrap()),
|
||||||
|
offset: 0,
|
||||||
|
shader_location: input_variable.location,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn reflect_bind_group(descriptor_set: &ReflectDescriptorSet) -> BindGroup {
|
fn reflect_bind_group(descriptor_set: &ReflectDescriptorSet) -> BindGroup {
|
||||||
let mut bindings = Vec::new();
|
let mut bindings = Vec::new();
|
||||||
for descriptor_binding in descriptor_set.bindings.iter() {
|
for descriptor_binding in descriptor_set.bindings.iter() {
|
||||||
@ -180,6 +278,55 @@ fn reflect_uniform_numeric(type_description: &ReflectTypeDescription) -> Uniform
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn reflect_vertex_format(type_description: &ReflectTypeDescription) -> VertexFormat {
|
||||||
|
let traits = &type_description.traits;
|
||||||
|
let number_type = if type_description.type_flags.contains(ReflectTypeFlags::INT) {
|
||||||
|
match traits.numeric.scalar.signedness {
|
||||||
|
0 => NumberType::UInt,
|
||||||
|
1 => NumberType::Int,
|
||||||
|
signedness => panic!("unexpected signedness {}", signedness),
|
||||||
|
}
|
||||||
|
} else if type_description
|
||||||
|
.type_flags
|
||||||
|
.contains(ReflectTypeFlags::FLOAT)
|
||||||
|
{
|
||||||
|
NumberType::Float
|
||||||
|
} else {
|
||||||
|
panic!("unexpected type flag {:?}", type_description.type_flags);
|
||||||
|
};
|
||||||
|
|
||||||
|
let width = traits.numeric.scalar.width;
|
||||||
|
|
||||||
|
match (number_type, traits.numeric.vector.component_count, width) {
|
||||||
|
(NumberType::UInt, 2, 8) => VertexFormat::Uchar2,
|
||||||
|
(NumberType::UInt, 4, 8) => VertexFormat::Uchar4,
|
||||||
|
(NumberType::Int, 2, 8) => VertexFormat::Char2,
|
||||||
|
(NumberType::Int, 4, 8) => VertexFormat::Char4,
|
||||||
|
(NumberType::UInt, 2, 16) => VertexFormat::Ushort2,
|
||||||
|
(NumberType::UInt, 4, 16) => VertexFormat::Ushort4,
|
||||||
|
(NumberType::Int, 2, 16) => VertexFormat::Short2,
|
||||||
|
(NumberType::Int, 8, 16) => VertexFormat::Short4,
|
||||||
|
(NumberType::Float, 2, 16) => VertexFormat::Half2,
|
||||||
|
(NumberType::Float, 4, 16) => VertexFormat::Half4,
|
||||||
|
(NumberType::Float, 0, 32) => VertexFormat::Float,
|
||||||
|
(NumberType::Float, 2, 32) => VertexFormat::Float2,
|
||||||
|
(NumberType::Float, 3, 32) => VertexFormat::Float3,
|
||||||
|
(NumberType::Float, 4, 32) => VertexFormat::Float4,
|
||||||
|
(NumberType::UInt, 0, 32) => VertexFormat::Uint,
|
||||||
|
(NumberType::UInt, 2, 32) => VertexFormat::Uint2,
|
||||||
|
(NumberType::UInt, 3, 32) => VertexFormat::Uint3,
|
||||||
|
(NumberType::UInt, 4, 32) => VertexFormat::Uint4,
|
||||||
|
(NumberType::Int, 0, 32) => VertexFormat::Int,
|
||||||
|
(NumberType::Int, 2, 32) => VertexFormat::Int2,
|
||||||
|
(NumberType::Int, 3, 32) => VertexFormat::Int3,
|
||||||
|
(NumberType::Int, 4, 32) => VertexFormat::Int4,
|
||||||
|
(number_type, component_count, width) => panic!(
|
||||||
|
"unexpected uniform property format {:?} {} {}",
|
||||||
|
number_type, component_count, width
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -191,7 +338,10 @@ mod tests {
|
|||||||
ShaderStage::Vertex,
|
ShaderStage::Vertex,
|
||||||
r#"
|
r#"
|
||||||
#version 450
|
#version 450
|
||||||
layout(location = 0) in vec4 a_Pos;
|
layout(location = 0) in vec4 Vertex_Position;
|
||||||
|
layout(location = 1) in uvec4 Vertex_Normal;
|
||||||
|
layout(location = 2) in uvec4 I_TestInstancing_Property;
|
||||||
|
|
||||||
layout(location = 0) out vec4 v_Position;
|
layout(location = 0) out vec4 v_Position;
|
||||||
layout(set = 0, binding = 0) uniform Camera {
|
layout(set = 0, binding = 0) uniform Camera {
|
||||||
mat4 ViewProj;
|
mat4 ViewProj;
|
||||||
@ -199,7 +349,7 @@ mod tests {
|
|||||||
layout(set = 1, binding = 0) uniform texture2D Texture;
|
layout(set = 1, binding = 0) uniform texture2D Texture;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
v_Position = a_Pos;
|
v_Position = Vertex_Position;
|
||||||
gl_Position = ViewProj * v_Position;
|
gl_Position = ViewProj * v_Position;
|
||||||
}
|
}
|
||||||
"#,
|
"#,
|
||||||
@ -211,6 +361,40 @@ mod tests {
|
|||||||
layout,
|
layout,
|
||||||
ShaderLayout {
|
ShaderLayout {
|
||||||
entry_point: "main".to_string(),
|
entry_point: "main".to_string(),
|
||||||
|
vertex_buffer_descriptors: vec![
|
||||||
|
VertexBufferDescriptor {
|
||||||
|
name: "Vertex".to_string(),
|
||||||
|
attributes: vec![
|
||||||
|
VertexAttributeDescriptor {
|
||||||
|
name: "Vertex_Position".to_string(),
|
||||||
|
format: VertexFormat::Float4,
|
||||||
|
offset: 0,
|
||||||
|
shader_location: 0,
|
||||||
|
},
|
||||||
|
VertexAttributeDescriptor {
|
||||||
|
name: "Vertex_Normal".to_string(),
|
||||||
|
format: VertexFormat::Uint4,
|
||||||
|
offset: 16,
|
||||||
|
shader_location: 1,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
step_mode: InputStepMode::Vertex,
|
||||||
|
stride: 32,
|
||||||
|
},
|
||||||
|
VertexBufferDescriptor {
|
||||||
|
name: "TestInstancing".to_string(),
|
||||||
|
attributes: vec![
|
||||||
|
VertexAttributeDescriptor {
|
||||||
|
name: "I_TestInstancing_Property".to_string(),
|
||||||
|
format: VertexFormat::Uint4,
|
||||||
|
offset: 0,
|
||||||
|
shader_location: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
step_mode: InputStepMode::Instance,
|
||||||
|
stride: 16,
|
||||||
|
}
|
||||||
|
],
|
||||||
bind_groups: vec![
|
bind_groups: vec![
|
||||||
BindGroup::new(
|
BindGroup::new(
|
||||||
0,
|
0,
|
||||||
@ -246,4 +430,32 @@ mod tests {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "Vertex attribute buffer names must be consecutive.")]
|
||||||
|
fn test_reflection_consecutive_buffer_validation() {
|
||||||
|
let vertex_shader = Shader::from_glsl(
|
||||||
|
ShaderStage::Vertex,
|
||||||
|
r#"
|
||||||
|
#version 450
|
||||||
|
layout(location = 0) in vec4 Vertex_Position;
|
||||||
|
layout(location = 1) in uvec4 Other_Property;
|
||||||
|
layout(location = 2) in uvec4 Vertex_Normal;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 v_Position;
|
||||||
|
layout(set = 0, binding = 0) uniform Camera {
|
||||||
|
mat4 ViewProj;
|
||||||
|
};
|
||||||
|
layout(set = 1, binding = 0) uniform texture2D Texture;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
v_Position = Vertex_Position;
|
||||||
|
gl_Position = ViewProj * v_Position;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.get_spirv_shader(None);
|
||||||
|
|
||||||
|
let _layout = vertex_shader.reflect_layout().unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const LOCAL_TO_WORLD_FIELD_INFOS: &[FieldInfo] = &[FieldInfo {
|
|||||||
uniform_name: "Object",
|
uniform_name: "Object",
|
||||||
texture_name: "",
|
texture_name: "",
|
||||||
sampler_name: "",
|
sampler_name: "",
|
||||||
is_instanceable: false,
|
is_instanceable: true,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
use super::pipeline::{InputStepMode, VertexBufferDescriptor, VertexFormat};
|
|
||||||
use crate::render::pipeline::VertexAttributeDescriptor;
|
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use zerocopy::{AsBytes, FromBytes};
|
use zerocopy::{AsBytes, FromBytes};
|
||||||
|
|
||||||
@ -11,32 +9,6 @@ pub struct Vertex {
|
|||||||
pub uv: [f32; 2],
|
pub uv: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vertex {
|
|
||||||
pub fn get_vertex_buffer_descriptor() -> VertexBufferDescriptor {
|
|
||||||
VertexBufferDescriptor {
|
|
||||||
stride: std::mem::size_of::<Vertex>() as u64,
|
|
||||||
step_mode: InputStepMode::Vertex,
|
|
||||||
attributes: vec![
|
|
||||||
VertexAttributeDescriptor {
|
|
||||||
format: VertexFormat::Float4,
|
|
||||||
offset: 0,
|
|
||||||
shader_location: 0,
|
|
||||||
},
|
|
||||||
VertexAttributeDescriptor {
|
|
||||||
format: VertexFormat::Float4,
|
|
||||||
offset: 4 * 4,
|
|
||||||
shader_location: 1,
|
|
||||||
},
|
|
||||||
VertexAttributeDescriptor {
|
|
||||||
format: VertexFormat::Float2,
|
|
||||||
offset: 8 * 4,
|
|
||||||
shader_location: 2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<([f32; 4], [f32; 4], [f32; 2])> for Vertex {
|
impl From<([f32; 4], [f32; 4], [f32; 2])> for Vertex {
|
||||||
fn from((position, normal, uv): ([f32; 4], [f32; 4], [f32; 2])) -> Self {
|
fn from((position, normal, uv): ([f32; 4], [f32; 4], [f32; 2])) -> Self {
|
||||||
Vertex {
|
Vertex {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user