WebGPU Voxel Game

Basic shadow-mapping

j0.lol e1a51087 15777f3a

+9 -3
.gitignore
··· 1 - /target 2 - /pkg 1 + # Rust 2 + target/ 3 + **/*.rs.bk 4 + 5 + # cargo-mobile 6 + .cargo/ 7 + /gen 8 + 9 + # macOS 3 10 .DS_Store 4 - save.bl0ck
+11 -19
Cargo.lock
··· 266 266 "fs_extra", 267 267 "futures", 268 268 "glam", 269 - "glob", 270 269 "image", 271 270 "itertools", 272 271 "log", ··· 946 945 dependencies = [ 947 946 "bytemuck", 948 947 ] 949 - 950 - [[package]] 951 - name = "glob" 952 - version = "0.3.2" 953 - source = "registry+https://github.com/rust-lang/crates.io-index" 954 - checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" 955 948 956 949 [[package]] 957 950 name = "glow" ··· 2148 2141 dependencies = [ 2149 2142 "rand_chacha", 2150 2143 "rand_core", 2151 - "zerocopy 0.8.16", 2144 + "zerocopy 0.8.17", 2152 2145 ] 2153 2146 2154 2147 [[package]] ··· 2168 2161 checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff" 2169 2162 dependencies = [ 2170 2163 "getrandom 0.3.1", 2171 - "zerocopy 0.8.16", 2164 + "zerocopy 0.8.17", 2172 2165 ] 2173 2166 2174 2167 [[package]] ··· 3049 3042 3050 3043 [[package]] 3051 3044 name = "wasm-bindgen-futures" 3052 - version = "0.4.50" 3045 + version = "0.4.45" 3053 3046 source = "registry+https://github.com/rust-lang/crates.io-index" 3054 - checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" 3047 + checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" 3055 3048 dependencies = [ 3056 3049 "cfg-if", 3057 3050 "js-sys", 3058 - "once_cell", 3059 3051 "wasm-bindgen", 3060 3052 "web-sys", 3061 3053 ] ··· 3621 3613 3622 3614 [[package]] 3623 3615 name = "winit" 3624 - version = "0.30.8" 3616 + version = "0.30.9" 3625 3617 source = "registry+https://github.com/rust-lang/crates.io-index" 3626 - checksum = "f5d74280aabb958072864bff6cfbcf9025cf8bfacdde5e32b5e12920ef703b0f" 3618 + checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0" 3627 3619 dependencies = [ 3628 3620 "ahash", 3629 3621 "android-activity", ··· 3800 3792 3801 3793 [[package]] 3802 3794 name = "zerocopy" 3803 - version = "0.8.16" 3795 + version = "0.8.17" 3804 3796 source = "registry+https://github.com/rust-lang/crates.io-index" 3805 - checksum = "7b8c07a70861ce02bad1607b5753ecb2501f67847b9f9ada7c160fff0ec6300c" 3797 + checksum = "aa91407dacce3a68c56de03abe2760159582b846c6a4acd2f456618087f12713" 3806 3798 dependencies = [ 3807 - "zerocopy-derive 0.8.16", 3799 + "zerocopy-derive 0.8.17", 3808 3800 ] 3809 3801 3810 3802 [[package]] ··· 3820 3812 3821 3813 [[package]] 3822 3814 name = "zerocopy-derive" 3823 - version = "0.8.16" 3815 + version = "0.8.17" 3824 3816 source = "registry+https://github.com/rust-lang/crates.io-index" 3825 - checksum = "5226bc9a9a9836e7428936cde76bb6b22feea1a8bfdbc0d241136e4d13417e25" 3817 + checksum = "06718a168365cad3d5ff0bb133aad346959a2074bd4a85c121255a11304a8626" 3826 3818 dependencies = [ 3827 3819 "proc-macro2", 3828 3820 "quote",
+2 -3
Cargo.toml
··· 27 27 28 28 [build-dependencies] 29 29 fs_extra = "1.3" 30 - glob = "0.3" 31 30 32 31 [lib] 33 32 crate-type = ["cdylib", "rlib"] ··· 35 34 [target.'cfg(target_arch = "wasm32")'.dependencies] 36 35 console_error_panic_hook = "0.1.6" 37 36 console_log = "1.0" 38 - wgpu = { version = "24", features = ["webgl"]} 37 + wgpu = { version = "24", features = ["webgl"] } 39 38 wasm-bindgen = "0.2" 40 39 wasm-bindgen-futures = "0.4" 41 40 web-sys = { version = "0.3", features = [ ··· 43 42 "Window", 44 43 "Element", 45 44 "Location", 46 - ]} 45 + ] } 47 46 reqwest = "0.12"
+537 -204
src/gfx.rs
··· 1 + use std::borrow::Borrow; 1 2 mod camera; 3 + mod light; 2 4 mod model; 3 5 mod resources; 4 6 mod texture; 5 7 6 - use std::sync::Arc; 7 - 8 + use egui::text_selection::text_cursor_state::slice_char_range; 9 + use egui::Key::A; 8 10 use egui_wgpu::ScreenDescriptor; 9 - use glam::{vec3, IVec3, Quat, Vec3}; 11 + use glam::{vec3, IVec3, Mat4, Quat, Vec3, Vec4, Vec4Swizzles}; 12 + use light::LightUniform; 13 + use std::ops::Deref; 14 + use std::{f32::consts::PI, path::Path, sync::Arc}; 10 15 use wgpu::util::DeviceExt; 16 + use wgpu::BindingResource; 11 17 use winit::{ 12 18 dpi::PhysicalSize, 13 19 event::{ElementState, KeyEvent, WindowEvent}, ··· 16 22 window::Window, 17 23 }; 18 24 25 + use crate::gfx::camera::CameraUniform; 26 + use crate::gfx::model::DrawLight; 19 27 use crate::{ 20 - app::WASM_WIN_SIZE, gfx::model::Vertex, gui::EguiRenderer, world::map::{sl3get, Block, WorldMap, CHUNK_SIZE}, world::World, Instance, InstanceRaw 28 + app::WASM_WIN_SIZE, 29 + gfx::model::Vertex, 30 + gui::EguiRenderer, 31 + world::map::{sl3get, Block, WorldMap, CHUNK_SIZE}, 32 + world::World, 33 + Instance, InstanceRaw, 21 34 }; 22 35 23 - #[repr(C)] 24 - #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] 25 - pub(crate) struct LightUniform { 26 - position: Vec3, 27 - _pad: u32, 28 - color: Vec3, 29 - _pad2: u32, 30 - } 31 - impl LightUniform { 32 - pub fn new(position: Vec3, color: Vec3) -> LightUniform { 33 - LightUniform { 34 - position, 35 - color, 36 - _pad: 0, 37 - _pad2: 0, 38 - } 39 - } 40 - } 41 - 42 36 pub struct CameraState { 43 - pub positioning: camera::Camera, 37 + pub object: camera::Camera, 44 38 pub controller: camera::CameraController, 45 - pub uniform: camera::CameraUniform, 46 - pub buffer: wgpu::Buffer, 47 - pub bind_group: wgpu::BindGroup, 39 + pub uniform: CameraUniform, 48 40 } 49 41 pub struct InteractState { 50 42 pub clear_color: wgpu::Color, ··· 58 50 } 59 51 60 52 pub struct LightState { 61 - pub uniform: LightUniform, 62 - pub buffer: wgpu::Buffer, 63 - pub bind_group: wgpu::BindGroup, 53 + pub object: camera::Camera, 54 + pub uniform: CameraUniform, 55 + pub shadow_map: texture::Texture, 64 56 } 65 57 66 58 pub struct RenderPipelines { ··· 117 109 vertex_layouts: &[wgpu::VertexBufferLayout], 118 110 shader: wgpu::ShaderModuleDescriptor, 119 111 polygon_mode: wgpu::PolygonMode, 112 + label: Option<&str>, 120 113 ) -> wgpu::RenderPipeline { 121 114 let shader = device.create_shader_module(shader); 122 115 123 116 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { 124 - label: Some("Render Pipeline"), 117 + label, 125 118 layout: Some(layout), 126 119 vertex: wgpu::VertexState { 127 120 module: &shader, ··· 171 164 }) 172 165 } 173 166 167 + pub enum OneOrTwo<T> { 168 + One(T), 169 + Two(T, T), 170 + } 171 + 172 + impl<T> OneOrTwo<T> { 173 + pub fn one(&mut self) -> &mut T { 174 + match self { 175 + OneOrTwo::One(t) => t, 176 + OneOrTwo::Two(_, _) => { 177 + panic!("Used one() on a Two.") 178 + } 179 + } 180 + } 181 + pub fn two(&mut self) -> (&mut T, &mut T) { 182 + match self { 183 + OneOrTwo::One(t) => panic!("Used two() on a One."), 184 + OneOrTwo::Two(x, y) => (x, y), 185 + } 186 + } 187 + } 188 + pub struct Pass { 189 + pipeline: OneOrTwo<wgpu::RenderPipeline>, 190 + bind_group: wgpu::BindGroup, 191 + uniform_bufs: Vec<wgpu::Buffer>, 192 + } 193 + 174 194 pub struct Gfx { 175 195 pub surface: wgpu::Surface<'static>, 176 196 pub device: wgpu::Device, 177 197 pub queue: wgpu::Queue, 178 198 pub surface_config: wgpu::SurfaceConfiguration, 179 - pub render_pipelines: RenderPipelines, 199 + // pub render_pipelines: RenderPipelines, 180 200 pub depth_texture: texture::Texture, 201 + 202 + // pub shadow_map_buffer: wgpu::Buffer, 203 + // pub shadow_bind_group: wgpu::BindGroup, 204 + pub shadow_pass: Pass, 205 + pub forward_pass: Pass, 181 206 182 207 pub object: ObjectState, 183 208 pub camera: CameraState, ··· 297 322 target: Vec3::ZERO, 298 323 up: Vec3::Y, 299 324 aspect: surface_config.width as f32 / surface_config.height as f32, 300 - fovy: 45.0, 325 + fovy: PI / 2., 301 326 znear: 0.1, 302 327 zfar: 1000.0, 303 328 }; 304 329 let camera_controller = camera::CameraController::new(0.2); 305 330 let mut camera_uniform = camera::CameraUniform::new(); 306 331 camera_uniform.update_view_proj(&camera); 307 - let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 308 - label: Some("Camera Buffer"), 309 - contents: bytemuck::cast_slice(&[camera_uniform]), 310 - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, 311 - }); 312 - let camera_bind_group_layout = 313 - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 314 - entries: &[wgpu::BindGroupLayoutEntry { 315 - binding: 0, 316 - visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, 317 - ty: wgpu::BindingType::Buffer { 318 - ty: wgpu::BufferBindingType::Uniform, 319 - has_dynamic_offset: false, 320 - min_binding_size: None, 321 - }, 322 - count: None, 323 - }], 324 - label: Some("camera_bind_group_layout"), 325 - }); 326 - let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { 327 - layout: &camera_bind_group_layout, 328 - entries: &[wgpu::BindGroupEntry { 329 - binding: 0, 330 - resource: camera_buffer.as_entire_binding(), 331 - }], 332 - label: Some("camera_bind_group"), 333 - }); 332 + 333 + // let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { 334 + // layout: &camera_bind_group_layout, 335 + // entries: &[wgpu::BindGroupEntry { 336 + // binding: 0, 337 + // resource: camera_buffer.as_entire_binding(), 338 + // }], 339 + // label: Some("camera_bind_group"), 340 + // }); 334 341 let camera_state = CameraState { 335 - positioning: camera, 342 + object: camera, 336 343 controller: camera_controller, 337 344 uniform: camera_uniform, 338 - buffer: camera_buffer, 339 - bind_group: camera_bind_group, 340 345 }; 341 346 342 347 // MAP LOAD ··· 361 366 .await 362 367 .unwrap(); 363 368 364 - let light_uniform = LightUniform::new(Vec3::splat(90.0).with_y(40.0), vec3(1.0, 1.0, 0.5)); 369 + log::info!("Light setup!"); 370 + let light = camera::Camera { 371 + eye: vec3(90., 40., 90.), 372 + target: Vec3::ZERO, 373 + up: Vec3::Y, 374 + aspect: surface_config.width as f32 / surface_config.height as f32, 375 + fovy: PI / 2., 376 + znear: 0.1, 377 + zfar: 1000.0, 378 + }; 379 + let mut light_uniform = camera::CameraUniform::new(); 380 + light_uniform.update_view_proj(&light); 381 + 382 + //let light_uniform = LightUniform::new(Vec3::splat(90.0).with_y(40.0), vec3(1.0, 1.0, 1.0)); 365 383 366 - let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 367 - label: Some("Light VB"), 368 - contents: bytemuck::cast_slice(&[light_uniform]), 369 - usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, 384 + log::info!("Shadowmap setup!"); 385 + let shadow_sampler = device.create_sampler(&wgpu::SamplerDescriptor { 386 + label: Some("Shadow Sampler"), 387 + address_mode_u: wgpu::AddressMode::ClampToEdge, 388 + address_mode_v: wgpu::AddressMode::ClampToEdge, 389 + address_mode_w: wgpu::AddressMode::ClampToEdge, 390 + mag_filter: wgpu::FilterMode::Linear, 391 + min_filter: wgpu::FilterMode::Linear, 392 + mipmap_filter: wgpu::FilterMode::Nearest, 393 + compare: Some(wgpu::CompareFunction::LessEqual), 394 + ..Default::default() 370 395 }); 371 396 372 - let light_bind_group_layout = 373 - device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 374 - entries: &[wgpu::BindGroupLayoutEntry { 375 - binding: 0, 376 - visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, 377 - ty: wgpu::BindingType::Buffer { 378 - ty: wgpu::BufferBindingType::Uniform, 379 - has_dynamic_offset: false, 380 - min_binding_size: None, 381 - }, 382 - count: None, 383 - }], 384 - label: None, 397 + log::info!("asdfasdgf"); 398 + 399 + let shadow_map = 400 + texture::Texture::create_depth_texture(&device, &surface_config, "Shadow Map"); 401 + // let shadow_texture = device.create_texture(&wgpu::TextureDescriptor { 402 + // size: wgpu::Extent3d { 403 + // width: 1024, 404 + // height: 1024, 405 + // depth_or_array_layers: 10, 406 + // }, 407 + // mip_level_count: 1, 408 + // sample_count: 1, 409 + // dimension: wgpu::TextureDimension::D2, 410 + // format: wgpu::TextureFormat::Depth32Float, 411 + // usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING, 412 + // label: Some("Shadow texture"), 413 + // view_formats: &[], 414 + // }); 415 + // For forward pass 416 + // let shadow_view = shadow_texture.create_view(&wgpu::TextureViewDescriptor::default()); 417 + 418 + log::info!("alskjgsdl;kfgjs;dkjl"); 419 + // For light in shadow pass 420 + // let light_shadow_map = shadow_texture.create_view(&wgpu::TextureViewDescriptor { 421 + // label: Some("Shadow Map"), 422 + // format: Some(wgpu::TextureFormat::Depth32Float), 423 + // dimension: Some(wgpu::TextureViewDimension::D2), 424 + // usage: None, 425 + // aspect: wgpu::TextureAspect::All, 426 + // base_mip_level: 0, 427 + // mip_level_count: None, 428 + // base_array_layer: 0 as u32, 429 + // array_layer_count: Some(1), 430 + // }); 431 + 432 + // let shadow_map_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 433 + // label: Some("Shadow Map Buffer"), 434 + // contents: bytemuck::cast_slice(&[camera_uniform]), 435 + // usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, 436 + // }); 437 + 438 + // let shadow_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 439 + // entries: &[wgpu::BindGroupLayoutEntry { 440 + // binding: 0, 441 + // visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, 442 + // ty: wgpu::BindingType::Buffer { 443 + // ty: wgpu::BufferBindingType::Uniform, 444 + // has_dynamic_offset: false, 445 + // min_binding_size: None, 446 + // }, 447 + // count: None, 448 + // }], 449 + // label: None, 450 + // }); 451 + // let shadow_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { 452 + // layout: &shadow_bgl, 453 + // entries: &[wgpu::BindGroupEntry { 454 + // binding: 0, 455 + // resource: light_buffer.as_entire_binding(), 456 + // }], 457 + // label: None, 458 + // }); 459 + 460 + log::info!("Pipeline setup!"); 461 + // New stuff goes above here! 462 + 463 + log::info!("Pipeline/Globals setup!"); 464 + // let render_pipeline = { 465 + // let shader = wgpu::ShaderModuleDescriptor { 466 + // label: Some("Normal Shader"), 467 + // source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), 468 + // }; 469 + // create_render_pipeline( 470 + // &device, 471 + // &render_pipeline_layout, 472 + // surface_config.format, 473 + // Some(texture::Texture::DEPTH_FORMAT), 474 + // &[model::ModelVertex::desc(), InstanceRaw::desc()], 475 + // shader, 476 + // wgpu::PolygonMode::Fill, 477 + // Some("Normal Render Pipeline"), 478 + // ) 479 + // }; 480 + // 481 + // //let fill_pipeline = render_pipeline(wgpu::PolygonMode::Fill); 482 + // let wireframe_render_pipeline = if (device.features() & wgpu::Features::POLYGON_MODE_LINE) 483 + // == wgpu::Features::POLYGON_MODE_LINE 484 + // { 485 + // Some({ 486 + // let shader = wgpu::ShaderModuleDescriptor { 487 + // label: Some("Normal Shader"), 488 + // source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), 489 + // }; 490 + // create_render_pipeline( 491 + // &device, 492 + // &render_pipeline_layout, 493 + // surface_config.format, 494 + // Some(texture::Texture::DEPTH_FORMAT), 495 + // &[model::ModelVertex::desc(), InstanceRaw::desc()], 496 + // shader, 497 + // wgpu::PolygonMode::Line, 498 + // Some("Normal Render Pipeline"), 499 + // ) 500 + // }) 501 + // } else { 502 + // None 503 + // }; 504 + 505 + fn bgl_t(binding: u32) -> wgpu::BindGroupLayoutEntry { 506 + wgpu::BindGroupLayoutEntry { 507 + binding, 508 + visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT, 509 + ty: wgpu::BindingType::Buffer { 510 + ty: wgpu::BufferBindingType::Uniform, 511 + has_dynamic_offset: false, 512 + min_binding_size: None, 513 + }, 514 + count: None, 515 + } 516 + } 517 + fn bge(binding: u32, resource: BindingResource<'_>) -> wgpu::BindGroupEntry { 518 + wgpu::BindGroupEntry { binding, resource } 519 + } 520 + 521 + log::info!("Pipeline/Shadow setup!"); 522 + 523 + let shadow_pass = { 524 + let camera_buffer = device.create_buffer(&wgpu::BufferDescriptor { 525 + label: Some("Camera Buffer"), 526 + size: size_of::<camera::CameraUniform>() as wgpu::BufferAddress, 527 + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, 528 + mapped_at_creation: false, 529 + }); 530 + let light_buffer = device.create_buffer(&wgpu::BufferDescriptor { 531 + label: Some("Light VB"), 532 + size: size_of::<CameraUniform>() as wgpu::BufferAddress, 533 + usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, 534 + mapped_at_creation: false, 385 535 }); 386 536 387 - let light_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { 388 - layout: &light_bind_group_layout, 389 - entries: &[wgpu::BindGroupEntry { 390 - binding: 0, 391 - resource: light_buffer.as_entire_binding(), 392 - }], 393 - label: None, 394 - }); 537 + let bind_group_layout = 538 + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 539 + label: None, 540 + entries: &[ 541 + // Camera 542 + bgl_t(0), 543 + // Light position 544 + bgl_t(1), 545 + ], 546 + }); 395 547 396 - // New stuff goes above here! 397 - let render_pipeline_layout = 398 - device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { 399 - label: Some("Render Pipeline Layout"), 400 - bind_group_layouts: &[ 401 - &texture_bind_group_layout, 402 - &camera_bind_group_layout, 403 - &light_bind_group_layout, 548 + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { 549 + label: None, 550 + layout: &bind_group_layout, 551 + entries: &[ 552 + bge(0, camera_buffer.as_entire_binding()), 553 + bge(1, light_buffer.as_entire_binding()), 404 554 ], 555 + }); 556 + 557 + let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { 558 + label: Some("Shadow Pipeline Layout"), 559 + bind_group_layouts: &[&bind_group_layout], 405 560 push_constant_ranges: &[], 406 561 }); 407 562 408 - let render_pipeline = { 409 563 let shader = wgpu::ShaderModuleDescriptor { 410 - label: Some("Normal Shader"), 411 - source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), 564 + label: Some("Shadow Shader"), 565 + source: wgpu::ShaderSource::Wgsl(include_str!("shadows.wgsl").into()), 412 566 }; 413 - create_render_pipeline( 567 + 568 + let shader = device.create_shader_module(shader); 569 + 570 + let pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { 571 + label: Some("Shadows Render Pipeline"), 572 + layout: Some(&pipeline_layout), 573 + vertex: wgpu::VertexState { 574 + module: &shader, 575 + entry_point: Some("vs_main"), 576 + buffers: &[model::ModelVertex::desc(), InstanceRaw::desc()], 577 + compilation_options: Default::default(), 578 + }, 579 + fragment: None, 580 + primitive: wgpu::PrimitiveState { 581 + topology: wgpu::PrimitiveTopology::TriangleList, 582 + strip_index_format: None, 583 + front_face: wgpu::FrontFace::Ccw, 584 + cull_mode: Some(wgpu::Face::Back), 585 + // Setting this to anything other than Fill requires Features::NON_FILL_POLYGON_MODE 586 + polygon_mode: wgpu::PolygonMode::Fill, 587 + // Requires Features::DEPTH_CLIP_CONTROL 588 + unclipped_depth: false, 589 + // Requires Features::CONSERVATIVE_RASTERIZATION 590 + conservative: false, 591 + }, 592 + depth_stencil: Some(wgpu::DepthStencilState { 593 + format: wgpu::TextureFormat::Depth32Float, 594 + depth_write_enabled: true, 595 + depth_compare: wgpu::CompareFunction::Less, 596 + stencil: wgpu::StencilState::default(), 597 + bias: wgpu::DepthBiasState::default(), 598 + }), 599 + multisample: wgpu::MultisampleState { 600 + count: 1, 601 + mask: !0, 602 + alpha_to_coverage_enabled: false, 603 + }, 604 + multiview: None, 605 + cache: None, 606 + }); 607 + 608 + Pass { 609 + pipeline: OneOrTwo::One(pipeline), 610 + bind_group, 611 + uniform_bufs: vec![camera_buffer, light_buffer], 612 + } 613 + }; 614 + 615 + let forward_pass = { 616 + let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 617 + label: Some("Camera Buffer"), 618 + contents: bytemuck::cast_slice(&[camera_uniform]), 619 + usage: wgpu::BufferUsages::UNIFORM 620 + | wgpu::BufferUsages::COPY_DST 621 + | wgpu::BufferUsages::COPY_SRC, 622 + }); 623 + let light_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { 624 + label: Some("Light VB"), 625 + contents: bytemuck::cast_slice(&[light_uniform]), 626 + usage: wgpu::BufferUsages::UNIFORM 627 + | wgpu::BufferUsages::COPY_DST 628 + | wgpu::BufferUsages::COPY_SRC, 629 + }); 630 + 631 + let bind_group_layout = 632 + device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { 633 + entries: &[ 634 + // Camera positional Data 635 + bgl_t(0), 636 + // Light positional data 637 + bgl_t(1), 638 + // Shadowmap 639 + wgpu::BindGroupLayoutEntry { 640 + binding: 2, 641 + visibility: wgpu::ShaderStages::FRAGMENT, 642 + ty: wgpu::BindingType::Texture { 643 + sample_type: wgpu::TextureSampleType::Depth, 644 + view_dimension: wgpu::TextureViewDimension::D2, 645 + multisampled: false, 646 + }, 647 + count: None, 648 + }, 649 + wgpu::BindGroupLayoutEntry { 650 + binding: 3, 651 + visibility: wgpu::ShaderStages::FRAGMENT, 652 + ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Comparison), 653 + count: None, 654 + }, 655 + ], 656 + label: None, 657 + }); 658 + 659 + let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor { 660 + layout: &bind_group_layout, 661 + entries: &[ 662 + bge(0, camera_buffer.as_entire_binding()), 663 + bge(1, light_buffer.as_entire_binding()), 664 + bge(2, BindingResource::TextureView(&shadow_map.view)), 665 + bge(3, BindingResource::Sampler(&shadow_map.sampler)), 666 + ], 667 + label: None, 668 + }); 669 + 670 + let render_pipeline = create_render_pipeline( 414 671 &device, 415 - &render_pipeline_layout, 672 + &device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { 673 + label: Some("Render Pipeline Layout"), 674 + bind_group_layouts: &[&texture_bind_group_layout, &bind_group_layout], 675 + push_constant_ranges: &[], 676 + }), 416 677 surface_config.format, 417 678 Some(texture::Texture::DEPTH_FORMAT), 418 679 &[model::ModelVertex::desc(), InstanceRaw::desc()], 419 - shader, 420 - wgpu::PolygonMode::Fill, 421 - ) 422 - }; 423 - 424 - //let fill_pipeline = render_pipeline(wgpu::PolygonMode::Fill); 425 - let wireframe_render_pipeline = if (device.features() & wgpu::Features::POLYGON_MODE_LINE) 426 - == wgpu::Features::POLYGON_MODE_LINE 427 - { 428 - Some({ 429 - let shader = wgpu::ShaderModuleDescriptor { 680 + wgpu::ShaderModuleDescriptor { 430 681 label: Some("Normal Shader"), 431 682 source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), 432 - }; 433 - create_render_pipeline( 434 - &device, 435 - &render_pipeline_layout, 436 - surface_config.format, 437 - Some(texture::Texture::DEPTH_FORMAT), 438 - &[model::ModelVertex::desc(), InstanceRaw::desc()], 439 - shader, 440 - wgpu::PolygonMode::Line, 441 - ) 442 - }) 443 - } else { 444 - None 445 - }; 683 + }, 684 + wgpu::PolygonMode::Fill, 685 + Some("Normal Render Pipeline"), 686 + ); 446 687 447 - let light_render_pipeline = { 448 - let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { 449 - label: Some("Light Pipeline Layout"), 450 - bind_group_layouts: &[&camera_bind_group_layout, &light_bind_group_layout], 451 - push_constant_ranges: &[], 452 - }); 453 - let shader = wgpu::ShaderModuleDescriptor { 454 - label: Some("Light Shader"), 455 - source: wgpu::ShaderSource::Wgsl(include_str!("light.wgsl").into()), 456 - }; 457 - create_render_pipeline( 688 + log::info!("Pipeline/Light setup!"); 689 + let light_render_pipeline = create_render_pipeline( 458 690 &device, 459 - &layout, 691 + &device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { 692 + label: Some("Light Pipeline Layout"), 693 + bind_group_layouts: &[&bind_group_layout], 694 + push_constant_ranges: &[], 695 + }), 460 696 surface_config.format, 461 697 Some(texture::Texture::DEPTH_FORMAT), 462 - &[model::ModelVertex::desc()], 463 - shader, 698 + &[model::ModelVertex::desc(), InstanceRaw::desc()], 699 + wgpu::ShaderModuleDescriptor { 700 + label: Some("Light Shader"), 701 + source: wgpu::ShaderSource::Wgsl(include_str!("light.wgsl").into()), 702 + }, 464 703 wgpu::PolygonMode::Fill, 465 - ) 704 + Some("Light Render Pipeline"), 705 + ); 706 + 707 + Pass { 708 + pipeline: OneOrTwo::Two(render_pipeline, light_render_pipeline), 709 + bind_group, 710 + uniform_bufs: vec![camera_buffer, light_buffer], 711 + } 466 712 }; 713 + 714 + log::debug!("Initialized!"); 467 715 468 716 Self { 469 717 surface, ··· 472 720 surface_config, 473 721 depth_texture, 474 722 camera: camera_state, 723 + shadow_pass, 724 + forward_pass, 475 725 interact: InteractState { 476 726 wireframe: false, 477 727 clear_color: wgpu::Color { ··· 480 730 b: 0.3, 481 731 a: 1.0, 482 732 }, 483 - }, 484 - render_pipelines: RenderPipelines { 485 - camera: render_pipeline, 486 - camera_wireframe: wireframe_render_pipeline, 487 - light: light_render_pipeline, 488 733 }, 489 734 object: ObjectState { 490 735 model: obj_model, ··· 493 738 remake: false, 494 739 }, 495 740 light: LightState { 741 + object: light, 496 742 uniform: light_uniform, 497 - buffer: light_buffer, 498 - bind_group: light_bind_group, 743 + shadow_map, 499 744 }, 500 745 } 501 746 } ··· 507 752 508 753 self.surface_config.width = new_size.width; 509 754 self.surface_config.height = new_size.height; 510 - self.camera.positioning.aspect = 755 + self.camera.object.aspect = 511 756 self.surface_config.width as f32 / self.surface_config.height as f32; 512 757 self.surface.configure(&self.device, &self.surface_config); 513 758 ··· 531 776 return None; 532 777 } 533 778 534 - let chunk_offset = IVec3::from(*coords).as_vec3() * (SPACE_BETWEEN * CHUNK_SIZE.0 as f32); 779 + let chunk_offset = 780 + IVec3::from(*coords).as_vec3() * (SPACE_BETWEEN * CHUNK_SIZE.0 as f32); 535 781 536 782 let mapping = |n| SPACE_BETWEEN * (n as f32 - CHUNK_SIZE.0 as f32 / 2.0); 537 783 let position = vec3( ··· 552 798 } 553 799 554 800 pub fn update_instance_buf(&mut self, map: &WorldMap) { 555 - let instances = Self::remake_instance_buf(&map); 801 + let instances = Self::remake_instance_buf(map); 556 802 557 803 let instance_data = instances.iter().map(Instance::to_raw).collect::<Vec<_>>(); 558 804 let instance_buffer = self ··· 585 831 label: Some("Render Encoder"), 586 832 }); 587 833 588 - let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { 589 - label: Some("Render Pass"), 590 - color_attachments: &[Some(wgpu::RenderPassColorAttachment { 591 - view: &view, 592 - resolve_target: None, 593 - ops: wgpu::Operations { 594 - load: wgpu::LoadOp::Clear(self.interact.clear_color), 595 - store: wgpu::StoreOp::Store, 596 - }, 597 - })], 598 - depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { 599 - view: &self.depth_texture.view, 600 - depth_ops: Some(wgpu::Operations { 601 - load: wgpu::LoadOp::Clear(1.0), 602 - store: wgpu::StoreOp::Store, 834 + log::debug!("Hi renderer!"); 835 + 836 + encoder.push_debug_group("Shadow pass"); 837 + use crate::gfx::model::DrawModel; 838 + 839 + // Shadow-map Pass 840 + { 841 + let Pass { 842 + pipeline, 843 + bind_group, 844 + uniform_bufs, 845 + } = &mut self.shadow_pass; 846 + 847 + encoder.copy_buffer_to_buffer( 848 + &self.forward_pass.uniform_bufs[0], 849 + 0, 850 + &uniform_bufs[0], 851 + 0, 852 + size_of::<CameraUniform>() as wgpu::BufferAddress, 853 + ); 854 + encoder.copy_buffer_to_buffer( 855 + &self.forward_pass.uniform_bufs[1], 856 + 0, 857 + &uniform_bufs[1], 858 + 0, 859 + size_of::<CameraUniform>() as wgpu::BufferAddress, 860 + ); 861 + 862 + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { 863 + label: Some("Shadow Render Pass"), 864 + color_attachments: &[], 865 + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { 866 + view: &self.light.shadow_map.view, // Shadow map written here 867 + depth_ops: Some(wgpu::Operations { 868 + load: wgpu::LoadOp::Clear(1.0), 869 + store: wgpu::StoreOp::Store, 870 + }), 871 + stencil_ops: None, 872 + }), 873 + occlusion_query_set: None, 874 + timestamp_writes: None, 875 + }); 876 + render_pass.set_pipeline(pipeline.one()); 877 + render_pass.set_vertex_buffer(1, self.object.instance_buffer.slice(..)); 878 + 879 + render_pass.draw_light_model_instanced( 880 + &self.object.model, 881 + 0..self.object.instances.len() as u32, 882 + &[bind_group], 883 + ); 884 + 885 + drop(render_pass); 886 + } 887 + 888 + encoder.pop_debug_group(); 889 + 890 + encoder.push_debug_group("Forward pass"); 891 + 892 + { 893 + let Pass { 894 + pipeline, 895 + bind_group, 896 + uniform_bufs, 897 + } = &mut self.forward_pass; 898 + 899 + let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { 900 + label: Some("Forward Render Pass"), 901 + color_attachments: &[Some(wgpu::RenderPassColorAttachment { 902 + view: &view, 903 + resolve_target: None, 904 + ops: wgpu::Operations { 905 + load: wgpu::LoadOp::Clear(self.interact.clear_color), 906 + store: wgpu::StoreOp::Store, 907 + }, 908 + })], 909 + depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment { 910 + view: &self.depth_texture.view, 911 + depth_ops: Some(wgpu::Operations { 912 + load: wgpu::LoadOp::Clear(1.0), 913 + store: wgpu::StoreOp::Store, 914 + }), 915 + stencil_ops: None, 603 916 }), 604 - stencil_ops: None, 605 - }), 606 - occlusion_query_set: None, 607 - timestamp_writes: None, 608 - }); 917 + occlusion_query_set: None, 918 + timestamp_writes: None, 919 + }); 609 920 610 - render_pass.set_vertex_buffer(1, self.object.instance_buffer.slice(..)); 921 + render_pass.set_vertex_buffer(1, self.object.instance_buffer.slice(..)); 611 922 612 - use crate::gfx::model::DrawLight; 613 - render_pass.set_pipeline(&self.render_pipelines.light); 614 - render_pass.draw_light_model( 615 - &self.object.model, 616 - &self.camera.bind_group, 617 - &self.light.bind_group, 618 - ); 923 + // use crate::gfx::model::DrawLight; 924 + // render_pass.set_pipeline(pipeline.two().1); 925 + // render_pass.draw_light_model( 926 + // &self.object.model, 927 + // &self.camera.bind_group, 928 + // &self.light.bind_group, 929 + // ); 619 930 620 - use crate::gfx::model::DrawModel; 621 - render_pass.set_pipeline( 622 - self.interact 623 - .wireframe 624 - .then_some(self.render_pipelines.camera_wireframe.as_ref()) 625 - .flatten() 626 - .unwrap_or(&self.render_pipelines.camera), 627 - ); 931 + // render_pass.set_pipeline(&self.render_pipelines.cam); 932 + // render_pass.draw_model_instanced( 933 + // &self.object.model, 934 + // 0..self.object.instances.len() as u32, 935 + // &self.camera.bind_group, 936 + // &self.light.bind_group, 937 + // ); 628 938 629 - render_pass.draw_model_instanced( 630 - &self.object.model, 631 - 0..self.object.instances.len() as u32, 632 - &self.camera.bind_group, 633 - &self.light.bind_group, 634 - ); 939 + /* render_pass.set_pipeline( 940 + self.interact 941 + .wireframe 942 + .then_some(self.render_pipelines.camera_wireframe.as_ref()) 943 + .flatten() 944 + .unwrap_or(&self.render_pipelines.camera), 945 + );*/ 946 + 947 + render_pass.set_pipeline(pipeline.two().0); 948 + 949 + render_pass.draw_model_instanced( 950 + &self.object.model, 951 + 0..self.object.instances.len() as u32, 952 + &[bind_group], 953 + ); 954 + 955 + drop(render_pass); 956 + } 635 957 636 958 // drop render pass before we submit to drop the mut borrow on encoder 637 - drop(render_pass); 959 + 960 + encoder.pop_debug_group(); 638 961 639 962 // Layer EGUI on top of frame! 640 963 ··· 671 994 pub fn update(&mut self, world: &mut World) { 672 995 self.camera 673 996 .controller 674 - .update_camera(&mut self.camera.positioning); 675 - self.camera 676 - .uniform 677 - .update_view_proj(&self.camera.positioning); 997 + .update_camera(&mut self.camera.object); 998 + 999 + // dbg 1000 + //self.camera.object.eye = self.light.uniform.view_pos; 1001 + 1002 + self.camera.uniform.update_view_proj(&self.camera.object); 678 1003 self.queue.write_buffer( 679 - &self.camera.buffer, 1004 + &self.forward_pass.uniform_bufs[0], 680 1005 0, 681 1006 bytemuck::cast_slice(&[self.camera.uniform]), 682 1007 ); 683 1008 684 - let old_position: Vec3 = self.light.uniform.position; 685 - self.light.uniform.position = 686 - Quat::from_axis_angle(vec3(0.0, 1.0, 0.0), 0.01) * old_position; 1009 + self.light.object.eye = 1010 + Quat::from_axis_angle(vec3(0.0, 1.0, 0.0), 0.01) * self.light.object.eye; 1011 + self.light.uniform.update_view_proj(&self.light.object); 1012 + 1013 + // let old_position: Vec3 = self.light.uniform.view_pos; 1014 + // self.light.uniform.view_pos = 1015 + // Quat::from_axis_angle(vec3(0.0, 1.0, 0.0), 0.01) * old_position; 1016 + // self.light 1017 + // .uniform 1018 + // .update_view_proj(self.surface_config.width as f32 / self.surface_config.height as f32); 1019 + 687 1020 self.queue.write_buffer( 688 - &self.light.buffer, 1021 + &self.forward_pass.uniform_bufs[1], 689 1022 0, 690 1023 bytemuck::cast_slice(&[self.light.uniform]), 691 1024 );
+2 -2
src/gfx/camera.rs
··· 27 27 #[repr(C)] 28 28 #[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] 29 29 pub struct CameraUniform { 30 - view_position: Vec4, 31 - view_proj: Mat4, 30 + pub view_position: Vec4, 31 + pub view_proj: Mat4, 32 32 } 33 33 34 34 impl CameraUniform {
+46
src/gfx/light.rs
··· 1 + use std::f32::consts::PI; 2 + 3 + use crate::gfx::camera::Camera; 4 + use glam::{vec3, Mat4, Vec3, Vec4}; 5 + 6 + #[repr(C)] 7 + #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] 8 + pub(crate) struct LightUniform { 9 + pub view_pos: Vec3, 10 + _pad: u32, 11 + pub view_proj: Mat4, 12 + pub color: Vec3, 13 + _pad2: u32, 14 + } 15 + impl LightUniform { 16 + pub fn new(position: Vec3, color: Vec3) -> LightUniform { 17 + LightUniform { 18 + view_pos: position, 19 + view_proj: { 20 + let view = Mat4::look_at_rh(position, Vec3::ZERO, Vec3::Y); 21 + let proj = Mat4::perspective_rh(PI / 2., 1.0, 0.1, 1000.0); 22 + 23 + view * proj 24 + }, 25 + color, 26 + _pad: 0, 27 + _pad2: 0, 28 + } 29 + } 30 + 31 + pub fn update_view_proj(&mut self, aspect_ratio: f32) { 32 + self.view_proj = { 33 + let view = Mat4::look_at_rh(vec3(50., 20., 50.), Vec3::ZERO, Vec3::Y); 34 + let proj = Mat4::perspective_rh(PI / 2., aspect_ratio, 0.1, 1000.0); 35 + 36 + view * proj 37 + }; 38 + } 39 + 40 + // pub fn build_view_projection_matrix(&self) -> Mat4 { 41 + // let view = Mat4::look_at_rh(self.eye, self.target, self.up); 42 + // let proj = Mat4::perspective_rh(self.fovy, self.aspect, self.znear, self.zfar); 43 + 44 + // proj * view 45 + // } 46 + }
+30 -79
src/gfx/model.rs
··· 1 - use std::ops::Range; 2 - 3 1 use super::texture; 2 + use std::ops::Range; 3 + use wasm_bindgen::__rt::__wbindgen_exn_store; 4 4 5 5 pub trait Vertex { 6 6 fn desc() -> wgpu::VertexBufferLayout<'static>; ··· 66 66 &mut self, 67 67 mesh: &'a Mesh, 68 68 material: &'a Material, 69 - camera_bind_group: &'a wgpu::BindGroup, 70 - light_bind_group: &'a wgpu::BindGroup, 69 + bind_groups: &[&'a wgpu::BindGroup], 71 70 ); 72 71 fn draw_mesh_instanced( 73 72 &mut self, 74 73 mesh: &'a Mesh, 75 74 material: &'a Material, 76 75 instances: Range<u32>, 77 - camera_bind_group: &'a wgpu::BindGroup, 78 - light_bind_group: &'a wgpu::BindGroup, 79 - ); 80 - fn draw_model( 81 - &mut self, 82 - model: &'a Model, 83 - camera_bind_group: &'a wgpu::BindGroup, 84 - light_bind_group: &'a wgpu::BindGroup, 76 + bind_groups: &[&'a wgpu::BindGroup], 85 77 ); 78 + fn draw_model(&mut self, model: &'a Model, bind_groups: &[&'a wgpu::BindGroup]); 86 79 fn draw_model_instanced( 87 80 &mut self, 88 81 model: &'a Model, 89 82 instances: Range<u32>, 90 - camera_bind_group: &'a wgpu::BindGroup, 91 - light_bind_group: &'a wgpu::BindGroup, 83 + bind_groups: &[&'a wgpu::BindGroup], 92 84 ); 93 85 } 94 86 ··· 100 92 &mut self, 101 93 mesh: &'b Mesh, 102 94 material: &'b Material, 103 - camera_bind_group: &'b wgpu::BindGroup, 104 - light_bind_group: &'b wgpu::BindGroup, 95 + bind_groups: &[&'b wgpu::BindGroup], 105 96 ) { 106 - self.draw_mesh_instanced(mesh, material, 0..1, camera_bind_group, light_bind_group); 97 + self.draw_mesh_instanced(mesh, material, 0..1, bind_groups); 107 98 } 108 99 109 100 fn draw_mesh_instanced( ··· 111 102 mesh: &'b Mesh, 112 103 material: &'a Material, 113 104 instances: Range<u32>, 114 - camera_bind_group: &'b wgpu::BindGroup, 115 - light_bind_group: &'b wgpu::BindGroup, 105 + bind_groups: &[&'b wgpu::BindGroup], 116 106 ) { 117 107 self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); 118 108 self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32); 119 109 self.set_bind_group(0, &material.bind_group, &[]); 120 - self.set_bind_group(1, camera_bind_group, &[]); 121 - self.set_bind_group(2, light_bind_group, &[]); 110 + for (i, group) in bind_groups.iter().enumerate() { 111 + self.set_bind_group((i + 1) as u32, *group, &[]); 112 + } 122 113 self.draw_indexed(0..mesh.num_elements, 0, instances); 123 114 } 124 - fn draw_model( 125 - &mut self, 126 - model: &'b Model, 127 - camera_bind_group: &'b wgpu::BindGroup, 128 - light_bind_group: &'b wgpu::BindGroup, 129 - ) { 130 - self.draw_model_instanced(model, 0..1, camera_bind_group, light_bind_group); 115 + fn draw_model(&mut self, model: &'b Model, bind_groups: &[&'b wgpu::BindGroup]) { 116 + self.draw_model_instanced(model, 0..1, bind_groups); 131 117 } 132 118 133 119 fn draw_model_instanced( 134 120 &mut self, 135 121 model: &'b Model, 136 122 instances: Range<u32>, 137 - camera_bind_group: &'b wgpu::BindGroup, 138 - light_bind_group: &'b wgpu::BindGroup, 123 + bind_groups: &[&'b wgpu::BindGroup], 139 124 ) { 140 125 for mesh in &model.meshes { 141 126 let material = &model.materials[mesh.material]; 142 - self.draw_mesh_instanced( 143 - mesh, 144 - material, 145 - instances.clone(), 146 - camera_bind_group, 147 - light_bind_group, 148 - ); 127 + self.draw_mesh_instanced(mesh, material, instances.clone(), bind_groups); 149 128 } 150 129 } 151 130 } 152 131 153 132 pub trait DrawLight<'a> { 154 - fn draw_light_mesh( 155 - &mut self, 156 - mesh: &'a Mesh, 157 - camera_bind_group: &'a wgpu::BindGroup, 158 - light_bind_group: &'a wgpu::BindGroup, 159 - ); 133 + fn draw_light_mesh(&mut self, mesh: &'a Mesh, bind_groups: &[&'a wgpu::BindGroup]); 160 134 fn draw_light_mesh_instanced( 161 135 &mut self, 162 136 mesh: &'a Mesh, 163 137 instances: Range<u32>, 164 - camera_bind_group: &'a wgpu::BindGroup, 165 - light_bind_group: &'a wgpu::BindGroup, 138 + bind_groups: &[&'a wgpu::BindGroup], 166 139 ); 167 140 168 - fn draw_light_model( 169 - &mut self, 170 - model: &'a Model, 171 - camera_bind_group: &'a wgpu::BindGroup, 172 - light_bind_group: &'a wgpu::BindGroup, 173 - ); 141 + fn draw_light_model(&mut self, model: &'a Model, bind_groups: &[&'a wgpu::BindGroup]); 174 142 fn draw_light_model_instanced( 175 143 &mut self, 176 144 model: &'a Model, 177 145 instances: Range<u32>, 178 - camera_bind_group: &'a wgpu::BindGroup, 179 - light_bind_group: &'a wgpu::BindGroup, 146 + bind_groups: &[&'a wgpu::BindGroup], 180 147 ); 181 148 } 182 149 ··· 184 151 where 185 152 'b: 'a, 186 153 { 187 - fn draw_light_mesh( 188 - &mut self, 189 - mesh: &'b Mesh, 190 - camera_bind_group: &'b wgpu::BindGroup, 191 - light_bind_group: &'b wgpu::BindGroup, 192 - ) { 193 - self.draw_light_mesh_instanced(mesh, 0..1, camera_bind_group, light_bind_group); 154 + fn draw_light_mesh(&mut self, mesh: &'b Mesh, bind_groups: &[&'b wgpu::BindGroup]) { 155 + self.draw_light_mesh_instanced(mesh, 0..1, bind_groups); 194 156 } 195 157 196 158 fn draw_light_mesh_instanced( 197 159 &mut self, 198 160 mesh: &'b Mesh, 199 161 instances: Range<u32>, 200 - camera_bind_group: &'b wgpu::BindGroup, 201 - light_bind_group: &'b wgpu::BindGroup, 162 + bind_groups: &[&'b wgpu::BindGroup], 202 163 ) { 203 164 self.set_vertex_buffer(0, mesh.vertex_buffer.slice(..)); 204 165 self.set_index_buffer(mesh.index_buffer.slice(..), wgpu::IndexFormat::Uint32); 205 - self.set_bind_group(0, camera_bind_group, &[]); 206 - self.set_bind_group(1, light_bind_group, &[]); 166 + for (i, group) in bind_groups.iter().enumerate() { 167 + self.set_bind_group(i as u32, *group, &[]); 168 + } 207 169 self.draw_indexed(0..mesh.num_elements, 0, instances); 208 170 } 209 171 210 - fn draw_light_model( 211 - &mut self, 212 - model: &'b Model, 213 - camera_bind_group: &'b wgpu::BindGroup, 214 - light_bind_group: &'b wgpu::BindGroup, 215 - ) { 216 - self.draw_light_model_instanced(model, 0..1, camera_bind_group, light_bind_group); 172 + fn draw_light_model(&mut self, model: &'b Model, bind_groups: &[&'b wgpu::BindGroup]) { 173 + self.draw_light_model_instanced(model, 0..1, bind_groups); 217 174 } 218 175 fn draw_light_model_instanced( 219 176 &mut self, 220 177 model: &'b Model, 221 178 instances: Range<u32>, 222 - camera_bind_group: &'b wgpu::BindGroup, 223 - light_bind_group: &'b wgpu::BindGroup, 179 + bind_groups: &[&'b wgpu::BindGroup], 224 180 ) { 225 181 for mesh in &model.meshes { 226 - self.draw_light_mesh_instanced( 227 - mesh, 228 - instances.clone(), 229 - camera_bind_group, 230 - light_bind_group, 231 - ); 182 + self.draw_light_mesh_instanced(mesh, instances.clone(), bind_groups); 232 183 } 233 184 } 234 185 }
+29 -19
src/gui.rs
··· 2 2 use glam::{ivec2, ivec3, IVec2}; 3 3 use winit::window::Window; 4 4 5 - use crate::{gfx::Gfx, world::map::{chunk_scramble_dispatch, ChunkScramble}, world::World}; 5 + use crate::{ 6 + gfx::Gfx, 7 + world::map::{chunk_scramble_dispatch, ChunkScramble}, 8 + world::World, 9 + }; 6 10 7 11 pub struct EguiRenderer { 8 12 state: egui_winit::State, ··· 54 58 renderer, 55 59 frame_started: false, 56 60 scale_factor: 1.0, 57 - chunk_influence: (0,0) 61 + chunk_influence: (0, 0), 58 62 } 59 63 } 60 64 61 65 pub fn handle_input(&mut self, window: &Window, event: &winit::event::WindowEvent) -> bool { 62 - let EventResponse {consumed, ..} = self.state.on_window_event(window, event); 66 + let EventResponse { consumed, .. } = self.state.on_window_event(window, event); 63 67 consumed 64 68 } 65 69 ··· 83 87 } 84 88 85 89 #[cfg(not(target_arch = "wasm32"))] 86 - self.ctx().set_pixels_per_point(screen_descriptor.pixels_per_point); 90 + self.ctx() 91 + .set_pixels_per_point(screen_descriptor.pixels_per_point); 87 92 88 93 let full_output = self.ctx().end_pass(); 89 94 ··· 96 101 .tessellate(full_output.shapes, self.ctx().pixels_per_point()); 97 102 98 103 #[cfg(target_arch = "wasm32")] 99 - let tris = self 100 - .ctx() 101 - .tessellate(full_output.shapes, 1.0); 104 + let tris = self.ctx().tessellate(full_output.shapes, 1.0); 102 105 103 106 for (id, image_delta) in &full_output.textures_delta.set { 104 107 self.renderer ··· 168 171 169 172 ui.separator(); 170 173 171 - ui.add(egui::Slider::new(&mut gfx.camera.controller.speed, 0.1..=10.0).text("Cam Speed")); 174 + ui.add( 175 + egui::Slider::new(&mut gfx.camera.controller.speed, 0.1..=10.0) 176 + .text("Cam Speed"), 177 + ); 172 178 173 179 ui.separator(); 174 180 175 - ui.label(format!("The camera is pointing at {:?}", gfx.camera.positioning.target)); 176 - ui.add(egui::Slider::new(&mut gfx.camera.positioning.eye.x, -500.0..=500.0).text("Cam X")); 177 - ui.add(egui::Slider::new(&mut gfx.camera.positioning.eye.y, -500.0..=500.0).text("Cam Y")); 178 - ui.add(egui::Slider::new(&mut gfx.camera.positioning.eye.z, -500.0..=500.0).text("Cam Z")); 181 + ui.label(format!( 182 + "The camera is pointing at {:?}", 183 + gfx.camera.object.target 184 + )); 185 + ui.add( 186 + egui::Slider::new(&mut gfx.camera.object.eye.x, -500.0..=500.0).text("Cam X"), 187 + ); 188 + ui.add( 189 + egui::Slider::new(&mut gfx.camera.object.eye.y, -500.0..=500.0).text("Cam Y"), 190 + ); 191 + ui.add( 192 + egui::Slider::new(&mut gfx.camera.object.eye.z, -500.0..=500.0).text("Cam Z"), 193 + ); 179 194 180 195 ui.separator(); 181 196 ui.horizontal(|ui| { ··· 200 215 }); 201 216 202 217 ui.horizontal(|ui| { 203 - let pos = ivec3(chunk_x,0,chunk_z); 218 + let pos = ivec3(chunk_x, 0, chunk_z); 204 219 205 220 if ui.button("Random").clicked() { 206 221 let c = chunk_scramble_dispatch(ChunkScramble::Random)(pos); ··· 220 235 }); 221 236 222 237 ui.separator(); 223 - 224 238 225 239 ui.horizontal(|ui| { 226 - 227 240 if ui.button("Save").clicked() { 228 241 world.save().unwrap(); 229 242 } ··· 231 244 *world = World::load().unwrap(); 232 245 gfx.object.remake = true; 233 246 } 234 - 235 247 }); 236 - 237 - 238 248 }); 239 249 240 250 self.scale_factor = scale_factor; 241 251 self.chunk_influence = (chunk_x, chunk_z); 242 252 } 243 - } 253 + }
+8 -8
src/lib.rs
··· 38 38 use std::mem; 39 39 40 40 wgpu::VertexBufferLayout { 41 - array_stride: mem::size_of::<InstanceRaw>() as wgpu::BufferAddress, 41 + array_stride: size_of::<InstanceRaw>() as wgpu::BufferAddress, 42 42 step_mode: wgpu::VertexStepMode::Instance, 43 43 attributes: &[ 44 44 wgpu::VertexAttribute { ··· 47 47 format: wgpu::VertexFormat::Float32x4, 48 48 }, 49 49 wgpu::VertexAttribute { 50 - offset: mem::size_of::<[f32; 4]>() as wgpu::BufferAddress, 50 + offset: size_of::<[f32; 4]>() as wgpu::BufferAddress, 51 51 shader_location: 6, 52 52 format: wgpu::VertexFormat::Float32x4, 53 53 }, 54 54 wgpu::VertexAttribute { 55 - offset: mem::size_of::<[f32; 8]>() as wgpu::BufferAddress, 55 + offset: size_of::<[f32; 8]>() as wgpu::BufferAddress, 56 56 shader_location: 7, 57 57 format: wgpu::VertexFormat::Float32x4, 58 58 }, 59 59 wgpu::VertexAttribute { 60 - offset: mem::size_of::<[f32; 12]>() as wgpu::BufferAddress, 60 + offset: size_of::<[f32; 12]>() as wgpu::BufferAddress, 61 61 shader_location: 8, 62 62 format: wgpu::VertexFormat::Float32x4, 63 63 }, 64 64 wgpu::VertexAttribute { 65 - offset: mem::size_of::<[f32; 16]>() as wgpu::BufferAddress, 65 + offset: size_of::<[f32; 16]>() as wgpu::BufferAddress, 66 66 shader_location: 9, 67 67 format: wgpu::VertexFormat::Float32x3, 68 68 }, 69 69 wgpu::VertexAttribute { 70 - offset: mem::size_of::<[f32; 19]>() as wgpu::BufferAddress, 70 + offset: size_of::<[f32; 19]>() as wgpu::BufferAddress, 71 71 shader_location: 10, 72 72 format: wgpu::VertexFormat::Float32x3, 73 73 }, 74 74 wgpu::VertexAttribute { 75 - offset: mem::size_of::<[f32; 22]>() as wgpu::BufferAddress, 75 + offset: size_of::<[f32; 22]>() as wgpu::BufferAddress, 76 76 shader_location: 11, 77 77 format: wgpu::VertexFormat::Float32x3, 78 78 }, ··· 88 88 console_log::init_with_level(log::Level::Debug).expect("Couldn't initialize logger"); 89 89 } else { 90 90 //env_logger::init(); 91 - env_logger::builder().filter_level(log::LevelFilter::Info).init(); 91 + env_logger::builder().filter_level(log::LevelFilter::Warn).init(); 92 92 } 93 93 } 94 94 }
+5 -9
src/light.wgsl
··· 5 5 @group(0) @binding(0) 6 6 var<uniform> camera: Camera; 7 7 8 - struct Light { 9 - position: vec3<f32>, 10 - color: vec3<f32>, 11 - } 12 - 13 - @group(1) @binding(0) 14 - var<uniform> light: Light; 8 + @group(0) @binding(1) 9 + var<uniform> light: Camera; 15 10 16 11 struct VertexInput { 17 12 @location(0) position: vec3<f32>, ··· 27 22 model: VertexInput, 28 23 ) -> VertexOutput { 29 24 let scale = 0.75; 25 + let light_color = vec3<f32>(1.0, 1.0, 1.0); 30 26 var out: VertexOutput; 31 - out.clip_position = camera.view_proj * vec4<f32>(model.position * scale + light.position, 1.0); 32 - out.color = light.color; 27 + out.clip_position = camera.view_proj * vec4<f32>(model.position * scale + light.view_pos.xyz, 1.0); 28 + out.color = light_color; 33 29 return out; 34 30 } 35 31
+31 -12
src/shader.wgsl
··· 18 18 @group(1) @binding(0) 19 19 var<uniform> camera: Camera; 20 20 21 + @group(1) @binding(1) 22 + var<uniform> light: Camera; 21 23 22 - struct Light { 23 - position: vec3<f32>, 24 - color: vec3<f32>, 25 - } 26 - @group(2) @binding(0) 27 - var<uniform> light: Light; 28 24 29 25 struct VertexInput { 30 26 @location(0) position: vec3<f32>, ··· 74 70 @group(0) @binding(1) 75 71 var s_diffuse: sampler; 76 72 73 + @group(1) @binding(2) 74 + var t_shadow: texture_depth_2d; 75 + @group(1) @binding(3) 76 + var s_shadow: sampler_comparison; 77 + 78 + 79 + fn fetch_shadow(homogeneous_coords: vec4<f32>) -> f32 { 80 + if (homogeneous_coords.w <= 0.0) { 81 + return 1.0; 82 + } 83 + // compensate for the Y-flip difference between the NDC and texture coordinates 84 + let flip_correction = vec2<f32>(0.5, -0.5); 85 + // compute texture coordinates for shadow lookup 86 + let proj_correction = 1.0 / homogeneous_coords.w; 87 + let light_local = homogeneous_coords.xy * flip_correction * proj_correction + vec2<f32>(0.5, 0.5); 88 + // do the lookup, using HW PCF and comparison 89 + return textureSampleCompareLevel(t_shadow, s_shadow, light_local, homogeneous_coords.z * proj_correction); 90 + } 91 + 77 92 @fragment 78 93 fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> { 94 + let light_color = vec3<f32>(1.0, 1.0, 1.0); 95 + 79 96 let object_color: vec4<f32> = textureSample(t_diffuse, s_diffuse, in.tex_coords); 80 97 81 98 let ambient_strength = 0.1; 82 - let ambient_color = light.color * ambient_strength; 99 + let ambient_color = light_color * ambient_strength; 83 100 84 - let light_dir = normalize(light.position - in.world_position); 101 + let light_dir = normalize(light.view_pos.xyz - in.world_position.xyz); 85 102 let diffuse_strength = max(dot(in.world_normal, light_dir), 0.0); 86 - let diffuse_color = light.color * diffuse_strength; 103 + let diffuse_color = light_color * diffuse_strength; 87 104 88 - let view_dir = normalize(camera.view_pos.xyz - in.world_position); 105 + let view_dir = normalize(camera.view_pos.xyz - in.world_position.xyz); 89 106 let half_dir = normalize(view_dir + light_dir); 90 107 91 108 let specular_strength = pow(max(dot(in.world_normal, half_dir), 0.0), 32.0); 92 - let specular_color = specular_strength * light.color; 109 + let specular_color = specular_strength * light_color; 93 110 94 - let result = (ambient_color + diffuse_color + specular_color) * object_color.xyz; 111 + let shadow = fetch_shadow(light.view_proj * vec4<f32>(in.world_position, 1.0)); 112 + 113 + let result = (ambient_color + diffuse_color + specular_color) * shadow * object_color.xyz; 95 114 96 115 return vec4<f32>(result, object_color.a); 97 116 }
+50
src/shadows.wgsl
··· 1 + // Vertex shader 2 + 3 + // TODO CITE 4 + // Somewhat referenced from: 5 + // https://github.com/gfx-rs/wgpu/blob/trunk/examples/features/src/shadow/shader.wgsl 6 + 7 + struct InstanceInput { 8 + @location(5) model_matrix_0: vec4<f32>, 9 + @location(6) model_matrix_1: vec4<f32>, 10 + @location(7) model_matrix_2: vec4<f32>, 11 + @location(8) model_matrix_3: vec4<f32>, 12 + 13 + @location(9) normal_matrix_0: vec3<f32>, 14 + @location(10) normal_matrix_1: vec3<f32>, 15 + @location(11) normal_matrix_2: vec3<f32>, 16 + }; 17 + 18 + struct Camera { 19 + view_pos: vec4<f32>, 20 + view_proj: mat4x4<f32>, 21 + } 22 + @group(0) @binding(0) 23 + var<uniform> camera: Camera; 24 + 25 + @group(0) @binding(1) 26 + var<uniform> light: Camera; 27 + 28 + struct VertexInput { 29 + @location(0) position: vec3<f32>, 30 + @location(1) tex_coords: vec2<f32>, 31 + @location(2) normal: vec3<f32>, 32 + } 33 + 34 + @vertex 35 + fn vs_main( 36 + model: VertexInput, 37 + instance: InstanceInput, 38 + ) -> @builtin(position) vec4<f32> { 39 + 40 + let model_matrix = mat4x4<f32> ( 41 + instance.model_matrix_0, 42 + instance.model_matrix_1, 43 + instance.model_matrix_2, 44 + instance.model_matrix_3, 45 + ); 46 + 47 + let world_position: vec4<f32> = model_matrix * vec4<f32>(model.position, 1.0); 48 + 49 + return light.view_proj * world_position; 50 + }
+14 -13
src/world/map.rs
··· 1 1 use bincode::{Decode, Encode}; 2 2 use glam::{ivec2, ivec3, IVec2, IVec3}; 3 3 use itertools::Itertools; 4 - use rand::{distr::{Distribution, StandardUniform}, Rng}; 4 + use rand::{ 5 + distr::{Distribution, StandardUniform}, 6 + Rng, 7 + }; 5 8 use std::collections::HashMap; 6 9 7 10 // I have arbitrarily decided that this is (x,z,y) where +y is up. ··· 45 48 } 46 49 } 47 50 48 - 49 51 fn new_chunk(world_pos: IVec3) -> Chunk { 50 52 let blocks = itertools::iproduct!(0..CHUNK_SIZE.0, 0..CHUNK_SIZE.1, 0..CHUNK_SIZE.2) 51 53 .map(|(x, z, y)| { 52 - let tile_pos = ivec3(x as _,y as _,z as _); 54 + let tile_pos = ivec3(x as _, y as _, z as _); 53 55 54 56 // let (xf, zf, yf) = ( 55 57 // (x as i32 + (world_x * CHUNK_SIZE.0 as i32)) as f32, ··· 58 60 // ); 59 61 let tile_pos_worldspace = (tile_pos + (world_pos * CHUNK_SIZE.0 as i32)).as_vec3(); 60 62 61 - let sines = f32::sin(tile_pos_worldspace.x * 0.1) + f32::sin(tile_pos_worldspace.z * 0.1); 63 + let sines = 64 + f32::sin(tile_pos_worldspace.x * 0.1) + f32::sin(tile_pos_worldspace.z * 0.1); 62 65 63 66 // Pretty arbitrary numbers! Just trying to get something interesting 64 - let n = (((sines / 4. + 0.5) * CHUNK_SIZE.2 as f32).round() as i32) <= tile_pos_worldspace.y as _; 67 + let n = (((sines / 4. + 0.5) * CHUNK_SIZE.2 as f32).round() as i32) 68 + <= tile_pos_worldspace.y as _; 65 69 66 70 if n { 67 71 Block::Brick ··· 82 86 let mut chunks = HashMap::new(); 83 87 84 88 for (x, z) in itertools::iproduct!(iter.clone(), iter) { 85 - let p = ivec3(x,0,z); 89 + let p = ivec3(x, 0, z); 86 90 chunks.insert(p.into(), new_chunk(p)); 87 91 chunks.insert(p.with_y(1).into(), new_chunk(p.with_y(1))); 88 - 89 92 } 90 93 91 94 WorldMap { chunks } ··· 106 109 .collect_array() 107 110 .unwrap(), 108 111 }, 109 - C::Random => |_| { 110 - Chunk { 111 - blocks: rand::rng().random() 112 - } 113 - } 112 + C::Random => |_| Chunk { 113 + blocks: rand::rng().random(), 114 + }, 114 115 } 115 116 } 116 117 ··· 118 119 Normal, 119 120 Inverse, 120 121 Random, 121 - } 122 + }