1 use super::util::MatrixUniform;
2 use cgmath::{prelude::*, Deg, Matrix4, Rad};
3 use fps_camera::{FirstPerson, FirstPersonSettings};
4 use std::time::Duration;
7 pub surface: wgpu::Surface,
8 pub device: wgpu::Device,
9 pub queue: wgpu::Queue,
10 pub config: wgpu::SurfaceConfiguration,
12 pub view: Matrix4<f32>,
13 pub proj: Matrix4<f32>,
14 pub camera: FirstPerson,
15 pub camera_uniform: MatrixUniform,
16 pub camera_bind_group_layout: wgpu::BindGroupLayout,
17 pub depth_texture: wgpu::Texture,
18 pub depth_view: wgpu::TextureView,
19 pub depth_sampler: wgpu::Sampler,
23 pub async fn new(window: &winit::window::Window) -> Self {
24 let size = window.inner_size();
26 let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
27 backends: wgpu::Backends::all(),
28 dx12_shader_compiler: Default::default(),
31 let surface = unsafe { instance.create_surface(window) }.unwrap();
33 let adapter = instance
34 .request_adapter(&wgpu::RequestAdapterOptions {
35 power_preference: wgpu::PowerPreference::default(),
36 compatible_surface: Some(&surface),
37 force_fallback_adapter: false,
42 let (device, queue) = adapter
44 &wgpu::DeviceDescriptor {
45 features: wgpu::Features::empty(),
46 limits: Default::default(),
54 let surface_caps = surface.get_capabilities(&adapter);
55 let surface_format = surface_caps
59 .find(|f| f.describe().srgb)
60 .unwrap_or(surface_caps.formats[0]);
62 let config = wgpu::SurfaceConfiguration {
63 usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
64 format: surface_format,
67 present_mode: surface_caps.present_modes[0],
68 alpha_mode: surface_caps.alpha_modes[0],
72 let (depth_texture, depth_view, depth_sampler) =
73 Self::create_depth_texture(&config, &device);
75 let camera = FirstPerson::new(
78 speed_horizontal: 10.0,
80 mouse_sensitivity_horizontal: 1.0,
81 mouse_sensitivity_vertical: 1.0,
85 let camera_bind_group_layout = MatrixUniform::layout(&device, "camera");
87 let camera_uniform = MatrixUniform::new(
89 &camera_bind_group_layout,
95 let mut state = Self {
100 fov: Deg(90.0).into(),
101 proj: Matrix4::identity(),
102 view: Matrix4::identity(),
105 camera_bind_group_layout,
116 pub fn create_depth_texture(
117 config: &wgpu::SurfaceConfiguration,
118 device: &wgpu::Device,
119 ) -> (wgpu::Texture, wgpu::TextureView, wgpu::Sampler) {
120 let depth_size = wgpu::Extent3d {
122 height: config.height,
123 depth_or_array_layers: 1,
125 let depth_descriptor = wgpu::TextureDescriptor {
126 label: Some("depth texture"),
130 dimension: wgpu::TextureDimension::D2,
131 format: wgpu::TextureFormat::Depth32Float,
132 usage: wgpu::TextureUsages::RENDER_ATTACHMENT // 3.
133 | wgpu::TextureUsages::TEXTURE_BINDING,
136 let depth_texture = device.create_texture(&depth_descriptor);
138 let depth_view = depth_texture.create_view(&wgpu::TextureViewDescriptor::default());
139 let depth_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
140 address_mode_u: wgpu::AddressMode::ClampToEdge,
141 address_mode_v: wgpu::AddressMode::ClampToEdge,
142 address_mode_w: wgpu::AddressMode::ClampToEdge,
143 mag_filter: wgpu::FilterMode::Linear,
144 min_filter: wgpu::FilterMode::Linear,
145 mipmap_filter: wgpu::FilterMode::Nearest,
146 compare: Some(wgpu::CompareFunction::LessEqual),
148 lod_max_clamp: 100.0,
152 (depth_texture, depth_view, depth_sampler)
155 pub fn resize(&mut self, size: winit::dpi::PhysicalSize<u32>) {
156 if size.width > 0 && size.height > 0 {
157 self.config.width = size.width;
158 self.config.height = size.height;
159 self.configure_surface();
160 self.update_projection();
161 (self.depth_texture, self.depth_view, self.depth_sampler) =
162 Self::create_depth_texture(&self.config, &self.device);
166 pub fn configure_surface(&mut self) {
167 self.surface.configure(&self.device, &self.config);
170 pub fn update_projection(&mut self) {
171 self.proj = cgmath::perspective(
173 self.config.width as f32 / self.config.height as f32,
179 pub fn update(&mut self, dt: Duration) {
180 self.camera.yaw += Rad::from(Deg(180.0)).0;
181 self.camera.yaw *= -1.0;
183 let cam = self.camera.camera(dt.as_secs_f32());
185 self.camera.yaw *= -1.0;
186 self.camera.yaw -= Rad::from(Deg(180.0)).0;
188 self.camera.position = cam.position;
190 self.view = Matrix4::from(cam.orthogonal());
191 self.camera_uniform.set(&self.queue, self.proj * self.view);
194 pub fn render(&self, map: &Option<super::map::MapRender>) -> Result<(), wgpu::SurfaceError> {
195 let output = self.surface.get_current_texture()?;
198 .create_view(&wgpu::TextureViewDescriptor::default());
200 let mut encoder = self
202 .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
205 let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
207 color_attachments: &[Some(wgpu::RenderPassColorAttachment {
209 resolve_target: None,
210 ops: wgpu::Operations {
211 load: wgpu::LoadOp::Clear(wgpu::Color {
212 r: 0x87 as f64 / 255.0,
213 g: 0xCE as f64 / 255.0,
214 b: 0xEB as f64 / 255.0,
220 depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
221 view: &self.depth_view,
222 depth_ops: Some(wgpu::Operations {
223 load: wgpu::LoadOp::Clear(1.0),
230 if let Some(map) = map.as_ref() {
231 map.render(self, &mut render_pass);
235 self.queue.submit(std::iter::once(encoder.finish()));