diff options
author | Bastiaan Olij <mux213@gmail.com> | 2022-02-11 22:33:54 +1100 |
---|---|---|
committer | Bastiaan Olij <mux213@gmail.com> | 2022-07-17 15:42:24 +1000 |
commit | d139131aab7f228d5cca612b35289e6abd18e26a (patch) | |
tree | 65a6c1d6cfa959cc010f32284b5f1ba6ed866647 /servers/xr | |
parent | e3a8ab68ce7497b3752d29965c6a54c50d548144 (diff) |
Adding Variable Rate Shading support to Godot
Improve GI renderer and add VRS support
Implement render device has_feature and move subgroup settings to limit_get
Diffstat (limited to 'servers/xr')
-rw-r--r-- | servers/xr/xr_interface.cpp | 88 | ||||
-rw-r--r-- | servers/xr/xr_interface.h | 7 | ||||
-rw-r--r-- | servers/xr/xr_interface_extension.cpp | 10 | ||||
-rw-r--r-- | servers/xr/xr_interface_extension.h | 2 |
4 files changed, 105 insertions, 2 deletions
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp index 7ae111b5e7..0808b1fd7b 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... + CameraMatrix 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..b4eb4694f6 100644 --- a/servers/xr/xr_interface.h +++ b/servers/xr/xr_interface.h @@ -120,6 +120,7 @@ public: 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 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 1f3d07c357..94953c69a9 100644 --- a/servers/xr/xr_interface_extension.cpp +++ b/servers/xr/xr_interface_extension.cpp @@ -50,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); @@ -273,6 +274,15 @@ CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, doub return CameraMatrix(); } +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) { BlitToScreen blit; diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h index 5a436b9fd0..7174b412c5 100644 --- a/servers/xr/xr_interface_extension.h +++ b/servers/xr/xr_interface_extension.h @@ -101,12 +101,14 @@ public: 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 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); |