Skip to content

Commit f65df85

Browse files
authored
feat(client): ✨ Add reprojection support for C API (alvr-org#2543)
* feat(client): ✨ Add reprojection support for C API * Address comment
1 parent d5ea185 commit f65df85

File tree

9 files changed

+180
-90
lines changed

9 files changed

+180
-90
lines changed

alvr/client_core/resources/lobby_quad.wgsl

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,23 @@
1-
struct VertexOutput {
2-
@builtin(position) position: vec4f,
3-
@location(0) uv: vec2f,
4-
}
5-
6-
@group(0) @binding(0) var hud_texture: texture_2d<f32>;
7-
@group(0) @binding(1) var hud_sampler: sampler;
8-
91
struct PushConstant {
102
transform: mat4x4f,
113
object_type: u32,
124
floor_side: f32,
135
}
146
var<push_constant> pc: PushConstant;
157

8+
@group(0) @binding(0) var hud_texture: texture_2d<f32>;
9+
@group(0) @binding(1) var hud_sampler: sampler;
10+
11+
struct VertexOutput {
12+
@builtin(position) position: vec4f,
13+
@location(0) uv: vec2f,
14+
}
15+
1616
@vertex
1717
fn vertex_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
1818
var result: VertexOutput;
1919

20-
let norm_vert_a = f32(vertex_index & 1);
21-
let norm_vert_b = f32(vertex_index >> 1);
22-
23-
result.uv = vec2f(norm_vert_a, norm_vert_b);
20+
result.uv = vec2f(f32(vertex_index & 1), f32(vertex_index >> 1));
2421
result.position = pc.transform * vec4f(result.uv.x - 0.5, 0.5 - result.uv.y, 0.0, 1.0);
2522

2623
return result;

alvr/client_core/resources/stream.wgsl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,26 @@ override C_RIGHT_Y: f32 = 0.;
4242

4343
override COLOR_ALPHA: f32 = 1.0;
4444

45-
struct VertexOutput {
46-
@builtin(position) position: vec4f,
47-
@location(0) uv: vec2f,
45+
struct PushConstant {
46+
reprojection_transform: mat4x4f,
47+
view_idx: u32,
4848
}
49+
var<push_constant> pc: PushConstant;
4950

5051
@group(0) @binding(0) var stream_texture: texture_2d<f32>;
5152
@group(0) @binding(1) var stream_sampler: sampler;
5253

53-
var<push_constant> view_idx: u32;
54+
struct VertexOutput {
55+
@builtin(position) position: vec4f,
56+
@location(0) uv: vec2f,
57+
}
5458

5559
@vertex
5660
fn vertex_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
5761
var result: VertexOutput;
5862

59-
let screen_uv = vec2f(f32(vertex_index & 1), f32(vertex_index >> 1));
60-
result.position = vec4f((screen_uv - 0.5) * 2.0, 0.0, 1.0);
61-
result.uv = vec2f(screen_uv.x, screen_uv.y);
63+
result.uv = vec2f(f32(vertex_index & 1), f32(vertex_index >> 1));
64+
result.position = pc.reprojection_transform * vec4f(result.uv.x - 0.5, 0.5 - result.uv.y, 0.0, 1.0);
6265

6366
return result;
6467
}
@@ -82,7 +85,7 @@ fn fragment_main(@location(0) uv: vec2f) -> @location(0) vec4f {
8285
let b_right = vec2f(B_RIGHT_X, B_RIGHT_Y);
8386
let c_right = vec2f(C_RIGHT_X, C_RIGHT_Y);
8487

85-
if view_idx == 1 {
88+
if pc.view_idx == 1 {
8689
corrected_uv.x = 1.0 - corrected_uv.x;
8790
}
8891

@@ -108,7 +111,7 @@ fn fragment_main(@location(0) uv: vec2f) -> @location(0) vec4f {
108111

109112
corrected_uv = corrected_uv * view_size_ratio;
110113

111-
if view_idx == 1 {
114+
if pc.view_idx == 1 {
112115
corrected_uv.x = 1.0 - corrected_uv.x;
113116
}
114117
}

alvr/client_core/src/c_api.rs

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::{
2-
graphics::{GraphicsContext, LobbyRenderer, RenderViewInput, StreamRenderer},
2+
graphics::{GraphicsContext, LobbyRenderer, LobbyViewParams, StreamRenderer, StreamViewParams},
33
storage,
44
video_decoder::{self, VideoDecoderConfig, VideoDecoderSource},
55
ClientCapabilities, ClientCoreContext, ClientCoreEvent,
@@ -159,8 +159,8 @@ pub fn to_capi_pose(pose: Pose) -> AlvrPose {
159159

160160
#[repr(C)]
161161
pub struct AlvrViewParams {
162-
pub pose: AlvrPose,
163-
pub fov: AlvrFov,
162+
pose: AlvrPose,
163+
fov: AlvrFov,
164164
}
165165

166166
#[repr(C)]
@@ -675,25 +675,32 @@ thread_local! {
675675
}
676676

677677
#[repr(C)]
678-
pub struct AlvrViewInput {
678+
pub struct AlvrLobbyViewParams {
679+
swapchain_index: u32,
679680
pose: AlvrPose,
680681
fov: AlvrFov,
682+
}
683+
684+
#[repr(C)]
685+
pub struct AlvrStreamViewParams {
681686
swapchain_index: u32,
687+
reprojection_rotation: AlvrQuat,
688+
fov: AlvrFov,
682689
}
683690

684691
#[repr(C)]
685692
pub struct AlvrStreamConfig {
686-
pub view_resolution_width: u32,
687-
pub view_resolution_height: u32,
688-
pub swapchain_textures: *mut *const u32,
689-
pub swapchain_length: u32,
690-
pub enable_foveation: bool,
691-
pub foveation_center_size_x: f32,
692-
pub foveation_center_size_y: f32,
693-
pub foveation_center_shift_x: f32,
694-
pub foveation_center_shift_y: f32,
695-
pub foveation_edge_ratio_x: f32,
696-
pub foveation_edge_ratio_y: f32,
693+
view_resolution_width: u32,
694+
view_resolution_height: u32,
695+
swapchain_textures: *mut *const u32,
696+
swapchain_length: u32,
697+
enable_foveation: bool,
698+
foveation_center_size_x: f32,
699+
foveation_center_size_y: f32,
700+
foveation_center_shift_x: f32,
701+
foveation_center_shift_y: f32,
702+
foveation_edge_ratio_x: f32,
703+
foveation_edge_ratio_y: f32,
697704
}
698705

699706
#[no_mangle]
@@ -788,19 +795,19 @@ pub unsafe extern "C" fn alvr_start_stream_opengl(config: AlvrStreamConfig) {
788795
// todo: support hands
789796
#[no_mangle]
790797
pub unsafe extern "C" fn alvr_render_lobby_opengl(
791-
view_inputs: *const AlvrViewInput,
798+
view_inputs: *const AlvrLobbyViewParams,
792799
render_background: bool,
793800
) {
794801
let view_inputs = [
795-
RenderViewInput {
802+
LobbyViewParams {
803+
swapchain_index: (*view_inputs).swapchain_index,
796804
pose: from_capi_pose((*view_inputs).pose),
797805
fov: from_capi_fov((*view_inputs).fov),
798-
swapchain_index: (*view_inputs).swapchain_index,
799806
},
800-
RenderViewInput {
807+
LobbyViewParams {
808+
swapchain_index: (*view_inputs.offset(1)).swapchain_index,
801809
pose: from_capi_pose((*view_inputs.offset(1)).pose),
802810
fov: from_capi_fov((*view_inputs.offset(1)).fov),
803-
swapchain_index: (*view_inputs.offset(1)).swapchain_index,
804811
},
805812
];
806813

@@ -816,16 +823,30 @@ pub unsafe extern "C" fn alvr_render_lobby_opengl(
816823
});
817824
}
818825

826+
/// view_params: array of 2
819827
#[no_mangle]
820828
pub unsafe extern "C" fn alvr_render_stream_opengl(
821829
hardware_buffer: *mut c_void,
822-
swapchain_indices: *const u32,
830+
view_params: *const AlvrStreamViewParams,
823831
) {
824832
STREAM_RENDERER.with_borrow(|renderer| {
825833
if let Some(renderer) = renderer {
834+
let left_params = &*view_params;
835+
let right_params = &*view_params.offset(1);
826836
renderer.render(
827837
hardware_buffer,
828-
[*swapchain_indices, *swapchain_indices.offset(1)],
838+
[
839+
StreamViewParams {
840+
swapchain_index: left_params.swapchain_index,
841+
reprojection_rotation: from_capi_quat(left_params.reprojection_rotation),
842+
fov: from_capi_fov(left_params.fov),
843+
},
844+
StreamViewParams {
845+
swapchain_index: right_params.swapchain_index,
846+
reprojection_rotation: from_capi_quat(right_params.reprojection_rotation),
847+
fov: from_capi_fov(right_params.fov),
848+
},
849+
],
829850
);
830851
}
831852
});
@@ -967,3 +988,8 @@ pub extern "C" fn alvr_get_frame(
967988
false
968989
}
969990
}
991+
992+
#[no_mangle]
993+
pub extern "C" fn alvr_rotation_delta(source: AlvrQuat, destination: AlvrQuat) -> AlvrQuat {
994+
to_capi_quat(from_capi_quat(source).inverse() * from_capi_quat(destination))
995+
}

alvr/client_core/src/graphics/lobby.rs

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{GraphicsContext, SDR_FORMAT};
22
use alvr_common::{
3-
glam::{IVec2, Mat4, Quat, UVec2, Vec3, Vec4},
3+
glam::{IVec2, Mat4, Quat, UVec2, Vec3},
44
Fov, Pose,
55
};
66
use glyph_brush_layout::{
@@ -103,29 +103,6 @@ const BODY_SKELETON_BONES_FB: [(usize, usize); 30] = [
103103
(82, 83),
104104
];
105105

106-
fn projection_from_fov(fov: Fov) -> Mat4 {
107-
const NEAR: f32 = 0.1;
108-
109-
let tanl = f32::tan(fov.left);
110-
let tanr = f32::tan(fov.right);
111-
let tanu = f32::tan(fov.up);
112-
let tand = f32::tan(fov.down);
113-
let a = 2.0 / (tanr - tanl);
114-
let b = 2.0 / (tanu - tand);
115-
let c = (tanr + tanl) / (tanr - tanl);
116-
let d = (tanu + tand) / (tanu - tand);
117-
118-
// note: for wgpu compatibility, the b and d components should be flipped. Maybe a bug in the
119-
// viewport handling in wgpu?
120-
Mat4::from_cols(
121-
Vec4::new(a, 0.0, c, 0.0),
122-
Vec4::new(0.0, -b, -d, 0.0),
123-
Vec4::new(0.0, 0.0, -1.0, -NEAR),
124-
Vec4::new(0.0, 0.0, -1.0, 0.0),
125-
)
126-
.transpose()
127-
}
128-
129106
fn create_pipeline(
130107
device: &Device,
131108
label: &str,
@@ -183,10 +160,10 @@ fn create_pipeline(
183160
})
184161
}
185162

186-
pub struct RenderViewInput {
163+
pub struct LobbyViewParams {
164+
pub swapchain_index: u32,
187165
pub pose: Pose,
188166
pub fov: Fov,
189-
pub swapchain_index: u32,
190167
}
191168

192169
pub struct LobbyRenderer {
@@ -374,7 +351,7 @@ impl LobbyRenderer {
374351

375352
pub fn render(
376353
&self,
377-
view_inputs: [RenderViewInput; 2],
354+
view_params: [LobbyViewParams; 2],
378355
hand_data: [(Option<Pose>, Option<[Pose; 26]>); 2],
379356
body_skeleton_fb: Option<Vec<Option<Pose>>>,
380357
render_background: bool,
@@ -386,13 +363,13 @@ impl LobbyRenderer {
386363
label: Some("lobby_command_encoder"),
387364
});
388365

389-
for (view_idx, view_input) in view_inputs.iter().enumerate() {
366+
for (view_idx, view_input) in view_params.iter().enumerate() {
390367
let view = Mat4::from_rotation_translation(
391368
view_input.pose.orientation,
392369
view_input.pose.position,
393370
)
394371
.inverse();
395-
let view_proj = projection_from_fov(view_input.fov) * view;
372+
let view_proj = super::projection_from_fov(view_input.fov) * view;
396373

397374
let clear_color = if render_background {
398375
Color {

alvr/client_core/src/graphics/mod.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ mod stream;
55
pub use lobby::*;
66
pub use stream::*;
77

8-
use alvr_common::glam::UVec2;
8+
use alvr_common::{
9+
glam::{Mat4, UVec2, Vec4},
10+
Fov,
11+
};
912
use glow::{self as gl, HasContext};
1013
use khronos_egl as egl;
1114
use std::{ffi::c_void, mem, num::NonZeroU32, ptr};
@@ -50,6 +53,29 @@ macro_rules! ck {
5053
}
5154
pub(crate) use ck;
5255

56+
fn projection_from_fov(fov: Fov) -> Mat4 {
57+
const NEAR: f32 = 0.1;
58+
59+
let tanl = f32::tan(fov.left);
60+
let tanr = f32::tan(fov.right);
61+
let tanu = f32::tan(fov.up);
62+
let tand = f32::tan(fov.down);
63+
let a = 2.0 / (tanr - tanl);
64+
let b = 2.0 / (tanu - tand);
65+
let c = (tanr + tanl) / (tanr - tanl);
66+
let d = (tanu + tand) / (tanu - tand);
67+
68+
// note: for wgpu compatibility, the b and d components should be flipped. Maybe a bug in the
69+
// viewport handling in wgpu?
70+
Mat4::from_cols(
71+
Vec4::new(a, 0.0, c, 0.0),
72+
Vec4::new(0.0, -b, -d, 0.0),
73+
Vec4::new(0.0, 0.0, -1.0, -NEAR),
74+
Vec4::new(0.0, 0.0, -1.0, 0.0),
75+
)
76+
.transpose()
77+
}
78+
5379
pub fn choose_swapchain_format(supported_formats: &[u32], enable_hdr: bool) -> u32 {
5480
// Priority-sorted list of swapchain formats we'll accept--
5581
let mut app_supported_swapchain_formats = vec![gl::SRGB8_ALPHA8, gl::RGBA8];

0 commit comments

Comments
 (0)