1
0
Fork 0

tutorial8-depth

This commit is contained in:
Adrian Hedqvist 2020-09-20 23:26:11 +02:00
parent 9e10a99aed
commit 9e2877b657
4 changed files with 216 additions and 63 deletions

View file

@ -1,3 +1,3 @@
# doing the wgpu-rs tutorial # doing the wgpu-rs tutorial
[current chapter](https://sotrh.github.io/learn-wgpu/beginner/tutorial7-instancing/#the-instance-buffer) [current chapter](https://sotrh.github.io/learn-wgpu/beginner/tutorial9-models/#accessing-files-in-the-res-folder)

View file

@ -25,6 +25,9 @@ const INDICES: &[u16] = &[
2, 3, 4 2, 3, 4
]; ];
const NUM_INSTANCES_PER_ROW: u32 = 10;
const NUM_INSTANCES: u32 = NUM_INSTANCES_PER_ROW * NUM_INSTANCES_PER_ROW;
fn main() { fn main() {
let event_loop = EventLoop::new(); let event_loop = EventLoop::new();
let window = WindowBuilder::new() let window = WindowBuilder::new()
@ -116,11 +119,12 @@ impl CameraController {
fn process_events(&mut self, event: &WindowEvent) -> bool { fn process_events(&mut self, event: &WindowEvent) -> bool {
match event { match event {
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
input: KeyboardInput { input:
state, KeyboardInput {
virtual_keycode: Some(keycode), state,
.. virtual_keycode: Some(keycode),
}, ..
},
.. ..
} => { } => {
let is_pressed = *state == ElementState::Pressed; let is_pressed = *state == ElementState::Pressed;
@ -129,30 +133,30 @@ impl CameraController {
VirtualKeyCode::Space => { VirtualKeyCode::Space => {
self.is_up_pressed = is_pressed; self.is_up_pressed = is_pressed;
true true
}, }
VirtualKeyCode::LControl => { VirtualKeyCode::LControl => {
self.is_down_pressed = is_pressed; self.is_down_pressed = is_pressed;
true true
}, }
VirtualKeyCode::W | VirtualKeyCode::Up => { VirtualKeyCode::W | VirtualKeyCode::Up => {
self.is_forward_pressed = is_pressed; self.is_forward_pressed = is_pressed;
true true
}, }
VirtualKeyCode::A | VirtualKeyCode::Left => { VirtualKeyCode::A | VirtualKeyCode::Left => {
self.is_left_pressed = is_pressed; self.is_left_pressed = is_pressed;
true true
}, }
VirtualKeyCode::S | VirtualKeyCode::Down => { VirtualKeyCode::S | VirtualKeyCode::Down => {
self.is_backward_pressed = is_pressed; self.is_backward_pressed = is_pressed;
true true
}, }
VirtualKeyCode::D | VirtualKeyCode::Right => { VirtualKeyCode::D | VirtualKeyCode::Right => {
self.is_right_pressed = is_pressed; self.is_right_pressed = is_pressed;
true true
}, }
_ => false _ => false,
} }
}, }
_ => false, _ => false,
} }
} }
@ -176,11 +180,13 @@ impl CameraController {
let forward_mag = glm::magnitude(&forward); let forward_mag = glm::magnitude(&forward);
if self.is_right_pressed { if self.is_right_pressed {
camera.eye = camera.target - glm::normalize(&(forward + right * self.speed)) * forward_mag; camera.eye =
camera.target - glm::normalize(&(forward + right * self.speed)) * forward_mag;
} }
if self.is_left_pressed { if self.is_left_pressed {
camera.eye = camera.target - glm::normalize(&(forward - right * self.speed)) * forward_mag; camera.eye =
camera.target - glm::normalize(&(forward - right * self.speed)) * forward_mag;
} }
} }
} }
@ -206,6 +212,28 @@ impl Uniforms {
unsafe impl bytemuck::Pod for Uniforms {} unsafe impl bytemuck::Pod for Uniforms {}
unsafe impl bytemuck::Zeroable for Uniforms {} unsafe impl bytemuck::Zeroable for Uniforms {}
struct Instance {
position: glm::Vec3,
rotation: glm::Quat,
}
impl Instance {
fn to_raw(&self) -> InstanceRaw {
InstanceRaw {
model: glm::translation(&self.position) * glm::quat_to_mat4(&self.rotation),
}
}
}
#[repr(C)]
#[derive(Copy, Clone)]
struct InstanceRaw {
model: glm::Mat4,
}
unsafe impl bytemuck::Pod for InstanceRaw {}
unsafe impl bytemuck::Zeroable for InstanceRaw {}
struct State { struct State {
instance: wgpu::Instance, instance: wgpu::Instance,
surface: wgpu::Surface, surface: wgpu::Surface,
@ -217,6 +245,7 @@ struct State {
diffuse_texture: texture::Texture, diffuse_texture: texture::Texture,
diffuse_bind_group: wgpu::BindGroup, diffuse_bind_group: wgpu::BindGroup,
depth_texture: texture::Texture,
camera: Camera, camera: Camera,
camera_controller: CameraController, camera_controller: CameraController,
@ -229,6 +258,9 @@ struct State {
index_buffer: wgpu::Buffer, index_buffer: wgpu::Buffer,
num_indices: u32, num_indices: u32,
instances: Vec<Instance>,
instance_buffer: wgpu::Buffer,
render_pipeline: wgpu::RenderPipeline, render_pipeline: wgpu::RenderPipeline,
size: winit::dpi::PhysicalSize<u32>, size: winit::dpi::PhysicalSize<u32>,
@ -320,7 +352,7 @@ impl State {
eye: glm::vec3(0.0, 1.0, 2.0), eye: glm::vec3(0.0, 1.0, 2.0),
target: glm::vec3(0.0, 0.0, 0.0), target: glm::vec3(0.0, 0.0, 0.0),
up: glm::vec3(0.0, 1.0, 0.0), up: glm::vec3(0.0, 1.0, 0.0),
aspect: (sc_desc.width / sc_desc.height) as f32, aspect: sc_desc.width as f32 / sc_desc.height as f32,
fovy: 45.0, fovy: 45.0,
znear: 0.1, znear: 0.1,
zfar: 100.0, zfar: 100.0,
@ -328,6 +360,48 @@ impl State {
let camera_controller = CameraController::new(0.2); let camera_controller = CameraController::new(0.2);
// Setup buffers
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("vertex_buffer"),
contents: bytemuck::cast_slice(&VERTICES),
usage: wgpu::BufferUsage::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("index_buffer"),
contents: bytemuck::cast_slice(&INDICES),
usage: wgpu::BufferUsage::INDEX,
});
let num_indices = INDICES.len() as u32;
let instance_displacement = glm::vec3(
NUM_INSTANCES_PER_ROW as f32 * 0.5,
0.0,
NUM_INSTANCES_PER_ROW as f32 * 0.5,
);
let instances: Vec<Instance> = (0..NUM_INSTANCES_PER_ROW)
.flat_map(|z| {
(0..NUM_INSTANCES_PER_ROW).map(move |x| {
let position = glm::vec3(x as f32, 0.0, z as f32) - instance_displacement;
let rotation = if glm::zero::<glm::Vec3>() == position {
glm::quat_angle_axis(0.0, &glm::vec3(0.0, 0.0, 1.0))
} else {
glm::quat_angle_axis(45.0, &glm::normalize(&position))
};
Instance { position, rotation }
})
})
.collect();
let instance_data: Vec<_> = instances.iter().map(Instance::to_raw).collect();
let instance_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("instance_buffer"),
contents: bytemuck::cast_slice(&instance_data),
usage: wgpu::BufferUsage::STORAGE,
});
let depth_texture =
texture::Texture::create_depth_texture(&device, &sc_desc, "depth_texture");
// Uniforms // Uniforms
let mut uniforms = Uniforms::new(); let mut uniforms = Uniforms::new();
uniforms.update_view_proj(&camera); uniforms.update_view_proj(&camera);
@ -338,21 +412,31 @@ impl State {
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
}); });
let uniform_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { let uniform_bind_group_layout =
label: Some("uniform_bind_group_layout"), device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[ label: Some("uniform_bind_group_layout"),
wgpu::BindGroupLayoutEntry { entries: &[
binding: 0, wgpu::BindGroupLayoutEntry {
visibility: wgpu::ShaderStage::VERTEX, binding: 0,
ty: wgpu::BindingType::UniformBuffer { visibility: wgpu::ShaderStage::VERTEX,
dynamic: false, ty: wgpu::BindingType::UniformBuffer {
min_binding_size: None, dynamic: false,
min_binding_size: None,
},
count: None,
}, },
count: None, wgpu::BindGroupLayoutEntry {
binding: 1,
} visibility: wgpu::ShaderStage::VERTEX,
], ty: wgpu::BindingType::StorageBuffer {
}); dynamic: false,
min_binding_size: None,
readonly: true,
},
count: None,
},
],
});
let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("uniform_bind_group"), label: Some("uniform_bind_group"),
@ -360,8 +444,15 @@ impl State {
entries: &[ entries: &[
wgpu::BindGroupEntry { wgpu::BindGroupEntry {
binding: 0, binding: 0,
resource: wgpu::BindingResource::Buffer(uniform_buffer.slice(0..std::mem::size_of_val(&uniforms) as wgpu::BufferAddress)), resource: wgpu::BindingResource::Buffer(
} uniform_buffer
.slice(0..std::mem::size_of_val(&uniforms) as wgpu::BufferAddress),
),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::Buffer(instance_buffer.slice(..)),
},
], ],
}); });
@ -395,20 +486,6 @@ impl State {
let vs_module = device.create_shader_module(vs_data); let vs_module = device.create_shader_module(vs_data);
let fs_module = device.create_shader_module(fs_data); let fs_module = device.create_shader_module(fs_data);
// Setup buffers
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("vertex_buffer"),
contents: bytemuck::cast_slice(&VERTICES),
usage: wgpu::BufferUsage::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("index_buffer"),
contents: bytemuck::cast_slice(&INDICES),
usage: wgpu::BufferUsage::INDEX,
});
let num_indices = INDICES.len() as u32;
// Setup render pipeline // Setup render pipeline
let render_pipeline_layout = let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -443,7 +520,12 @@ impl State {
color_blend: wgpu::BlendDescriptor::REPLACE, color_blend: wgpu::BlendDescriptor::REPLACE,
write_mask: wgpu::ColorWrite::ALL, write_mask: wgpu::ColorWrite::ALL,
}], }],
depth_stencil_state: None, // TODO depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
format: texture::Texture::DEPTH_FORMAT,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
stencil: wgpu::StencilStateDescriptor::default(),
}),
vertex_state: wgpu::VertexStateDescriptor { vertex_state: wgpu::VertexStateDescriptor {
index_format: wgpu::IndexFormat::Uint16, index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[Vertex::desc()], vertex_buffers: &[Vertex::desc()],
@ -465,12 +547,15 @@ impl State {
diffuse_bind_group, diffuse_bind_group,
camera, camera,
camera_controller, camera_controller,
depth_texture,
uniforms, uniforms,
uniform_buffer, uniform_buffer,
uniform_bind_group, uniform_bind_group,
vertex_buffer, vertex_buffer,
index_buffer, index_buffer,
num_indices, num_indices,
instances,
instance_buffer,
render_pipeline, render_pipeline,
size, size,
} }
@ -480,6 +565,9 @@ impl State {
self.size = new_size; self.size = new_size;
self.sc_desc.width = new_size.width; self.sc_desc.width = new_size.width;
self.sc_desc.height = new_size.height; self.sc_desc.height = new_size.height;
self.depth_texture =
texture::Texture::create_depth_texture(&self.device, &self.sc_desc, "depth_texture");
self.camera.aspect = new_size.width as f32 / new_size.height as f32;
self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc); self.swap_chain = self.device.create_swap_chain(&self.surface, &self.sc_desc);
} }
@ -491,17 +579,27 @@ impl State {
self.camera_controller.update_camera(&mut self.camera); self.camera_controller.update_camera(&mut self.camera);
self.uniforms.update_view_proj(&self.camera); self.uniforms.update_view_proj(&self.camera);
let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor { let mut encoder = self
label: Some("update encoder"), .device
}); .create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("update encoder"),
});
let staging_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let staging_buffer = self
label: Some("staging_buffer"), .device
contents: bytemuck::cast_slice(&[self.uniforms]), .create_buffer_init(&wgpu::util::BufferInitDescriptor {
usage: wgpu::BufferUsage::COPY_SRC, label: Some("staging_buffer"),
}); contents: bytemuck::cast_slice(&[self.uniforms]),
usage: wgpu::BufferUsage::COPY_SRC,
});
encoder.copy_buffer_to_buffer(&staging_buffer, 0, &self.uniform_buffer, 0, std::mem::size_of::<Uniforms>() as wgpu::BufferAddress); encoder.copy_buffer_to_buffer(
&staging_buffer,
0,
&self.uniform_buffer,
0,
std::mem::size_of::<Uniforms>() as wgpu::BufferAddress,
);
self.queue.submit(Some(encoder.finish())); self.queue.submit(Some(encoder.finish()));
} }
@ -532,7 +630,14 @@ impl State {
store: true, store: true,
}, },
}], }],
depth_stencil_attachment: None, depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
attachment: &self.depth_texture.view,
depth_ops: Some(wgpu::Operations {
load: wgpu::LoadOp::Clear(1.0),
store: true,
}),
stencil_ops: None,
}),
}); });
render_pass.set_pipeline(&self.render_pipeline); render_pass.set_pipeline(&self.render_pipeline);
@ -540,7 +645,7 @@ impl State {
render_pass.set_bind_group(1, &self.uniform_bind_group, &[]); render_pass.set_bind_group(1, &self.uniform_bind_group, &[]);
render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(0..)); render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(0..));
render_pass.set_index_buffer(self.index_buffer.slice(0..)); render_pass.set_index_buffer(self.index_buffer.slice(0..));
render_pass.draw_indexed(0..self.num_indices, 0, 0..1); render_pass.draw_indexed(0..self.num_indices, 0, 0..self.instances.len() as _);
drop(render_pass); drop(render_pass);

View file

@ -9,7 +9,11 @@ layout(set=1, binding=0) uniform Uniforms {
mat4 u_view_proj; mat4 u_view_proj;
}; };
layout(set=1, binding=1) buffer Instances {
mat4 s_models[];
};
void main() { void main() {
v_tex_coords = a_tex_coords; v_tex_coords = a_tex_coords;
gl_Position = u_view_proj * vec4(a_position, 1.0); gl_Position = u_view_proj * s_models[gl_InstanceIndex] * vec4(a_position, 1.0);
} }

View file

@ -33,7 +33,7 @@ impl Texture {
}; };
let texture = device.create_texture(&wgpu::TextureDescriptor { let texture = device.create_texture(&wgpu::TextureDescriptor {
label: Some("texture"), label,
size, size,
mip_level_count: 1, mip_level_count: 1,
sample_count: 1, sample_count: 1,
@ -43,7 +43,7 @@ impl Texture {
}); });
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("buffer"), label: Some("texture_buffer"),
contents: &rgba, contents: &rgba,
usage: wgpu::BufferUsage::COPY_SRC, usage: wgpu::BufferUsage::COPY_SRC,
}); });
@ -74,7 +74,7 @@ impl Texture {
let view = texture.create_view(&Default::default()); let view = texture.create_view(&Default::default());
let sampler = device.create_sampler(&wgpu::SamplerDescriptor { let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("sampler"), label: Some("texture_sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge, address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge, address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge, address_mode_w: wgpu::AddressMode::ClampToEdge,
@ -96,4 +96,48 @@ impl Texture {
command, command,
)) ))
} }
pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
pub fn create_depth_texture(
device: &wgpu::Device,
sc_desc: &wgpu::SwapChainDescriptor,
label: &str,
) -> Self {
let size = wgpu::Extent3d {
width: sc_desc.width,
height: sc_desc.height,
depth: 1,
};
let desc = wgpu::TextureDescriptor {
label: Some(label),
size,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: Self::DEPTH_FORMAT,
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
};
let texture = device.create_texture(&desc);
let view = texture.create_view(&wgpu::TextureViewDescriptor::default());
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
lod_min_clamp: -100.0,
lod_max_clamp: 100.0,
compare: Some(wgpu::CompareFunction::LessEqual),
..Default::default()
});
Self {
texture,
view,
sampler,
}
}
} }