mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2024-12-29 11:06:18 +00:00
c/[util/shader]: Implement cylinder layer for compute renderer
This commit is contained in:
parent
3259fb583a
commit
9b288a6a1a
|
@ -1149,11 +1149,25 @@ struct render_compute_layer_ubo_data
|
|||
uint32_t padding[2];
|
||||
} images_samplers[RENDER_MAX_LAYERS];
|
||||
|
||||
//! Shared between cylinder and equirect2.
|
||||
struct xrt_matrix_4x4 mv_inverse[RENDER_MAX_LAYERS];
|
||||
|
||||
|
||||
/*!
|
||||
* For cylinder layer
|
||||
*/
|
||||
struct
|
||||
{
|
||||
float radius;
|
||||
float central_angle;
|
||||
float aspect_ratio;
|
||||
float padding;
|
||||
} cylinder_data[RENDER_MAX_LAYERS];
|
||||
|
||||
|
||||
/*!
|
||||
* For equirect2 layers
|
||||
*/
|
||||
struct xrt_matrix_4x4 mv_inverse[RENDER_MAX_LAYERS];
|
||||
struct
|
||||
{
|
||||
float radius;
|
||||
|
|
|
@ -44,9 +44,15 @@ layout(set = 0, binding = 3, std140) uniform restrict Config
|
|||
// which image/sampler(s) correspond to each layer
|
||||
ivec2 images_samplers[RENDER_MAX_LAYERS];
|
||||
|
||||
// shared between cylinder and equirect2
|
||||
mat4 mv_inverse[RENDER_MAX_LAYERS];
|
||||
|
||||
|
||||
// for cylinder layer
|
||||
vec4 cylinder_data[RENDER_MAX_LAYERS];
|
||||
|
||||
|
||||
// for equirect2 layer
|
||||
mat4 mv_inverse[RENDER_MAX_LAYERS];
|
||||
vec4 eq2_data[RENDER_MAX_LAYERS];
|
||||
|
||||
|
||||
|
@ -127,6 +133,111 @@ vec2 transform_uv(vec2 uv, uint layer)
|
|||
}
|
||||
}
|
||||
|
||||
vec4 do_cylinder(vec2 view_uv, uint layer)
|
||||
{
|
||||
// Get ray position in model space.
|
||||
const vec3 ray_origin = (ubo.mv_inverse[layer] * vec4(0, 0, 0, 1)).xyz;
|
||||
|
||||
// [0 .. 1] to tangent lengths (at unit Z).
|
||||
const vec2 uv = fma(view_uv, ubo.pre_transform.zw, ubo.pre_transform.xy);
|
||||
|
||||
// With Z at the unit plane and flip y for OpenXR coordinate system,
|
||||
// transform the ray into model space.
|
||||
const vec3 ray_dir = normalize((ubo.mv_inverse[layer] * vec4(uv.x, -uv.y, -1, 0)).xyz);
|
||||
|
||||
const float radius = ubo.cylinder_data[layer].x;
|
||||
const float central_angle = ubo.cylinder_data[layer].y;
|
||||
const float aspect_ratio = ubo.cylinder_data[layer].z;
|
||||
|
||||
vec3 dir_from_cyl;
|
||||
// CPU code will set +INFINITY to zero.
|
||||
if (radius == 0) {
|
||||
dir_from_cyl = ray_dir;
|
||||
} else {
|
||||
// Find if the cylinder intersects with the ray direction
|
||||
// Inspired by Inigo Quilez
|
||||
// https://iquilezles.org/articles/intersectors/
|
||||
|
||||
const vec3 axis = vec3(0.f, 1.f, 0.f);
|
||||
|
||||
float card = dot(axis, ray_dir);
|
||||
float caoc = dot(axis, ray_origin);
|
||||
float a = 1.f - card * card;
|
||||
float b = dot(ray_origin, ray_dir) - caoc * card;
|
||||
float c = dot(ray_origin, ray_origin) - caoc * caoc - radius * radius;
|
||||
float h = b * b - a * c;
|
||||
if(h < 0.f) {
|
||||
// no intersection
|
||||
return vec4(0.f);
|
||||
}
|
||||
|
||||
h = sqrt(h);
|
||||
vec2 distances = vec2(-b - h, -b + h) / a;
|
||||
|
||||
if (distances.y < 0) {
|
||||
return vec4(0.f);
|
||||
}
|
||||
|
||||
dir_from_cyl = normalize(ray_origin + (ray_dir * distances.y));
|
||||
}
|
||||
|
||||
const float lon = atan(dir_from_cyl.x, -dir_from_cyl.z) / (2 * PI) + 0.5; // => [0, 1]
|
||||
// float lat = -asin(dir_from_cyl.y); // => [-π/2, π/2]
|
||||
// float y = tan(lat); // => [-inf, inf]
|
||||
// simplified: -y/sqrt(1 - y^2)
|
||||
const float y = -dir_from_cyl.y / sqrt(1 - (dir_from_cyl.y * dir_from_cyl.y)); // => [-inf, inf]
|
||||
|
||||
vec4 out_color = vec4(0.f);
|
||||
|
||||
#ifdef DEBUG
|
||||
const int lon_int = int(lon * 1000.f);
|
||||
const int y_int = int(y * 1000.f);
|
||||
|
||||
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 (y_int % 50 == 0) {
|
||||
out_color = vec4(1, 1, 1, 1);
|
||||
} else {
|
||||
out_color = vec4(lon, y, 0, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
const float chan = central_angle / (PI * 2.f);
|
||||
|
||||
// height in radii, radius only matters for determining intersection
|
||||
const float height = central_angle * aspect_ratio;
|
||||
|
||||
// Normalize [0, 2π] to [0, 1]
|
||||
const float uhan = 0.5 + chan / 2.f;
|
||||
const float lhan = 0.5 - chan / 2.f;
|
||||
|
||||
const float ymin = -height / 2;
|
||||
const float ymax = height / 2;
|
||||
|
||||
if (y < ymax && y > ymin && lon < uhan && lon > lhan) {
|
||||
// map configured display region to whole texture
|
||||
vec2 offset = vec2(lhan, ymin);
|
||||
vec2 extent = vec2(uhan - lhan, ymax - ymin);
|
||||
vec2 sample_point = (vec2(lon, y) - offset) / extent;
|
||||
|
||||
vec2 uv_sub = fma(sample_point, ubo.post_transform[layer].zw, ubo.post_transform[layer].xy);
|
||||
|
||||
uint index = ubo.images_samplers[layer].x;
|
||||
#ifdef DEBUG
|
||||
out_color += texture(source[index], uv_sub) / 2.f;
|
||||
#else
|
||||
|
||||
out_color = texture(source[index], uv_sub);
|
||||
#endif
|
||||
} else {
|
||||
out_color += vec4(0.f);
|
||||
}
|
||||
|
||||
return out_color;
|
||||
}
|
||||
|
||||
vec4 do_equirect2(vec2 view_uv, uint layer)
|
||||
{
|
||||
// Get ray position in model space.
|
||||
|
@ -347,6 +458,9 @@ vec4 do_layers(vec2 view_uv)
|
|||
vec4 rgba = vec4(0, 0, 0, 0);
|
||||
|
||||
switch (ubo.layer_type_and_unpremultiplied[layer].x) {
|
||||
case XRT_LAYER_CYLINDER:
|
||||
rgba = do_cylinder(view_uv, layer);
|
||||
break;
|
||||
case XRT_LAYER_EQUIRECT2:
|
||||
rgba = do_equirect2(view_uv, layer);
|
||||
break;
|
||||
|
|
|
@ -242,6 +242,71 @@ do_cs_quad_layer(const struct xrt_layer_data *data,
|
|||
}
|
||||
|
||||
|
||||
static inline void
|
||||
do_cs_cylinder_layer(const struct xrt_layer_data *data,
|
||||
const struct comp_layer *layer,
|
||||
const struct xrt_matrix_4x4 *eye_view_mat,
|
||||
const struct xrt_matrix_4x4 *world_view_mat,
|
||||
uint32_t view_index,
|
||||
uint32_t cur_layer,
|
||||
uint32_t cur_image,
|
||||
VkSampler clamp_to_edge,
|
||||
VkSampler clamp_to_border_black,
|
||||
VkSampler src_samplers[RENDER_MAX_IMAGES],
|
||||
VkImageView src_image_views[RENDER_MAX_IMAGES],
|
||||
struct render_compute_layer_ubo_data *ubo_data,
|
||||
uint32_t *out_cur_image)
|
||||
{
|
||||
const struct xrt_layer_cylinder_data *c = &data->cylinder;
|
||||
|
||||
const struct comp_swapchain_image *image = &layer->sc_array[0]->images[c->sub.image_index];
|
||||
uint32_t array_index = c->sub.array_index;
|
||||
|
||||
// Image to use.
|
||||
src_samplers[cur_image] = clamp_to_edge;
|
||||
src_image_views[cur_image] = get_image_view(image, data->flags, array_index);
|
||||
|
||||
// Used for Subimage and OpenGL flip.
|
||||
set_post_transform_rect( //
|
||||
data, // data
|
||||
&c->sub.norm_rect, // src_norm_rect
|
||||
false, // invert_flip
|
||||
&ubo_data->post_transforms[cur_layer]); // out_norm_rect
|
||||
|
||||
ubo_data->cylinder_data[cur_layer].central_angle = c->central_angle;
|
||||
ubo_data->cylinder_data[cur_layer].aspect_ratio = c->aspect_ratio;
|
||||
|
||||
struct xrt_vec3 scale = {1.f, 1.f, 1.f};
|
||||
|
||||
struct xrt_matrix_4x4 model;
|
||||
math_matrix_4x4_model(&c->pose, &scale, &model);
|
||||
|
||||
struct xrt_matrix_4x4 model_inv;
|
||||
math_matrix_4x4_inverse(&model, &model_inv);
|
||||
|
||||
const struct xrt_matrix_4x4 *v = is_layer_view_space(data) ? eye_view_mat : world_view_mat;
|
||||
|
||||
struct xrt_matrix_4x4 v_inv;
|
||||
math_matrix_4x4_inverse(v, &v_inv);
|
||||
|
||||
math_matrix_4x4_multiply(&model_inv, &v_inv, &ubo_data->mv_inverse[cur_layer]);
|
||||
|
||||
// Simplifies the shader.
|
||||
if (c->radius >= INFINITY) {
|
||||
ubo_data->cylinder_data[cur_layer].radius = 0.f;
|
||||
} else {
|
||||
ubo_data->cylinder_data[cur_layer].radius = c->radius;
|
||||
}
|
||||
|
||||
ubo_data->cylinder_data[cur_layer].central_angle = c->central_angle;
|
||||
ubo_data->cylinder_data[cur_layer].aspect_ratio = c->aspect_ratio;
|
||||
|
||||
ubo_data->images_samplers[cur_layer].images[0] = cur_image;
|
||||
cur_image++;
|
||||
|
||||
*out_cur_image = cur_image;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Compute distortion helpers.
|
||||
|
@ -408,6 +473,7 @@ comp_render_cs_layer(struct render_compute *crc,
|
|||
*/
|
||||
uint32_t required_image_samplers;
|
||||
switch (data->type) {
|
||||
case XRT_LAYER_CYLINDER: required_image_samplers = 1; break;
|
||||
case XRT_LAYER_EQUIRECT2: required_image_samplers = 1; break;
|
||||
case XRT_LAYER_STEREO_PROJECTION: required_image_samplers = 1; break;
|
||||
case XRT_LAYER_STEREO_PROJECTION_DEPTH: required_image_samplers = 2; break;
|
||||
|
@ -423,6 +489,22 @@ comp_render_cs_layer(struct render_compute *crc,
|
|||
}
|
||||
|
||||
switch (data->type) {
|
||||
case XRT_LAYER_CYLINDER:
|
||||
do_cs_cylinder_layer( //
|
||||
data, // data
|
||||
layer, // layer
|
||||
&eye_view_mat, // eye_view_mat
|
||||
&world_view_mat, // world_view_mat
|
||||
view_index, // view_index
|
||||
cur_layer, // cur_layer
|
||||
cur_image, // cur_image
|
||||
clamp_to_edge, // clamp_to_edge
|
||||
clamp_to_border_black, // clamp_to_border_black
|
||||
src_samplers, // src_samplers
|
||||
src_image_views, // src_image_views
|
||||
ubo_data, // ubo_data
|
||||
&cur_image); // out_cur_image
|
||||
break;
|
||||
case XRT_LAYER_EQUIRECT2:
|
||||
do_cs_equirect2_layer( //
|
||||
data, // data
|
||||
|
|
Loading…
Reference in a new issue