WebGPU Voxel Game

Merge pull request #11 from j0lol/egui

Basic EGUI integration

authored by j0.lol and committed by GitHub 598d580f 0035ca00

+233 -5
Cargo.lock
··· 142 142 ] 143 143 144 144 [[package]] 145 + name = "arboard" 146 + version = "3.4.1" 147 + source = "registry+https://github.com/rust-lang/crates.io-index" 148 + checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" 149 + dependencies = [ 150 + "clipboard-win", 151 + "core-graphics", 152 + "image", 153 + "log", 154 + "objc2", 155 + "objc2-app-kit", 156 + "objc2-foundation", 157 + "parking_lot", 158 + "windows-sys 0.48.0", 159 + "x11rb", 160 + ] 161 + 162 + [[package]] 145 163 name = "arrayref" 146 164 version = "0.3.9" 147 165 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 239 257 "cfg-if", 240 258 "console_error_panic_hook", 241 259 "console_log", 260 + "egui", 261 + "egui-wgpu", 262 + "egui-winit", 242 263 "env_logger", 243 264 "fs_extra", 244 265 "futures", ··· 365 386 version = "0.2.1" 366 387 source = "registry+https://github.com/rust-lang/crates.io-index" 367 388 checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 389 + 390 + [[package]] 391 + name = "clipboard-win" 392 + version = "5.4.0" 393 + source = "registry+https://github.com/rust-lang/crates.io-index" 394 + checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" 395 + dependencies = [ 396 + "error-code", 397 + ] 368 398 369 399 [[package]] 370 400 name = "codespan-reporting" ··· 432 462 ] 433 463 434 464 [[package]] 465 + name = "core-foundation" 466 + version = "0.10.0" 467 + source = "registry+https://github.com/rust-lang/crates.io-index" 468 + checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" 469 + dependencies = [ 470 + "core-foundation-sys", 471 + "libc", 472 + ] 473 + 474 + [[package]] 435 475 name = "core-foundation-sys" 436 476 version = "0.8.7" 437 477 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 444 484 checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" 445 485 dependencies = [ 446 486 "bitflags 1.3.2", 447 - "core-foundation", 487 + "core-foundation 0.9.4", 448 488 "core-graphics-types", 449 489 "foreign-types 0.5.0", 450 490 "libc", ··· 457 497 checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" 458 498 dependencies = [ 459 499 "bitflags 1.3.2", 460 - "core-foundation", 500 + "core-foundation 0.9.4", 461 501 "libc", 462 502 ] 463 503 ··· 530 570 checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" 531 571 532 572 [[package]] 573 + name = "ecolor" 574 + version = "0.31.0" 575 + source = "registry+https://github.com/rust-lang/crates.io-index" 576 + checksum = "878e9005799dd739e5d5d89ff7480491c12d0af571d44399bcaefa1ee172dd76" 577 + dependencies = [ 578 + "bytemuck", 579 + "emath", 580 + ] 581 + 582 + [[package]] 583 + name = "egui" 584 + version = "0.31.0" 585 + source = "registry+https://github.com/rust-lang/crates.io-index" 586 + checksum = "7d2768eaa6d5c80a6e2a008da1f0e062dff3c83eb2b28605ea2d0732d46e74d6" 587 + dependencies = [ 588 + "ahash", 589 + "bitflags 2.8.0", 590 + "emath", 591 + "epaint", 592 + "log", 593 + "nohash-hasher", 594 + "profiling", 595 + ] 596 + 597 + [[package]] 598 + name = "egui-wgpu" 599 + version = "0.31.0" 600 + source = "registry+https://github.com/rust-lang/crates.io-index" 601 + checksum = "6d8151704bcef6271bec1806c51544d70e79ef20e8616e5eac01facfd9c8c54a" 602 + dependencies = [ 603 + "ahash", 604 + "bytemuck", 605 + "document-features", 606 + "egui", 607 + "epaint", 608 + "log", 609 + "profiling", 610 + "thiserror 1.0.69", 611 + "type-map", 612 + "web-time", 613 + "wgpu", 614 + ] 615 + 616 + [[package]] 617 + name = "egui-winit" 618 + version = "0.31.0" 619 + source = "registry+https://github.com/rust-lang/crates.io-index" 620 + checksum = "ace791b367c1f63e6044aef2f3834904509d1d1a6912fd23ebf3f6a9af92cd84" 621 + dependencies = [ 622 + "ahash", 623 + "arboard", 624 + "bytemuck", 625 + "egui", 626 + "log", 627 + "profiling", 628 + "raw-window-handle", 629 + "smithay-clipboard", 630 + "web-time", 631 + "webbrowser", 632 + "winit", 633 + ] 634 + 635 + [[package]] 533 636 name = "either" 534 637 version = "1.13.0" 535 638 source = "registry+https://github.com/rust-lang/crates.io-index" 536 639 checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 640 + 641 + [[package]] 642 + name = "emath" 643 + version = "0.31.0" 644 + source = "registry+https://github.com/rust-lang/crates.io-index" 645 + checksum = "55b7b6be5ad1d247f11738b0e4699d9c20005ed366f2c29f5ec1f8e1de180bc2" 646 + dependencies = [ 647 + "bytemuck", 648 + ] 537 649 538 650 [[package]] 539 651 name = "encoding_rs" ··· 568 680 ] 569 681 570 682 [[package]] 683 + name = "epaint" 684 + version = "0.31.0" 685 + source = "registry+https://github.com/rust-lang/crates.io-index" 686 + checksum = "275b665a7b9611d8317485187e5458750850f9e64604d3c58434bb3fc1d22915" 687 + dependencies = [ 688 + "ab_glyph", 689 + "ahash", 690 + "bytemuck", 691 + "ecolor", 692 + "emath", 693 + "epaint_default_fonts", 694 + "log", 695 + "nohash-hasher", 696 + "parking_lot", 697 + "profiling", 698 + ] 699 + 700 + [[package]] 701 + name = "epaint_default_fonts" 702 + version = "0.31.0" 703 + source = "registry+https://github.com/rust-lang/crates.io-index" 704 + checksum = "9343d356d7cac894dacafc161b4654e0881301097bdf32a122ed503d97cb94b6" 705 + 706 + [[package]] 571 707 name = "equivalent" 572 708 version = "1.0.1" 573 709 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 582 718 "libc", 583 719 "windows-sys 0.59.0", 584 720 ] 721 + 722 + [[package]] 723 + name = "error-code" 724 + version = "3.3.1" 725 + source = "registry+https://github.com/rust-lang/crates.io-index" 726 + checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" 585 727 586 728 [[package]] 587 729 name = "fastrand" ··· 950 1092 checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" 951 1093 952 1094 [[package]] 1095 + name = "home" 1096 + version = "0.5.11" 1097 + source = "registry+https://github.com/rust-lang/crates.io-index" 1098 + checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" 1099 + dependencies = [ 1100 + "windows-sys 0.59.0", 1101 + ] 1102 + 1103 + [[package]] 953 1104 name = "http" 954 1105 version = "1.2.0" 955 1106 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1216 1367 "byteorder-lite", 1217 1368 "num-traits", 1218 1369 "png", 1370 + "tiff", 1219 1371 "zune-core", 1220 1372 "zune-jpeg", 1221 1373 ] ··· 1289 1441 ] 1290 1442 1291 1443 [[package]] 1444 + name = "jpeg-decoder" 1445 + version = "0.3.1" 1446 + source = "registry+https://github.com/rust-lang/crates.io-index" 1447 + checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" 1448 + 1449 + [[package]] 1292 1450 name = "js-sys" 1293 1451 version = "0.3.77" 1294 1452 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1519 1677 dependencies = [ 1520 1678 "jni-sys", 1521 1679 ] 1680 + 1681 + [[package]] 1682 + name = "nohash-hasher" 1683 + version = "0.2.0" 1684 + source = "registry+https://github.com/rust-lang/crates.io-index" 1685 + checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" 1522 1686 1523 1687 [[package]] 1524 1688 name = "num-traits" ··· 2253 2417 checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 2254 2418 dependencies = [ 2255 2419 "bitflags 2.8.0", 2256 - "core-foundation", 2420 + "core-foundation 0.9.4", 2257 2421 "core-foundation-sys", 2258 2422 "libc", 2259 2423 "security-framework-sys", ··· 2375 2539 ] 2376 2540 2377 2541 [[package]] 2542 + name = "smithay-clipboard" 2543 + version = "0.7.2" 2544 + source = "registry+https://github.com/rust-lang/crates.io-index" 2545 + checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" 2546 + dependencies = [ 2547 + "libc", 2548 + "smithay-client-toolkit", 2549 + "wayland-backend", 2550 + ] 2551 + 2552 + [[package]] 2378 2553 name = "smol_str" 2379 2554 version = "0.2.2" 2380 2555 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2492 2667 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 2493 2668 dependencies = [ 2494 2669 "bitflags 2.8.0", 2495 - "core-foundation", 2670 + "core-foundation 0.9.4", 2496 2671 "system-configuration-sys", 2497 2672 ] 2498 2673 ··· 2567 2742 "proc-macro2", 2568 2743 "quote", 2569 2744 "syn", 2745 + ] 2746 + 2747 + [[package]] 2748 + name = "tiff" 2749 + version = "0.9.1" 2750 + source = "registry+https://github.com/rust-lang/crates.io-index" 2751 + checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" 2752 + dependencies = [ 2753 + "flate2", 2754 + "jpeg-decoder", 2755 + "weezl", 2570 2756 ] 2571 2757 2572 2758 [[package]] ··· 2734 2920 checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" 2735 2921 2736 2922 [[package]] 2923 + name = "type-map" 2924 + version = "0.5.0" 2925 + source = "registry+https://github.com/rust-lang/crates.io-index" 2926 + checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" 2927 + dependencies = [ 2928 + "rustc-hash", 2929 + ] 2930 + 2931 + [[package]] 2737 2932 name = "unicode-ident" 2738 2933 version = "1.0.16" 2739 2934 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3039 3234 ] 3040 3235 3041 3236 [[package]] 3237 + name = "webbrowser" 3238 + version = "1.0.3" 3239 + source = "registry+https://github.com/rust-lang/crates.io-index" 3240 + checksum = "ea9fe1ebb156110ff855242c1101df158b822487e4957b0556d9ffce9db0f535" 3241 + dependencies = [ 3242 + "block2", 3243 + "core-foundation 0.10.0", 3244 + "home", 3245 + "jni", 3246 + "log", 3247 + "ndk-context", 3248 + "objc2", 3249 + "objc2-foundation", 3250 + "url", 3251 + "web-sys", 3252 + ] 3253 + 3254 + [[package]] 3255 + name = "weezl" 3256 + version = "0.1.8" 3257 + source = "registry+https://github.com/rust-lang/crates.io-index" 3258 + checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" 3259 + 3260 + [[package]] 3042 3261 name = "wgpu" 3043 3262 version = "24.0.1" 3044 3263 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3238 3457 checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 3239 3458 dependencies = [ 3240 3459 "windows-targets 0.42.2", 3460 + ] 3461 + 3462 + [[package]] 3463 + name = "windows-sys" 3464 + version = "0.48.0" 3465 + source = "registry+https://github.com/rust-lang/crates.io-index" 3466 + checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 3467 + dependencies = [ 3468 + "windows-targets 0.48.5", 3241 3469 ] 3242 3470 3243 3471 [[package]] ··· 3451 3679 "calloop", 3452 3680 "cfg_aliases", 3453 3681 "concurrent-queue", 3454 - "core-foundation", 3682 + "core-foundation 0.9.4", 3455 3683 "core-graphics", 3456 3684 "cursor-icon", 3457 3685 "dpi",
+3
Cargo.toml
··· 19 19 tobj = { version = "4", default-features = false, features = ["async"] } 20 20 futures = "0.3" 21 21 itertools = "0.14" 22 + egui = "0.31" 23 + egui-wgpu = "0.31" 24 + egui-winit = "0.31" 22 25 23 26 [build-dependencies] 24 27 fs_extra = "1.3"
+22 -2
src/app.rs
··· 1 - use crate::gfx::{Gfx, GfxBuilder, MaybeGfx}; 1 + use crate::{ 2 + gfx::{Gfx, GfxBuilder, MaybeGfx}, 3 + gui::EguiRenderer, 4 + }; 2 5 use std::sync::Arc; 3 6 use winit::{ 4 7 application::ApplicationHandler, ··· 19 22 window_attributes: WindowAttributes, 20 23 gfx_state: MaybeGfx, 21 24 window: Option<Arc<Window>>, 25 + egui: Option<EguiRenderer>, 22 26 } 23 27 24 28 impl Application { ··· 27 31 window_attributes: Window::default_attributes().with_title(title), 28 32 gfx_state: MaybeGfx::Builder(GfxBuilder::new(event_loop.create_proxy())), 29 33 window: None, 34 + egui: None, 30 35 } 31 36 } 32 37 } ··· 69 74 } 70 75 71 76 fn user_event(&mut self, _event_loop: &ActiveEventLoop, gfx: Gfx) { 77 + if let Some(window) = &self.window { 78 + let egui = EguiRenderer::new(&gfx.device, gfx.surface_config.format, None, 1, window); 79 + self.egui = Some(egui); 80 + } 72 81 self.gfx_state = MaybeGfx::Graphics(gfx); 73 82 } 74 83 ··· 86 95 }; 87 96 88 97 if let Some(ref window) = &self.window { 98 + // Returns true if EGUI consumes the input. 99 + if self 100 + .egui 101 + .as_mut() 102 + .map(|egui| egui.handle_input(window, &event)) 103 + .is_some_and(|x| x) 104 + { 105 + return; 106 + } 107 + 89 108 gfx.input(&event, window.inner_size()); 90 109 } 91 110 ··· 111 130 // Some horrible nesting here! Don't tell Linus... 112 131 if let Some(ref window) = &self.window { 113 132 window.request_redraw(); 114 - match gfx.render() { 133 + match gfx.render(&mut self.egui, window.clone()) { 115 134 Ok(_) => { 135 + // TODO CITE https://github.com/kaphula/winit-egui-wgpu-template/blob/master/src/app.rs#L3 116 136 gfx.update(); 117 137 } 118 138 Err(wgpu::SurfaceError::Lost | wgpu::SurfaceError::Outdated) => {
+71 -32
src/gfx.rs
··· 5 5 6 6 use std::sync::Arc; 7 7 8 + use egui_wgpu::ScreenDescriptor; 8 9 use glam::{vec3, Quat, Vec3}; 9 10 use wgpu::util::DeviceExt; 10 11 use winit::{ ··· 15 16 window::Window, 16 17 }; 17 18 18 - use crate::{app::WASM_WIN_SIZE, gfx::model::Vertex, map::{sl3get, Block, CHUNK_SIZE}, Instance, InstanceRaw}; 19 + use crate::{ 20 + app::WASM_WIN_SIZE, 21 + gfx::model::Vertex, 22 + gui::EguiRenderer, 23 + map::{sl3get, Block, CHUNK_SIZE}, 24 + Instance, InstanceRaw, 25 + }; 19 26 20 27 #[repr(C)] 21 28 #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] ··· 59 66 bind_group: wgpu::BindGroup, 60 67 } 61 68 62 - struct RenderPipelines { 69 + pub struct RenderPipelines { 63 70 camera: wgpu::RenderPipeline, 64 71 camera_wireframe: Option<wgpu::RenderPipeline>, 65 72 light: wgpu::RenderPipeline, ··· 168 175 } 169 176 170 177 pub struct Gfx { 171 - surface: wgpu::Surface<'static>, 172 - device: wgpu::Device, 173 - queue: wgpu::Queue, 174 - surface_config: wgpu::SurfaceConfiguration, 175 - render_pipelines: RenderPipelines, 176 - depth_texture: texture::Texture, 178 + pub surface: wgpu::Surface<'static>, 179 + pub device: wgpu::Device, 180 + pub queue: wgpu::Queue, 181 + pub surface_config: wgpu::SurfaceConfiguration, 182 + pub render_pipelines: RenderPipelines, 183 + pub depth_texture: texture::Texture, 177 184 178 185 object: ObjectState, 179 186 camera: CameraState, ··· 288 295 label: Some("texture_bind_group_layout"), 289 296 }); 290 297 291 - 292 298 let camera = camera::Camera { 293 299 eye: vec3(50., 20., 50.), 294 300 target: Vec3::ZERO, ··· 346 352 for (coords, chunk) in map.chunks { 347 353 let _3diter = itertools::iproduct!(0..CHUNK_SIZE.0, 0..CHUNK_SIZE.1, 0..CHUNK_SIZE.2); 348 354 349 - let mut i = _3diter.filter_map(|(x,y,z)| { 355 + let mut i = _3diter 356 + .filter_map(|(x, y, z)| { 357 + if let Block::Air = sl3get(&chunk.blocks, x, y, z) { 358 + return None; 359 + } 350 360 351 - if let Block::AIR = sl3get(&chunk.blocks, x, y, z) { 352 - return None; 353 - } 361 + let chunk_offset = coords.as_vec2() * (SPACE_BETWEEN * CHUNK_SIZE.0 as f32); 354 362 355 - let chunk_offset = coords.as_vec2() * (SPACE_BETWEEN * CHUNK_SIZE.0 as f32); 363 + let mapping = |n| SPACE_BETWEEN * (n as f32 - CHUNK_SIZE.0 as f32 / 2.0); 364 + let position = vec3( 365 + mapping(x) + chunk_offset.x, 366 + -mapping(y), 367 + mapping(z) + chunk_offset.y, 368 + ); 356 369 357 - let mapping = |n| SPACE_BETWEEN * (n as f32 - CHUNK_SIZE.0 as f32 / 2.0); 358 - let position = vec3(mapping(x) + chunk_offset.x, -mapping(y), mapping(z) + chunk_offset.y); 370 + // this is needed so an object at (0, 0, 0) won't get scaled to zero 371 + // as Quaternions can affect scale if they're not created correctly 372 + // let rotation = match position.try_normalize() { 373 + // Some(position) => Quat::from_axis_angle(position, 45.0), 374 + // _ => Quat::from_axis_angle(Vec3::Z, 0.0), 375 + // }; 376 + let rotation = Quat::from_axis_angle(Vec3::Y, 0.0); 359 377 360 - // this is needed so an object at (0, 0, 0) won't get scaled to zero 361 - // as Quaternions can affect scale if they're not created correctly 362 - // let rotation = match position.try_normalize() { 363 - // Some(position) => Quat::from_axis_angle(position, 45.0), 364 - // _ => Quat::from_axis_angle(Vec3::Z, 0.0), 365 - // }; 366 - let rotation = Quat::from_axis_angle(Vec3::Y, 0.0); 367 - 368 - Some(Instance { position, rotation }) 369 - 370 - }).collect::<Vec<_>>(); 378 + Some(Instance { position, rotation }) 379 + }) 380 + .collect::<Vec<_>>(); 371 381 372 382 instances.append(&mut i); 373 383 } ··· 379 389 usage: wgpu::BufferUsages::VERTEX, 380 390 }); 381 391 382 - let obj_model = 383 - resources::load_model("blender_default_cube.obj", &device, &queue, &texture_bind_group_layout) 384 - .await 385 - .unwrap(); 392 + let obj_model = resources::load_model( 393 + "blender_default_cube.obj", 394 + &device, 395 + &queue, 396 + &texture_bind_group_layout, 397 + ) 398 + .await 399 + .unwrap(); 386 400 387 401 let light_uniform = LightUniform::new(Vec3::splat(90.0).with_y(40.0), vec3(1.0, 1.0, 0.5)); 388 402 ··· 536 550 texture::Texture::create_depth_texture(&self.device, &self.surface_config, "depth_texture"); 537 551 } 538 552 539 - pub(crate) fn render(&self) -> Result<(), wgpu::SurfaceError> { 553 + pub(crate) fn render( 554 + &self, 555 + egui: &mut Option<EguiRenderer>, 556 + window: Arc<Window>, 557 + ) -> Result<(), wgpu::SurfaceError> { 540 558 let output = self.surface.get_current_texture()?; 541 559 542 560 let view = output ··· 597 615 &self.light.bind_group, 598 616 ); 599 617 618 + 600 619 // drop render pass before we submit to drop the mut borrow on encoder 601 620 drop(render_pass); 621 + 622 + // Layer EGUI on top of frame! 623 + if let Some(egui) = egui { 624 + let screen_descriptor = ScreenDescriptor { 625 + size_in_pixels: [self.surface_config.width, self.surface_config.height], 626 + pixels_per_point: window.scale_factor() as f32 * egui.scale_factor, 627 + }; 628 + egui.begin_frame(&window); 629 + 630 + egui.update(); 631 + 632 + egui.end_frame_and_draw( 633 + &self.device, 634 + &self.queue, 635 + &mut encoder, 636 + &window, 637 + &view, 638 + screen_descriptor, 639 + ); 640 + } 602 641 603 642 self.queue.submit(std::iter::once(encoder.finish())); 604 643 output.present();
+150
src/gui.rs
··· 1 + use egui_winit::EventResponse; 2 + use winit::window::Window; 3 + 4 + pub struct EguiRenderer { 5 + state: egui_winit::State, 6 + renderer: egui_wgpu::Renderer, 7 + frame_started: bool, 8 + pub scale_factor: f32, 9 + } 10 + 11 + impl EguiRenderer { 12 + // Just a helper 13 + pub fn ctx(&self) -> &egui::Context { 14 + self.state.egui_ctx() 15 + } 16 + 17 + pub fn new( 18 + device: &wgpu::Device, 19 + output_color_format: wgpu::TextureFormat, 20 + output_depth_format: Option<wgpu::TextureFormat>, 21 + msaa_samples: u32, 22 + window: &Window, 23 + ) -> EguiRenderer { 24 + let context = egui::Context::default(); 25 + let state = egui_winit::State::new( 26 + context, 27 + egui::viewport::ViewportId::ROOT, 28 + &window, 29 + Some(window.scale_factor() as f32), 30 + None, 31 + Some(2 * 1024), // "max texture side" of 2048 32 + ); 33 + 34 + let renderer = egui_wgpu::Renderer::new( 35 + device, 36 + output_color_format, 37 + output_depth_format, 38 + msaa_samples, 39 + true, 40 + ); 41 + 42 + EguiRenderer { 43 + state, 44 + renderer, 45 + frame_started: false, 46 + scale_factor: 1.0 47 + } 48 + } 49 + 50 + pub fn handle_input(&mut self, window: &Window, event: &winit::event::WindowEvent) -> bool { 51 + let EventResponse {consumed, ..} = self.state.on_window_event(window, event); 52 + consumed 53 + } 54 + 55 + pub(crate) fn begin_frame(&mut self, window: &Window) { 56 + let raw_input = self.state.take_egui_input(window); 57 + self.ctx().begin_pass(raw_input); 58 + self.frame_started = true; 59 + } 60 + 61 + pub(crate) fn end_frame_and_draw( 62 + &mut self, 63 + device: &wgpu::Device, 64 + queue: &wgpu::Queue, 65 + encoder: &mut wgpu::CommandEncoder, 66 + window: &Window, 67 + surface_view: &wgpu::TextureView, 68 + screen_descriptor: egui_wgpu::ScreenDescriptor, 69 + ) { 70 + if !self.frame_started { 71 + panic!("begin_frame must be called before end_frame_and_draw can be called!"); 72 + } 73 + 74 + self.ctx().set_pixels_per_point(screen_descriptor.pixels_per_point); 75 + 76 + let full_output = self.ctx().end_pass(); 77 + 78 + self.state 79 + .handle_platform_output(window, full_output.platform_output); 80 + 81 + let tris = self 82 + .ctx() 83 + .tessellate(full_output.shapes, self.ctx().pixels_per_point()); 84 + 85 + for (id, image_delta) in &full_output.textures_delta.set { 86 + self.renderer 87 + .update_texture(device, queue, *id, image_delta); 88 + } 89 + 90 + self.renderer 91 + .update_buffers(device, queue, encoder, &tris, &screen_descriptor); 92 + 93 + let render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { 94 + label: Some("EGUI Main Render Pass"), 95 + color_attachments: &[Some(wgpu::RenderPassColorAttachment { 96 + view: surface_view, 97 + resolve_target: None, 98 + ops: wgpu::Operations { 99 + load: wgpu::LoadOp::Load, 100 + store: wgpu::StoreOp::Store, 101 + }, 102 + })], 103 + depth_stencil_attachment: None, 104 + timestamp_writes: None, 105 + occlusion_query_set: None, 106 + }); 107 + 108 + self.renderer.render( 109 + &mut render_pass.forget_lifetime(), 110 + &tris, 111 + &screen_descriptor, 112 + ); 113 + for x in &full_output.textures_delta.free { 114 + self.renderer.free_texture(x) 115 + } 116 + 117 + self.frame_started = false; 118 + } 119 + 120 + pub fn update(&mut self) { 121 + let ctx = self.ctx(); 122 + 123 + let mut scale_factor = self.scale_factor; 124 + 125 + egui::Window::new("winit + egui + wgpu says hello!") 126 + .resizable(true) 127 + .vscroll(true) 128 + .default_open(false) 129 + .show(ctx, |ui| { 130 + ui.label("Label!"); 131 + 132 + if ui.button("Button!").clicked() { 133 + println!("boom!") 134 + } 135 + 136 + ui.separator(); 137 + ui.horizontal(|ui| { 138 + ui.label(format!("Pixels per point: {}", ctx.pixels_per_point())); 139 + if ui.button("-").clicked() { 140 + scale_factor = (scale_factor - 0.1).max(0.3); 141 + } 142 + if ui.button("+").clicked() { 143 + scale_factor = (scale_factor + 0.1).min(3.0); 144 + } 145 + }); 146 + }); 147 + 148 + self.scale_factor = scale_factor; 149 + } 150 + }
+2 -1
src/lib.rs
··· 3 3 mod app; 4 4 mod gfx; 5 5 mod map; 6 + mod gui; 6 7 7 - use glam::{Mat3, Mat4, Quat, Vec3}; 8 + use glam::{Mat3, Quat, Vec3}; 8 9 #[cfg(target_arch = "wasm32")] 9 10 use wasm_bindgen::prelude::*; 10 11 use wasm_bindgen::UnwrapThrowExt;
+3 -3
src/map.rs
··· 27 27 #[repr(u32)] 28 28 pub enum Block { 29 29 #[default] 30 - AIR = 0, 31 - BRICK, 30 + Air = 0, 31 + Brick, 32 32 } 33 33 34 34 fn new_chunk(world_x: i32, world_z: i32) -> Chunk { ··· 45 45 // Pretty arbitrary numbers! Just trying to get something interesting 46 46 let n = (((sines / 4. + 0.5) * CHUNK_SIZE.2 as f32).round() as i32) <= y as _; 47 47 sl3set(&mut blocks, x, y, z, { 48 - if n { Block::BRICK } else { Block::AIR } 48 + if n { Block::Brick } else { Block::Air } 49 49 }); 50 50 } 51 51