From f76b41420e5486b73427d7e39852ba23bb779194 Mon Sep 17 00:00:00 2001 From: Svenn-Arne Dragly Date: Fri, 5 Jul 2019 15:02:19 +0200 Subject: [PATCH 1/3] [rs] Add conversion matrix from OpenGL to wgpu The matrices in the examples are given in an OpenGL-like coordinate system, while a Vulkan-like coordinate system is used by wgpu. This was previously partially corrected in the shader and by flipping the up axis of the camera, but left the x-axis mirrored in the final result. This change adds a conversion matrix to framework.rs that can be used to convert from OpenGL to wgpu. This also allows us to set the winding-order to counter-clockwise, which matches the ordering in the data. --- wgpu/examples/cube/main.rs | 7 ++++--- wgpu/examples/cube/shader.vert | 2 -- wgpu/examples/framework.rs | 8 ++++++++ wgpu/examples/mipmap/draw.vert | 2 -- wgpu/examples/mipmap/main.rs | 9 +++++---- wgpu/examples/shadow/forward.vert | 2 -- wgpu/examples/shadow/main.rs | 11 ++++++----- 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index 5e055407f1..dbb25e468d 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -98,9 +98,10 @@ impl Example { let mx_view = cgmath::Matrix4::look_at( cgmath::Point3::new(1.5f32, -5.0, 3.0), cgmath::Point3::new(0f32, 0.0, 0.0), - -cgmath::Vector3::unit_z(), + cgmath::Vector3::unit_z(), ); - mx_projection * mx_view + let mx_correction = framework::opengl_to_wgpu_matrix(); + mx_correction * mx_projection * mx_view } } @@ -251,7 +252,7 @@ impl framework::Example for Example { entry_point: "main", }), rasterization_state: wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Cw, + front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/wgpu/examples/cube/shader.vert b/wgpu/examples/cube/shader.vert index badc7fc203..6a4028e7a1 100644 --- a/wgpu/examples/cube/shader.vert +++ b/wgpu/examples/cube/shader.vert @@ -11,6 +11,4 @@ layout(set = 0, binding = 0) uniform Locals { void main() { v_TexCoord = a_TexCoord; gl_Position = u_Transform * a_Pos; - // convert from -1,1 Z to 0,1 - gl_Position.z = 0.5 * (gl_Position.z + gl_Position.w); } diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index f945b84526..424da2ab92 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -30,6 +30,14 @@ pub fn load_glsl(code: &str, stage: ShaderStage) -> Vec { spv } +pub fn opengl_to_wgpu_matrix() -> cgmath::Matrix4 { + // converts from -1,1 Z to 0,1 Z and flips Y + cgmath::Matrix4::new(1.0, 0.0, 0.0, 0.0, + 0.0, -1.0, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.0, 0.0, 0.5, 1.0) +} + pub trait Example { fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self; fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device); diff --git a/wgpu/examples/mipmap/draw.vert b/wgpu/examples/mipmap/draw.vert index 5d920f6753..f646a282b8 100644 --- a/wgpu/examples/mipmap/draw.vert +++ b/wgpu/examples/mipmap/draw.vert @@ -10,6 +10,4 @@ layout(set = 0, binding = 0) uniform Locals { void main() { v_TexCoord = a_Pos.xy / 20.0 + 0.5; gl_Position = u_Transform * a_Pos; - // convert from -1,1 Z to 0,1 - gl_Position.z = 0.5 * (gl_Position.z + gl_Position.w); } diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index feaceed8e9..f6c39c7466 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -62,9 +62,10 @@ impl Example { let mx_view = cgmath::Matrix4::look_at( cgmath::Point3::new(0f32, 0.0, 10.0), cgmath::Point3::new(0f32, 50.0, 0.0), - -cgmath::Vector3::unit_z(), + cgmath::Vector3::unit_z(), ); - mx_projection * mx_view + let mx_correction = framework::opengl_to_wgpu_matrix(); + mx_correction * mx_projection * mx_view } fn generate_mipmaps( @@ -110,7 +111,7 @@ impl Example { entry_point: "main", }), rasterization_state: wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Cw, + front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::None, depth_bias: 0, depth_bias_slope_scale: 0.0, @@ -337,7 +338,7 @@ impl framework::Example for Example { entry_point: "main", }), rasterization_state: wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Cw, + front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, depth_bias: 0, depth_bias_slope_scale: 0.0, diff --git a/wgpu/examples/shadow/forward.vert b/wgpu/examples/shadow/forward.vert index f12281db10..5e02939393 100644 --- a/wgpu/examples/shadow/forward.vert +++ b/wgpu/examples/shadow/forward.vert @@ -19,6 +19,4 @@ void main() { v_Normal = mat3(u_World) * vec3(a_Normal.xyz); v_Position = u_World * vec4(a_Pos); gl_Position = u_ViewProj * v_Position; - // convert from -1,1 Z to 0,1 - gl_Position.z = 0.5 * (gl_Position.z + gl_Position.w); } diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index fba01979d6..e0608d425e 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -106,7 +106,7 @@ impl Light { fn to_raw(&self) -> LightRaw { use cgmath::{Deg, EuclideanSpace, Matrix4, PerspectiveFov, Point3, Vector3}; - let mx_view = Matrix4::look_at(self.pos, Point3::origin(), -Vector3::unit_z()); + let mx_view = Matrix4::look_at(self.pos, Point3::origin(), Vector3::unit_z()); let projection = PerspectiveFov { fovy: Deg(self.fov).into(), aspect: 1.0, @@ -172,9 +172,10 @@ impl Example { let mx_view = cgmath::Matrix4::look_at( cgmath::Point3::new(3.0f32, -10.0, 6.0), cgmath::Point3::new(0f32, 0.0, 0.0), - -cgmath::Vector3::unit_z(), + cgmath::Vector3::unit_z(), ); - mx_projection * mx_view + let mx_correction = framework::opengl_to_wgpu_matrix(); + mx_correction * mx_projection * mx_view } } @@ -450,7 +451,7 @@ impl framework::Example for Example { entry_point: "main", }), rasterization_state: wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Cw, + front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, depth_bias: 2, // corresponds to bilinear filtering depth_bias_slope_scale: 2.0, @@ -573,7 +574,7 @@ impl framework::Example for Example { entry_point: "main", }), rasterization_state: wgpu::RasterizationStateDescriptor { - front_face: wgpu::FrontFace::Cw, + front_face: wgpu::FrontFace::Ccw, cull_mode: wgpu::CullMode::Back, depth_bias: 0, depth_bias_slope_scale: 0.0, From 8cf1dff41fb7ba700261603ed7a6b31069bf8dd1 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 5 Jul 2019 13:43:57 -0400 Subject: [PATCH 2/3] [rs] Use the correction matrix in shadow baking --- wgpu/examples/shadow/bake.vert | 2 -- wgpu/examples/shadow/forward.frag | 3 ++- wgpu/examples/shadow/main.rs | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wgpu/examples/shadow/bake.vert b/wgpu/examples/shadow/bake.vert index 32e257c6b7..e4426b7455 100644 --- a/wgpu/examples/shadow/bake.vert +++ b/wgpu/examples/shadow/bake.vert @@ -13,6 +13,4 @@ layout(set = 1, binding = 0) uniform Entity { void main() { gl_Position = u_ViewProj * u_World * vec4(a_Pos); - // convert from -1,1 Z to 0,1 - gl_Position.z = 0.5 * (gl_Position.z + gl_Position.w); } diff --git a/wgpu/examples/shadow/forward.frag b/wgpu/examples/shadow/forward.frag index 9a2bd8fc67..7af5dbdc7f 100644 --- a/wgpu/examples/shadow/forward.frag +++ b/wgpu/examples/shadow/forward.frag @@ -39,7 +39,8 @@ void main() { // project into the light space vec4 light_local = light.proj * v_Position; // compute texture coordinates for shadow lookup - light_local.xyw = (light_local.xyz/light_local.w + 1.0) / 2.0; + light_local.xy = (light_local.xy/light_local.w + 1.0) / 2.0; + light_local.w = light_local.z / light_local.w; light_local.z = i; // do the lookup, using HW PCF and comparison float shadow = texture(sampler2DArrayShadow(t_Shadow, s_Shadow), light_local); diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index e0608d425e..8a4cc86a4a 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -113,7 +113,8 @@ impl Light { near: self.depth.start, far: self.depth.end, }; - let mx_view_proj = cgmath::Matrix4::from(projection.to_perspective()) * mx_view; + let mx_correction = framework::opengl_to_wgpu_matrix(); + let mx_view_proj = mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view; LightRaw { proj: *mx_view_proj.as_ref(), pos: [self.pos.x, self.pos.y, self.pos.z, 1.0], From a4b500ff4b02165fdccd6d90c652f083c7114d4b Mon Sep 17 00:00:00 2001 From: Svenn-Arne Dragly Date: Mon, 8 Jul 2019 10:36:25 +0200 Subject: [PATCH 3/3] [rs] Make opengl_to_wgpu_matrix into a constant --- wgpu/examples/cube/main.rs | 2 +- wgpu/examples/framework.rs | 16 ++++++++-------- wgpu/examples/mipmap/main.rs | 2 +- wgpu/examples/shadow/main.rs | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/wgpu/examples/cube/main.rs b/wgpu/examples/cube/main.rs index dbb25e468d..b5544deb73 100644 --- a/wgpu/examples/cube/main.rs +++ b/wgpu/examples/cube/main.rs @@ -100,7 +100,7 @@ impl Example { cgmath::Point3::new(0f32, 0.0, 0.0), cgmath::Vector3::unit_z(), ); - let mx_correction = framework::opengl_to_wgpu_matrix(); + let mx_correction = framework::OPENGL_TO_WGPU_MATRIX; mx_correction * mx_projection * mx_view } } diff --git a/wgpu/examples/framework.rs b/wgpu/examples/framework.rs index 424da2ab92..40ea24f663 100644 --- a/wgpu/examples/framework.rs +++ b/wgpu/examples/framework.rs @@ -1,5 +1,13 @@ use log::info; +#[cfg_attr(rustfmt, rustfmt_skip)] +pub const OPENGL_TO_WGPU_MATRIX: cgmath::Matrix4 = cgmath::Matrix4::new( + 1.0, 0.0, 0.0, 0.0, + 0.0, -1.0, 0.0, 0.0, + 0.0, 0.0, 0.5, 0.0, + 0.0, 0.0, 0.5, 1.0, +); + #[allow(dead_code)] pub fn cast_slice(data: &[T]) -> &[u8] { use std::mem::size_of; @@ -30,14 +38,6 @@ pub fn load_glsl(code: &str, stage: ShaderStage) -> Vec { spv } -pub fn opengl_to_wgpu_matrix() -> cgmath::Matrix4 { - // converts from -1,1 Z to 0,1 Z and flips Y - cgmath::Matrix4::new(1.0, 0.0, 0.0, 0.0, - 0.0, -1.0, 0.0, 0.0, - 0.0, 0.0, 0.5, 0.0, - 0.0, 0.0, 0.5, 1.0) -} - pub trait Example { fn init(sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device) -> Self; fn resize(&mut self, sc_desc: &wgpu::SwapChainDescriptor, device: &mut wgpu::Device); diff --git a/wgpu/examples/mipmap/main.rs b/wgpu/examples/mipmap/main.rs index f6c39c7466..7194f2d231 100644 --- a/wgpu/examples/mipmap/main.rs +++ b/wgpu/examples/mipmap/main.rs @@ -64,7 +64,7 @@ impl Example { cgmath::Point3::new(0f32, 50.0, 0.0), cgmath::Vector3::unit_z(), ); - let mx_correction = framework::opengl_to_wgpu_matrix(); + let mx_correction = framework::OPENGL_TO_WGPU_MATRIX; mx_correction * mx_projection * mx_view } diff --git a/wgpu/examples/shadow/main.rs b/wgpu/examples/shadow/main.rs index 8a4cc86a4a..e57af3ea49 100644 --- a/wgpu/examples/shadow/main.rs +++ b/wgpu/examples/shadow/main.rs @@ -113,7 +113,7 @@ impl Light { near: self.depth.start, far: self.depth.end, }; - let mx_correction = framework::opengl_to_wgpu_matrix(); + let mx_correction = framework::OPENGL_TO_WGPU_MATRIX; let mx_view_proj = mx_correction * cgmath::Matrix4::from(projection.to_perspective()) * mx_view; LightRaw { proj: *mx_view_proj.as_ref(), @@ -175,7 +175,7 @@ impl Example { cgmath::Point3::new(0f32, 0.0, 0.0), cgmath::Vector3::unit_z(), ); - let mx_correction = framework::opengl_to_wgpu_matrix(); + let mx_correction = framework::OPENGL_TO_WGPU_MATRIX; mx_correction * mx_projection * mx_view } }