The open source OpenXR runtime
1// Copyright 2023, Collabora Ltd.
2// Author: Jakob Bornecrantz <jakob@collabora.com>
3// SPDX-License-Identifier: BSL-1.0
4
5#version 460
6
7
8// Number of subdivisions.
9layout(constant_id = 0) const uint subdivision_count = 360;
10
11layout (binding = 0, std140) uniform Config
12{
13 vec4 post_transform;
14 mat4 mvp;
15 float radius;
16 float central_angle;
17 float aspect_ratio;
18 float _pad;
19} ubo;
20
21layout (location = 0) out vec2 out_uv;
22
23out gl_PerVertex
24{
25 vec4 gl_Position;
26};
27
28
29vec2 get_uv_for_vertex()
30{
31 // One edge on either endstop and one between each subdivision.
32 uint edges = subdivision_count + 1;
33
34 // Goes from [0 .. 2^31], two vertices per edge.
35 uint x_u32 = bitfieldExtract(uint(gl_VertexIndex), 1, 31);
36
37 // Goes from [0 .. 1] every other vertex.
38 uint y_u32 = bitfieldExtract(uint(gl_VertexIndex), 0, 1);
39
40 // Starts at zero to get to [0 .. 1], there is two vertices per edge.
41 float x = float(x_u32) / float(edges);
42
43 // Already in [0 .. 1] just transform to float.
44 float y = float(y_u32);
45
46 return vec2(x, y);
47}
48
49vec3 get_position_for_uv(vec2 uv)
50{
51 float radius = ubo.radius;
52 float angle = ubo.central_angle;
53 float ratio = ubo.aspect_ratio;
54
55 // [0 .. 1] to [-0.5 .. 0.5]
56 float mixed_u = uv.x - 0.5;
57
58 // [-0.5 .. 0.5] to [-angle / 2 .. angle / 2].
59 float a = mixed_u * angle;
60
61 // [0 .. 1] to [0.5 .. -0.5] notice fliped sign to be in OpenXR space.
62 float mixed_v = 0.5 - uv.y;
63
64 // This the total height acording to the spec.
65 float total_height = (angle * radius) / ratio;
66
67 // Calculate the position.
68 float x = sin(a) * radius; // At angle zero at x = 0.
69 float y = total_height * mixed_v;
70 float z = -cos(a) * radius; // At angle zero at z = -1.
71
72 return vec3(x, y, z);
73}
74
75void main()
76{
77 // We now get a unmodified UV position.
78 vec2 raw_uv = get_uv_for_vertex();
79
80 // Get the position for the raw UV.
81 vec3 position = get_position_for_uv(raw_uv);
82
83 // To deal with OpenGL flip and sub image view.
84 vec2 uv = fma(raw_uv, ubo.post_transform.zw, ubo.post_transform.xy);
85
86 gl_Position = ubo.mvp * vec4(position, 1.0);
87 out_uv = uv;
88}