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),
})
// 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 {

View file

@ -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,
}
}
}

View file

@ -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;
}

View file

@ -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;
}

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(

View file

@ -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,