The open source OpenXR runtime
at prediction-2 170 lines 4.9 kB view raw
1// Copyright 2019-2022, Collabora, Ltd. 2// SPDX-License-Identifier: BSL-1.0 3/*! 4 * @file 5 * @brief The compositor compute based rendering code. 6 * @author Jakob Bornecrantz <jakob@collabora.com> 7 * @ingroup comp_render 8 */ 9 10#include "math/m_api.h" 11#include "math/m_matrix_4x4_f64.h" 12 13#include "render/render_interface.h" 14 15 16/*! 17 * Create a simplified projection matrix for timewarp. 18 */ 19static void 20calc_projection(const struct xrt_fov *fov, struct xrt_matrix_4x4_f64 *result) 21{ 22 const double tan_left = tan(fov->angle_left); 23 const double tan_right = tan(fov->angle_right); 24 25 const double tan_down = tan(fov->angle_down); 26 const double tan_up = tan(fov->angle_up); 27 28 const bool vulkan_projection_space_y = true; 29 30 const double tan_width = tan_right - tan_left; 31 const double tan_height = vulkan_projection_space_y // Projection space y direction: 32 ? (tan_down - tan_up) // Vulkan Y down 33 : (tan_up - tan_down); // OpenGL Y up 34 35 const double near_plane = 0.5; 36 const double far_plane = 1.5; 37 38 const double a11 = 2 / tan_width; 39 const double a22 = 2 / tan_height; 40 41 const double a31 = (tan_right + tan_left) / tan_width; 42 const double a32 = (tan_up + tan_down) / tan_height; 43 44 const double a33 = -far_plane / (far_plane - near_plane); 45 const double a43 = -(far_plane * near_plane) / (far_plane - near_plane); 46 47 48#if 0 49 // We skip a33 & a43 because we don't have depth. 50 (void)a33; 51 (void)a43; 52 53 // clang-format off 54 *result = (struct xrt_matrix_4x4_f64){ 55 { 56 a11, 0, 0, 0, 57 0, a22, 0, 0, 58 a31, a32, -1, 0, 59 0, 0, 0, 1, 60 } 61 }; 62 // clang-format on 63#else 64 /* 65 * Apparently the timewarp doesn't look good without this path being 66 * used. With the above it stretches out. I tried with the code to see 67 * if I could affect the depth where the view was placed but couldn't 68 * see to do it, which is a head scratcher. 69 */ 70 // clang-format off 71 *result = (struct xrt_matrix_4x4_f64) { 72 .v = { 73 a11, 0, 0, 0, 74 0, a22, 0, 0, 75 a31, a32, a33, -1, 76 0, 0, a43, 0, 77 } 78 }; 79 // clang-format on 80#endif 81} 82 83 84/* 85 * 86 * 'Exported' functions. 87 * 88 */ 89 90void 91render_calc_time_warp_matrix(const struct xrt_pose *src_pose, 92 const struct xrt_fov *src_fov, 93 const struct xrt_pose *new_pose, 94 struct xrt_matrix_4x4 *matrix) 95{ 96 // Src projection matrix. 97 struct xrt_matrix_4x4_f64 src_proj; 98 calc_projection(src_fov, &src_proj); 99 100 // Src rotation matrix. 101 struct xrt_matrix_4x4_f64 src_rot_inv; 102 struct xrt_quat src_q = src_pose->orientation; 103 m_mat4_f64_orientation(&src_q, &src_rot_inv); // This is a model matrix, a inverted view matrix. 104 105 // New rotation matrix. 106 struct xrt_matrix_4x4_f64 new_rot, new_rot_inv; 107 struct xrt_quat new_q = new_pose->orientation; 108 m_mat4_f64_orientation(&new_q, &new_rot_inv); // This is a model matrix, a inverted view matrix. 109 m_mat4_f64_invert(&new_rot_inv, &new_rot); // Invert to make it a view matrix. 110 111 // Combine both rotation matrices to get difference. 112 struct xrt_matrix_4x4_f64 delta_rot, delta_rot_inv; 113 m_mat4_f64_multiply(&new_rot, &src_rot_inv, &delta_rot); 114 m_mat4_f64_invert(&delta_rot, &delta_rot_inv); 115 116 // Combine the source projection matrix and 117 struct xrt_matrix_4x4_f64 result; 118 m_mat4_f64_multiply(&src_proj, &delta_rot_inv, &result); 119 120 // Convert from f64 to f32. 121 for (int i = 0; i < 16; i++) { 122 matrix->v[i] = (float)result.v[i]; 123 } 124} 125 126void 127render_calc_time_warp_projection(const struct xrt_fov *fov, struct xrt_matrix_4x4 *result) 128{ 129 struct xrt_matrix_4x4_f64 tmp; 130 calc_projection(fov, &tmp); 131 132 for (int i = 0; i < 16; i++) { 133 result->v[i] = (float)tmp.v[i]; 134 } 135} 136 137void 138render_calc_uv_to_tangent_lengths_rect(const struct xrt_fov *fov, struct xrt_normalized_rect *out_rect) 139{ 140 const struct xrt_fov copy = *fov; 141 142 const double tan_left = tan(copy.angle_left); 143 const double tan_right = tan(copy.angle_right); 144 145 const double tan_down = tan(copy.angle_down); 146 const double tan_up = tan(copy.angle_up); 147 148 const double tan_width = tan_right - tan_left; 149 const double tan_height = tan_up - tan_down; 150 151 /* 152 * I do not know why we have to calculate the offsets like this, but 153 * this one is the one that seems to work with what is currently in the 154 * calc timewarp matrix function and the distortion shader. It works 155 * with Index (unbalanced left and right angles) and WMR (unbalanced up 156 * and down angles) so here it is. In so far it matches what the gfx 157 * and non-timewarp compute pipeline produces. 158 */ 159 const double tan_offset_x = ((tan_right + tan_left) - tan_width) / 2; 160 const double tan_offset_y = (-(tan_up + tan_down) - tan_height) / 2; 161 162 struct xrt_normalized_rect transform = { 163 .x = (float)tan_offset_x, 164 .y = (float)tan_offset_y, 165 .w = (float)tan_width, 166 .h = (float)tan_height, 167 }; 168 169 *out_rect = transform; 170}