The open source OpenXR runtime
at main 116 lines 2.9 kB view raw
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 (binding = 1) uniform sampler2D image; 24 25layout (location = 0) flat in vec3 in_camera_position; 26layout (location = 1) in vec3 in_camera_ray_unnormalized; 27layout (location = 0) out vec4 out_color; 28 29const float PI = acos(-1); 30 31 32vec2 sphere_intersect(vec3 ray_origin, vec3 ray_direction, vec3 sphere_center, float radius) 33{ 34 vec3 ray_sphere_diff = ray_origin - sphere_center; 35 36 float B = dot(ray_sphere_diff, ray_direction); 37 38 vec3 QC = ray_sphere_diff - B * ray_direction; 39 40 float H = radius * radius - dot(QC, QC); 41 42 if (H < 0.0) { 43 return vec2(-1.0); // no intersection 44 } 45 46 H = sqrt(H); 47 48 return vec2(-B - H, -B + H); 49} 50 51void main () 52{ 53 vec3 ray_origin = in_camera_position; 54 vec3 ray_dir = normalize(in_camera_ray_unnormalized); 55 56 vec3 dir_from_sph; 57 // CPU code will set +INFINITY to zero. 58 if (ubo.radius == 0) { 59 dir_from_sph = ray_dir; 60 } else { 61 vec2 distances = sphere_intersect(ray_origin, ray_dir, vec3(0, 0, 0), ubo.radius); 62 63 if (distances.y < 0) { 64 out_color = vec4(0.0); 65 return; 66 } 67 68 vec3 pos = ray_origin + (ray_dir * distances.y); 69 dir_from_sph = normalize(pos); 70 } 71 72 float lon = atan(dir_from_sph.x, -dir_from_sph.z) / (2 * PI) + 0.5; 73 float lat = acos(dir_from_sph.y) / PI; 74 75#ifdef DEBUG 76 int lon_int = int(lon * 1000.0); 77 int lat_int = int(lat * 1000.0); 78 79 if (lon < 0.001 && lon > -0.001) { 80 out_color = vec4(1, 0, 0, 1); 81 } else if (lon_int % 50 == 0) { 82 out_color = vec4(1, 1, 1, 1); 83 } else if (lat_int % 50 == 0) { 84 out_color = vec4(1, 1, 1, 1); 85 } else { 86 out_color = vec4(lon, lat, 0, 1); 87 } 88#endif 89 90 float chan = ubo.central_horizontal_angle / (PI * 2.0f); 91 92 // Normalize [0, 2π] to [0, 1] 93 float uhan = 0.5 + chan / 2.0f; 94 float lhan = 0.5 - chan / 2.0f; 95 96 // Normalize [-π/2, π/2] to [0, 1] 97 float uvan = ubo.upper_vertical_angle / PI + 0.5f; 98 float lvan = ubo.lower_vertical_angle / PI + 0.5f; 99 100 if (lat < uvan && lat > lvan && lon < uhan && lon > lhan) { 101 // map configured display region to whole texture 102 vec2 ll_offset = vec2(lhan, lvan); 103 vec2 ll_extent = vec2(uhan - lhan, uvan - lvan); 104 vec2 sample_point = (vec2(lon, lat) - ll_offset) / ll_extent; 105 106 vec2 uv_sub = fma(sample_point, ubo.post_transform.zw, ubo.post_transform.xy); 107 108#ifdef DEBUG 109 out_color += texture(image, uv_sub) / 2.0; 110#else 111 out_color = texture(image, uv_sub); 112 } else { 113 out_color = vec4(0, 0, 0, 0); 114#endif 115 } 116}