mirror of
https://github.com/bevyengine/bevy
synced 2024-11-21 20:23:28 +00:00
port forward lighting and add struct + array uniforms
This commit is contained in:
parent
380e59ee23
commit
489580f688
6 changed files with 102 additions and 29 deletions
|
@ -103,22 +103,22 @@ fn setup(world: &mut World) {
|
|||
translation: Translation::new(-2.0, 0.0, 1.0),
|
||||
})
|
||||
// light
|
||||
// .add_archetype(LightEntity {
|
||||
// light: Light {
|
||||
// color: wgpu::Color {
|
||||
// r: 0.8,
|
||||
// g: 0.8,
|
||||
// b: 0.5,
|
||||
// a: 1.0,
|
||||
// },
|
||||
// fov: f32::to_radians(60.0),
|
||||
// depth: 0.1..50.0,
|
||||
// target_view: None,
|
||||
// },
|
||||
// local_to_world: LocalToWorld::identity(),
|
||||
// translation: Translation::new(4.0, -4.0, 5.0),
|
||||
// rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
// })
|
||||
.add_archetype(LightEntity {
|
||||
light: Light {
|
||||
color: wgpu::Color {
|
||||
r: 0.8,
|
||||
g: 0.8,
|
||||
b: 0.5,
|
||||
a: 1.0,
|
||||
},
|
||||
fov: f32::to_radians(60.0),
|
||||
depth: 0.1..50.0,
|
||||
target_view: None,
|
||||
},
|
||||
local_to_world: LocalToWorld::identity(),
|
||||
translation: Translation::new(4.0, -4.0, 5.0),
|
||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||
})
|
||||
// camera
|
||||
.add_archetype(CameraEntity {
|
||||
camera: Camera::new(CameraType::Projection {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use std::{
|
||||
collections::{hash_map::DefaultHasher},
|
||||
collections::hash_map::DefaultHasher,
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
pub struct PipelineLayout {
|
||||
|
@ -50,7 +50,7 @@ pub struct Binding {
|
|||
pub enum BindType {
|
||||
Uniform {
|
||||
dynamic: bool,
|
||||
properties: Vec<UniformProperty>
|
||||
properties: Vec<UniformProperty>,
|
||||
},
|
||||
Buffer {
|
||||
dynamic: bool,
|
||||
|
@ -70,9 +70,11 @@ impl BindType {
|
|||
pub fn get_uniform_size(&self) -> Option<u64> {
|
||||
match self {
|
||||
BindType::Uniform { properties, .. } => {
|
||||
Some(properties.iter().fold(0, |total, property| total + property.property_type.get_size()))
|
||||
},
|
||||
_ => None
|
||||
Some(properties.iter().fold(0, |total, property| {
|
||||
total + property.property_type.get_size()
|
||||
}))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +94,8 @@ pub enum UniformPropertyType {
|
|||
Vec3,
|
||||
Vec4,
|
||||
Mat4,
|
||||
// Struct(Vec<UniformPropertyType>),
|
||||
// Array(Box<UniformPropertyType>, usize),
|
||||
Struct(Vec<UniformPropertyType>),
|
||||
Array(Box<UniformPropertyType>, usize),
|
||||
}
|
||||
|
||||
impl UniformPropertyType {
|
||||
|
@ -105,6 +107,11 @@ impl UniformPropertyType {
|
|||
UniformPropertyType::Vec3 => 4 * 3,
|
||||
UniformPropertyType::Vec4 => 4 * 4,
|
||||
UniformPropertyType::Mat4 => 4 * 4 * 4,
|
||||
UniformPropertyType::Struct(properties) => properties
|
||||
.iter()
|
||||
.map(|p| p.get_size())
|
||||
.fold(0, |total, size| total + size),
|
||||
UniformPropertyType::Array(property, length) => property.get_size() * *length as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
#version 450
|
||||
|
||||
const int MAX_LIGHTS = 10;
|
||||
|
||||
struct Light {
|
||||
mat4 proj;
|
||||
vec4 pos;
|
||||
vec4 color;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 v_Position;
|
||||
layout(location = 1) in vec3 v_Normal;
|
||||
layout(location = 2) in vec2 v_Uv;
|
||||
|
@ -10,12 +18,29 @@ layout(set = 0, binding = 0) uniform Camera {
|
|||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 0, binding = 1) uniform Lights {
|
||||
uvec4 NumLights;
|
||||
Light SceneLights[MAX_LIGHTS];
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform StandardMaterial {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
|
||||
void main() {
|
||||
vec3 normal = normalize(v_Normal);
|
||||
vec3 ambient = vec3(0.05, 0.05, 0.05);
|
||||
// accumulate color
|
||||
vec3 color = ambient;
|
||||
for (int i=0; i<int(NumLights.x) && i<MAX_LIGHTS; ++i) {
|
||||
Light light = SceneLights[i];
|
||||
// compute Lambertian diffuse term
|
||||
vec3 light_dir = normalize(light.pos.xyz - v_Position.xyz);
|
||||
float diffuse = max(0.0, dot(normal, light_dir));
|
||||
// add light contribution
|
||||
color += diffuse * light.color.xyz;
|
||||
}
|
||||
// multiply the light by material color
|
||||
o_Target = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
o_Target = Albedo;
|
||||
o_Target = vec4(color, 1.0) * Albedo;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ layout(set = 1, binding = 1) uniform StandardMaterial {
|
|||
void main() {
|
||||
v_Normal = mat3(Model) * vec3(a_Normal.xyz);
|
||||
v_Position = Model * vec4(a_Pos);
|
||||
// v_Normal = vec3(a_Normal.xyz);
|
||||
// v_Position = vec4(a_Pos);
|
||||
v_Uv = a_Uv;
|
||||
gl_Position = ViewProj * v_Position;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,29 @@ impl ForwardPipelineBuilder for RenderGraphBuilder {
|
|||
]
|
||||
}
|
||||
},
|
||||
Binding {
|
||||
name: "Lights".to_string(),
|
||||
bind_type: BindType::Uniform {
|
||||
dynamic: false,
|
||||
properties: vec![
|
||||
UniformProperty {
|
||||
name: "NumLights".to_string(),
|
||||
property_type: UniformPropertyType::UVec4,
|
||||
},
|
||||
UniformProperty {
|
||||
name: "SceneLights".to_string(),
|
||||
property_type: UniformPropertyType::Array(
|
||||
Box::new(UniformPropertyType::Struct(vec![
|
||||
UniformPropertyType::Mat4, // proj
|
||||
UniformPropertyType::Vec4, // pos
|
||||
UniformPropertyType::Vec4, // color
|
||||
])),
|
||||
10, // max lights
|
||||
),
|
||||
},
|
||||
]
|
||||
}
|
||||
},
|
||||
]
|
||||
))
|
||||
.add_bind_group(BindGroup::new(
|
||||
|
|
|
@ -58,6 +58,12 @@ pub struct LightResourceProvider {
|
|||
pub max_lights: usize,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, AsBytes)]
|
||||
pub struct LightCount {
|
||||
pub num_lights: [u32; 4],
|
||||
}
|
||||
|
||||
impl LightResourceProvider {
|
||||
pub fn new(max_lights: usize) -> Self {
|
||||
LightResourceProvider {
|
||||
|
@ -70,7 +76,7 @@ impl LightResourceProvider {
|
|||
impl ResourceProvider for LightResourceProvider {
|
||||
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
|
||||
let light_uniform_size =
|
||||
(self.max_lights * std::mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
|
||||
(std::mem::size_of::<LightCount>() + self.max_lights * std::mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
|
||||
|
||||
renderer.create_buffer(
|
||||
resource_name::uniform::LIGHTS,
|
||||
|
@ -91,6 +97,7 @@ impl ResourceProvider for LightResourceProvider {
|
|||
self.lights_are_dirty = false;
|
||||
let size = std::mem::size_of::<LightRaw>();
|
||||
let total_size = size * light_count;
|
||||
let light_count_size = std::mem::size_of::<LightCount>();
|
||||
renderer
|
||||
.create_buffer_mapped("LIGHT_TMP", total_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
|
||||
for ((light, local_to_world, translation), slot) in light_query
|
||||
|
@ -102,10 +109,22 @@ impl ResourceProvider for LightResourceProvider {
|
|||
);
|
||||
}
|
||||
});
|
||||
renderer
|
||||
.create_buffer_mapped("LIGHT_COUNT_TMP", light_count_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
|
||||
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
});
|
||||
|
||||
renderer.copy_buffer_to_buffer(
|
||||
"LIGHT_COUNT_TMP",
|
||||
0,
|
||||
resource_name::uniform::LIGHTS,
|
||||
0,
|
||||
light_count_size as wgpu::BufferAddress,
|
||||
);
|
||||
|
||||
renderer.copy_buffer_to_buffer(
|
||||
"LIGHT_TMP",
|
||||
0,
|
||||
light_count_size as u64,
|
||||
resource_name::uniform::LIGHTS,
|
||||
0,
|
||||
total_size as wgpu::BufferAddress,
|
||||
|
|
Loading…
Reference in a new issue