|
@@ -387,18 +387,26 @@ RasterizerGLES3::RasterizerGLES3() {
|
|
|
RasterizerGLES3::~RasterizerGLES3() {
|
|
|
}
|
|
|
|
|
|
-void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, DisplayServer::WindowID p_screen, const Rect2 &p_screen_rect, uint32_t p_layer, bool p_first) {
|
|
|
- GLES3::RenderTarget *rt = GLES3::TextureStorage::get_singleton()->get_render_target(p_render_target);
|
|
|
+void RasterizerGLES3::_blit_render_target_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen &p_blit, bool p_first) {
|
|
|
+ GLES3::RenderTarget *rt = GLES3::TextureStorage::get_singleton()->get_render_target(p_blit.render_target);
|
|
|
|
|
|
ERR_FAIL_NULL(rt);
|
|
|
|
|
|
// We normally render to the render target upside down, so flip Y when blitting to the screen.
|
|
|
bool flip_y = true;
|
|
|
+ bool linear_to_srgb = false;
|
|
|
if (rt->overridden.color.is_valid()) {
|
|
|
// If we've overridden the render target's color texture, that means we
|
|
|
// didn't render upside down, so we don't need to flip it.
|
|
|
// We're probably rendering directly to an XR device.
|
|
|
flip_y = false;
|
|
|
+
|
|
|
+ // It is 99% likely our texture uses the GL_SRGB8_ALPHA8 texture format in
|
|
|
+ // which case we have a GPU sRGB to Linear conversion on texture read.
|
|
|
+ // We need to counter this.
|
|
|
+ // Unfortunately we do not have an API to check this as Godot does not
|
|
|
+ // track this.
|
|
|
+ linear_to_srgb = true;
|
|
|
}
|
|
|
|
|
|
#ifdef WINDOWS_ENABLED
|
|
@@ -410,7 +418,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
|
|
|
|
|
|
if (p_first) {
|
|
|
- if (p_screen_rect.position != Vector2() || p_screen_rect.size != rt->size) {
|
|
|
+ if (p_blit.dst_rect.position != Vector2() || p_blit.dst_rect.size != rt->size) {
|
|
|
// Viewport doesn't cover entire window so clear window to black before blitting.
|
|
|
// Querying the actual window size from the DisplayServer would deadlock in separate render thread mode,
|
|
|
// so let's set the biggest viewport the implementation supports, to be sure the window is fully covered.
|
|
@@ -421,7 +429,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Vector2 screen_rect_end = p_screen_rect.get_end();
|
|
|
+ Vector2 screen_rect_end = p_blit.dst_rect.get_end();
|
|
|
|
|
|
// Adreno (TM) 3xx devices have a bug that create wrong Landscape rotation of 180 degree
|
|
|
// Reversing both the X and Y axis is equivalent to rotating 180 degrees
|
|
@@ -431,8 +439,8 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
|
|
|
flip_x = !flip_x;
|
|
|
}
|
|
|
|
|
|
- Vector2 p1 = Vector2(flip_x ? screen_rect_end.x : p_screen_rect.position.x, flip_y ? screen_rect_end.y : p_screen_rect.position.y);
|
|
|
- Vector2 p2 = Vector2(flip_x ? p_screen_rect.position.x : screen_rect_end.x, flip_y ? p_screen_rect.position.y : screen_rect_end.y);
|
|
|
+ Vector2 p1 = Vector2(flip_x ? screen_rect_end.x : p_blit.dst_rect.position.x, flip_y ? screen_rect_end.y : p_blit.dst_rect.position.y);
|
|
|
+ Vector2 p2 = Vector2(flip_x ? p_blit.dst_rect.position.x : screen_rect_end.x, flip_y ? p_blit.dst_rect.position.y : screen_rect_end.y);
|
|
|
Vector2 size = p2 - p1;
|
|
|
|
|
|
Rect2 screenrect = Rect2(Vector2(flip_x ? 1.0 : 0.0, flip_y ? 1.0 : 0.0), Vector2(flip_x ? -1.0 : 1.0, flip_y ? -1.0 : 1.0));
|
|
@@ -450,10 +458,12 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
|
|
|
glEnable(GL_BLEND);
|
|
|
glBlendFunc(GL_ONE, GL_ZERO);
|
|
|
|
|
|
- if (rt->view_count > 1) {
|
|
|
- copy_effects->copy_to_rect_3d(screenrect, p_layer, GLES3::Texture::TYPE_LAYERED);
|
|
|
+ if (p_blit.lens_distortion.apply && (p_blit.lens_distortion.k1 != 0.0 || p_blit.lens_distortion.k2)) {
|
|
|
+ copy_effects->copy_with_lens_distortion(screenrect, p_blit.multi_view.use_layer ? p_blit.multi_view.layer : 0, p_blit.lens_distortion.eye_center, p_blit.lens_distortion.k1, p_blit.lens_distortion.k2, p_blit.lens_distortion.upscale, p_blit.lens_distortion.aspect_ratio, linear_to_srgb);
|
|
|
+ } else if (rt->view_count > 1) {
|
|
|
+ copy_effects->copy_to_rect_3d(screenrect, p_blit.multi_view.use_layer ? p_blit.multi_view.layer : 0, GLES3::Texture::TYPE_LAYERED, 0.0, linear_to_srgb);
|
|
|
} else {
|
|
|
- copy_effects->copy_to_rect(screenrect);
|
|
|
+ copy_effects->copy_to_rect(screenrect, linear_to_srgb);
|
|
|
}
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
@@ -462,12 +472,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
|
|
|
// is this p_screen useless in a multi window environment?
|
|
|
void RasterizerGLES3::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
|
|
|
for (int i = 0; i < p_amount; i++) {
|
|
|
- const BlitToScreen &blit = p_render_targets[i];
|
|
|
-
|
|
|
- RID rid_rt = blit.render_target;
|
|
|
-
|
|
|
- Rect2 dst_rect = blit.dst_rect;
|
|
|
- _blit_render_target_to_screen(rid_rt, p_screen, dst_rect, blit.multi_view.use_layer ? blit.multi_view.layer : 0, i == 0);
|
|
|
+ _blit_render_target_to_screen(p_screen, p_render_targets[i], i == 0);
|
|
|
}
|
|
|
}
|
|
|
|