+7
-1
.nova/Publishing/J0.lol.json
+7
-1
.nova/Publishing/J0.lol.json
+4
-1
Cargo.toml
+4
-1
Cargo.toml
···
22
22
egui = "0.31"
23
23
egui-wgpu = "0.31"
24
24
egui-winit = { version = "0.31", default-features = false }
25
-
rand = "0.9.0"
26
25
bincode = "2.0.0-RC.3"
27
26
28
27
[build-dependencies]
···
30
29
31
30
[lib]
32
31
crate-type = ["cdylib", "rlib"]
32
+
33
+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
34
+
rand = "0.9.0"
35
+
33
36
34
37
[target.'cfg(target_arch = "wasm32")'.dependencies]
35
38
console_error_panic_hook = "0.1.6"
+17
-198
src/gfx.rs
+17
-198
src/gfx.rs
···
42
42
pub clear_color: wgpu::Color,
43
43
pub wireframe: bool,
44
44
pub shadows: bool,
45
+
pub sun_speed: f32,
45
46
}
46
47
pub struct ObjectState {
47
48
pub model: model::Model,
···
214
215
pub async fn new(window: std::sync::Arc<winit::window::Window>) -> Self {
215
216
// 0 size can cause web-app to crash, better to enforce this than not.
216
217
let size = if cfg!(target_arch = "wasm32") {
217
-
winit::dpi::PhysicalSize {
218
+
PhysicalSize {
218
219
width: WASM_WIN_SIZE.0,
219
220
height: WASM_WIN_SIZE.1,
220
221
}
···
331
332
let mut camera_uniform = camera::CameraUniform::new();
332
333
camera_uniform.update_view_proj(&camera);
333
334
334
-
// let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
335
-
// layout: &camera_bind_group_layout,
336
-
// entries: &[wgpu::BindGroupEntry {
337
-
// binding: 0,
338
-
// resource: camera_buffer.as_entire_binding(),
339
-
// }],
340
-
// label: Some("camera_bind_group"),
341
-
// });
342
335
let camera_state = CameraState {
343
336
object: camera,
344
337
controller: camera_controller,
···
380
373
let mut light_uniform = camera::CameraUniform::new();
381
374
light_uniform.update_view_proj(&light);
382
375
383
-
//let light_uniform = LightUniform::new(Vec3::splat(90.0).with_y(40.0), vec3(1.0, 1.0, 1.0));
384
-
385
-
log::info!("Shadowmap setup!");
386
-
let shadow_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
387
-
label: Some("Shadow Sampler"),
388
-
address_mode_u: wgpu::AddressMode::ClampToEdge,
389
-
address_mode_v: wgpu::AddressMode::ClampToEdge,
390
-
address_mode_w: wgpu::AddressMode::ClampToEdge,
391
-
mag_filter: wgpu::FilterMode::Linear,
392
-
min_filter: wgpu::FilterMode::Linear,
393
-
mipmap_filter: wgpu::FilterMode::Nearest,
394
-
compare: Some(wgpu::CompareFunction::LessEqual),
395
-
..Default::default()
396
-
});
397
-
398
-
log::info!("asdfasdgf");
399
-
400
376
let shadow_map = texture::Texture::create_depth_texture(
401
377
&device,
402
378
&surface_config,
403
-
Some((1000, 1000)),
379
+
Some({
380
+
if cfg!(target_arch = "wasm32") {
381
+
(2048, 2048)
382
+
} else {
383
+
(5000, 5000)
384
+
}
385
+
}),
404
386
"Shadow Map",
405
387
);
406
-
// let shadow_texture = device.create_texture(&wgpu::TextureDescriptor {
407
-
// size: wgpu::Extent3d {
408
-
// width: 1024,
409
-
// height: 1024,
410
-
// depth_or_array_layers: 10,
411
-
// },
412
-
// mip_level_count: 1,
413
-
// sample_count: 1,
414
-
// dimension: wgpu::TextureDimension::D2,
415
-
// format: wgpu::TextureFormat::Depth32Float,
416
-
// usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
417
-
// label: Some("Shadow texture"),
418
-
// view_formats: &[],
419
-
// });
420
-
// For forward pass
421
-
// let shadow_view = shadow_texture.create_view(&wgpu::TextureViewDescriptor::default());
422
-
423
-
log::info!("alskjgsdl;kfgjs;dkjl");
424
-
// For light in shadow pass
425
-
// let light_shadow_map = shadow_texture.create_view(&wgpu::TextureViewDescriptor {
426
-
// label: Some("Shadow Map"),
427
-
// format: Some(wgpu::TextureFormat::Depth32Float),
428
-
// dimension: Some(wgpu::TextureViewDimension::D2),
429
-
// usage: None,
430
-
// aspect: wgpu::TextureAspect::All,
431
-
// base_mip_level: 0,
432
-
// mip_level_count: None,
433
-
// base_array_layer: 0 as u32,
434
-
// array_layer_count: Some(1),
435
-
// });
436
-
437
-
// let shadow_map_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
438
-
// label: Some("Shadow Map Buffer"),
439
-
// contents: bytemuck::cast_slice(&[camera_uniform]),
440
-
// usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
441
-
// });
442
-
443
-
// let shadow_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
444
-
// entries: &[wgpu::BindGroupLayoutEntry {
445
-
// binding: 0,
446
-
// visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
447
-
// ty: wgpu::BindingType::Buffer {
448
-
// ty: wgpu::BufferBindingType::Uniform,
449
-
// has_dynamic_offset: false,
450
-
// min_binding_size: None,
451
-
// },
452
-
// count: None,
453
-
// }],
454
-
// label: None,
455
-
// });
456
-
// let shadow_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
457
-
// layout: &shadow_bgl,
458
-
// entries: &[wgpu::BindGroupEntry {
459
-
// binding: 0,
460
-
// resource: light_buffer.as_entire_binding(),
461
-
// }],
462
-
// label: None,
463
-
// });
464
-
465
-
log::info!("Pipeline setup!");
466
-
// New stuff goes above here!
467
-
468
-
log::info!("Pipeline/Globals setup!");
469
-
// let render_pipeline = {
470
-
// let shader = wgpu::ShaderModuleDescriptor {
471
-
// label: Some("Normal Shader"),
472
-
// source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
473
-
// };
474
-
// create_render_pipeline(
475
-
// &device,
476
-
// &render_pipeline_layout,
477
-
// surface_config.format,
478
-
// Some(texture::Texture::DEPTH_FORMAT),
479
-
// &[model::ModelVertex::desc(), InstanceRaw::desc()],
480
-
// shader,
481
-
// wgpu::PolygonMode::Fill,
482
-
// Some("Normal Render Pipeline"),
483
-
// )
484
-
// };
485
-
//
486
-
// //let fill_pipeline = render_pipeline(wgpu::PolygonMode::Fill);
487
-
// let wireframe_render_pipeline = if (device.features() & wgpu::Features::POLYGON_MODE_LINE)
488
-
// == wgpu::Features::POLYGON_MODE_LINE
489
-
// {
490
-
// Some({
491
-
// let shader = wgpu::ShaderModuleDescriptor {
492
-
// label: Some("Normal Shader"),
493
-
// source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
494
-
// };
495
-
// create_render_pipeline(
496
-
// &device,
497
-
// &render_pipeline_layout,
498
-
// surface_config.format,
499
-
// Some(texture::Texture::DEPTH_FORMAT),
500
-
// &[model::ModelVertex::desc(), InstanceRaw::desc()],
501
-
// shader,
502
-
// wgpu::PolygonMode::Line,
503
-
// Some("Normal Render Pipeline"),
504
-
// )
505
-
// })
506
-
// } else {
507
-
// None
508
-
// };
509
388
510
389
fn bgl_t(binding: u32) -> wgpu::BindGroupLayoutEntry {
511
390
wgpu::BindGroupLayoutEntry {
···
736
615
a: 1.0,
737
616
},
738
617
shadows: true,
618
+
sun_speed: 0.001,
739
619
},
740
620
object: ObjectState {
741
621
model: obj_model,
···
751
631
}
752
632
}
753
633
754
-
pub(crate) fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
634
+
pub(crate) fn resize(&mut self, new_size: PhysicalSize<u32>) {
755
635
if new_size.width == 0 || new_size.height == 0 {
756
636
return;
757
637
}
···
888
768
0..self.object.instances.len() as u32,
889
769
&[bind_group],
890
770
);
891
-
892
-
drop(render_pass);
893
771
}
894
772
895
773
encoder.pop_debug_group();
896
774
897
775
encoder.push_debug_group("Forward pass");
898
-
899
776
{
900
777
let Pass {
901
778
pipeline,
···
928
805
render_pass.set_vertex_buffer(1, self.object.instance_buffer.slice(..));
929
806
930
807
use crate::gfx::model::DrawLight;
931
-
// render_pass.set_pipeline(pipeline.two().1);
932
-
// render_pass.draw_light_model(
933
-
// &self.object.model,
934
-
// &self.camera.bind_group,
935
-
// &self.light.bind_group,
936
-
// );
937
-
938
-
// render_pass.set_pipeline(&self.render_pipelines.cam);
939
-
// render_pass.draw_model_instanced(
940
-
// &self.object.model,
941
-
// 0..self.object.instances.len() as u32,
942
-
// &self.camera.bind_group,
943
-
// &self.light.bind_group,
944
-
// );
945
-
946
-
/* render_pass.set_pipeline(
947
-
self.interact
948
-
.wireframe
949
-
.then_some(self.render_pipelines.camera_wireframe.as_ref())
950
-
.flatten()
951
-
.unwrap_or(&self.render_pipelines.camera),
952
-
);*/
953
808
954
809
render_pass.set_pipeline(pipeline.two().1);
955
-
956
810
render_pass.draw_light_model(&self.object.model, &[bind_group]);
957
811
958
812
render_pass.set_pipeline(pipeline.two().0);
959
-
960
813
render_pass.draw_model_instanced(
961
814
&self.object.model,
962
815
0..self.object.instances.len() as u32,
963
816
&[bind_group],
964
817
);
965
-
966
-
drop(render_pass);
967
818
}
968
-
969
-
// drop render pass before we submit to drop the mut borrow on encoder
970
819
971
820
encoder.pop_debug_group();
972
821
···
1003
852
}
1004
853
1005
854
pub fn update(&mut self, world: &mut World) {
855
+
// Camera update
1006
856
self.camera
1007
857
.controller
1008
858
.update_camera(&mut self.camera.object);
1009
859
1010
-
// dbg
1011
-
//self.camera.object.eye = self.light.uniform.view_pos;
1012
-
1013
860
self.camera.uniform.update_view_proj(&self.camera.object);
1014
861
self.queue.write_buffer(
1015
862
&self.forward_pass.uniform_bufs[0],
···
1017
864
bytemuck::cast_slice(&[self.camera.uniform]),
1018
865
);
1019
866
1020
-
self.light.object.eye =
1021
-
Quat::from_axis_angle(vec3(0.0, 0.0, 1.0), 0.01) * self.light.object.eye;
867
+
// Light update
868
+
self.light.object.eye = Quat::from_axis_angle(vec3(0.0, 0.0, 1.0), self.interact.sun_speed)
869
+
* self.light.object.eye;
1022
870
self.light.uniform.update_view_proj(&self.light.object);
1023
-
1024
-
// let old_position: Vec3 = self.light.uniform.view_pos;
1025
-
// self.light.uniform.view_pos =
1026
-
// Quat::from_axis_angle(vec3(0.0, 1.0, 0.0), 0.01) * old_position;
1027
-
// self.light
1028
-
// .uniform
1029
-
// .update_view_proj(self.surface_config.width as f32 / self.surface_config.height as f32);
1030
871
1031
872
self.queue.write_buffer(
1032
873
&self.forward_pass.uniform_bufs[1],
1033
874
0,
1034
875
bytemuck::cast_slice(&[self.light.uniform]),
1035
876
);
877
+
878
+
// Object update
1036
879
if self.object.remake {
1037
880
self.update_instance_buf(&world.map);
1038
881
}
···
1040
883
1041
884
pub fn input(&mut self, event: &WindowEvent, window_size: PhysicalSize<u32>) -> bool {
1042
885
self.camera.controller.process_events(event);
1043
-
1044
-
// Deprecated! Replaced with EGUI debug ui.
1045
-
// match event {
1046
-
// WindowEvent::CursorMoved {
1047
-
// device_id: _,
1048
-
// position,
1049
-
// } => {}
1050
-
// WindowEvent::KeyboardInput {
1051
-
// event:
1052
-
// KeyEvent {
1053
-
// state,
1054
-
// physical_key: PhysicalKey::Code(keycode),
1055
-
// ..
1056
-
// },
1057
-
// ..
1058
-
// } => {
1059
-
// let is_pressed = *state == ElementState::Pressed;
1060
-
// if *keycode == KeyCode::KeyL && is_pressed {
1061
-
// self.interact.wireframe = !self.interact.wireframe;
1062
-
// return true;
1063
-
// }
1064
-
// }
1065
-
// _ => {}
1066
-
// }
1067
886
1068
887
false
1069
888
}
+7
-3
src/gui.rs
+7
-3
src/gui.rs
···
193
193
);
194
194
ui.separator();
195
195
196
-
ui.checkbox(
197
-
&mut gfx.interact.shadows,
198
-
"Light shadowing (via shadow-maps)",
196
+
// ui.checkbox(
197
+
// &mut gfx.interact.shadows,
198
+
// "Light shadowing (via shadow-maps)",
199
+
// );
200
+
201
+
ui.add(
202
+
egui::Slider::new(&mut gfx.interact.sun_speed, 0.000001..=0.01).text("Sun rotational speed (radians per frame)").logarithmic(true),
199
203
);
200
204
201
205
ui.separator();
+25
-1
src/shader.wgsl
+25
-1
src/shader.wgsl
···
105
105
let view_dir = normalize(camera.view_pos.xyz - in.world_position.xyz);
106
106
let half_dir = normalize(view_dir + light_dir);
107
107
108
+
// https://github.com/mcclure/webgpu-tutorial-rs/blob/webgpu-tutorial/src/shader.wgsl
109
+
// This one-dimensional separable blur filter samples five points and averages them by different amounts.
110
+
// If we do it on two separate axes, we get a 2d blur.
111
+
// Weights and offsets taken from http://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
112
+
113
+
// The weights for the center, one-point-out, and two-point-out samples
114
+
const WEIGHT0 = 0.2270270270;
115
+
const WEIGHT1 = 0.3162162162;
116
+
const WEIGHT2 = 0.0702702703;
117
+
118
+
// The distances-from-center for the samples
119
+
const OFFSET1 = 1.3846153846;
120
+
const OFFSET2 = 3.2307692308;
121
+
122
+
let blur_resolution = vec2<f32>(60.0, 60.0);
123
+
124
+
var shadow_guassian = 0.0;
125
+
shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position, 1.0)) * WEIGHT0;
126
+
shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy + blur_resolution * OFFSET1, in.world_position.z, 1.0)) * WEIGHT1;
127
+
shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy - blur_resolution * OFFSET1, in.world_position.z, 1.0)) * WEIGHT1;
128
+
shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy + blur_resolution * OFFSET2, in.world_position.z, 1.0)) * WEIGHT2;
129
+
shadow_guassian += fetch_shadow(light.view_proj* vec4<f32>(in.world_position.xy - blur_resolution * OFFSET2, in.world_position.z, 1.0)) * WEIGHT2;
130
+
131
+
let shadow_strength = 0.7;
108
132
let shadow = fetch_shadow(light.view_proj * vec4<f32>(in.world_position, 1.0));
109
133
110
134
···
114
138
let specular_color = specular_strength * light_color * shadow;
115
139
116
140
// let result = (ambient_color + diffuse_color + specular_color) * shadow * object_color.xyz;
117
-
let result = (ambient_color + diffuse_color + specular_color) * (shadow * 0.5 + 0.5);
141
+
let result = (ambient_color + diffuse_color + specular_color) * (shadow_guassian * 0.7 + (1.0 - 0.7)) * object_color.xyz;
118
142
119
143
return vec4<f32>(result, object_color.a);
120
144
}
+7
-1
src/world/map.rs
+7
-1
src/world/map.rs
···
1
1
use bincode::{Decode, Encode};
2
2
use glam::{ivec2, ivec3, IVec2, IVec3};
3
3
use itertools::Itertools;
4
+
#[cfg(not(target_arch = "wasm32"))]
4
5
use rand::{
5
6
distr::{Distribution, StandardUniform},
6
-
Rng,
7
+
rngs::OsRng,
8
+
Rng, TryRngCore,
7
9
};
8
10
use std::collections::HashMap;
9
11
···
39
41
Brick,
40
42
}
41
43
44
+
#[cfg(not(target_arch = "wasm32"))]
42
45
impl Distribution<Block> for StandardUniform {
43
46
fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Block {
44
47
match rng.random_range(0..=1) {
···
110
113
.unwrap(),
111
114
},
112
115
C::Random => |_| Chunk {
116
+
#[cfg(not(target_arch = "wasm32"))]
113
117
blocks: rand::rng().random(),
118
+
#[cfg(target_arch = "wasm32")]
119
+
blocks: { panic!("i hate the web") },
114
120
},
115
121
}
116
122
}