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
This commit is contained in:
parent
e3a8ab68ce
commit
d139131aab
44 changed files with 1574 additions and 466 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue