port forward lighting and add struct + array uniforms

This commit is contained in:
Carter Anderson 2020-02-05 09:59:36 -08:00
parent 380e59ee23
commit 489580f688
6 changed files with 102 additions and 29 deletions

View file

@ -103,22 +103,22 @@ fn setup(world: &mut World) {
translation: Translation::new(-2.0, 0.0, 1.0), translation: Translation::new(-2.0, 0.0, 1.0),
}) })
// light // light
// .add_archetype(LightEntity { .add_archetype(LightEntity {
// light: Light { light: Light {
// color: wgpu::Color { color: wgpu::Color {
// r: 0.8, r: 0.8,
// g: 0.8, g: 0.8,
// b: 0.5, b: 0.5,
// a: 1.0, a: 1.0,
// }, },
// fov: f32::to_radians(60.0), fov: f32::to_radians(60.0),
// depth: 0.1..50.0, depth: 0.1..50.0,
// target_view: None, target_view: None,
// }, },
// local_to_world: LocalToWorld::identity(), local_to_world: LocalToWorld::identity(),
// translation: Translation::new(4.0, -4.0, 5.0), translation: Translation::new(4.0, -4.0, 5.0),
// rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0), rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
// }) })
// camera // camera
.add_archetype(CameraEntity { .add_archetype(CameraEntity {
camera: Camera::new(CameraType::Projection { camera: Camera::new(CameraType::Projection {

View file

@ -1,5 +1,5 @@
use std::{ use std::{
collections::{hash_map::DefaultHasher}, collections::hash_map::DefaultHasher,
hash::{Hash, Hasher}, hash::{Hash, Hasher},
}; };
pub struct PipelineLayout { pub struct PipelineLayout {
@ -50,7 +50,7 @@ pub struct Binding {
pub enum BindType { pub enum BindType {
Uniform { Uniform {
dynamic: bool, dynamic: bool,
properties: Vec<UniformProperty> properties: Vec<UniformProperty>,
}, },
Buffer { Buffer {
dynamic: bool, dynamic: bool,
@ -70,9 +70,11 @@ impl BindType {
pub fn get_uniform_size(&self) -> Option<u64> { pub fn get_uniform_size(&self) -> Option<u64> {
match self { match self {
BindType::Uniform { properties, .. } => { BindType::Uniform { properties, .. } => {
Some(properties.iter().fold(0, |total, property| total + property.property_type.get_size())) Some(properties.iter().fold(0, |total, property| {
}, total + property.property_type.get_size()
_ => None }))
}
_ => None,
} }
} }
} }
@ -92,8 +94,8 @@ pub enum UniformPropertyType {
Vec3, Vec3,
Vec4, Vec4,
Mat4, Mat4,
// Struct(Vec<UniformPropertyType>), Struct(Vec<UniformPropertyType>),
// Array(Box<UniformPropertyType>, usize), Array(Box<UniformPropertyType>, usize),
} }
impl UniformPropertyType { impl UniformPropertyType {
@ -105,6 +107,11 @@ impl UniformPropertyType {
UniformPropertyType::Vec3 => 4 * 3, UniformPropertyType::Vec3 => 4 * 3,
UniformPropertyType::Vec4 => 4 * 4, UniformPropertyType::Vec4 => 4 * 4,
UniformPropertyType::Mat4 => 4 * 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,
} }
} }
} }

View file

@ -1,5 +1,13 @@
#version 450 #version 450
const int MAX_LIGHTS = 10;
struct Light {
mat4 proj;
vec4 pos;
vec4 color;
};
layout(location = 0) in vec4 v_Position; layout(location = 0) in vec4 v_Position;
layout(location = 1) in vec3 v_Normal; layout(location = 1) in vec3 v_Normal;
layout(location = 2) in vec2 v_Uv; layout(location = 2) in vec2 v_Uv;
@ -10,12 +18,29 @@ layout(set = 0, binding = 0) uniform Camera {
mat4 ViewProj; mat4 ViewProj;
}; };
layout(set = 0, binding = 1) uniform Lights {
uvec4 NumLights;
Light SceneLights[MAX_LIGHTS];
};
layout(set = 1, binding = 1) uniform StandardMaterial { layout(set = 1, binding = 1) uniform StandardMaterial {
vec4 Albedo; vec4 Albedo;
}; };
void main() { 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 // multiply the light by material color
o_Target = vec4(1.0, 0.0, 0.0, 1.0); o_Target = vec4(color, 1.0) * Albedo;
o_Target = Albedo;
} }

View file

@ -23,7 +23,6 @@ layout(set = 1, binding = 1) uniform StandardMaterial {
void main() { void main() {
v_Normal = mat3(Model) * vec3(a_Normal.xyz); v_Normal = mat3(Model) * vec3(a_Normal.xyz);
v_Position = Model * vec4(a_Pos); v_Position = Model * vec4(a_Pos);
// v_Normal = vec3(a_Normal.xyz); v_Uv = a_Uv;
// v_Position = vec4(a_Pos);
gl_Position = ViewProj * v_Position; gl_Position = ViewProj * v_Position;
} }

View file

@ -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( .add_bind_group(BindGroup::new(

View file

@ -58,6 +58,12 @@ pub struct LightResourceProvider {
pub max_lights: usize, pub max_lights: usize,
} }
#[repr(C)]
#[derive(Clone, Copy, AsBytes)]
pub struct LightCount {
pub num_lights: [u32; 4],
}
impl LightResourceProvider { impl LightResourceProvider {
pub fn new(max_lights: usize) -> Self { pub fn new(max_lights: usize) -> Self {
LightResourceProvider { LightResourceProvider {
@ -70,7 +76,7 @@ impl LightResourceProvider {
impl ResourceProvider for LightResourceProvider { impl ResourceProvider for LightResourceProvider {
fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) { fn initialize(&mut self, renderer: &mut dyn Renderer, _world: &mut World) {
let light_uniform_size = 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( renderer.create_buffer(
resource_name::uniform::LIGHTS, resource_name::uniform::LIGHTS,
@ -91,6 +97,7 @@ impl ResourceProvider for LightResourceProvider {
self.lights_are_dirty = false; self.lights_are_dirty = false;
let size = std::mem::size_of::<LightRaw>(); let size = std::mem::size_of::<LightRaw>();
let total_size = size * light_count; let total_size = size * light_count;
let light_count_size = std::mem::size_of::<LightCount>();
renderer renderer
.create_buffer_mapped("LIGHT_TMP", total_size, wgpu::BufferUsage::COPY_SRC, &mut |data| { .create_buffer_mapped("LIGHT_TMP", total_size, wgpu::BufferUsage::COPY_SRC, &mut |data| {
for ((light, local_to_world, translation), slot) in light_query 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( renderer.copy_buffer_to_buffer(
"LIGHT_TMP", "LIGHT_TMP",
0, light_count_size as u64,
resource_name::uniform::LIGHTS, resource_name::uniform::LIGHTS,
0, 0,
total_size as wgpu::BufferAddress, total_size as wgpu::BufferAddress,