summaryrefslogtreecommitdiff
path: root/src/gfx
diff options
context:
space:
mode:
authorLizzy Fleckenstein <eliasfleckenstein@web.de>2023-05-16 15:20:39 +0200
committerLizzy Fleckenstein <eliasfleckenstein@web.de>2023-05-16 15:20:39 +0200
commitef8c75b9dc47142527fc1741d75cf34c66c3ac9d (patch)
tree836e541b516717f9c00d06e659d4cc7b238193b2 /src/gfx
parent0fc89aa3ec523d3d06546220bae5393232274e13 (diff)
downloadmt_client-ef8c75b9dc47142527fc1741d75cf34c66c3ac9d.tar.xz
Split state.rs and add debug menu
Diffstat (limited to 'src/gfx')
-rw-r--r--src/gfx/camera.rs67
-rw-r--r--src/gfx/debug_menu.rs57
-rw-r--r--src/gfx/font.rs44
-rw-r--r--src/gfx/gpu.rs168
-rw-r--r--src/gfx/map.rs89
-rw-r--r--src/gfx/map/mesh.rs2
-rw-r--r--src/gfx/state.rs243
7 files changed, 383 insertions, 287 deletions
diff --git a/src/gfx/camera.rs b/src/gfx/camera.rs
new file mode 100644
index 0000000..874c9fc
--- /dev/null
+++ b/src/gfx/camera.rs
@@ -0,0 +1,67 @@
+use super::{gpu::Gpu, util::MatrixUniform};
+use cgmath::{prelude::*, Deg, Matrix4, Rad};
+use collision::Frustum;
+use fps_camera::{FirstPerson, FirstPersonSettings};
+use std::time::Duration;
+
+pub struct Camera {
+ pub fov: Rad<f32>,
+ pub view: Matrix4<f32>,
+ pub proj: Matrix4<f32>,
+ pub frustum: Frustum<f32>,
+ pub first_person: FirstPerson,
+ pub uniform: MatrixUniform,
+ pub layout: wgpu::BindGroupLayout,
+}
+
+impl Camera {
+ pub fn new(gpu: &Gpu) -> Self {
+ let first_person = FirstPerson::new(
+ [0.0, 0.0, 0.0],
+ FirstPersonSettings {
+ speed_horizontal: 10.0,
+ speed_vertical: 10.0,
+ mouse_sensitivity_horizontal: 1.0,
+ mouse_sensitivity_vertical: 1.0,
+ },
+ );
+
+ let layout = MatrixUniform::layout(&gpu.device, "camera");
+ let uniform = MatrixUniform::new(&gpu.device, &layout, Matrix4::identity(), "camera", true);
+
+ Self {
+ fov: Deg(90.0).into(),
+ proj: Matrix4::identity(),
+ view: Matrix4::identity(),
+ frustum: Frustum::from_matrix4(Matrix4::identity()).unwrap(),
+ first_person,
+ uniform,
+ layout,
+ }
+ }
+
+ pub fn update(&mut self, gpu: &Gpu, dt: Duration) {
+ self.first_person.yaw += Rad::from(Deg(180.0)).0;
+ self.first_person.yaw *= -1.0;
+
+ let cam = self.first_person.camera(dt.as_secs_f32());
+
+ self.first_person.yaw *= -1.0;
+ self.first_person.yaw -= Rad::from(Deg(180.0)).0;
+
+ self.first_person.position = cam.position;
+
+ self.view = Matrix4::from(cam.orthogonal());
+ self.uniform.set(&gpu.queue, self.proj * self.view);
+ }
+
+ pub fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
+ self.proj = cgmath::perspective(
+ self.fov,
+ size.width as f32 / size.height as f32,
+ 0.1,
+ 100000.0,
+ );
+ self.frustum = Frustum::from_matrix4(self.proj).unwrap();
+ }
+}
diff --git a/src/gfx/debug_menu.rs b/src/gfx/debug_menu.rs
new file mode 100644
index 0000000..daca08d
--- /dev/null
+++ b/src/gfx/debug_menu.rs
@@ -0,0 +1,57 @@
+use super::{camera::Camera, font::Font};
+use cgmath::{Deg, Rad};
+use wgpu_glyph::{Section, Text};
+
+pub struct DebugMenu {
+ pub enabled: bool,
+ pub fps: usize,
+}
+
+impl DebugMenu {
+ pub fn new() -> Self {
+ Self {
+ enabled: false,
+ fps: 0,
+ }
+ }
+
+ pub fn render(&self, bounds: (f32, f32), camera: &Camera, font: &mut Font) {
+ if !self.enabled {
+ return;
+ }
+
+ let mut offset = 0.0;
+
+ let mut add_text = |txt: &str| {
+ offset += 2.0;
+
+ font.add(Section {
+ screen_position: (2.0, offset),
+ bounds,
+ text: vec![Text::new(txt)
+ .with_color([1.0, 1.0, 1.0, 1.0])
+ .with_scale(20.0)],
+ ..Section::default()
+ });
+
+ offset += 20.0;
+ };
+
+ let angle = |x| Deg::from(Rad(x)).0;
+
+ let pos = camera.first_person.position;
+
+ add_text(&format!(
+ "{} {}",
+ env!("CARGO_PKG_NAME"),
+ env!("CARGO_PKG_VERSION")
+ ));
+ add_text(&format!("{} FPS", self.fps));
+ add_text(&format!("({:.1}, {:.1}, {:.1})", pos[0], pos[1], pos[2]));
+ add_text(&format!(
+ "yaw: {:.1}°",
+ (angle(camera.first_person.yaw) + 360.0) % 360.0
+ ));
+ add_text(&format!("pitch: {:.1}°", angle(camera.first_person.pitch)));
+ }
+}
diff --git a/src/gfx/font.rs b/src/gfx/font.rs
new file mode 100644
index 0000000..6875a3b
--- /dev/null
+++ b/src/gfx/font.rs
@@ -0,0 +1,44 @@
+use super::gpu::{Frame, Gpu};
+
+pub struct Font {
+ glyph_brush: wgpu_glyph::GlyphBrush<()>,
+ staging_belt: wgpu::util::StagingBelt,
+}
+
+impl Font {
+ pub fn new(gpu: &Gpu) -> Self {
+ Self {
+ glyph_brush: wgpu_glyph::GlyphBrushBuilder::using_font(
+ wgpu_glyph::ab_glyph::FontArc::try_from_slice(include_bytes!(
+ "../../assets/font/regular.otf"
+ ))
+ .unwrap(),
+ )
+ .build(&gpu.device, gpu.config.format),
+ staging_belt: wgpu::util::StagingBelt::new(1024),
+ }
+ }
+
+ pub fn add(&mut self, section: wgpu_glyph::Section) {
+ self.glyph_brush.queue(section);
+ }
+
+ pub fn submit(&mut self, frame: &mut Frame) {
+ self.glyph_brush
+ .draw_queued(
+ &frame.gpu.device,
+ &mut self.staging_belt,
+ &mut frame.encoder,
+ &frame.view,
+ frame.gpu.config.width,
+ frame.gpu.config.height,
+ )
+ .unwrap();
+
+ self.staging_belt.finish();
+ }
+
+ pub fn cleanup(&mut self) {
+ self.staging_belt.recall();
+ }
+}
diff --git a/src/gfx/gpu.rs b/src/gfx/gpu.rs
new file mode 100644
index 0000000..f187fee
--- /dev/null
+++ b/src/gfx/gpu.rs
@@ -0,0 +1,168 @@
+pub struct Frame<'a> {
+ pub gpu: &'a mut Gpu,
+ pub encoder: wgpu::CommandEncoder,
+ pub output: wgpu::SurfaceTexture,
+ pub view: wgpu::TextureView,
+}
+
+impl<'a> Frame<'a> {
+ pub fn new(gpu: &'a mut Gpu) -> Result<Self, wgpu::SurfaceError> {
+ let output = gpu.surface.get_current_texture()?;
+ let view = output
+ .texture
+ .create_view(&wgpu::TextureViewDescriptor::default());
+
+ let encoder = gpu
+ .device
+ .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
+
+ Ok(Self {
+ gpu,
+ encoder,
+ output,
+ view,
+ })
+ }
+
+ pub fn pass(&mut self) -> wgpu::RenderPass {
+ self.encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
+ label: None,
+ color_attachments: &[Some(wgpu::RenderPassColorAttachment {
+ view: &self.view,
+ resolve_target: None,
+ ops: wgpu::Operations {
+ load: wgpu::LoadOp::Clear(wgpu::Color {
+ r: 0x87 as f64 / 255.0,
+ g: 0xCE as f64 / 255.0,
+ b: 0xEB as f64 / 255.0,
+ a: 1.0,
+ }),
+ store: true,
+ },
+ })],
+ depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
+ view: &self.gpu.depth_texture,
+ depth_ops: Some(wgpu::Operations {
+ load: wgpu::LoadOp::Clear(1.0),
+ store: true,
+ }),
+ stencil_ops: None,
+ }),
+ })
+ }
+
+ pub fn finish(self) {
+ self.gpu.queue.submit(Some(self.encoder.finish()));
+ self.output.present();
+ }
+}
+
+pub struct Gpu {
+ pub surface: wgpu::Surface,
+ pub device: wgpu::Device,
+ pub queue: wgpu::Queue,
+ pub config: wgpu::SurfaceConfiguration,
+ pub depth_texture: wgpu::TextureView,
+}
+
+impl Gpu {
+ pub async fn new(window: &winit::window::Window) -> Self {
+ let size = window.inner_size();
+
+ let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
+ backends: wgpu::Backends::all(),
+ dx12_shader_compiler: Default::default(),
+ });
+
+ let surface = unsafe { instance.create_surface(window) }.unwrap();
+
+ let adapter = instance
+ .request_adapter(&wgpu::RequestAdapterOptions {
+ power_preference: wgpu::PowerPreference::default(),
+ compatible_surface: Some(&surface),
+ force_fallback_adapter: false,
+ })
+ .await
+ .unwrap();
+
+ let (device, queue) = adapter
+ .request_device(
+ &wgpu::DeviceDescriptor {
+ features: wgpu::Features::empty(),
+ limits: Default::default(),
+ label: None,
+ },
+ None,
+ )
+ .await
+ .unwrap();
+
+ let surface_caps = surface.get_capabilities(&adapter);
+ let surface_format = surface_caps
+ .formats
+ .iter()
+ .copied()
+ .find(|f| f.describe().srgb)
+ .unwrap_or(surface_caps.formats[0]);
+
+ let config = wgpu::SurfaceConfiguration {
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
+ format: surface_format,
+ width: size.width,
+ height: size.height,
+ present_mode: surface_caps.present_modes[0],
+ alpha_mode: surface_caps.alpha_modes[0],
+ view_formats: vec![],
+ };
+
+ let depth_texture = Self::create_depth_texture(&config, &device);
+
+ let mut state = Self {
+ surface,
+ device,
+ queue,
+ config,
+ depth_texture,
+ };
+
+ state.resize(size);
+
+ state
+ }
+
+ pub fn create_depth_texture(
+ config: &wgpu::SurfaceConfiguration,
+ device: &wgpu::Device,
+ ) -> wgpu::TextureView {
+ device
+ .create_texture(&wgpu::TextureDescriptor {
+ label: Some("depth texture"),
+ size: wgpu::Extent3d {
+ width: config.width,
+ height: config.height,
+ depth_or_array_layers: 1,
+ },
+ mip_level_count: 1,
+ sample_count: 1,
+ dimension: wgpu::TextureDimension::D2,
+ format: wgpu::TextureFormat::Depth32Float,
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT
+ | wgpu::TextureUsages::TEXTURE_BINDING,
+ view_formats: &[],
+ })
+ .create_view(&wgpu::TextureViewDescriptor::default())
+ }
+
+ pub fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
+ if size.width > 0 && size.height > 0 {
+ self.config.width = size.width;
+ self.config.height = size.height;
+ self.configure_surface();
+ self.depth_texture = Self::create_depth_texture(&self.config, &self.device);
+ }
+ }
+
+ pub fn configure_surface(&mut self) {
+ self.surface.configure(&self.device, &self.config);
+ }
+}
diff --git a/src/gfx/map.rs b/src/gfx/map.rs
index 7bd5dd3..04865a6 100644
--- a/src/gfx/map.rs
+++ b/src/gfx/map.rs
@@ -1,7 +1,9 @@
mod atlas;
mod mesh;
-use super::{media::MediaMgr, state::State, util::MatrixUniform};
+use super::{
+ camera::Camera, debug_menu::DebugMenu, gpu::Gpu, media::MediaMgr, util::MatrixUniform,
+};
use atlas::create_atlas;
use cgmath::{prelude::*, Matrix4, Point3, Vector3};
use collision::{prelude::*, Aabb3, Relation};
@@ -101,13 +103,13 @@ struct BlockMesh {
}
impl BlockMesh {
- fn new(state: &State, vertices: &[Vertex]) -> Option<Self> {
+ fn new(gpu: &Gpu, vertices: &[Vertex]) -> Option<Self> {
if vertices.is_empty() {
return None;
}
Some(BlockMesh {
- vertex_buffer: state
+ vertex_buffer: gpu
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("mapblock.vertex_buffer"),
@@ -136,10 +138,15 @@ fn block_float_pos(pos: Point3<i16>) -> Point3<f32> {
}
impl MapRender {
- pub fn render<'a>(&'a self, state: &'a State, pass: &mut wgpu::RenderPass<'a>) {
+ pub fn render<'a>(
+ &'a self,
+ camera: &'a Camera,
+ debug_menu: &mut DebugMenu,
+ pass: &mut wgpu::RenderPass<'a>,
+ ) {
pass.set_pipeline(&self.pipeline);
pass.set_bind_group(0, &self.atlas, &[]);
- pass.set_bind_group(1, &state.camera_uniform.bind_group, &[]);
+ pass.set_bind_group(1, &camera.uniform.bind_group, &[]);
struct BlendEntry<'a> {
dist: f32,
@@ -157,9 +164,9 @@ impl MapRender {
let fpos = block_float_pos(pos);
let one = Vector3::new(1.0, 1.0, 1.0);
- let aabb = Aabb3::new(fpos - one * 0.5, fpos + one * 15.5).transform(&state.view);
+ let aabb = Aabb3::new(fpos - one * 0.5, fpos + one * 15.5).transform(&camera.view);
- if state.frustum.contains(&aabb) == Relation::Out {
+ if camera.frustum.contains(&aabb) == Relation::Out {
continue;
}
@@ -170,7 +177,7 @@ impl MapRender {
if let Some(mesh) = &model.mesh_blend {
blend.push(BlendEntry {
index,
- dist: (state.view * (fpos + one * 8.5).to_homogeneous())
+ dist: (camera.view * (fpos + one * 8.5).to_homogeneous())
.truncate()
.magnitude(),
mesh,
@@ -191,7 +198,7 @@ impl MapRender {
}
}
- pub fn update(&mut self, state: &mut State) {
+ pub fn update(&mut self, gpu: &Gpu) {
for (pos, _) in self
.blocks_defer
.drain_filter(|_, v| v.time.elapsed().as_millis() > 100)
@@ -208,10 +215,10 @@ impl MapRender {
self.block_models.insert(
pos,
BlockModel {
- mesh: BlockMesh::new(state, &data.vertices),
- mesh_blend: BlockMesh::new(state, &data.vertices_blend),
+ mesh: BlockMesh::new(gpu, &data.vertices),
+ mesh_blend: BlockMesh::new(gpu, &data.vertices_blend),
transform: MatrixUniform::new(
- &state.device,
+ &gpu.device,
&self.model,
Matrix4::from_translation(block_float_pos(pos).to_vec()),
"mapblock",
@@ -277,7 +284,12 @@ impl MapRender {
}
}
- pub fn new(state: &mut State, media: &MediaMgr, mut nodes: HashMap<u16, NodeDef>) -> Self {
+ pub fn new(
+ gpu: &mut Gpu,
+ camera: &Camera,
+ media: &MediaMgr,
+ mut nodes: HashMap<u16, NodeDef>,
+ ) -> Self {
let (atlas_img, atlas_slices) = create_atlas(&mut nodes, media);
let atlas_size = wgpu::Extent3d {
@@ -286,7 +298,7 @@ impl MapRender {
depth_or_array_layers: 1,
};
- let atlas_texture = state.device.create_texture(&wgpu::TextureDescriptor {
+ let atlas_texture = gpu.device.create_texture(&wgpu::TextureDescriptor {
size: atlas_size,
mip_level_count: 1,
sample_count: 1,
@@ -297,7 +309,7 @@ impl MapRender {
view_formats: &[],
});
- state.queue.write_texture(
+ gpu.queue.write_texture(
wgpu::ImageCopyTexture {
texture: &atlas_texture,
mip_level: 0,
@@ -315,7 +327,7 @@ impl MapRender {
let atlas_view = atlas_texture.create_view(&wgpu::TextureViewDescriptor::default());
- let atlas_sampler = state.device.create_sampler(&wgpu::SamplerDescriptor {
+ let atlas_sampler = gpu.device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
@@ -328,8 +340,7 @@ impl MapRender {
});
let atlas_bind_group_layout =
- state
- .device
+ gpu.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[
wgpu::BindGroupLayoutEntry {
@@ -352,7 +363,7 @@ impl MapRender {
label: Some("atlas.bind_group_layout"),
});
- let atlas_bind_group = state.device.create_bind_group(&wgpu::BindGroupDescriptor {
+ let atlas_bind_group = gpu.device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &atlas_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
@@ -367,26 +378,25 @@ impl MapRender {
label: Some("atlas.bind_group"),
});
- let model_bind_group_layout = MatrixUniform::layout(&state.device, "mapblock");
+ let model_bind_group_layout = MatrixUniform::layout(&gpu.device, "mapblock");
- let shader = state
+ let shader = gpu
.device
.create_shader_module(wgpu::include_wgsl!("../../assets/shaders/map.wgsl"));
- let pipeline_layout =
- state
- .device
- .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
- label: None,
- bind_group_layouts: &[
- &atlas_bind_group_layout,
- &model_bind_group_layout,
- &state.camera_bind_group_layout,
- ],
- push_constant_ranges: &[],
- });
+ let pipeline_layout = gpu
+ .device
+ .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+ label: None,
+ bind_group_layouts: &[
+ &atlas_bind_group_layout,
+ &model_bind_group_layout,
+ &camera.layout,
+ ],
+ push_constant_ranges: &[],
+ });
- let pipeline = state
+ let pipeline = gpu
.device
.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
@@ -400,15 +410,8 @@ impl MapRender {
module: &shader,
entry_point: "fs_main",
targets: &[Some(wgpu::ColorTargetState {
- format: state.config.format,
- blend: Some(wgpu::BlendState {
- color: wgpu::BlendComponent {
- src_factor: wgpu::BlendFactor::SrcAlpha,
- dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
- operation: wgpu::BlendOperation::Add,
- },
- alpha: wgpu::BlendComponent::OVER,
- }),
+ format: gpu.config.format,
+ blend: Some(wgpu::BlendState::ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
})],
}),
diff --git a/src/gfx/map/mesh.rs b/src/gfx/map/mesh.rs
index 139b6c7..3d56ad8 100644
--- a/src/gfx/map/mesh.rs
+++ b/src/gfx/map/mesh.rs
@@ -93,7 +93,7 @@ pub(super) fn create_mesh(
if let Some(ndef) = &mkinfo.nodes[ncontent as usize] {
if match draw_type {
DrawType::Cube => ndef.draw_type == DrawType::Cube,
- DrawType::Liquid => ncontent == content,
+ DrawType::Liquid => ndef.draw_type == DrawType::Cube || ncontent == content,
_ => false,
} {
continue;
diff --git a/src/gfx/state.rs b/src/gfx/state.rs
deleted file mode 100644
index b307d85..0000000
--- a/src/gfx/state.rs
+++ /dev/null
@@ -1,243 +0,0 @@
-use super::util::MatrixUniform;
-use cgmath::{prelude::*, Deg, Matrix4, Rad};
-use collision::Frustum;
-use fps_camera::{FirstPerson, FirstPersonSettings};
-use std::time::Duration;
-
-pub struct State {
- pub surface: wgpu::Surface,
- pub device: wgpu::Device,
- pub queue: wgpu::Queue,
- pub config: wgpu::SurfaceConfiguration,
- pub fov: Rad<f32>,
- pub view: Matrix4<f32>,
- pub proj: Matrix4<f32>,
- pub frustum: Frustum<f32>,
- pub camera: FirstPerson,
- pub camera_uniform: MatrixUniform,
- pub camera_bind_group_layout: wgpu::BindGroupLayout,
- pub depth_texture: wgpu::Texture,
- pub depth_view: wgpu::TextureView,
- pub depth_sampler: wgpu::Sampler,
-}
-
-impl State {
- pub async fn new(window: &winit::window::Window) -> Self {
- let size = window.inner_size();
-
- let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
- backends: wgpu::Backends::all(),
- dx12_shader_compiler: Default::default(),
- });
-
- let surface = unsafe { instance.create_surface(window) }.unwrap();
-
- let adapter = instance
- .request_adapter(&wgpu::RequestAdapterOptions {
- power_preference: wgpu::PowerPreference::default(),
- compatible_surface: Some(&surface),
- force_fallback_adapter: false,
- })
- .await
- .unwrap();
-
- let (device, queue) = adapter
- .request_device(
- &wgpu::DeviceDescriptor {
- features: wgpu::Features::empty(),
- limits: Default::default(),
- label: None,
- },
- None,
- )
- .await
- .unwrap();
-
- let surface_caps = surface.get_capabilities(&adapter);
- let surface_format = surface_caps
- .formats
- .iter()
- .copied()
- .find(|f| f.describe().srgb)
- .unwrap_or(surface_caps.formats[0]);
-
- let config = wgpu::SurfaceConfiguration {
- usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
- format: surface_format,
- width: size.width,
- height: size.height,
- present_mode: surface_caps.present_modes[0],
- alpha_mode: surface_caps.alpha_modes[0],
- view_formats: vec![],
- };
-
- let (depth_texture, depth_view, depth_sampler) =
- Self::create_depth_texture(&config, &device);
-
- let camera = FirstPerson::new(
- [0.0, 0.0, 0.0],
- FirstPersonSettings {
- speed_horizontal: 10.0,
- speed_vertical: 10.0,
- mouse_sensitivity_horizontal: 1.0,
- mouse_sensitivity_vertical: 1.0,
- },
- );
-
- let camera_bind_group_layout = MatrixUniform::layout(&device, "camera");
-
- let camera_uniform = MatrixUniform::new(
- &device,
- &camera_bind_group_layout,
- Matrix4::identity(),
- "camera",
- true,
- );
-
- let mut state = Self {
- surface,
- device,
- queue,
- config,
- fov: Deg(90.0).into(),
- proj: Matrix4::identity(),
- view: Matrix4::identity(),
- frustum: Frustum::from_matrix4(Matrix4::identity()).unwrap(),
- camera,
- camera_uniform,
- camera_bind_group_layout,
- depth_texture,
- depth_view,
- depth_sampler,
- };
-
- state.resize(size);
-
- state
- }
-
- pub fn create_depth_texture(
- config: &wgpu::SurfaceConfiguration,
- device: &wgpu::Device,
- ) -> (wgpu::Texture, wgpu::TextureView, wgpu::Sampler) {
- let depth_size = wgpu::Extent3d {
- width: config.width,
- height: config.height,
- depth_or_array_layers: 1,
- };
- let depth_descriptor = wgpu::TextureDescriptor {
- label: Some("depth texture"),
- size: depth_size,
- mip_level_count: 1,
- sample_count: 1,
- dimension: wgpu::TextureDimension::D2,
- format: wgpu::TextureFormat::Depth32Float,
- usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
- view_formats: &[],
- };
- let depth_texture = device.create_texture(&depth_descriptor);
-
- let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
- let depth_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,
- compare: Some(wgpu::CompareFunction::LessEqual),
- lod_min_clamp: 0.0,
- lod_max_clamp: 100.0,
- ..Default::default()
- });
-
- (depth_texture, depth_view, depth_sampler)
- }
-
- pub fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
- if size.width > 0 && size.height > 0 {
- self.config.width = size.width;
- self.config.height = size.height;
- self.configure_surface();
- self.update_projection();
- (self.depth_texture, self.depth_view, self.depth_sampler) =
- Self::create_depth_texture(&self.config, &self.device);
- }
- }
-
- pub fn configure_surface(&mut self) {
- self.surface.configure(&self.device, &self.config);
- }
-
- pub fn update_projection(&mut self) {
- self.proj = cgmath::perspective(
- self.fov,
- self.config.width as f32 / self.config.height as f32,
- 0.1,
- 100000.0,
- );
- self.frustum = Frustum::from_matrix4(self.proj).unwrap();
- }
-
- pub fn update(&mut self, dt: Duration) {
- self.camera.yaw += Rad::from(Deg(180.0)).0;
- self.camera.yaw *= -1.0;
-
- let cam = self.camera.camera(dt.as_secs_f32());
-
- self.camera.yaw *= -1.0;
- self.camera.yaw -= Rad::from(Deg(180.0)).0;
-
- self.camera.position = cam.position;
-
- self.view = Matrix4::from(cam.orthogonal());
- self.camera_uniform.set(&self.queue, self.proj * self.view);
- }
-
- pub fn render(&self, map: &Option<super::map::MapRender>) -> Result<(), wgpu::SurfaceError> {
- let output = self.surface.get_current_texture()?;
- let view = output
- .texture
- .create_view(&wgpu::TextureViewDescriptor::default());
-
- let mut encoder = self
- .device
- .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
-
- {
- let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
- label: None,
- color_attachments: &[Some(wgpu::RenderPassColorAttachment {
- view: &view,
- resolve_target: None,
- ops: wgpu::Operations {
- load: wgpu::LoadOp::Clear(wgpu::Color {
- r: 0x87 as f64 / 255.0,
- g: 0xCE as f64 / 255.0,
- b: 0xEB as f64 / 255.0,
- a: 1.0,
- }),
- store: true,
- },
- })],
- depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
- view: &self.depth_view,
- depth_ops: Some(wgpu::Operations {
- load: wgpu::LoadOp::Clear(1.0),
- store: true,
- }),
- stencil_ops: None,
- }),
- });
-
- if let Some(map) = map.as_ref() {
- map.render(self, &mut render_pass);
- }
- }
-
- self.queue.submit(std::iter::once(encoder.finish()));
- output.present();
-
- Ok(())
- }
-}