The open source OpenXR runtime
1// Copyright 2019-2023, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Matrix function for creating projection matrices.
6 * @author Jakob Bornecrantz <jakob@collabora.com>
7 * @ingroup aux_math
8 */
9
10#include "m_mathinclude.h"
11#include "xrt/xrt_defines.h"
12
13
14/*
15 *
16 * Helpers.
17 *
18 */
19
20template <typename Scalar, typename ResultType>
21void
22calc_vulkan_projection_infinite_reverse(const xrt_fov &fov, Scalar near_plane, ResultType &result)
23{
24 const Scalar tan_left = static_cast<Scalar>(tan(fov.angle_left));
25 const Scalar tan_right = static_cast<Scalar>(tan(fov.angle_right));
26
27 const Scalar tan_down = static_cast<Scalar>(tan(fov.angle_down));
28 const Scalar tan_up = static_cast<Scalar>(tan(fov.angle_up));
29
30 // This is here for clarity.
31 const bool vulkan_projection_space_y = true;
32
33 const Scalar tan_width = tan_right - tan_left;
34 const Scalar tan_height = vulkan_projection_space_y // Projection space y direction:
35 ? (tan_down - tan_up) // Vulkan Y down
36 : (tan_up - tan_down); // OpenGL Y up
37
38 const Scalar a11 = 2 / tan_width;
39 const Scalar a22 = 2 / tan_height;
40
41 const Scalar a31 = (tan_right + tan_left) / tan_width;
42 const Scalar a32 = (tan_up + tan_down) / tan_height;
43
44
45 /*
46 * Vulkan's Z clip space is [0 .. 1] (OpenGL [-1 .. 0 .. 1]).
47 * We are using reverse depth for better floating value.
48 * - Near is 1
49 * - Far is 0 (infinite)
50 *
51 * https://vincent-p.github.io/posts/vulkan_perspective_matrix/
52 */
53
54 const Scalar a33 = 0; // vulkan = 0, opengl = -1
55 const Scalar a34 = -1;
56 const Scalar a43 = near_plane; // Reverse depth and half vs opengl, `-2 * near_plane`.
57
58 // clang-format off
59 result = ResultType({
60 a11, 0, 0, 0,
61 0, a22, 0, 0,
62 a31, a32, a33, a34,
63 0, 0, a43, 0,
64 });
65 // clang-format on
66}
67
68
69/*
70 *
71 * 'Exported' functions.
72 *
73 */
74
75extern "C" void
76math_matrix_4x4_projection_vulkan_infinite_reverse(const struct xrt_fov *fov,
77 float near_plane,
78 struct xrt_matrix_4x4 *result)
79{
80 calc_vulkan_projection_infinite_reverse<float, xrt_matrix_4x4>(*fov, near_plane, *result);
81}