diff options
Diffstat (limited to 'servers/xr')
-rw-r--r-- | servers/xr/xr_interface.cpp | 88 | ||||
-rw-r--r-- | servers/xr/xr_interface.h | 11 | ||||
-rw-r--r-- | servers/xr/xr_interface_extension.cpp | 27 | ||||
-rw-r--r-- | servers/xr/xr_interface_extension.h | 6 | ||||
-rw-r--r-- | servers/xr/xr_pose.h | 2 | ||||
-rw-r--r-- | servers/xr/xr_positional_tracker.h | 4 |
6 files changed, 120 insertions, 18 deletions
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 7ae111b5e7..4b9ea40223 100644 --- a/servers/xr/xr_interface.cpp +++ b/servers/xr/xr_interface.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "xr_interface.h" -// #include "servers/rendering/renderer_compositor.h" +#include "servers/rendering/renderer_compositor.h" void XRInterface::_bind_methods() { ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode"))); @@ -114,7 +114,12 @@ void XRInterface::set_primary(bool p_primary) { XRInterface::XRInterface() {} -XRInterface::~XRInterface() {} +XRInterface::~XRInterface() { + if (vrs.vrs_texture.is_valid()) { + RS::get_singleton()->free(vrs.vrs_texture); + vrs.vrs_texture = RID(); + } +} // query if this interface supports this play area mode bool XRInterface::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) { @@ -151,6 +156,85 @@ int XRInterface::get_camera_feed_id() { return 0; } +RID XRInterface::get_vrs_texture() { + // Default logic will return a standard VRS image based on our target size and default projections. + // Note that this only gets called if VRS is supported on the hardware. + + Size2 texel_size = Size2(16.0, 16.0); // For now we assume we always use 16x16 texels, seems to be the standard. + int view_count = get_view_count(); + Size2 target_size = get_render_target_size(); + real_t aspect = target_size.x / target_size.y; // is this y/x ? + Size2 vrs_size = Size2(round(0.5 + target_size.x / texel_size.x), round(0.5 + target_size.y / texel_size.y)); + real_t radius = vrs_size.length() * 0.5; + Size2 vrs_sizei = vrs_size; + + if (vrs.size != vrs_sizei) { + const uint8_t densities[] = { + 0, // 1x1 + 1, // 1x2 + // 4, // 2x1 + 5, // 2x2 + 6, // 2x4 + // 9, // 4x2 + 10, // 4x4 + }; + + // out with the old + if (vrs.vrs_texture.is_valid()) { + RS::get_singleton()->free(vrs.vrs_texture); + vrs.vrs_texture = RID(); + } + + // in with the new + Vector<Ref<Image>> images; + vrs.size = vrs_sizei; + + for (int i = 0; i < view_count && i < 2; i++) { + PackedByteArray data; + data.resize(vrs_sizei.x * vrs_sizei.y); + uint8_t *data_ptr = data.ptrw(); + + // Our near and far don't matter much for what we're doing here, but there are some interfaces that will remember this as the near and far and may fail as a result... + Projection cm = get_projection_for_view(i, aspect, 0.1, 1000.0); + Vector3 center = cm.xform(Vector3(0.0, 0.0, 999.0)); + + Vector2i view_center; + view_center.x = int(vrs_size.x * (center.x + 1.0) * 0.5); + view_center.y = int(vrs_size.y * (center.y + 1.0) * 0.5); + + int d = 0; + for (int y = 0; y < vrs_sizei.y; y++) { + for (int x = 0; x < vrs_sizei.x; x++) { + Vector2 offset = Vector2(x - view_center.x, y - view_center.y); + offset.y *= aspect; + real_t distance = offset.length(); + int idx = round(5.0 * distance / radius); + if (idx > 4) { + idx = 4; + } + uint8_t density = densities[idx]; + + data_ptr[d++] = density; + } + } + + Ref<Image> image; + image.instantiate(); + image->create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data); + + images.push_back(image); + } + + if (images.size() == 1) { + vrs.vrs_texture = RS::get_singleton()->texture_2d_create(images[0]); + } else { + vrs.vrs_texture = RS::get_singleton()->texture_2d_layered_create(images, RS::TEXTURE_LAYERED_2D_ARRAY); + } + } + + return vrs.vrs_texture; +} + /** these are optional, so we want dummies **/ PackedStringArray XRInterface::get_suggested_tracker_names() const { PackedStringArray arr; diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h index 62eba2f00b..f11458f1cc 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -31,7 +31,7 @@ #ifndef XR_INTERFACE_H #define XR_INTERFACE_H -#include "core/math/camera_matrix.h" +#include "core/math/projection.h" #include "core/os/thread_safe.h" #include "servers/xr_server.h" @@ -119,7 +119,8 @@ public: virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */ virtual Transform3D get_camera_transform() = 0; /* returns the position of our camera for updating our camera node. For monoscopic this is equal to the views transform, for stereoscopic this should be an average */ virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) = 0; /* get each views transform */ - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */ + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) = 0; /* get each view projection matrix */ + virtual RID get_vrs_texture(); /* obtain VRS texture */ // note, external color/depth/vrs texture support will be added here soon. @@ -133,6 +134,12 @@ public: XRInterface(); ~XRInterface(); + +private: + struct VRSData { + RID vrs_texture; + Size2i size; + } vrs; }; VARIANT_ENUM_CAST(XRInterface::Capabilities); diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp index 18131c1e89..7395cd5ad4 100644 --- a/servers/xr/xr_interface_extension.cpp +++ b/servers/xr/xr_interface_extension.cpp @@ -29,8 +29,7 @@ /*************************************************************************/ #include "xr_interface_extension.h" -#include "servers/rendering/renderer_rd/renderer_storage_rd.h" -#include "servers/rendering/renderer_storage.h" +#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" #include "servers/rendering/rendering_server_globals.h" void XRInterfaceExtension::_bind_methods() { @@ -51,6 +50,7 @@ void XRInterfaceExtension::_bind_methods() { GDVIRTUAL_BIND(_get_camera_transform); GDVIRTUAL_BIND(_get_transform_for_view, "view", "cam_transform"); GDVIRTUAL_BIND(_get_projection_for_view, "view", "aspect", "z_near", "z_far"); + GDVIRTUAL_BIND(_get_vrs_texture); GDVIRTUAL_BIND(_process); GDVIRTUAL_BIND(_pre_render); @@ -258,12 +258,12 @@ Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const return Transform3D(); } -CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { - CameraMatrix cm; +Projection XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) { + Projection cm; PackedFloat64Array arr; if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) { - ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats"); + ERR_FAIL_COND_V_MSG(arr.size() != 16, Projection(), "Projection matrix must contain 16 floats"); real_t *m = (real_t *)cm.matrix; for (int i = 0; i < 16; i++) { m[i] = arr[i]; @@ -271,7 +271,16 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub return cm; } - return CameraMatrix(); + return Projection(); +} + +RID XRInterfaceExtension::get_vrs_texture() { + RID vrs_texture; + if (GDVIRTUAL_CALL(_get_vrs_texture, vrs_texture)) { + return vrs_texture; + } else { + return XRInterface::get_vrs_texture(); + } } void XRInterfaceExtension::add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer, uint32_t p_layer, bool p_apply_lens_distortion, Vector2 p_eye_center, double p_k1, double p_k2, double p_upscale, double p_aspect_ratio) { @@ -339,10 +348,10 @@ void XRInterfaceExtension::notification(int p_what) { RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) { // In due time this will need to be enhance to return the correct INTERNAL RID for the chosen rendering engine. // So once a GLES driver is implemented we'll return that and the implemented plugin needs to handle this correctly too. - RendererStorageRD *rd_storage = RendererStorageRD::base_singleton; - ERR_FAIL_NULL_V_MSG(rd_storage, RID(), "Renderer storage not setup"); + RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); + ERR_FAIL_NULL_V_MSG(texture_storage, RID(), "Texture storage not setup"); - return rd_storage->render_target_get_rd_texture(p_render_target); + return texture_storage->render_target_get_rd_texture(p_render_target); } /* diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h index 5a436b9fd0..65b474425e 100644 --- a/servers/xr/xr_interface_extension.h +++ b/servers/xr/xr_interface_extension.h @@ -100,13 +100,15 @@ public: virtual uint32_t get_view_count() override; virtual Transform3D get_camera_transform() override; virtual Transform3D get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) override; - virtual CameraMatrix get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual Projection get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) override; + virtual RID get_vrs_texture() override; GDVIRTUAL0R(Size2, _get_render_target_size); GDVIRTUAL0R(uint32_t, _get_view_count); GDVIRTUAL0R(Transform3D, _get_camera_transform); GDVIRTUAL2R(Transform3D, _get_transform_for_view, uint32_t, const Transform3D &); GDVIRTUAL4R(PackedFloat64Array, _get_projection_for_view, uint32_t, double, double, double); + GDVIRTUAL0R(RID, _get_vrs_texture); void add_blit(RID p_render_target, Rect2 p_src_rect, Rect2i p_dst_rect, bool p_use_layer = false, uint32_t p_layer = 0, bool p_apply_lens_distortion = false, Vector2 p_eye_center = Vector2(), double p_k1 = 0.0, double p_k2 = 0.0, double p_upscale = 1.0, double p_aspect_ratio = 1.0); @@ -130,4 +132,4 @@ public: // RID get_render_target_depth(RID p_render_target); }; -#endif // !XR_INTERFACE_EXTENSION_H +#endif // XR_INTERFACE_EXTENSION_H diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h index f306c22390..e7d363764b 100644 --- a/servers/xr/xr_pose.h +++ b/servers/xr/xr_pose.h @@ -78,4 +78,4 @@ public: VARIANT_ENUM_CAST(XRPose::TrackingConfidence); -#endif +#endif // XR_POSE_H diff --git a/servers/xr/xr_positional_tracker.h b/servers/xr/xr_positional_tracker.h index cd06d4a087..8371dfcbb5 100644 --- a/servers/xr/xr_positional_tracker.h +++ b/servers/xr/xr_positional_tracker.h @@ -60,8 +60,8 @@ private: String profile; // this is interface dependent, for OpenXR this will be the interaction profile bound for to the tracker TrackerHand hand; // if known, the hand this tracker is held in - Map<StringName, Ref<XRPose>> poses; - Map<StringName, Variant> inputs; + HashMap<StringName, Ref<XRPose>> poses; + HashMap<StringName, Variant> inputs; protected: static void _bind_methods(); |