Shadow example shaders and improvements

This commit is contained in:
Dzmitry Malyshau 2019-02-22 10:26:29 -05:00
parent 957a5b57dd
commit 056cc64eb4
9 changed files with 101 additions and 23 deletions

View File

@ -30,7 +30,7 @@ else
endif endif
.PHONY: all check test doc clear lib-native lib-rust examples-native examples-rust gfx-cube .PHONY: all check test doc clear lib-native lib-rust examples-native examples-rust gfx
all: examples-native examples-rust examples-gfx all: examples-native examples-rust examples-gfx
@ -65,5 +65,5 @@ examples-rust: lib-rust examples/Cargo.toml $(wildcard wgpu-native/**/*.rs)
examples-gfx: lib-rust gfx-examples/Cargo.toml $(wildcard gfx-examples/*.rs) examples-gfx: lib-rust gfx-examples/Cargo.toml $(wildcard gfx-examples/*.rs)
cargo build --manifest-path gfx-examples/Cargo.toml --features $(FEATURE_RUST) cargo build --manifest-path gfx-examples/Cargo.toml --features $(FEATURE_RUST)
gfx-cube: gfx:
cargo run --manifest-path gfx-examples/Cargo.toml --bin cube --features $(FEATURE_RUST) cargo run --manifest-path gfx-examples/Cargo.toml --bin $(name) --features $(FEATURE_RUST)

View File

@ -86,14 +86,14 @@ fn main() {
}); });
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
encoder.copy_buffer_tobuffer(&staging_buffer, 0, &storage_buffer, 0, size); encoder.copy_buffer_to_buffer(&staging_buffer, 0, &storage_buffer, 0, size);
{ {
let mut cpass = encoder.begin_compute_pass(); let mut cpass = encoder.begin_compute_pass();
cpass.set_pipeline(&compute_pipeline); cpass.set_pipeline(&compute_pipeline);
cpass.set_bind_group(0, &bind_group); cpass.set_bind_group(0, &bind_group);
cpass.dispatch(numbers.len() as u32, 1, 1); cpass.dispatch(numbers.len() as u32, 1, 1);
} }
encoder.copy_buffer_tobuffer(&storage_buffer, 0, &staging_buffer, 0, size); encoder.copy_buffer_to_buffer(&storage_buffer, 0, &staging_buffer, 0, size);
// TODO: read the results back out of the staging buffer // TODO: read the results back out of the staging buffer

View File

@ -0,0 +1,4 @@
#version 450
void main() {
}

View File

@ -0,0 +1,16 @@
#version 450
layout(location = 0) in ivec4 a_Pos;
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
};
layout(set = 1, binding = 0) uniform Entity {
mat4 u_World;
vec4 u_Color;
};
void main() {
gl_Position = u_ViewProj * u_World * vec4(a_Pos);
}

View File

@ -0,0 +1,10 @@
#version 450
layout(location = 0) out vec4 o_Target;
layout(set = 0, binding = 2) uniform texture2D u_ShadowTexture;
layout(set = 0, binding = 3) uniform sampler u_ShadowSampler;
void main() {
o_Target = vec4(1.0);
}

View File

@ -0,0 +1,25 @@
#version 450
layout(location = 0) in ivec4 a_Pos;
layout(location = 1) in ivec4 a_Normal;
struct Light {
mat4 proj;
vec4 color;
};
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
uvec4 u_NumLights;
};
layout(set = 0, binding = 1) uniform Lights {
Light u_Lights[];
};
layout(set = 1, binding = 0) uniform Entity {
mat4 u_World;
vec4 u_Color;
};
void main() {
gl_Position = u_ViewProj * u_World * vec4(a_Pos);
}

View File

@ -30,7 +30,11 @@ pub fn load_glsl(name: &str, stage: ShaderStage) -> Vec<u8> {
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("data") .join("data")
.join(name); .join(name);
let code = read_to_string(path).unwrap(); let code = match read_to_string(&path) {
Ok(code) => code,
Err(e) => panic!("Unable to read {:?}: {:?}", path, e),
};
let mut output = glsl_to_spirv::compile(&code, ty).unwrap(); let mut output = glsl_to_spirv::compile(&code, ty).unwrap();
let mut spv = Vec::new(); let mut spv = Vec::new();
output.read_to_end(&mut spv).unwrap(); output.read_to_end(&mut spv).unwrap();

View File

@ -1,3 +1,4 @@
use std::mem;
use std::ops::Range; use std::ops::Range;
use std::rc::Rc; use std::rc::Rc;
@ -82,6 +83,7 @@ fn create_plane(size: i8) -> (Vec<Vertex>, Vec<u16>) {
struct Entity { struct Entity {
mx_world: cgmath::Matrix4<f32>, mx_world: cgmath::Matrix4<f32>,
color: wgpu::Color,
vertex_buf: Rc<wgpu::Buffer>, vertex_buf: Rc<wgpu::Buffer>,
index_buf: Rc<wgpu::Buffer>, index_buf: Rc<wgpu::Buffer>,
index_count: usize, index_count: usize,
@ -99,9 +101,9 @@ struct Light {
#[repr(C)] #[repr(C)]
struct LightRaw { struct LightRaw {
proj: [[f32; 4]; 4],
pos: [f32; 4], pos: [f32; 4],
color: [f32; 4], color: [f32; 4],
proj: [[f32; 4]; 4],
} }
impl Light { impl Light {
@ -131,10 +133,15 @@ impl Light {
#[repr(C)] #[repr(C)]
struct ForwardUniforms { struct ForwardUniforms {
proj: [[f32; 4]; 4], proj: [[f32; 4]; 4],
color: [f32; 4],
num_lights: [u32; 4], num_lights: [u32; 4],
} }
#[repr(C)]
struct EntityUniforms {
model: [[f32; 4]; 4],
color: [f32; 4],
}
#[repr(C)] #[repr(C)]
struct ShadowUniforms { struct ShadowUniforms {
proj: [[f32; 4]; 4], proj: [[f32; 4]; 4],
@ -177,8 +184,6 @@ impl Example {
impl framework::Example for Example { impl framework::Example for Example {
fn init(device: &mut wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor) -> Self { fn init(device: &mut wgpu::Device, sc_desc: &wgpu::SwapChainDescriptor) -> Self {
use std::mem;
// Create the vertex and index buffers // Create the vertex and index buffers
let vertex_size = mem::size_of::<Vertex>(); let vertex_size = mem::size_of::<Vertex>();
let (cube_vertex_data, cube_index_data) = create_cube(); let (cube_vertex_data, cube_index_data) = create_cube();
@ -204,8 +209,9 @@ impl framework::Example for Example {
usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST, usage: wgpu::BufferUsageFlags::INDEX | wgpu::BufferUsageFlags::TRANSFER_DST,
}); });
plane_index_buf.set_sub_data(0, framework::cast_slice(&plane_index_data)); plane_index_buf.set_sub_data(0, framework::cast_slice(&plane_index_data));
let entity_uniform_size = mem::size_of::<EntityUniforms>() as u32;
let plane_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { let plane_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
size: 64, size: entity_uniform_size,
usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST, usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST,
}); });
@ -229,13 +235,14 @@ impl framework::Example for Example {
binding: 0, binding: 0,
resource: wgpu::BindingResource::Buffer { resource: wgpu::BindingResource::Buffer {
buffer: &plane_uniform_buf, buffer: &plane_uniform_buf,
range: 0 .. 64, range: 0 .. entity_uniform_size,
}, },
}, },
], ],
}); });
Entity { Entity {
mx_world: cgmath::Matrix4::identity(), mx_world: cgmath::Matrix4::identity(),
color: wgpu::Color::WHITE,
vertex_buf: Rc::new(plane_vertex_buf), vertex_buf: Rc::new(plane_vertex_buf),
index_buf: Rc::new(plane_index_buf), index_buf: Rc::new(plane_index_buf),
index_count: plane_index_data.len(), index_count: plane_index_data.len(),
@ -284,11 +291,12 @@ impl framework::Example for Example {
scale: cube.scale, scale: cube.scale,
}; };
let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor { let uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
size: 64, size: entity_uniform_size,
usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST, usage: wgpu::BufferUsageFlags::UNIFORM | wgpu::BufferUsageFlags::TRANSFER_DST,
}); });
entities.push(Entity { entities.push(Entity {
mx_world: cgmath::Matrix4::from(transform), mx_world: cgmath::Matrix4::from(transform),
color: wgpu::Color::GREEN,
vertex_buf: Rc::clone(&cube_vertex_buf), vertex_buf: Rc::clone(&cube_vertex_buf),
index_buf: Rc::clone(&cube_index_buf), index_buf: Rc::clone(&cube_index_buf),
index_count: cube_index_data.len(), index_count: cube_index_data.len(),
@ -299,7 +307,7 @@ impl framework::Example for Example {
binding: 0, binding: 0,
resource: wgpu::BindingResource::Buffer { resource: wgpu::BindingResource::Buffer {
buffer: &uniform_buf, buffer: &uniform_buf,
range: 0 .. 64, range: 0 .. entity_uniform_size,
}, },
}, },
], ],
@ -421,7 +429,7 @@ impl framework::Example for Example {
}); });
// Create the render pipeline // Create the render pipeline
let vs_bytes = framework::load_glsl("shadow-base.vert", framework::ShaderStage::Vertex); let vs_bytes = framework::load_glsl("shadow-bake.vert", framework::ShaderStage::Vertex);
let fs_bytes = framework::load_glsl("shadow-bake.frag", framework::ShaderStage::Fragment); let fs_bytes = framework::load_glsl("shadow-bake.frag", framework::ShaderStage::Fragment);
let vs_module = device.create_shader_module(&vs_bytes); let vs_module = device.create_shader_module(&vs_bytes);
let fs_module = device.create_shader_module(&fs_bytes); let fs_module = device.create_shader_module(&fs_bytes);
@ -507,7 +515,6 @@ impl framework::Example for Example {
let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32); let mx_total = Self::generate_matrix(sc_desc.width as f32 / sc_desc.height as f32);
let data = ForwardUniforms { let data = ForwardUniforms {
proj: *mx_total.as_ref(), proj: *mx_total.as_ref(),
color: [1.0; 4],
num_lights: [lights.len() as u32, 0, 0, 0], num_lights: [lights.len() as u32, 0, 0, 0],
}; };
uniform_buf.set_sub_data(0, framework::cast_slice(&[data])); uniform_buf.set_sub_data(0, framework::cast_slice(&[data]));
@ -606,8 +613,11 @@ impl framework::Example for Example {
fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) { fn render(&mut self, frame: &wgpu::SwapChainOutput, device: &mut wgpu::Device) {
for entity in &self.entities { for entity in &self.entities {
let raw: &[f32; 16] = entity.mx_world.as_ref(); let data = EntityUniforms {
entity.uniform_buf.set_sub_data(0, framework::cast_slice(&raw[..])); model: *entity.mx_world.as_ref(),
color: [entity.color.r, entity.color.g, entity.color.b, entity.color.a],
};
entity.uniform_buf.set_sub_data(0, framework::cast_slice(&[data]));
} }
if self.lights_are_dirty { if self.lights_are_dirty {
self.lights_are_dirty = false; self.lights_are_dirty = false;
@ -620,8 +630,17 @@ impl framework::Example for Example {
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }); let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
for (_i, light) in self.lights.iter().enumerate() { for (i, light) in self.lights.iter().enumerate() {
//TODO: update light uniforms // The light uniform buffer already has the projection,
// let's just copy it over to the shadow uniform buffer.
encoder.copy_buffer_to_buffer(
&self.light_uniform_buf,
(i * mem::size_of::<LightRaw>()) as u32,
&self.shadow_pass.uniform_buf,
0,
64,
);
let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[], color_attachments: &[],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor { depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
@ -656,8 +675,8 @@ impl framework::Example for Example {
}], }],
depth_stencil_attachment: None, depth_stencil_attachment: None,
}); });
pass.set_pipeline(&self.shadow_pass.pipeline); pass.set_pipeline(&self.forward_pass.pipeline);
pass.set_bind_group(0, &self.shadow_pass.bind_group); pass.set_bind_group(0, &self.forward_pass.bind_group);
for entity in &self.entities { for entity in &self.entities {
pass.set_bind_group(1, &entity.bind_group); pass.set_bind_group(1, &entity.bind_group);

View File

@ -535,7 +535,7 @@ impl CommandEncoder {
} }
} }
pub fn copy_buffer_tobuffer( pub fn copy_buffer_to_buffer(
&mut self, &mut self,
source: &Buffer, source: &Buffer,
source_offset: u32, source_offset: u32,