@@ -387,18 +387,26 @@ RasterizerGLES3::RasterizerGLES3() {
387387RasterizerGLES3::~RasterizerGLES3 () {
388388}
389389
390- 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) {
391- GLES3::RenderTarget *rt = GLES3::TextureStorage::get_singleton ()->get_render_target (p_render_target );
390+ void RasterizerGLES3::_blit_render_target_to_screen (DisplayServer::WindowID p_screen, const BlitToScreen &p_blit , bool p_first) {
391+ GLES3::RenderTarget *rt = GLES3::TextureStorage::get_singleton ()->get_render_target (p_blit. render_target );
392392
393393 ERR_FAIL_NULL (rt);
394394
395395 // We normally render to the render target upside down, so flip Y when blitting to the screen.
396396 bool flip_y = true ;
397+ bool linear_to_srgb = false ;
397398 if (rt->overridden .color .is_valid ()) {
398399 // If we've overridden the render target's color texture, that means we
399400 // didn't render upside down, so we don't need to flip it.
400401 // We're probably rendering directly to an XR device.
401402 flip_y = false ;
403+
404+ // It is 99% likely our texture uses the GL_SRGB8_ALPHA8 texture format in
405+ // which case we have a GPU sRGB to Linear conversion on texture read.
406+ // We need to counter this.
407+ // Unfortunately we do not have an API to check this as Godot does not
408+ // track this.
409+ linear_to_srgb = true ;
402410 }
403411
404412#ifdef WINDOWS_ENABLED
@@ -410,7 +418,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
410418 glBindFramebuffer (GL_DRAW_FRAMEBUFFER, GLES3::TextureStorage::system_fbo);
411419
412420 if (p_first) {
413- if (p_screen_rect. position != Vector2 () || p_screen_rect .size != rt->size ) {
421+ if (p_blit. dst_rect . position != Vector2 () || p_blit. dst_rect .size != rt->size ) {
414422 // Viewport doesn't cover entire window so clear window to black before blitting.
415423 // Querying the actual window size from the DisplayServer would deadlock in separate render thread mode,
416424 // 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
421429 }
422430 }
423431
424- Vector2 screen_rect_end = p_screen_rect .get_end ();
432+ Vector2 screen_rect_end = p_blit. dst_rect .get_end ();
425433
426434 // Adreno (TM) 3xx devices have a bug that create wrong Landscape rotation of 180 degree
427435 // 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
431439 flip_x = !flip_x;
432440 }
433441
434- 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 );
435- 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 );
442+ 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 );
443+ 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 );
436444 Vector2 size = p2 - p1;
437445
438446 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
450458 glEnable (GL_BLEND);
451459 glBlendFunc (GL_ONE, GL_ZERO);
452460
453- if (rt->view_count > 1 ) {
454- copy_effects->copy_to_rect_3d (screenrect, p_layer, GLES3::Texture::TYPE_LAYERED);
461+ if (p_blit.lens_distortion .apply && (p_blit.lens_distortion .k1 != 0.0 || p_blit.lens_distortion .k2 )) {
462+ 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);
463+ } else if (rt->view_count > 1 ) {
464+ 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);
455465 } else {
456- copy_effects->copy_to_rect (screenrect);
466+ copy_effects->copy_to_rect (screenrect, linear_to_srgb );
457467 }
458468
459469 glBindTexture (GL_TEXTURE_2D, 0 );
@@ -462,12 +472,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
462472// is this p_screen useless in a multi window environment?
463473void RasterizerGLES3::blit_render_targets_to_screen (DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) {
464474 for (int i = 0 ; i < p_amount; i++) {
465- const BlitToScreen &blit = p_render_targets[i];
466-
467- RID rid_rt = blit.render_target ;
468-
469- Rect2 dst_rect = blit.dst_rect ;
470- _blit_render_target_to_screen (rid_rt, p_screen, dst_rect, blit.multi_view .use_layer ? blit.multi_view .layer : 0 , i == 0 );
475+ _blit_render_target_to_screen (p_screen, p_render_targets[i], i == 0 );
471476 }
472477}
473478
0 commit comments