diff --git a/lyra-game/src/render/camera.rs b/lyra-game/src/render/camera.rs index 00d904d..882f7c5 100755 --- a/lyra-game/src/render/camera.rs +++ b/lyra-game/src/render/camera.rs @@ -39,9 +39,11 @@ impl Projection { #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] pub struct CameraUniform { /// The view matrix of the camera - pub view_mat: glam::Mat4, + pub view: glam::Mat4, + /// The inverse of the projection matrix of the camera + pub inverse_projection: glam::Mat4, /// The view projection matrix - pub view_proj: glam::Mat4, + pub view_projection: glam::Mat4, /// The position of the camera pub position: glam::Vec3, _padding: u32, @@ -51,8 +53,9 @@ pub struct CameraUniform { impl Default for CameraUniform { fn default() -> Self { Self { - view_mat: glam::Mat4::IDENTITY, - view_proj: glam::Mat4::IDENTITY, + view: glam::Mat4::IDENTITY, + inverse_projection: glam::Mat4::IDENTITY, + view_projection: glam::Mat4::IDENTITY, position: Default::default(), _padding: 0, } @@ -60,10 +63,11 @@ impl Default for CameraUniform { } impl CameraUniform { - pub fn new(view_mat: glam::Mat4, view_proj: glam::Mat4, position: glam::Vec3) -> Self { + pub fn new(view: glam::Mat4, inverse_projection: glam::Mat4, view_projection: glam::Mat4, position: glam::Vec3) -> Self { Self { - view_mat, - view_proj, + view, + inverse_projection, + view_projection, position, _padding: 0 } @@ -101,7 +105,7 @@ impl RenderCamera { /// /// Returns: A tuple with the view projection as the first element, and the /// view matrix as the second. - pub fn calc_view_projection(&mut self, camera: &CameraComponent) -> (&glam::Mat4, glam::Mat4) { + pub fn calc_view_projection(&mut self, camera: &CameraComponent) -> CameraUniform { let position = camera.transform.translation; let forward = camera.transform.forward(); let up = camera.transform.up(); @@ -117,7 +121,15 @@ impl RenderCamera { let proj = glam::Mat4::perspective_rh_gl(camera.fov.to_radians(), self.aspect, self.znear, self.zfar); self.view_proj = OPENGL_TO_WGPU_MATRIX * proj * view; - (&self.view_proj, view) + //(&self.view_proj, view) + + CameraUniform { + view, + inverse_projection: proj.inverse(), + view_projection: self.view_proj, + position, + _padding: 0, + } }, CameraProjectionMode::Orthographic => { let target = camera.transform.rotation * glam::Vec3::new(0.0, 0.0, -1.0); @@ -132,7 +144,14 @@ impl RenderCamera { let proj = glam::Mat4::orthographic_rh_gl(-size_x, size_x, -size_y, size_y, self.znear, self.zfar); self.view_proj = OPENGL_TO_WGPU_MATRIX * proj; - (&self.view_proj, view) + + CameraUniform { + view, + inverse_projection: proj.inverse(), + view_projection: self.view_proj, + position, + _padding: 0, + } }, } } diff --git a/lyra-game/src/render/renderer.rs b/lyra-game/src/render/renderer.rs index 819801b..c960081 100755 --- a/lyra-game/src/render/renderer.rs +++ b/lyra-game/src/render/renderer.rs @@ -504,9 +504,9 @@ impl Renderer for BasicRenderer { } if let Some(camera) = main_world.view_iter::<&mut CameraComponent>().next() { - let (view_proj, view_mat) = self.inuse_camera.calc_view_projection(&camera); - let pos = camera.transform.translation; - let uniform = CameraUniform::new(view_mat, *view_proj, pos); + let uniform = self.inuse_camera.calc_view_projection(&camera); + //let pos = camera.transform.translation; + //let uniform = CameraUniform::new(view_mat, *view_proj, pos); self.camera_buffer.write_buffer(&self.queue, 0, &[uniform]); } else { warn!("Missing camera!"); diff --git a/lyra-game/src/render/shaders/base.wgsl b/lyra-game/src/render/shaders/base.wgsl index 7aa3024..f025ca4 100755 --- a/lyra-game/src/render/shaders/base.wgsl +++ b/lyra-game/src/render/shaders/base.wgsl @@ -20,9 +20,10 @@ struct VertexOutput { } struct CameraUniform { - view_mat: mat4x4, - view_proj: mat4x4, - view_pos: vec3, + view: mat4x4, + projection: mat4x4, + view_projection: mat4x4, + position: vec3, }; struct Light { @@ -63,7 +64,7 @@ fn vs_main( var out: VertexOutput; out.tex_coords = model.tex_coords; - out.clip_position = u_camera.view_proj * u_model_transform * vec4(model.position, 1.0); + out.clip_position = u_camera.view_projection * u_model_transform * vec4(model.position, 1.0); // the normal mat is actually only a mat3x3, but there's a bug in wgpu: https://github.com/gfx-rs/wgpu-rs/issues/36 let normal_mat = mat3x3(u_model_normal_matrix[0].xyz, u_model_normal_matrix[1].xyz, u_model_normal_matrix[2].xyz); @@ -174,7 +175,7 @@ fn debug_grid(in: VertexOutput) -> vec4 { fn blinn_phong_dir_light(world_pos: vec3, world_norm: vec3, dir_light: Light, material: Material, specular_factor: vec3) -> vec3 { let light_color = dir_light.color.xyz; - let camera_view_pos = u_camera.view_pos.xyz; + let camera_view_pos = u_camera.position; //// Ambient light //// var ambient_color = light_color * material.ambient.xyz * material.diffuse.xyz; @@ -204,7 +205,7 @@ fn blinn_phong_dir_light(world_pos: vec3, world_norm: vec3, dir_light: fn blinn_phong_point_light(world_pos: vec3, world_norm: vec3, point_light: Light, material: Material, specular_factor: vec3) -> vec3 { let light_color = point_light.color.xyz; let light_pos = point_light.position.xyz; - let camera_view_pos = u_camera.view_pos.xyz; + let camera_view_pos = u_camera.position; //// Ambient light //// var ambient_color = light_color * material.ambient.xyz * material.diffuse.xyz; diff --git a/lyra-game/src/render/shaders/light_cull.comp.wgsl b/lyra-game/src/render/shaders/light_cull.comp.wgsl index 4ee4353..e26f170 100644 --- a/lyra-game/src/render/shaders/light_cull.comp.wgsl +++ b/lyra-game/src/render/shaders/light_cull.comp.wgsl @@ -14,9 +14,10 @@ const LIGHT_TY_SPOT = 2u; // local_invocation_index struct CameraUniform { - view_mat: mat4x4, - view_proj: mat4x4, - view_pos: vec3, + view: mat4x4, + projection: mat4x4, + view_projection: mat4x4, + position: vec3, }; struct Light { @@ -103,11 +104,11 @@ fn cs_main( atomicMin(&wg_min_depth, depth_uint); atomicMax(&wg_max_depth, depth_uint); + workgroupBarrier(); + // convert them back into floats var min_depth: f32 = bitcast(wg_min_depth); var max_depth: f32 = bitcast(wg_max_depth); - - workgroupBarrier(); // Create the frustum planes that will be used for this time if (local_invocation_index == 0u) { @@ -124,14 +125,14 @@ fn cs_main( // convert the side and top planes from clip to view space for (var i = 0u; i < 4u; i++) { - wg_frustum_planes[i] *= u_camera.view_proj; + wg_frustum_planes[i] *= u_camera.view_projection; wg_frustum_planes[i] /= length(wg_frustum_planes[i].xyz); } // convert near and far planes from clip to view space - wg_frustum_planes[4] *= u_camera.view_mat; + wg_frustum_planes[4] *= u_camera.view; wg_frustum_planes[4] /= length(wg_frustum_planes[4].xyz); - wg_frustum_planes[5] *= u_camera.view_mat; + wg_frustum_planes[5] *= u_camera.view; wg_frustum_planes[5] /= length(wg_frustum_planes[5].xyz); } @@ -148,7 +149,7 @@ fn cs_main( // find the light index to check on this thread, make sure we're not trying to test // for more lights than we have. var light_index = i * thread_count + local_invocation_index; - if (light_index > u_lights.light_count) { + if (light_index >= u_lights.light_count) { break; } @@ -157,14 +158,15 @@ fn cs_main( var radius = light.range; if (light.light_ty == LIGHT_TY_DIRECTIONAL) { - add_light(light_index); + //add_light(light_index); } else if (light.light_ty == LIGHT_TY_POINT && sphere_inside_frustrum(wg_frustum_planes, position, radius)) { // TODO: add the light to the transparent geometry list + add_light(light_index); + // TODO: spotlights if (!sphere_inside_plane(position, radius, wg_frustum_planes[4])) { - add_light(light_index); /*var offset: u32 = wg_visible_light_count; if (offset < MAX_TILE_VISIBLE_LIGHTS) {