mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-01 12:46:12 +00:00
c/render: Add cylinder and equirect2 shaders
Co-authored-by: Simon Zeni <simon.zeni@collabora.com> Co-authored-by: Charlton Rodda <charlton.rodda@collabora.com>
This commit is contained in:
parent
505a54bf8f
commit
3b174b0dab
|
@ -95,6 +95,10 @@ if(XRT_HAVE_VULKAN)
|
|||
shaders/mesh.vert
|
||||
shaders/layer.frag
|
||||
shaders/layer.vert
|
||||
shaders/layer_cylinder.frag
|
||||
shaders/layer_cylinder.vert
|
||||
shaders/layer_equirect2.frag
|
||||
shaders/layer_equirect2.vert
|
||||
shaders/layer_projection.vert
|
||||
shaders/layer_quad.vert
|
||||
shaders/layer_shared.frag
|
||||
|
|
|
@ -755,6 +755,53 @@ render_gfx_render_pass_init(struct render_gfx_render_pass *rgrp,
|
|||
const VkBlendFactor blend_factor_premultiplied_alpha = VK_BLEND_FACTOR_ONE;
|
||||
const VkBlendFactor blend_factor_unpremultiplied_alpha = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
|
||||
// Cylinder
|
||||
ret = create_layer_pipeline( //
|
||||
vk, // vk
|
||||
rgrp->render_pass, // render_pass
|
||||
r->gfx.layer.shared.pipeline_layout, // pipeline_layout
|
||||
r->pipeline_cache, // pipeline_cache
|
||||
blend_factor_premultiplied_alpha, // src_blend_factor
|
||||
r->shaders->layer_cylinder_vert, // module_vert
|
||||
r->shaders->layer_cylinder_frag, // module_frag
|
||||
&rgrp->layer.cylinder_premultiplied_alpha); // out_pipeline
|
||||
VK_CHK_WITH_RET(ret, "create_layer_pipeline", false);
|
||||
|
||||
ret = create_layer_pipeline( //
|
||||
vk, // vk
|
||||
rgrp->render_pass, // render_pass
|
||||
r->gfx.layer.shared.pipeline_layout, // pipeline_layout
|
||||
r->pipeline_cache, // pipeline_cache
|
||||
blend_factor_unpremultiplied_alpha, // src_blend_factor
|
||||
r->shaders->layer_cylinder_vert, // module_vert
|
||||
r->shaders->layer_cylinder_frag, // module_frag
|
||||
&rgrp->layer.cylinder_unpremultiplied_alpha); // out_pipeline
|
||||
VK_CHK_WITH_RET(ret, "create_layer_pipeline", false);
|
||||
|
||||
// Equirect2
|
||||
ret = create_layer_pipeline( //
|
||||
vk, // vk
|
||||
rgrp->render_pass, // render_pass
|
||||
r->gfx.layer.shared.pipeline_layout, // pipeline_layout
|
||||
r->pipeline_cache, // pipeline_cache
|
||||
blend_factor_premultiplied_alpha, // src_blend_factor
|
||||
r->shaders->layer_equirect2_vert, // module_vert
|
||||
r->shaders->layer_equirect2_frag, // module_frag
|
||||
&rgrp->layer.equirect2_premultiplied_alpha); // out_pipeline
|
||||
VK_CHK_WITH_RET(ret, "create_layer_pipeline", false);
|
||||
|
||||
ret = create_layer_pipeline( //
|
||||
vk, // vk
|
||||
rgrp->render_pass, // render_pass
|
||||
r->gfx.layer.shared.pipeline_layout, // pipeline_layout
|
||||
r->pipeline_cache, // pipeline_cache
|
||||
blend_factor_unpremultiplied_alpha, // src_blend_factor
|
||||
r->shaders->layer_equirect2_vert, // module_vert
|
||||
r->shaders->layer_equirect2_frag, // module_frag
|
||||
&rgrp->layer.equirect2_unpremultiplied_alpha); // out_pipeline
|
||||
VK_CHK_WITH_RET(ret, "create_layer_pipeline", false);
|
||||
|
||||
// Projection.
|
||||
ret = create_layer_pipeline( //
|
||||
vk, // vk
|
||||
rgrp->render_pass, // render_pass
|
||||
|
@ -777,6 +824,7 @@ render_gfx_render_pass_init(struct render_gfx_render_pass *rgrp,
|
|||
&rgrp->layer.proj_unpremultiplied_alpha); // out_pipeline
|
||||
VK_CHK_WITH_RET(ret, "create_layer_pipeline", false);
|
||||
|
||||
// Quad
|
||||
ret = create_layer_pipeline( //
|
||||
vk, // vk
|
||||
rgrp->render_pass, // render_pass
|
||||
|
@ -818,6 +866,10 @@ render_gfx_render_pass_close(struct render_gfx_render_pass *rgrp)
|
|||
D(Pipeline, rgrp->mesh.pipeline);
|
||||
D(Pipeline, rgrp->mesh.pipeline_timewarp);
|
||||
|
||||
D(Pipeline, rgrp->layer.cylinder_premultiplied_alpha);
|
||||
D(Pipeline, rgrp->layer.cylinder_unpremultiplied_alpha);
|
||||
D(Pipeline, rgrp->layer.equirect2_premultiplied_alpha);
|
||||
D(Pipeline, rgrp->layer.equirect2_unpremultiplied_alpha);
|
||||
D(Pipeline, rgrp->layer.proj_premultiplied_alpha);
|
||||
D(Pipeline, rgrp->layer.proj_unpremultiplied_alpha);
|
||||
D(Pipeline, rgrp->layer.quad_premultiplied_alpha);
|
||||
|
@ -1163,6 +1215,50 @@ render_gfx_mesh_draw(struct render_gfx *rr, uint32_t mesh_index, VkDescriptorSet
|
|||
*
|
||||
*/
|
||||
|
||||
XRT_CHECK_RESULT VkResult
|
||||
render_gfx_layer_cylinder_alloc_and_write(struct render_gfx *rr,
|
||||
const struct render_gfx_layer_cylinder_data *data,
|
||||
VkSampler src_sampler,
|
||||
VkImageView src_image_view,
|
||||
VkDescriptorSet *out_descriptor_set)
|
||||
{
|
||||
struct render_resources *r = rr->r;
|
||||
|
||||
return do_ubo_and_src_alloc_and_write( //
|
||||
rr, // rr
|
||||
RENDER_BINDING_LAYER_SHARED_UBO, // ubo_binding
|
||||
data, // ubo_ptr
|
||||
sizeof(*data), // ubo_size
|
||||
RENDER_BINDING_LAYER_SHARED_SRC, // src_binding
|
||||
src_sampler, // src_sampler
|
||||
src_image_view, // src_image_view
|
||||
r->gfx.ubo_and_src_descriptor_pool, // descriptor_pool
|
||||
r->gfx.layer.shared.descriptor_set_layout, // descriptor_set_layout
|
||||
out_descriptor_set); // out_descriptor_set
|
||||
}
|
||||
|
||||
XRT_CHECK_RESULT VkResult
|
||||
render_gfx_layer_equirect2_alloc_and_write(struct render_gfx *rr,
|
||||
const struct render_gfx_layer_equirect2_data *data,
|
||||
VkSampler src_sampler,
|
||||
VkImageView src_image_view,
|
||||
VkDescriptorSet *out_descriptor_set)
|
||||
{
|
||||
struct render_resources *r = rr->r;
|
||||
|
||||
return do_ubo_and_src_alloc_and_write( //
|
||||
rr, // rr
|
||||
RENDER_BINDING_LAYER_SHARED_UBO, // ubo_binding
|
||||
data, // ubo_ptr
|
||||
sizeof(*data), // ubo_size
|
||||
RENDER_BINDING_LAYER_SHARED_SRC, // src_binding
|
||||
src_sampler, // src_sampler
|
||||
src_image_view, // src_image_view
|
||||
r->gfx.ubo_and_src_descriptor_pool, // descriptor_pool
|
||||
r->gfx.layer.shared.descriptor_set_layout, // descriptor_set_layout
|
||||
out_descriptor_set); // out_descriptor_set
|
||||
}
|
||||
|
||||
XRT_CHECK_RESULT VkResult
|
||||
render_gfx_layer_projection_alloc_and_write(struct render_gfx *rr,
|
||||
const struct render_gfx_layer_projection_data *data,
|
||||
|
@ -1207,6 +1303,46 @@ render_gfx_layer_quad_alloc_and_write(struct render_gfx *rr,
|
|||
out_descriptor_set); // out_descriptor_set
|
||||
}
|
||||
|
||||
void
|
||||
render_gfx_layer_cylinder(struct render_gfx *rr, bool premultiplied_alpha, VkDescriptorSet descriptor_set)
|
||||
{
|
||||
VkPipeline pipeline = //
|
||||
premultiplied_alpha //
|
||||
? rr->rtr->rgrp->layer.cylinder_premultiplied_alpha //
|
||||
: rr->rtr->rgrp->layer.cylinder_unpremultiplied_alpha; //
|
||||
|
||||
// One per degree.
|
||||
uint32_t subdivisions = 360;
|
||||
|
||||
// One edge on either endstop and one between each subdivision.
|
||||
uint32_t edges = subdivisions + 1;
|
||||
|
||||
// With triangle strip we get 2 vertices per edge.
|
||||
uint32_t vertex_count = edges * 2;
|
||||
|
||||
dispatch_no_vbo( //
|
||||
rr, // rr
|
||||
vertex_count, // vertex_count
|
||||
pipeline, // pipeline
|
||||
descriptor_set); // descriptor_set
|
||||
}
|
||||
|
||||
void
|
||||
render_gfx_layer_equirect2(struct render_gfx *rr, bool premultiplied_alpha, VkDescriptorSet descriptor_set)
|
||||
{
|
||||
VkPipeline pipeline = //
|
||||
premultiplied_alpha //
|
||||
? rr->rtr->rgrp->layer.equirect2_premultiplied_alpha //
|
||||
: rr->rtr->rgrp->layer.equirect2_unpremultiplied_alpha; //
|
||||
|
||||
// Hardcoded to 4 vertices.
|
||||
dispatch_no_vbo( //
|
||||
rr, // rr
|
||||
4, // vertex_count
|
||||
pipeline, // pipeline
|
||||
descriptor_set); // descriptor_set
|
||||
}
|
||||
|
||||
void
|
||||
render_gfx_layer_projection(struct render_gfx *rr, bool premultiplied_alpha, VkDescriptorSet descriptor_set)
|
||||
{
|
||||
|
|
|
@ -155,6 +155,12 @@ struct render_shaders
|
|||
* New layer renderer.
|
||||
*/
|
||||
|
||||
VkShaderModule layer_cylinder_vert;
|
||||
VkShaderModule layer_cylinder_frag;
|
||||
|
||||
VkShaderModule layer_equirect2_vert;
|
||||
VkShaderModule layer_equirect2_frag;
|
||||
|
||||
VkShaderModule layer_projection_vert;
|
||||
VkShaderModule layer_quad_vert;
|
||||
VkShaderModule layer_shared_frag;
|
||||
|
@ -721,8 +727,15 @@ struct render_gfx_render_pass
|
|||
|
||||
struct
|
||||
{
|
||||
VkPipeline cylinder_premultiplied_alpha;
|
||||
VkPipeline cylinder_unpremultiplied_alpha;
|
||||
|
||||
VkPipeline equirect2_premultiplied_alpha;
|
||||
VkPipeline equirect2_unpremultiplied_alpha;
|
||||
|
||||
VkPipeline proj_premultiplied_alpha;
|
||||
VkPipeline proj_unpremultiplied_alpha;
|
||||
|
||||
VkPipeline quad_premultiplied_alpha;
|
||||
VkPipeline quad_unpremultiplied_alpha;
|
||||
} layer;
|
||||
|
@ -872,6 +885,36 @@ struct render_gfx_mesh_ubo_data
|
|||
struct xrt_matrix_4x4 transform;
|
||||
};
|
||||
|
||||
/*!
|
||||
* UBO data that is sent to the layer cylinder shader.
|
||||
*/
|
||||
struct render_gfx_layer_cylinder_data
|
||||
{
|
||||
struct xrt_normalized_rect post_transform;
|
||||
struct xrt_matrix_4x4 mvp;
|
||||
float radius;
|
||||
float central_angle;
|
||||
float aspect_ratio;
|
||||
float _pad;
|
||||
};
|
||||
|
||||
/*!
|
||||
* UBO data that is sent to the layer equirect2 shader.
|
||||
*/
|
||||
struct render_gfx_layer_equirect2_data
|
||||
{
|
||||
struct xrt_normalized_rect post_transform;
|
||||
struct xrt_matrix_4x4 mv_inverse;
|
||||
|
||||
//! See @ref render_calc_uv_to_tangent_lengths_rect.
|
||||
struct xrt_normalized_rect to_tangent;
|
||||
|
||||
float radius;
|
||||
float central_horizontal_angle;
|
||||
float upper_vertical_angle;
|
||||
float lower_vertical_angle;
|
||||
};
|
||||
|
||||
/*!
|
||||
* UBO data that is sent to the layer projection shader.
|
||||
*/
|
||||
|
@ -951,6 +994,32 @@ render_gfx_mesh_alloc_and_write(struct render_gfx *rr,
|
|||
void
|
||||
render_gfx_mesh_draw(struct render_gfx *rr, uint32_t mesh_index, VkDescriptorSet descriptor_set, bool do_timewarp);
|
||||
|
||||
/*!
|
||||
* Allocate and write a UBO and descriptor_set to be used for cylinder layer
|
||||
* rendering, the content of @p data need to be valid at the time of the call.
|
||||
*
|
||||
* @public @memberof render_gfx
|
||||
*/
|
||||
XRT_CHECK_RESULT VkResult
|
||||
render_gfx_layer_cylinder_alloc_and_write(struct render_gfx *rr,
|
||||
const struct render_gfx_layer_cylinder_data *data,
|
||||
VkSampler src_sampler,
|
||||
VkImageView src_image_view,
|
||||
VkDescriptorSet *out_descriptor_set);
|
||||
|
||||
/*!
|
||||
* Allocate and write a UBO and descriptor_set to be used for equirect2 layer
|
||||
* rendering, the content of @p data need to be valid at the time of the call.
|
||||
*
|
||||
* @public @memberof render_gfx
|
||||
*/
|
||||
XRT_CHECK_RESULT VkResult
|
||||
render_gfx_layer_equirect2_alloc_and_write(struct render_gfx *rr,
|
||||
const struct render_gfx_layer_equirect2_data *data,
|
||||
VkSampler src_sampler,
|
||||
VkImageView src_image_view,
|
||||
VkDescriptorSet *out_descriptor_set);
|
||||
|
||||
/*!
|
||||
* Allocate and write a UBO and descriptor_set to be used for projection layer
|
||||
* rendering, the content of @p data need to be valid at the time of the call.
|
||||
|
@ -977,6 +1046,26 @@ render_gfx_layer_quad_alloc_and_write(struct render_gfx *rr,
|
|||
VkImageView src_image_view,
|
||||
VkDescriptorSet *out_descriptor_set);
|
||||
|
||||
/*!
|
||||
* Dispatch a cylinder layer shader into the current target and view,
|
||||
* allocate @p descriptor_set and ubo with
|
||||
* @ref render_gfx_layer_cylinder_alloc_and_write.
|
||||
*
|
||||
* @public @memberof render_gfx
|
||||
*/
|
||||
void
|
||||
render_gfx_layer_cylinder(struct render_gfx *rr, bool premultiplied_alpha, VkDescriptorSet descriptor_set);
|
||||
|
||||
/*!
|
||||
* Dispatch a equirect2 layer shader into the current target and view,
|
||||
* allocate @p descriptor_set and ubo with
|
||||
* @ref render_gfx_layer_equirect2_alloc_and_write.
|
||||
*
|
||||
* @public @memberof render_gfx
|
||||
*/
|
||||
void
|
||||
render_gfx_layer_equirect2(struct render_gfx *rr, bool premultiplied_alpha, VkDescriptorSet descriptor_set);
|
||||
|
||||
/*!
|
||||
* Dispatch a projection layer shader into the current target and view,
|
||||
* allocate @p descriptor_set and ubo with
|
||||
|
|
|
@ -36,6 +36,11 @@
|
|||
#include "shaders/equirect1.vert.h"
|
||||
#include "shaders/equirect2.frag.h"
|
||||
#include "shaders/equirect2.vert.h"
|
||||
#include "shaders/layer_cylinder.frag.h"
|
||||
#include "shaders/layer_cylinder.vert.h"
|
||||
#include "shaders/layer_equirect2.frag.h"
|
||||
#include "shaders/layer_equirect2.vert.h"
|
||||
#include "shaders/layer_projection.vert.h"
|
||||
#include "shaders/layer_projection.vert.h"
|
||||
#include "shaders/layer_quad.vert.h"
|
||||
#include "shaders/layer_shared.frag.h"
|
||||
|
@ -132,6 +137,10 @@ render_shaders_load(struct render_shaders *s, struct vk_bundle *vk)
|
|||
LOAD(layer_vert);
|
||||
LOAD(layer_frag);
|
||||
|
||||
LOAD(layer_cylinder_frag);
|
||||
LOAD(layer_cylinder_vert);
|
||||
LOAD(layer_equirect2_frag);
|
||||
LOAD(layer_equirect2_vert);
|
||||
LOAD(layer_projection_vert);
|
||||
LOAD(layer_quad_vert);
|
||||
LOAD(layer_shared_frag);
|
||||
|
@ -161,6 +170,10 @@ render_shaders_close(struct render_shaders *s, struct vk_bundle *vk)
|
|||
D(ShaderModule, s->layer_vert);
|
||||
D(ShaderModule, s->layer_frag);
|
||||
|
||||
D(ShaderModule, s->layer_cylinder_frag);
|
||||
D(ShaderModule, s->layer_cylinder_vert);
|
||||
D(ShaderModule, s->layer_equirect2_frag);
|
||||
D(ShaderModule, s->layer_equirect2_vert);
|
||||
D(ShaderModule, s->layer_projection_vert);
|
||||
D(ShaderModule, s->layer_quad_vert);
|
||||
D(ShaderModule, s->layer_shared_frag);
|
||||
|
|
17
src/xrt/compositor/shaders/layer_cylinder.frag
Normal file
17
src/xrt/compositor/shaders/layer_cylinder.frag
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright 2023, Collabora Ltd.
|
||||
// Author: Jakob Bornecrantz <jakob@collabora.com>
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#version 460
|
||||
|
||||
|
||||
layout (binding = 1) uniform sampler2D image;
|
||||
|
||||
layout (location = 0) in vec2 uv;
|
||||
layout (location = 0) out vec4 out_color;
|
||||
|
||||
|
||||
void main ()
|
||||
{
|
||||
out_color = texture(image, uv);
|
||||
}
|
88
src/xrt/compositor/shaders/layer_cylinder.vert
Normal file
88
src/xrt/compositor/shaders/layer_cylinder.vert
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2023, Collabora Ltd.
|
||||
// Author: Jakob Bornecrantz <jakob@collabora.com>
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#version 460
|
||||
|
||||
|
||||
// Number of subdivisions.
|
||||
layout(constant_id = 0) const uint subdivision_count = 360;
|
||||
|
||||
layout (binding = 0, std140) uniform Config
|
||||
{
|
||||
vec4 post_transform;
|
||||
mat4 mvp;
|
||||
float radius;
|
||||
float central_angle;
|
||||
float aspect_ratio;
|
||||
float _pad;
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) out vec2 out_uv;
|
||||
|
||||
out gl_PerVertex
|
||||
{
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
|
||||
vec2 get_uv_for_vertex()
|
||||
{
|
||||
// One edge on either endstop and one between each subdivision.
|
||||
uint edges = subdivision_count + 1;
|
||||
|
||||
// Goes from [0 .. 2^31], two vertices per edge.
|
||||
uint x_u32 = bitfieldExtract(uint(gl_VertexIndex), 1, 31);
|
||||
|
||||
// Goes from [0 .. 1] every other vertex.
|
||||
uint y_u32 = bitfieldExtract(uint(gl_VertexIndex), 0, 1);
|
||||
|
||||
// Starts at zero to get to [0 .. 1], there is two vertices per edge.
|
||||
float x = float(x_u32) / float(edges);
|
||||
|
||||
// Already in [0 .. 1] just transform to float.
|
||||
float y = float(y_u32);
|
||||
|
||||
return vec2(x, y);
|
||||
}
|
||||
|
||||
vec3 get_position_for_uv(vec2 uv)
|
||||
{
|
||||
float radius = ubo.radius;
|
||||
float angle = ubo.central_angle;
|
||||
float ratio = ubo.aspect_ratio;
|
||||
|
||||
// [0 .. 1] to [-0.5 .. 0.5]
|
||||
float mixed_u = uv.x - 0.5;
|
||||
|
||||
// [-0.5 .. 0.5] to [-angle / 2 .. angle / 2].
|
||||
float a = mixed_u * angle;
|
||||
|
||||
// [0 .. 1] to [0.5 .. -0.5] notice fliped sign to be in OpenXR space.
|
||||
float mixed_v = 0.5 - uv.y;
|
||||
|
||||
// This the total height acording to the spec.
|
||||
float total_height = (angle * radius) / ratio;
|
||||
|
||||
// Calculate the position.
|
||||
float x = sin(a) * radius; // At angle zero at x = 0.
|
||||
float y = total_height * mixed_v;
|
||||
float z = -cos(a) * radius; // At angle zero at z = -1.
|
||||
|
||||
return vec3(x, y, z);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// We now get a unmodified UV position.
|
||||
vec2 raw_uv = get_uv_for_vertex();
|
||||
|
||||
// Get the position for the raw UV.
|
||||
vec3 position = get_position_for_uv(raw_uv);
|
||||
|
||||
// To deal with OpenGL flip and sub image view.
|
||||
vec2 uv = fma(raw_uv, ubo.post_transform.zw, ubo.post_transform.xy);
|
||||
|
||||
gl_Position = ubo.mvp * vec4(position, 1.0);
|
||||
out_uv = uv;
|
||||
}
|
113
src/xrt/compositor/shaders/layer_equirect2.frag
Normal file
113
src/xrt/compositor/shaders/layer_equirect2.frag
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright 2023, Collabora Ltd.
|
||||
// Author: Jakob Bornecrantz <jakob@collabora.com>
|
||||
// Author: Charlton Rodda <charlton.rodda@collabora.com>
|
||||
// Author: Simon Zeni <simon.zeni@collabora.com>
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#version 460
|
||||
|
||||
layout (binding = 0, std140) uniform Config
|
||||
{
|
||||
vec4 post_transform;
|
||||
mat4 mv_inverse;
|
||||
vec4 to_tangent;
|
||||
float radius;
|
||||
float central_horizontal_angle;
|
||||
float upper_vertical_angle;
|
||||
float lower_vertical_angle;
|
||||
} ubo;
|
||||
|
||||
layout (binding = 1) uniform sampler2D image;
|
||||
|
||||
layout (location = 0) flat in vec3 in_camera_position;
|
||||
layout (location = 1) in vec3 in_camera_ray_unnormalized;
|
||||
layout (location = 0) out vec4 out_color;
|
||||
|
||||
const float PI = acos(-1);
|
||||
|
||||
|
||||
vec2 sphere_intersect(vec3 ray_origin, vec3 ray_direction, vec3 sphere_center, float radius)
|
||||
{
|
||||
vec3 ray_sphere_diff = ray_origin - sphere_center;
|
||||
|
||||
float B = dot(ray_sphere_diff, ray_direction);
|
||||
|
||||
vec3 QC = ray_sphere_diff - B * ray_direction;
|
||||
|
||||
float H = radius * radius - dot(QC, QC);
|
||||
|
||||
if (H < 0.0) {
|
||||
return vec2(-1.0); // no intersection
|
||||
}
|
||||
|
||||
H = sqrt(H);
|
||||
|
||||
return vec2(-B - H, -B + H);
|
||||
}
|
||||
|
||||
void main ()
|
||||
{
|
||||
vec3 ray_origin = in_camera_position;
|
||||
vec3 ray_dir = normalize(in_camera_ray_unnormalized);
|
||||
|
||||
vec3 dir_from_sph;
|
||||
// CPU code will set +INFINITY to zero.
|
||||
if (ubo.radius == 0) {
|
||||
dir_from_sph = ray_dir;
|
||||
} else {
|
||||
vec2 distances = sphere_intersect(ray_origin, ray_dir, vec3(0, 0, 0), ubo.radius);
|
||||
|
||||
if (distances.y < 0) {
|
||||
out_color = vec4(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 pos = ray_origin + (ray_dir * distances.y);
|
||||
dir_from_sph = normalize(pos);
|
||||
}
|
||||
|
||||
float lon = atan(dir_from_sph.x, -dir_from_sph.z) / (2 * PI) + 0.5;
|
||||
float lat = acos(dir_from_sph.y) / PI;
|
||||
|
||||
#ifdef DEBUG
|
||||
int lon_int = int(lon * 1000.0);
|
||||
int lat_int = int(lat * 1000.0);
|
||||
|
||||
if (lon < 0.001 && lon > -0.001) {
|
||||
out_color = vec4(1, 0, 0, 1);
|
||||
} else if (lon_int % 50 == 0) {
|
||||
out_color = vec4(1, 1, 1, 1);
|
||||
} else if (lat_int % 50 == 0) {
|
||||
out_color = vec4(1, 1, 1, 1);
|
||||
} else {
|
||||
out_color = vec4(lon, lat, 0, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
float chan = ubo.central_horizontal_angle / (PI * 2.0f);
|
||||
|
||||
// Normalize [0, 2π] to [0, 1]
|
||||
float uhan = 0.5 + chan / 2.0f;
|
||||
float lhan = 0.5 - chan / 2.0f;
|
||||
|
||||
// Normalize [-π/2, π/2] to [0, 1]
|
||||
float uvan = ubo.upper_vertical_angle / PI + 0.5f;
|
||||
float lvan = ubo.lower_vertical_angle / PI + 0.5f;
|
||||
|
||||
if (lat < uvan && lat > lvan && lon < uhan && lon > lhan) {
|
||||
// map configured display region to whole texture
|
||||
vec2 ll_offset = vec2(lhan, lvan);
|
||||
vec2 ll_extent = vec2(uhan - lhan, uvan - lvan);
|
||||
vec2 sample_point = (vec2(lon, lat) - ll_offset) / ll_extent;
|
||||
|
||||
vec2 uv_sub = fma(sample_point, ubo.post_transform.zw, ubo.post_transform.xy);
|
||||
|
||||
#ifdef DEBUG
|
||||
out_color += texture(image, uv_sub) / 2.0;
|
||||
#else
|
||||
out_color = texture(image, uv_sub);
|
||||
} else {
|
||||
out_color = vec4(0, 0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
}
|
65
src/xrt/compositor/shaders/layer_equirect2.vert
Normal file
65
src/xrt/compositor/shaders/layer_equirect2.vert
Normal file
|
@ -0,0 +1,65 @@
|
|||
// Copyright 2023, Collabora Ltd.
|
||||
// Author: Jakob Bornecrantz <jakob@collabora.com>
|
||||
// Author: Charlton Rodda <charlton.rodda@collabora.com>
|
||||
// Author: Simon Zeni <simon.zeni@collabora.com>
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#version 460
|
||||
|
||||
layout (binding = 0, std140) uniform Config
|
||||
{
|
||||
vec4 post_transform;
|
||||
mat4 mv_inverse;
|
||||
vec4 to_tangent;
|
||||
float radius;
|
||||
float central_horizontal_angle;
|
||||
float upper_vertical_angle;
|
||||
float lower_vertical_angle;
|
||||
} ubo;
|
||||
|
||||
layout (location = 0) flat out vec3 out_camera_position;
|
||||
layout (location = 1) out vec3 out_camera_ray_unnormalized;
|
||||
|
||||
out gl_PerVertex
|
||||
{
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
vec2 pos[4] = {
|
||||
vec2(0, 0),
|
||||
vec2(0, 1),
|
||||
vec2(1, 0),
|
||||
vec2(1, 1),
|
||||
};
|
||||
|
||||
vec3 intersection_with_unit_plane(vec2 uv_0_to_1)
|
||||
{
|
||||
// [0 .. 1] to tangent lengths (at unit Z).
|
||||
vec2 tangent_factors = fma(uv_0_to_1, ubo.to_tangent.zw, ubo.to_tangent.xy);
|
||||
|
||||
// With Z at the unit plane and flip y for OpenXR coordinate system.
|
||||
vec3 point_on_unit_plane = vec3(tangent_factors.x, -tangent_factors.y, -1);
|
||||
|
||||
return point_on_unit_plane;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = pos[gl_VertexIndex % 4];
|
||||
|
||||
// Get camera position in model space.
|
||||
out_camera_position = (ubo.mv_inverse * vec4(0, 0, 0, 1)).xyz;
|
||||
|
||||
// Get the point on the Z=-1 plane in view space that this pixel's ray intersects.
|
||||
vec3 out_camera_ray_in_view_space = intersection_with_unit_plane(uv);
|
||||
|
||||
// Transform into model space. Normalising here doesn't work because
|
||||
// the values are interpeted linearly in space, where a normal
|
||||
// doesn't move linearly in space, so do that in the fragment shader.
|
||||
out_camera_ray_unnormalized = (ubo.mv_inverse * vec4(out_camera_ray_in_view_space, 0)).xyz;
|
||||
|
||||
// Go from [0 .. 1] to [-1 .. 1] to fill whole view in NDC.
|
||||
vec2 pos = fma(uv, vec2(2.0), vec2(-1.0));
|
||||
|
||||
gl_Position = vec4(pos, 0.f, 1.f);
|
||||
}
|
Loading…
Reference in a new issue