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
[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
];
const NUM_INSTANCES_PER_ROW: u32 = 10;
const NUM_INSTANCES: u32 = NUM_INSTANCES_PER_ROW * NUM_INSTANCES_PER_ROW;
fn main() {
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
@ -116,11 +119,12 @@ impl CameraController {
fn process_events(&mut self, event: &WindowEvent) -> bool {
match event {
WindowEvent::KeyboardInput {
input: KeyboardInput {
state,
virtual_keycode: Some(keycode),
..
},
input:
KeyboardInput {
state,
virtual_keycode: Some(keycode),
..
},
..
} => {
let is_pressed = *state == ElementState::Pressed;
@ -129,30 +133,30 @@ impl CameraController {
VirtualKeyCode::Space => {
self.is_up_pressed = is_pressed;
true
},
}
VirtualKeyCode::LControl => {
self.is_down_pressed = is_pressed;
true
},
}
VirtualKeyCode::W | VirtualKeyCode::Up => {
self.is_forward_pressed = is_pressed;
true
},
}
VirtualKeyCode::A | VirtualKeyCode::Left => {
self.is_left_pressed = is_pressed;
true
},
}
VirtualKeyCode::S | VirtualKeyCode::Down => {
self.is_backward_pressed = is_pressed;
true
},
}
VirtualKeyCode::D | VirtualKeyCode::Right => {
self.is_right_pressed = is_pressed;
true
},
_ => false
}
_ => false,
}
},
}
_ => false,
}
}
@ -176,11 +180,13 @@ impl CameraController {
let forward_mag = glm::magnitude(&forward);
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 {
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::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 {
instance: wgpu::Instance,
surface: wgpu::Surface,
@ -217,6 +245,7 @@ struct State {
diffuse_texture: texture::Texture,
diffuse_bind_group: wgpu::BindGroup,
depth_texture: texture::Texture,
camera: Camera,
camera_controller: CameraController,
@ -229,6 +258,9 @@ struct State {
index_buffer: wgpu::Buffer,
num_indices: u32,
instances: Vec<Instance>,
instance_buffer: wgpu::Buffer,
render_pipeline: wgpu::RenderPipeline,
size: winit::dpi::PhysicalSize<u32>,
@ -320,7 +352,7 @@ impl State {
eye: glm::vec3(0.0, 1.0, 2.0),
target: glm::vec3(0.0, 0.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,
znear: 0.1,
zfar: 100.0,
@ -328,6 +360,48 @@ impl State {
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
let mut uniforms = Uniforms::new();
uniforms.update_view_proj(&camera);
@ -338,21 +412,31 @@ impl State {
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
});
let uniform_bind_group_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("uniform_bind_group_layout"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
ty: wgpu::BindingType::UniformBuffer {
dynamic: false,
min_binding_size: None,
let uniform_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("uniform_bind_group_layout"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX,
ty: wgpu::BindingType::UniformBuffer {
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 {
label: Some("uniform_bind_group"),
@ -360,8 +444,15 @@ impl State {
entries: &[
wgpu::BindGroupEntry {
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 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
let render_pipeline_layout =
device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
@ -443,7 +520,12 @@ impl State {
color_blend: wgpu::BlendDescriptor::REPLACE,
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 {
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[Vertex::desc()],
@ -465,12 +547,15 @@ impl State {
diffuse_bind_group,
camera,
camera_controller,
depth_texture,
uniforms,
uniform_buffer,
uniform_bind_group,
vertex_buffer,
index_buffer,
num_indices,
instances,
instance_buffer,
render_pipeline,
size,
}
@ -480,6 +565,9 @@ impl State {
self.size = new_size;
self.sc_desc.width = new_size.width;
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);
}
@ -491,17 +579,27 @@ impl State {
self.camera_controller.update_camera(&mut self.camera);
self.uniforms.update_view_proj(&self.camera);
let mut encoder = self.device.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("update encoder"),
});
let mut encoder = self
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("update encoder"),
});
let staging_buffer = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("staging_buffer"),
contents: bytemuck::cast_slice(&[self.uniforms]),
usage: wgpu::BufferUsage::COPY_SRC,
});
let staging_buffer = self
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
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()));
}
@ -532,7 +630,14 @@ impl State {
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);
@ -540,7 +645,7 @@ impl State {
render_pass.set_bind_group(1, &self.uniform_bind_group, &[]);
render_pass.set_vertex_buffer(0, self.vertex_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);

View file

@ -9,7 +9,11 @@ layout(set=1, binding=0) uniform Uniforms {
mat4 u_view_proj;
};
layout(set=1, binding=1) buffer Instances {
mat4 s_models[];
};
void main() {
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 {
label: Some("texture"),
label,
size,
mip_level_count: 1,
sample_count: 1,
@ -43,7 +43,7 @@ impl Texture {
});
let buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("buffer"),
label: Some("texture_buffer"),
contents: &rgba,
usage: wgpu::BufferUsage::COPY_SRC,
});
@ -74,7 +74,7 @@ impl Texture {
let view = texture.create_view(&Default::default());
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
label: Some("sampler"),
label: Some("texture_sampler"),
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
@ -96,4 +96,48 @@ impl Texture {
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,
}
}
}