lib.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. use std::{iter, time::{Duration, Instant}};
  2. use camera::{camera_buffer, camera_controller, camera_struct::Camera, camera_uniform};
  3. use wgpu::{util::DeviceExt, BlendState, ColorTargetState, PipelineLayoutDescriptor, RenderPipelineDescriptor};
  4. use winit::{
  5. event::*,
  6. event_loop::EventLoop,
  7. keyboard::{KeyCode, PhysicalKey},
  8. window::{Window, WindowBuilder},
  9. };
  10. mod camera;
  11. mod object;
  12. mod sky;
  13. #[cfg(target_arch = "wasm32")]
  14. use wasm_bindgen::prelude::*;
  15. struct State<'a> {
  16. surface: wgpu::Surface<'a>,
  17. device: wgpu::Device,
  18. queue: wgpu::Queue,
  19. config: wgpu::SurfaceConfiguration,
  20. size: winit::dpi::PhysicalSize<u32>,
  21. render_pipeline : wgpu::RenderPipeline,
  22. vertex_buffer: wgpu::Buffer,
  23. camera: camera::camera_struct::Camera,
  24. camera_buffer : wgpu::Buffer,
  25. camera_bind_group: wgpu::BindGroup,
  26. camera_uniform : camera_uniform::CameraUniform,
  27. camera_controller: camera_controller::CameraController,
  28. // The window must be declared after the surface so
  29. // it gets dropped after it as the surface contains
  30. // unsafe references to the window's resources.
  31. window: &'a Window,
  32. num_vertices: u32,
  33. last_frame: Instant,
  34. framecount: u64,
  35. frametime: f64,
  36. old_frame_times: Vec<f64>,
  37. max_history_size: usize,
  38. //sky_pipeline: wgpu::RenderPipeline,
  39. last_fps: Instant,
  40. }
  41. impl<'a> State<'a> {
  42. async fn new(window: &'a Window) -> State<'a> {
  43. let size = window.inner_size();
  44. // The instance is a handle to our GPU
  45. // BackendBit::PRIMARY => Vulkan + Metal + DX12 + Browser WebGPU
  46. let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
  47. #[cfg(not(target_arch = "wasm32"))]
  48. backends: wgpu::Backends::PRIMARY,
  49. #[cfg(target_arch = "wasm32")]
  50. backends: wgpu::Backends::GL,
  51. ..Default::default()
  52. });
  53. let surface = instance.create_surface(window).unwrap();
  54. let adapter = instance
  55. .request_adapter(&wgpu::RequestAdapterOptions {
  56. power_preference: wgpu::PowerPreference::default(),
  57. compatible_surface: Some(&surface),
  58. force_fallback_adapter: false,
  59. })
  60. .await
  61. .unwrap();
  62. let (device, queue) = adapter
  63. .request_device(
  64. &wgpu::DeviceDescriptor {
  65. label: None,
  66. required_features: wgpu::Features::empty(),
  67. // WebGL doesn't support all of wgpu's features, so if
  68. // we're building for the web we'll have to disable some.
  69. required_limits: if cfg!(target_arch = "wasm32") {
  70. wgpu::Limits::downlevel_webgl2_defaults()
  71. } else {
  72. wgpu::Limits::default()
  73. },
  74. },
  75. // Some(&std::path::Path::new("trace")), // Trace path
  76. None,
  77. )
  78. .await
  79. .unwrap();
  80. let surface_caps = surface.get_capabilities(&adapter);
  81. // Shader code in this tutorial assumes an Srgb surface texture. Using a different
  82. // one will result all the colors comming out darker. If you want to support non
  83. // Srgb surfaces, you'll need to account for that when drawing to the frame.
  84. let surface_format = surface_caps
  85. .formats
  86. .iter()
  87. .copied()
  88. .find(|f| f.is_srgb())
  89. .unwrap_or(surface_caps.formats[0]);
  90. let config = wgpu::SurfaceConfiguration {
  91. usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
  92. format: surface_format,
  93. width: size.width,
  94. height: size.height,
  95. present_mode: surface_caps.present_modes[0],
  96. alpha_mode: surface_caps.alpha_modes[0],
  97. desired_maximum_frame_latency: 2,
  98. view_formats: vec![],
  99. };
  100. let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
  101. label: Some("Shader 1 from shader.wgsl"),
  102. source: wgpu::ShaderSource::Wgsl(include_str!("./shaders/shader.wgsl").into()),
  103. });
  104. let plan1 = object::generate_plane(3,3,10.,10.);
  105. //println!("{:?}", plan1.positions_list());
  106. let plan2 = plan1.clone();
  107. let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor{
  108. label: Some("Vertex Buffer 1"),
  109. contents: bytemuck::cast_slice(&plan1.vertices()),
  110. usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
  111. });
  112. let num_vertices = plan2.len();
  113. let (camera, camera_uniform, camera_buffer,camera_bind_group, camera_bind_group_layout) = camera_buffer::new(&device, &config);
  114. let camera_controller = camera_controller::CameraController::new(0.1);
  115. let pipeline_layout = device.create_pipeline_layout(&PipelineLayoutDescriptor{
  116. label: Some("Pipeline Layout"),
  117. bind_group_layouts: &[
  118. &camera_bind_group_layout,
  119. ],
  120. push_constant_ranges: &[]
  121. });
  122. let render_pipeline = device.create_render_pipeline(&RenderPipelineDescriptor{
  123. label: Some("RenderPipeline"),
  124. layout: Some(&pipeline_layout),
  125. vertex: wgpu::VertexState {
  126. module: &shader,
  127. entry_point: "vs_main".into(),
  128. buffers: &[
  129. object::Vertex::desc(),
  130. ],
  131. },
  132. primitive: wgpu::PrimitiveState{
  133. topology: wgpu::PrimitiveTopology::TriangleList,
  134. strip_index_format: None,
  135. front_face: wgpu::FrontFace::Ccw,
  136. cull_mode: None,
  137. unclipped_depth: false,
  138. polygon_mode: wgpu::PolygonMode::Fill,
  139. conservative: false
  140. },
  141. depth_stencil: None,
  142. multisample: wgpu::MultisampleState{
  143. count: 1,
  144. mask: !0,
  145. alpha_to_coverage_enabled: false,
  146. },
  147. fragment: Some(wgpu::FragmentState{
  148. module: &shader,
  149. entry_point: "fs_main",
  150. targets: &[Some(ColorTargetState{
  151. format: config.format,
  152. blend: Some(BlendState::REPLACE),
  153. write_mask: wgpu::ColorWrites::ALL
  154. })]
  155. }),
  156. multiview: None
  157. });
  158. let last_frame: Instant = Instant::now();
  159. let delta: f64 = 0.2;
  160. //let sky_pipeline = sky::sky_pipeline::new_sky_pipeline(&device, &config);
  161. let framecount: u64 = 0;
  162. let old_frame_times : Vec<f64> = vec![];
  163. let max_history: usize = 60;
  164. let last_fps = Instant::now();
  165. Self {
  166. surface,
  167. vertex_buffer,
  168. render_pipeline,
  169. device,
  170. queue,
  171. config,
  172. size,
  173. window,
  174. camera,
  175. camera_bind_group,
  176. camera_buffer,
  177. camera_uniform,
  178. camera_controller,
  179. num_vertices: num_vertices,
  180. last_frame: last_frame,
  181. frametime: delta,
  182. //sky_pipeline: sky_pipeline
  183. framecount,
  184. old_frame_times: old_frame_times,
  185. max_history_size: max_history,
  186. last_fps: last_fps
  187. }
  188. }
  189. fn window(&self) -> &Window {
  190. &self.window
  191. }
  192. pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
  193. if new_size.width > 0 && new_size.height > 0 {
  194. self.size = new_size;
  195. self.config.width = new_size.width;
  196. self.config.height = new_size.height;
  197. self.surface.configure(&self.device, &self.config);
  198. self.camera.aspect = self.config.width as f32 / self.config.height as f32;
  199. }
  200. }
  201. fn input(&mut self, event: &WindowEvent) -> bool {
  202. self.camera_controller.process_events(event)
  203. }
  204. fn update(&mut self) {
  205. self.camera_controller.update_camera(&mut self.camera);
  206. self.camera_uniform.update_view_proj(&self.camera);
  207. self.queue.write_buffer(
  208. &self.camera_buffer,
  209. 0,
  210. bytemuck::cast_slice(&[self.camera_uniform]),
  211. );
  212. // self.queue.write_buffer(
  213. // &self.vertex_buffer,
  214. // 0,
  215. // bytemuck::cast_slice(todo!())
  216. // );
  217. }
  218. fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
  219. let output = self.surface.get_current_texture()?;
  220. let view = output
  221. .texture
  222. .create_view(&wgpu::TextureViewDescriptor::default());
  223. let mut encoder = self
  224. .device
  225. .create_command_encoder(&wgpu::CommandEncoderDescriptor {
  226. label: Some("Render Encoder"),
  227. });
  228. //Modify the buffer
  229. {
  230. let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
  231. label: Some("Render Pass"),
  232. color_attachments: &[Some(wgpu::RenderPassColorAttachment {
  233. view: &view,
  234. resolve_target: None,
  235. ops: wgpu::Operations {
  236. load: wgpu::LoadOp::Clear(wgpu::Color {
  237. r: 0.52,
  238. g: 0.80,
  239. b: 0.92,
  240. a: 1.0,
  241. }),
  242. store: wgpu::StoreOp::Store,
  243. },
  244. })],
  245. depth_stencil_attachment: None,
  246. occlusion_query_set: None,
  247. timestamp_writes: None,
  248. });
  249. //render_pass.set_pipeline(&self.sky_pipeline);
  250. render_pass.set_pipeline(&self.render_pipeline);
  251. render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
  252. render_pass.set_bind_group(0, &self.camera_bind_group, &[]);
  253. render_pass.draw(0..self.num_vertices, 0..1);
  254. //render_pass.draws
  255. }
  256. self.queue.submit(iter::once(encoder.finish()));
  257. output.present();
  258. //FPS logic
  259. self.frametime = (self.last_frame.elapsed().as_secs() as f64) + (self.last_frame.elapsed().as_nanos() as f64 / 1_000_000_000.0);
  260. self.last_frame = Instant::now();
  261. let interval_fps = Duration::from_millis(100);
  262. self.old_frame_times.push(self.frametime);
  263. if self.old_frame_times.len() > self.max_history_size {
  264. self.old_frame_times.remove(0);
  265. }
  266. let smoothed_frame_time = self.old_frame_times.iter().sum::<f64>() / self.old_frame_times.len() as f64;
  267. let smoothed_fps = 1.0 / smoothed_frame_time;
  268. if self.last_fps.elapsed() > interval_fps{
  269. self.last_fps = Instant::now();
  270. println!("{:?}", smoothed_fps.ceil());
  271. }
  272. Ok(())
  273. }
  274. }
  275. #[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
  276. pub async fn run() {
  277. cfg_if::cfg_if! {
  278. if #[cfg(target_arch = "wasm32")] {
  279. std::panic::set_hook(Box::new(console_error_panic_hook::hook));
  280. console_log::init_with_level(log::Level::Info).expect("Couldn't initialize logger");
  281. } else {
  282. env_logger::init();
  283. }
  284. }
  285. let event_loop = EventLoop::new().unwrap();
  286. let window = WindowBuilder::new().build(&event_loop).unwrap();
  287. #[cfg(target_arch = "wasm32")]
  288. {
  289. // Winit prevents sizing with CSS, so we have to set
  290. // the size manually when on web.
  291. use winit::dpi::PhysicalSize;
  292. use winit::platform::web::WindowExtWebSys;
  293. web_sys::window()
  294. .and_then(|win| win.document())
  295. .and_then(|doc| {
  296. let dst = doc.get_element_by_id("wasm-example")?;
  297. let canvas = web_sys::Element::from(window.canvas()?);
  298. dst.append_child(&canvas).ok()?;
  299. Some(())
  300. })
  301. .expect("Couldn't append canvas to document body.");
  302. let _ = window.request_inner_size(PhysicalSize::new(450, 400));
  303. }
  304. // State::new uses async code, so we're going to wait for it to finish
  305. let mut state = State::new(&window).await;
  306. let mut surface_configured = false;
  307. event_loop
  308. .run(move |event, control_flow| {
  309. match event {
  310. Event::WindowEvent {
  311. ref event,
  312. window_id,
  313. } if window_id == state.window().id() => {
  314. if !state.input(event) {
  315. // UPDATED!
  316. match event {
  317. WindowEvent::CloseRequested
  318. | WindowEvent::KeyboardInput {
  319. event:
  320. KeyEvent {
  321. state: ElementState::Pressed,
  322. physical_key: PhysicalKey::Code(KeyCode::Escape),
  323. ..
  324. },
  325. ..
  326. } => control_flow.exit(),
  327. WindowEvent::Resized(physical_size) => {
  328. log::info!("physical_size: {physical_size:?}");
  329. surface_configured = true;
  330. state.resize(*physical_size);
  331. }
  332. WindowEvent::RedrawRequested => {
  333. // This tells winit that we want another frame after this one
  334. state.window().request_redraw();
  335. if !surface_configured {
  336. return;
  337. }
  338. state.update();
  339. match state.render() {
  340. Ok(_) => {}
  341. // Reconfigure the surface if it's lost or outdated
  342. Err(
  343. wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated,
  344. ) => state.resize(state.size),
  345. // The system is out of memory, we should probably quit
  346. Err(wgpu::SurfaceError::OutOfMemory) => {
  347. log::error!("OutOfMemory");
  348. control_flow.exit();
  349. }
  350. // This happens when the a frame takes too long to present
  351. Err(wgpu::SurfaceError::Timeout) => {
  352. log::warn!("Surface timeout")
  353. }
  354. }
  355. }
  356. _ => {}
  357. }
  358. }
  359. }
  360. _ => {}
  361. }
  362. })
  363. .unwrap();
  364. }