The open source OpenXR runtime
1// Copyright 2020-2023, Collabora Ltd.
2//
3// Author: Jakob Bornecrantz <jakob@collabora.com>
4// Author: Charlton Rodda <charlton.rodda@collabora.com>
5// Author: Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
6// Author: Simon Zeni <simon.zeni@collabora.com>
7//
8// SPDX-License-Identifier: BSL-1.0
9
10#version 460
11
12layout (binding = 0, std140) uniform Config
13{
14 vec4 post_transform;
15 mat4 mv_inverse;
16 vec4 to_tangent;
17 float radius;
18 float central_horizontal_angle;
19 float upper_vertical_angle;
20 float lower_vertical_angle;
21} ubo;
22
23layout (location = 0) flat out vec3 out_camera_position;
24layout (location = 1) out vec3 out_camera_ray_unnormalized;
25
26out gl_PerVertex
27{
28 vec4 gl_Position;
29};
30
31vec2 pos[4] = {
32 vec2(0, 0),
33 vec2(0, 1),
34 vec2(1, 0),
35 vec2(1, 1),
36};
37
38vec3 intersection_with_unit_plane(vec2 uv_0_to_1)
39{
40 // [0 .. 1] to tangent lengths (at unit Z).
41 vec2 tangent_factors = fma(uv_0_to_1, ubo.to_tangent.zw, ubo.to_tangent.xy);
42
43 // With Z at the unit plane and flip y for OpenXR coordinate system.
44 vec3 point_on_unit_plane = vec3(tangent_factors.x, -tangent_factors.y, -1);
45
46 return point_on_unit_plane;
47}
48
49void main()
50{
51 vec2 uv = pos[gl_VertexIndex % 4];
52
53 // Get camera position in model space.
54 out_camera_position = (ubo.mv_inverse * vec4(0, 0, 0, 1)).xyz;
55
56 // Get the point on the Z=-1 plane in view space that this pixel's ray intersects.
57 vec3 out_camera_ray_in_view_space = intersection_with_unit_plane(uv);
58
59 // Transform into model space. Normalising here doesn't work because
60 // the values are interpeted linearly in space, where a normal
61 // doesn't move linearly in space, so do that in the fragment shader.
62 out_camera_ray_unnormalized = (ubo.mv_inverse * vec4(out_camera_ray_in_view_space, 0)).xyz;
63
64 // Go from [0 .. 1] to [-1 .. 1] to fill whole view in NDC.
65 vec2 pos = fma(uv, vec2(2.0), vec2(-1.0));
66
67 gl_Position = vec4(pos, 0.f, 1.f);
68}