2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* renderer_viewport.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2020-12-04 19:26:24 +01:00
# include "renderer_viewport.h"
2017-08-27 21:07:15 +02:00
2020-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2023-02-13 19:45:06 +01:00
# include "core/object/worker_thread_pool.h"
2020-12-04 19:26:24 +01:00
# include "renderer_canvas_cull.h"
# include "renderer_scene_cull.h"
2020-03-27 19:21:27 +01:00
# include "rendering_server_globals.h"
2022-04-07 16:00:51 +02:00
# include "storage/texture_storage.h"
2016-10-19 16:14:41 +02:00
2020-12-04 19:26:24 +01:00
static Transform2D _canvas_get_transform ( RendererViewport : : Viewport * p_viewport , RendererCanvasCull : : Canvas * p_canvas , RendererViewport : : Viewport : : CanvasData * p_canvas_data , const Vector2 & p_vp_size ) {
2019-04-05 15:24:54 +02:00
Transform2D xf = p_viewport - > global_transform ;
float scale = 1.0 ;
if ( p_viewport - > canvas_map . has ( p_canvas - > parent ) ) {
2020-10-29 22:09:16 +01:00
Transform2D c_xform = p_viewport - > canvas_map [ p_canvas - > parent ] . transform ;
if ( p_viewport - > snap_2d_transforms_to_pixel ) {
2022-04-24 23:59:24 +02:00
c_xform . columns [ 2 ] = c_xform . columns [ 2 ] . floor ( ) ;
2020-10-29 22:09:16 +01:00
}
xf = xf * c_xform ;
2019-04-05 15:24:54 +02:00
scale = p_canvas - > parent_scale ;
}
2020-10-29 22:09:16 +01:00
Transform2D c_xform = p_canvas_data - > transform ;
if ( p_viewport - > snap_2d_transforms_to_pixel ) {
2022-04-24 23:59:24 +02:00
c_xform . columns [ 2 ] = c_xform . columns [ 2 ] . floor ( ) ;
2020-10-29 22:09:16 +01:00
}
xf = xf * c_xform ;
2019-04-05 15:24:54 +02:00
2020-03-27 19:21:27 +01:00
if ( scale ! = 1.0 & & ! RSG : : canvas - > disable_scale ) {
2019-04-05 15:24:54 +02:00
Vector2 pivot = p_vp_size * 0.5 ;
Transform2D xfpivot ;
xfpivot . set_origin ( pivot ) ;
Transform2D xfscale ;
xfscale . scale ( Vector2 ( scale , scale ) ) ;
xf = xfpivot . affine_inverse ( ) * xf ;
xf = xfscale * xf ;
xf = xfpivot * xf ;
}
return xf ;
}
2022-07-17 01:59:13 +02:00
Vector < RendererViewport : : Viewport * > RendererViewport : : _sort_active_viewports ( ) {
2022-09-09 11:28:01 +02:00
// We need to sort the viewports in a "topological order", children first and
// parents last. We also need to keep sibling viewports in the original order
// from top to bottom.
2022-07-17 01:59:13 +02:00
Vector < Viewport * > result ;
List < Viewport * > nodes ;
2022-09-09 11:28:01 +02:00
for ( int i = active_viewports . size ( ) - 1 ; i > = 0 ; - - i ) {
Viewport * viewport = active_viewports [ i ] ;
2022-07-17 01:59:13 +02:00
if ( viewport - > parent . is_valid ( ) ) {
continue ;
}
nodes . push_back ( viewport ) ;
2022-09-09 11:28:01 +02:00
result . insert ( 0 , viewport ) ;
2022-07-17 01:59:13 +02:00
}
while ( ! nodes . is_empty ( ) ) {
2022-09-09 11:28:01 +02:00
const Viewport * node = nodes [ 0 ] ;
2022-07-17 01:59:13 +02:00
nodes . pop_front ( ) ;
2022-09-09 11:28:01 +02:00
for ( int i = active_viewports . size ( ) - 1 ; i > = 0 ; - - i ) {
Viewport * child = active_viewports [ i ] ;
2022-07-17 01:59:13 +02:00
if ( child - > parent ! = node - > self ) {
continue ;
}
if ( ! nodes . find ( child ) ) {
nodes . push_back ( child ) ;
2022-09-09 11:28:01 +02:00
result . insert ( 0 , child ) ;
2022-07-17 01:59:13 +02:00
}
}
}
return result ;
}
2021-08-19 03:52:06 +02:00
void RendererViewport : : _configure_3d_render_buffers ( Viewport * p_viewport ) {
if ( p_viewport - > render_buffers . is_valid ( ) ) {
if ( p_viewport - > size . width = = 0 | | p_viewport - > size . height = = 0 ) {
2022-08-04 10:40:39 +02:00
p_viewport - > render_buffers . unref ( ) ;
2021-08-19 03:52:06 +02:00
} else {
2023-01-13 02:54:15 +01:00
float scaling_3d_scale = p_viewport - > scaling_3d_scale ;
2021-11-23 22:16:03 +01:00
RS : : ViewportScaling3DMode scaling_3d_mode = p_viewport - > scaling_3d_mode ;
if ( ( scaling_3d_mode = = RS : : VIEWPORT_SCALING_3D_MODE_FSR ) & & ( scaling_3d_scale > 1.0 ) ) {
2022-04-09 17:52:38 +02:00
// FSR is not designed for downsampling.
// Fall back to bilinear scaling.
2021-11-23 22:16:03 +01:00
scaling_3d_mode = RS : : VIEWPORT_SCALING_3D_MODE_BILINEAR ;
2021-08-19 03:52:06 +02:00
}
2021-11-23 22:16:03 +01:00
if ( ( scaling_3d_mode = = RS : : VIEWPORT_SCALING_3D_MODE_FSR ) & & ! p_viewport - > fsr_enabled ) {
// FSR is not actually available.
2022-04-09 17:52:38 +02:00
// Fall back to bilinear scaling.
WARN_PRINT_ONCE ( " FSR 1.0 3D resolution scaling is not available. Falling back to bilinear 3D resolution scaling. " ) ;
scaling_3d_mode = RS : : VIEWPORT_SCALING_3D_MODE_BILINEAR ;
2021-11-23 22:16:03 +01:00
}
if ( scaling_3d_scale = = 1.0 ) {
2023-01-13 02:54:15 +01:00
scaling_3d_mode = RS : : VIEWPORT_SCALING_3D_MODE_OFF ;
2021-11-23 22:16:03 +01:00
}
int width ;
int height ;
int render_width ;
int render_height ;
2023-01-13 02:54:15 +01:00
switch ( scaling_3d_mode ) {
case RS : : VIEWPORT_SCALING_3D_MODE_BILINEAR :
// Clamp 3D rendering resolution to reasonable values supported on most hardware.
// This prevents freezing the engine or outright crashing on lower-end GPUs.
width = CLAMP ( p_viewport - > size . width * scaling_3d_scale , 1 , 16384 ) ;
height = CLAMP ( p_viewport - > size . height * scaling_3d_scale , 1 , 16384 ) ;
render_width = width ;
render_height = height ;
break ;
case RS : : VIEWPORT_SCALING_3D_MODE_FSR :
width = p_viewport - > size . width ;
height = p_viewport - > size . height ;
render_width = MAX ( width * scaling_3d_scale , 1.0 ) ; // width / (width * scaling)
render_height = MAX ( height * scaling_3d_scale , 1.0 ) ;
break ;
case RS : : VIEWPORT_SCALING_3D_MODE_OFF :
width = p_viewport - > size . width ;
height = p_viewport - > size . height ;
render_width = width ;
render_height = height ;
break ;
default :
// This is an unknown mode.
WARN_PRINT_ONCE ( vformat ( " Unknown scaling mode: %d. Disabling 3D resolution scaling. " , scaling_3d_mode ) ) ;
scaling_3d_mode = RS : : VIEWPORT_SCALING_3D_MODE_OFF ;
scaling_3d_scale = 1.0 ;
width = p_viewport - > size . width ;
height = p_viewport - > size . height ;
render_width = width ;
render_height = height ;
break ;
2021-11-23 22:16:03 +01:00
}
p_viewport - > internal_size = Size2 ( render_width , render_height ) ;
2022-08-10 17:16:02 +02:00
// At resolution scales lower than 1.0, use negative texture mipmap bias
// to compensate for the loss of sharpness.
const float texture_mipmap_bias = log2f ( MIN ( scaling_3d_scale , 1.0 ) ) + p_viewport - > texture_mipmap_bias ;
2023-01-13 02:54:15 +01:00
p_viewport - > render_buffers - > configure ( p_viewport - > render_target , Size2i ( render_width , render_height ) , Size2 ( width , height ) , scaling_3d_mode , p_viewport - > fsr_sharpness , texture_mipmap_bias , p_viewport - > msaa_3d , p_viewport - > screen_space_aa , p_viewport - > use_taa , p_viewport - > use_debanding , p_viewport - > view_count ) ;
2021-08-19 03:52:06 +02:00
}
}
}
2021-05-07 15:19:04 +02:00
void RendererViewport : : _draw_3d ( Viewport * p_viewport ) {
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " > Render 3D Scene " ) ;
2019-09-20 22:58:06 +02:00
2020-04-08 16:47:36 +02:00
Ref < XRInterface > xr_interface ;
2021-05-07 15:19:04 +02:00
if ( p_viewport - > use_xr & & XRServer : : get_singleton ( ) ! = nullptr ) {
2020-04-08 16:47:36 +02:00
xr_interface = XRServer : : get_singleton ( ) - > get_primary_interface ( ) ;
2019-07-05 21:14:43 +02:00
}
2019-03-30 14:03:49 +01:00
2021-04-20 18:40:24 +02:00
if ( p_viewport - > use_occlusion_culling ) {
if ( p_viewport - > occlusion_buffer_dirty ) {
float aspect = p_viewport - > size . aspect ( ) ;
2022-07-23 19:12:41 +02:00
int max_size = occlusion_rays_per_thread * WorkerThreadPool : : get_singleton ( ) - > get_thread_count ( ) ;
2021-04-20 18:40:24 +02:00
int viewport_size = p_viewport - > size . width * p_viewport - > size . height ;
max_size = CLAMP ( max_size , viewport_size / ( 32 * 32 ) , viewport_size / ( 2 * 2 ) ) ; // At least one depth pixel for every 16x16 region. At most one depth pixel for every 2x2 region.
float height = Math : : sqrt ( max_size / aspect ) ;
Size2i new_size = Size2i ( height * aspect , height ) ;
RendererSceneOcclusionCull : : get_singleton ( ) - > buffer_set_size ( p_viewport - > self , new_size ) ;
p_viewport - > occlusion_buffer_dirty = false ;
}
}
2021-12-29 00:10:41 +01:00
float screen_mesh_lod_threshold = p_viewport - > mesh_lod_threshold / float ( p_viewport - > size . width ) ;
2022-04-04 16:10:22 +02:00
RSG : : scene - > render_camera ( p_viewport - > render_buffers , p_viewport - > camera , p_viewport - > scenario , p_viewport - > self , p_viewport - > internal_size , p_viewport - > use_taa , screen_mesh_lod_threshold , p_viewport - > shadow_atlas , xr_interface , & p_viewport - > render_info ) ;
2021-05-07 15:19:04 +02:00
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " < Render 3D Scene " ) ;
2019-03-30 14:03:49 +01:00
}
2021-08-19 03:52:06 +02:00
void RendererViewport : : _draw_viewport ( Viewport * p_viewport ) {
2020-04-10 19:18:42 +02:00
if ( p_viewport - > measure_render_time ) {
String rt_id = " vp_begin_ " + itos ( p_viewport - > self . get_id ( ) ) ;
2022-06-21 02:08:33 +02:00
RSG : : utilities - > capture_timestamp ( rt_id ) ;
2020-04-10 19:18:42 +02:00
timestamp_vp_map [ rt_id ] = p_viewport - > self ;
}
2022-09-08 02:44:36 +02:00
if ( OS : : get_singleton ( ) - > get_current_rendering_method ( ) = = " gl_compatibility " ) {
2021-09-27 01:07:10 +02:00
// This is currently needed for GLES to keep the current window being rendered to up to date
DisplayServer : : get_singleton ( ) - > gl_window_make_current ( p_viewport - > viewport_to_screen ) ;
}
2020-11-18 19:11:30 +01:00
2017-06-24 13:58:27 +02:00
/* Camera should always be BEFORE any other 3D */
2016-10-03 21:33:42 +02:00
2017-06-24 13:58:27 +02:00
bool scenario_draw_canvas_bg = false ; //draw canvas, or some layer of it, as BG for 3D instead of in front
int scenario_canvas_max_layer = 0 ;
2023-02-01 01:23:13 +01:00
bool force_clear_render_target = false ;
2019-06-24 21:13:06 +02:00
2021-07-03 01:14:19 +02:00
for ( int i = 0 ; i < RS : : VIEWPORT_RENDER_INFO_TYPE_MAX ; i + + ) {
for ( int j = 0 ; j < RS : : VIEWPORT_RENDER_INFO_MAX ; j + + ) {
p_viewport - > render_info . info [ i ] [ j ] = 0 ;
}
}
2023-02-01 01:23:13 +01:00
if ( RSG : : scene - > is_scenario ( p_viewport - > scenario ) ) {
2020-12-03 22:09:47 +01:00
RID environment = RSG : : scene - > scenario_get_environment ( p_viewport - > scenario ) ;
if ( RSG : : scene - > is_environment ( environment ) ) {
2023-02-01 01:23:13 +01:00
if ( ! p_viewport - > disable_2d & & ! viewport_is_environment_disabled ( p_viewport ) ) {
scenario_draw_canvas_bg = RSG : : scene - > environment_get_background ( environment ) = = RS : : ENV_BG_CANVAS ;
scenario_canvas_max_layer = RSG : : scene - > environment_get_canvas_max_layer ( environment ) ;
} else if ( RSG : : scene - > environment_get_background ( environment ) = = RS : : ENV_BG_CANVAS ) {
// The scene renderer will still copy over the last frame, so we need to clear the render target.
force_clear_render_target = true ;
}
2016-10-03 21:33:42 +02:00
}
}
2021-06-29 18:36:32 +02:00
bool can_draw_3d = RSG : : scene - > is_camera ( p_viewport - > camera ) & & ! p_viewport - > disable_3d ;
2016-10-03 21:33:42 +02:00
2019-08-19 00:40:52 +02:00
if ( ( scenario_draw_canvas_bg | | can_draw_3d ) & & ! p_viewport - > render_buffers . is_valid ( ) ) {
//wants to draw 3D but there is no render buffer, create
2020-12-03 22:09:47 +01:00
p_viewport - > render_buffers = RSG : : scene - > render_buffers_create ( ) ;
2021-08-19 03:52:06 +02:00
_configure_3d_render_buffers ( p_viewport ) ;
2019-08-19 00:40:52 +02:00
}
2022-06-21 02:08:33 +02:00
Color bgcolor = p_viewport - > transparent_bg ? Color ( 0 , 0 , 0 , 0 ) : RSG : : texture_storage - > get_default_clear_color ( ) ;
2022-05-02 11:03:39 +02:00
if ( p_viewport - > clear_mode ! = RS : : VIEWPORT_CLEAR_NEVER ) {
RSG : : texture_storage - > render_target_request_clear ( p_viewport - > render_target , bgcolor ) ;
if ( p_viewport - > clear_mode = = RS : : VIEWPORT_CLEAR_ONLY_NEXT_FRAME ) {
p_viewport - > clear_mode = RS : : VIEWPORT_CLEAR_NEVER ;
}
}
2019-06-24 21:13:06 +02:00
2017-06-24 13:58:27 +02:00
if ( ! scenario_draw_canvas_bg & & can_draw_3d ) {
2023-02-01 01:23:13 +01:00
if ( force_clear_render_target ) {
RSG : : texture_storage - > render_target_do_clear_request ( p_viewport - > render_target ) ;
}
2021-05-07 15:19:04 +02:00
_draw_3d ( p_viewport ) ;
2016-10-19 16:14:41 +02:00
}
2021-07-01 04:17:47 +02:00
if ( ! p_viewport - > disable_2d ) {
2022-05-13 15:04:37 +02:00
RBMap < Viewport : : CanvasKey , Viewport : : CanvasData * > canvas_map ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Rect2 clip_rect ( 0 , 0 , p_viewport - > size . x , p_viewport - > size . y ) ;
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : Light * lights = nullptr ;
RendererCanvasRender : : Light * lights_with_shadow = nullptr ;
2020-11-03 20:51:53 +01:00
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : Light * directional_lights = nullptr ;
RendererCanvasRender : : Light * directional_lights_with_shadow = nullptr ;
2020-11-03 20:51:53 +01:00
2020-11-26 13:50:21 +01:00
if ( p_viewport - > sdf_active ) {
2022-05-10 12:05:52 +02:00
// Process SDF.
2020-11-26 13:50:21 +01:00
2022-04-07 16:00:51 +02:00
Rect2 sdf_rect = RSG : : texture_storage - > render_target_get_sdf_rect ( p_viewport - > render_target ) ;
2020-11-26 13:50:21 +01:00
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : LightOccluderInstance * occluders = nullptr ;
2020-11-26 13:50:21 +01:00
2022-05-10 12:05:52 +02:00
// Make list of occluders.
2021-08-09 22:13:42 +02:00
for ( KeyValue < RID , Viewport : : CanvasData > & E : p_viewport - > canvas_map ) {
RendererCanvasCull : : Canvas * canvas = static_cast < RendererCanvasCull : : Canvas * > ( E . value . canvas ) ;
Transform2D xf = _canvas_get_transform ( p_viewport , canvas , & E . value , clip_rect . size ) ;
2020-11-26 13:50:21 +01:00
2022-05-19 01:43:40 +02:00
for ( RendererCanvasRender : : LightOccluderInstance * F : canvas - > occluders ) {
if ( ! F - > enabled ) {
2020-11-26 13:50:21 +01:00
continue ;
}
2022-05-19 01:43:40 +02:00
F - > xform_cache = xf * F - > xform ;
2020-11-26 13:50:21 +01:00
2022-05-19 01:43:40 +02:00
if ( sdf_rect . intersects_transformed ( F - > xform_cache , F - > aabb_cache ) ) {
F - > next = occluders ;
occluders = F ;
2020-11-26 13:50:21 +01:00
}
}
}
RSG : : canvas_render - > render_sdf ( p_viewport - > render_target , occluders ) ;
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_mark_sdf_enabled ( p_viewport - > render_target , true ) ;
2020-11-26 13:50:21 +01:00
2022-05-10 12:05:52 +02:00
p_viewport - > sdf_active = false ; // If used, gets set active again.
2021-05-20 16:25:06 +02:00
} else {
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_mark_sdf_enabled ( p_viewport - > render_target , false ) ;
2020-11-26 13:50:21 +01:00
}
2016-10-03 21:33:42 +02:00
Rect2 shadow_rect ;
2020-10-24 17:15:43 +02:00
int shadow_count = 0 ;
2020-11-03 20:51:53 +01:00
int directional_light_count = 0 ;
2016-10-03 21:33:42 +02:00
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " Cull 2D Lights " ) ;
2021-08-09 22:13:42 +02:00
for ( KeyValue < RID , Viewport : : CanvasData > & E : p_viewport - > canvas_map ) {
RendererCanvasCull : : Canvas * canvas = static_cast < RendererCanvasCull : : Canvas * > ( E . value . canvas ) ;
2016-10-03 21:33:42 +02:00
2021-08-09 22:13:42 +02:00
Transform2D xf = _canvas_get_transform ( p_viewport , canvas , & E . value , clip_rect . size ) ;
2019-04-05 15:24:54 +02:00
2022-05-10 12:05:52 +02:00
// Find lights in canvas.
2016-10-03 21:33:42 +02:00
2022-05-19 01:43:40 +02:00
for ( RendererCanvasRender : : Light * F : canvas - > lights ) {
RendererCanvasRender : : Light * cl = F ;
2016-10-03 21:33:42 +02:00
if ( cl - > enabled & & cl - > texture . is_valid ( ) ) {
//not super efficient..
2022-03-12 12:19:59 +01:00
Size2 tsize = RSG : : texture_storage - > texture_size_with_proxy ( cl - > texture ) ;
2017-03-05 16:44:50 +01:00
tsize * = cl - > scale ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
Vector2 offset = tsize / 2.0 ;
cl - > rect_cache = Rect2 ( - offset + cl - > texture_offset , tsize ) ;
cl - > xform_cache = xf * cl - > xform ;
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
if ( clip_rect . intersects_transformed ( cl - > xform_cache , cl - > rect_cache ) ) {
cl - > filter_next_ptr = lights ;
lights = cl ;
2017-01-11 04:52:51 +01:00
Transform2D scale ;
2016-10-03 21:33:42 +02:00
scale . scale ( cl - > rect_cache . size ) ;
2022-04-24 23:59:24 +02:00
scale . columns [ 2 ] = cl - > rect_cache . position ;
2023-02-17 04:11:24 +01:00
cl - > light_shader_xform = xf * cl - > xform * scale ;
2019-07-05 03:54:32 +02:00
if ( cl - > use_shadow ) {
2017-03-05 16:44:50 +01:00
cl - > shadows_next_ptr = lights_with_shadow ;
2020-04-02 01:20:12 +02:00
if ( lights_with_shadow = = nullptr ) {
2016-10-03 21:33:42 +02:00
shadow_rect = cl - > xform_cache . xform ( cl - > rect_cache ) ;
} else {
2017-03-05 16:44:50 +01:00
shadow_rect = shadow_rect . merge ( cl - > xform_cache . xform ( cl - > rect_cache ) ) ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
lights_with_shadow = cl ;
cl - > radius_cache = cl - > rect_cache . size . length ( ) ;
2016-10-03 21:33:42 +02:00
}
}
}
}
2022-05-19 01:43:40 +02:00
for ( RendererCanvasRender : : Light * F : canvas - > directional_lights ) {
RendererCanvasRender : : Light * cl = F ;
2020-11-03 20:51:53 +01:00
if ( cl - > enabled ) {
cl - > filter_next_ptr = directional_lights ;
directional_lights = cl ;
cl - > xform_cache = xf * cl - > xform ;
2022-04-24 23:59:24 +02:00
cl - > xform_cache . columns [ 2 ] = Vector2 ( ) ; //translation is pointless
2020-11-03 20:51:53 +01:00
if ( cl - > use_shadow ) {
cl - > shadows_next_ptr = directional_lights_with_shadow ;
directional_lights_with_shadow = cl ;
}
directional_light_count + + ;
if ( directional_light_count = = RS : : MAX_2D_DIRECTIONAL_LIGHTS ) {
break ;
}
}
}
2021-08-09 22:13:42 +02:00
canvas_map [ Viewport : : CanvasKey ( E . key , E . value . layer , E . value . sublayer ) ] = & E . value ;
2016-10-03 21:33:42 +02:00
}
if ( lights_with_shadow ) {
//update shadows if any
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : LightOccluderInstance * occluders = nullptr ;
2016-10-03 21:33:42 +02:00
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " > Render PointLight2D Shadows " ) ;
RENDER_TIMESTAMP ( " Cull LightOccluder2Ds " ) ;
2019-09-20 22:58:06 +02:00
2016-10-03 21:33:42 +02:00
//make list of occluders
2021-08-09 22:13:42 +02:00
for ( KeyValue < RID , Viewport : : CanvasData > & E : p_viewport - > canvas_map ) {
RendererCanvasCull : : Canvas * canvas = static_cast < RendererCanvasCull : : Canvas * > ( E . value . canvas ) ;
Transform2D xf = _canvas_get_transform ( p_viewport , canvas , & E . value , clip_rect . size ) ;
2016-10-03 21:33:42 +02:00
2022-05-19 01:43:40 +02:00
for ( RendererCanvasRender : : LightOccluderInstance * F : canvas - > occluders ) {
if ( ! F - > enabled ) {
2016-10-03 21:33:42 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2022-05-19 01:43:40 +02:00
F - > xform_cache = xf * F - > xform ;
if ( shadow_rect . intersects_transformed ( F - > xform_cache , F - > aabb_cache ) ) {
F - > next = occluders ;
occluders = F ;
2016-10-03 21:33:42 +02:00
}
}
}
//update the light shadowmaps with them
2019-09-20 22:58:06 +02:00
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : Light * light = lights_with_shadow ;
2017-03-05 16:44:50 +01:00
while ( light ) {
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " Render PointLight2D Shadow " ) ;
2019-09-20 22:58:06 +02:00
2020-10-24 17:15:43 +02:00
RSG : : canvas_render - > light_update_shadow ( light - > light_internal , shadow_count + + , light - > xform_cache . affine_inverse ( ) , light - > item_shadow_mask , light - > radius_cache / 1000.0 , light - > radius_cache * 1.1 , occluders ) ;
2017-03-05 16:44:50 +01:00
light = light - > shadows_next_ptr ;
2016-10-03 21:33:42 +02:00
}
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " < Render PointLight2D Shadows " ) ;
2016-10-03 21:33:42 +02:00
}
2020-11-03 20:51:53 +01:00
if ( directional_lights_with_shadow ) {
//update shadows if any
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : Light * light = directional_lights_with_shadow ;
2020-11-03 20:51:53 +01:00
while ( light ) {
2022-04-24 23:59:24 +02:00
Vector2 light_dir = - light - > xform_cache . columns [ 1 ] . normalized ( ) ; // Y is light direction
2020-11-03 20:51:53 +01:00
float cull_distance = light - > directional_distance ;
Vector2 light_dir_sign ;
light_dir_sign . x = ( ABS ( light_dir . x ) < CMP_EPSILON ) ? 0.0 : ( ( light_dir . x > 0.0 ) ? 1.0 : - 1.0 ) ;
light_dir_sign . y = ( ABS ( light_dir . y ) < CMP_EPSILON ) ? 0.0 : ( ( light_dir . y > 0.0 ) ? 1.0 : - 1.0 ) ;
Vector2 points [ 6 ] ;
int point_count = 0 ;
for ( int j = 0 ; j < 4 ; j + + ) {
static const Vector2 signs [ 4 ] = { Vector2 ( 1 , 1 ) , Vector2 ( 1 , 0 ) , Vector2 ( 0 , 0 ) , Vector2 ( 0 , 1 ) } ;
Vector2 sign_cmp = signs [ j ] * 2.0 - Vector2 ( 1.0 , 1.0 ) ;
Vector2 point = clip_rect . position + clip_rect . size * signs [ j ] ;
if ( sign_cmp = = light_dir_sign ) {
2021-05-20 12:07:26 +02:00
//both point in same direction, plot offsetted
2020-11-03 20:51:53 +01:00
points [ point_count + + ] = point + light_dir * cull_distance ;
} else if ( sign_cmp . x = = light_dir_sign . x | | sign_cmp . y = = light_dir_sign . y ) {
int next_j = ( j + 1 ) % 4 ;
Vector2 next_sign_cmp = signs [ next_j ] * 2.0 - Vector2 ( 1.0 , 1.0 ) ;
//one point in the same direction, plot segment
if ( next_sign_cmp . x = = light_dir_sign . x | | next_sign_cmp . y = = light_dir_sign . y ) {
if ( light_dir_sign . x ! = 0.0 | | light_dir_sign . y ! = 0.0 ) {
points [ point_count + + ] = point ;
}
points [ point_count + + ] = point + light_dir * cull_distance ;
} else {
points [ point_count + + ] = point + light_dir * cull_distance ;
if ( light_dir_sign . x ! = 0.0 | | light_dir_sign . y ! = 0.0 ) {
points [ point_count + + ] = point ;
}
}
} else {
//plot normally
points [ point_count + + ] = point ;
}
}
Vector2 xf_points [ 6 ] ;
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : LightOccluderInstance * occluders = nullptr ;
2020-11-03 20:51:53 +01:00
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " > Render DirectionalLight2D Shadows " ) ;
2020-11-03 20:51:53 +01:00
2022-05-10 12:05:52 +02:00
// Make list of occluders.
2021-08-09 22:13:42 +02:00
for ( KeyValue < RID , Viewport : : CanvasData > & E : p_viewport - > canvas_map ) {
RendererCanvasCull : : Canvas * canvas = static_cast < RendererCanvasCull : : Canvas * > ( E . value . canvas ) ;
Transform2D xf = _canvas_get_transform ( p_viewport , canvas , & E . value , clip_rect . size ) ;
2020-11-03 20:51:53 +01:00
2022-05-19 01:43:40 +02:00
for ( RendererCanvasRender : : LightOccluderInstance * F : canvas - > occluders ) {
if ( ! F - > enabled ) {
2020-11-03 20:51:53 +01:00
continue ;
}
2022-05-19 01:43:40 +02:00
F - > xform_cache = xf * F - > xform ;
Transform2D localizer = F - > xform_cache . affine_inverse ( ) ;
2020-11-03 20:51:53 +01:00
for ( int j = 0 ; j < point_count ; j + + ) {
xf_points [ j ] = localizer . xform ( points [ j ] ) ;
}
2022-05-19 01:43:40 +02:00
if ( F - > aabb_cache . intersects_filled_polygon ( xf_points , point_count ) ) {
F - > next = occluders ;
occluders = F ;
2020-11-03 20:51:53 +01:00
}
}
}
RSG : : canvas_render - > light_update_directional_shadow ( light - > light_internal , shadow_count + + , light - > xform_cache , light - > item_shadow_mask , cull_distance , clip_rect , occluders ) ;
light = light - > shadows_next_ptr ;
}
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " < Render DirectionalLight2D Shadows " ) ;
2020-11-03 20:51:53 +01:00
}
2022-05-13 15:04:37 +02:00
if ( scenario_draw_canvas_bg & & canvas_map . begin ( ) & & canvas_map . begin ( ) - > key . get_layer ( ) > scenario_canvas_max_layer ) {
2023-01-04 00:46:03 +01:00
// There may be an outstanding clear request if a clear was requested, but no 2D elements were drawn.
// Clear now otherwise we copy over garbage from the render target.
RSG : : texture_storage - > render_target_do_clear_request ( p_viewport - > render_target ) ;
2018-04-30 14:30:11 +02:00
if ( ! can_draw_3d ) {
2020-03-27 19:21:27 +01:00
RSG : : scene - > render_empty_scene ( p_viewport - > render_buffers , p_viewport - > scenario , p_viewport - > shadow_atlas ) ;
2018-04-30 14:30:11 +02:00
} else {
2021-05-07 15:19:04 +02:00
_draw_3d ( p_viewport ) ;
2017-06-24 13:58:27 +02:00
}
scenario_draw_canvas_bg = false ;
2016-10-03 21:33:42 +02:00
}
2016-10-05 06:26:35 +02:00
2021-08-09 22:13:42 +02:00
for ( const KeyValue < Viewport : : CanvasKey , Viewport : : CanvasData * > & E : canvas_map ) {
RendererCanvasCull : : Canvas * canvas = static_cast < RendererCanvasCull : : Canvas * > ( E . value - > canvas ) ;
2016-10-03 21:33:42 +02:00
2021-08-09 22:13:42 +02:00
Transform2D xform = _canvas_get_transform ( p_viewport , canvas , E . value , clip_rect . size ) ;
2016-10-03 21:33:42 +02:00
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : Light * canvas_lights = nullptr ;
RendererCanvasRender : : Light * canvas_directional_lights = nullptr ;
2016-10-03 21:33:42 +02:00
2020-12-04 19:26:24 +01:00
RendererCanvasRender : : Light * ptr = lights ;
2017-03-05 16:44:50 +01:00
while ( ptr ) {
2021-08-09 22:13:42 +02:00
if ( E . value - > layer > = ptr - > layer_min & & E . value - > layer < = ptr - > layer_max ) {
2017-03-05 16:44:50 +01:00
ptr - > next_ptr = canvas_lights ;
canvas_lights = ptr ;
2016-10-03 21:33:42 +02:00
}
2017-03-05 16:44:50 +01:00
ptr = ptr - > filter_next_ptr ;
2016-10-03 21:33:42 +02:00
}
2020-11-03 20:51:53 +01:00
ptr = directional_lights ;
while ( ptr ) {
2021-08-09 22:13:42 +02:00
if ( E . value - > layer > = ptr - > layer_min & & E . value - > layer < = ptr - > layer_max ) {
2020-11-03 20:51:53 +01:00
ptr - > next_ptr = canvas_directional_lights ;
canvas_directional_lights = ptr ;
}
ptr = ptr - > filter_next_ptr ;
}
2021-09-02 20:07:04 +02:00
RSG : : canvas - > render_canvas ( p_viewport - > render_target , canvas , xform , canvas_lights , canvas_directional_lights , clip_rect , p_viewport - > texture_filter , p_viewport - > texture_repeat , p_viewport - > snap_2d_transforms_to_pixel , p_viewport - > snap_2d_vertices_to_pixel , p_viewport - > canvas_cull_mask ) ;
2020-11-26 13:50:21 +01:00
if ( RSG : : canvas - > was_sdf_used ( ) ) {
p_viewport - > sdf_active = true ;
}
2017-06-24 13:58:27 +02:00
2021-08-09 22:13:42 +02:00
if ( scenario_draw_canvas_bg & & E . key . get_layer ( ) > = scenario_canvas_max_layer ) {
2023-01-04 00:46:03 +01:00
// There may be an outstanding clear request if a clear was requested, but no 2D elements were drawn.
// Clear now otherwise we copy over garbage from the render target.
RSG : : texture_storage - > render_target_do_clear_request ( p_viewport - > render_target ) ;
2018-04-30 14:30:11 +02:00
if ( ! can_draw_3d ) {
2020-03-27 19:21:27 +01:00
RSG : : scene - > render_empty_scene ( p_viewport - > render_buffers , p_viewport - > scenario , p_viewport - > shadow_atlas ) ;
2018-04-30 14:30:11 +02:00
} else {
2021-05-07 15:19:04 +02:00
_draw_3d ( p_viewport ) ;
2017-06-24 13:58:27 +02:00
}
scenario_draw_canvas_bg = false ;
2016-10-03 21:33:42 +02:00
}
}
2017-06-24 13:58:27 +02:00
2016-10-03 21:33:42 +02:00
if ( scenario_draw_canvas_bg ) {
2023-01-04 00:46:03 +01:00
// There may be an outstanding clear request if a clear was requested, but no 2D elements were drawn.
// Clear now otherwise we copy over garbage from the render target.
RSG : : texture_storage - > render_target_do_clear_request ( p_viewport - > render_target ) ;
2018-04-30 14:30:11 +02:00
if ( ! can_draw_3d ) {
2020-03-27 19:21:27 +01:00
RSG : : scene - > render_empty_scene ( p_viewport - > render_buffers , p_viewport - > scenario , p_viewport - > shadow_atlas ) ;
2018-04-30 14:30:11 +02:00
} else {
2021-05-07 15:19:04 +02:00
_draw_3d ( p_viewport ) ;
2017-06-24 13:58:27 +02:00
}
2016-10-03 21:33:42 +02:00
}
}
2019-06-25 03:24:07 +02:00
2022-04-07 16:00:51 +02:00
if ( RSG : : texture_storage - > render_target_is_clear_requested ( p_viewport - > render_target ) ) {
2019-06-25 03:24:07 +02:00
//was never cleared in the end, force clear it
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_do_clear_request ( p_viewport - > render_target ) ;
2019-06-25 03:24:07 +02:00
}
2020-04-10 19:18:42 +02:00
if ( p_viewport - > measure_render_time ) {
String rt_id = " vp_end_ " + itos ( p_viewport - > self . get_id ( ) ) ;
2022-06-21 02:08:33 +02:00
RSG : : utilities - > capture_timestamp ( rt_id ) ;
2020-04-10 19:18:42 +02:00
timestamp_vp_map [ rt_id ] = p_viewport - > self ;
}
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : draw_viewports ( ) {
2020-04-10 19:18:42 +02:00
timestamp_vp_map . clear ( ) ;
2020-04-08 16:47:36 +02:00
// get our xr interface in case we need it
Ref < XRInterface > xr_interface ;
2022-01-26 02:25:20 +01:00
XRServer * xr_server = XRServer : : get_singleton ( ) ;
if ( xr_server ! = nullptr ) {
// let our XR server know we're about to render our frames so we can get our frame timing
xr_server - > pre_render ( ) ;
// retrieve the interface responsible for rendering
xr_interface = xr_server - > get_primary_interface ( ) ;
2019-07-05 21:14:43 +02:00
}
2016-10-03 21:33:42 +02:00
2018-07-29 20:09:42 +02:00
if ( Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
2021-02-17 17:44:49 +01:00
set_default_clear_color ( GLOBAL_GET ( " rendering/environment/defaults/default_clear_color " ) ) ;
2018-07-29 20:09:42 +02:00
}
2016-10-05 06:26:35 +02:00
2022-07-17 01:59:13 +02:00
if ( sorted_active_viewports_dirty ) {
sorted_active_viewports = _sort_active_viewports ( ) ;
sorted_active_viewports_dirty = false ;
}
2016-10-03 21:33:42 +02:00
2022-05-13 15:04:37 +02:00
HashMap < DisplayServer : : WindowID , Vector < BlitToScreen > > blit_to_screen_list ;
2017-04-23 14:10:41 +02:00
//draw viewports
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " > Render Viewports " ) ;
2019-09-20 22:58:06 +02:00
2020-03-14 17:06:39 +01:00
//determine what is visible
draw_viewports_pass + + ;
2022-07-17 01:59:13 +02:00
for ( int i = sorted_active_viewports . size ( ) - 1 ; i > = 0 ; i - - ) { //to compute parent dependency, must go in reverse draw order
2016-10-03 21:33:42 +02:00
2022-07-17 01:59:13 +02:00
Viewport * vp = sorted_active_viewports [ i ] ;
2016-10-03 21:33:42 +02:00
2020-05-14 16:41:43 +02:00
if ( vp - > update_mode = = RS : : VIEWPORT_UPDATE_DISABLED ) {
2016-10-03 21:33:42 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2016-10-03 21:33:42 +02:00
2019-06-07 18:07:57 +02:00
if ( ! vp - > render_target . is_valid ( ) ) {
continue ;
}
//ERR_CONTINUE(!vp->render_target.is_valid());
2016-10-03 21:33:42 +02:00
2020-03-14 17:06:39 +01:00
bool visible = vp - > viewport_to_screen_rect ! = Rect2 ( ) ;
2022-01-26 02:25:20 +01:00
if ( vp - > use_xr ) {
if ( xr_interface . is_valid ( ) ) {
2022-10-17 05:19:01 +02:00
// Ignore update mode we have to commit frames to our XR interface
visible = true ;
2022-01-26 02:25:20 +01:00
// Override our size, make sure it matches our required size and is created as a stereo target
Size2 xr_size = xr_interface - > get_render_target_size ( ) ;
2022-08-16 23:54:55 +02:00
_viewport_set_size ( vp , xr_size . width , xr_size . height , xr_interface - > get_view_count ( ) ) ;
2022-01-26 02:25:20 +01:00
} else {
// don't render anything
visible = false ;
vp - > size = Size2 ( ) ;
}
2022-10-17 05:19:01 +02:00
} else {
if ( vp - > update_mode = = RS : : VIEWPORT_UPDATE_ALWAYS | | vp - > update_mode = = RS : : VIEWPORT_UPDATE_ONCE ) {
visible = true ;
}
2020-03-14 17:06:39 +01:00
2022-10-17 05:19:01 +02:00
if ( vp - > update_mode = = RS : : VIEWPORT_UPDATE_WHEN_VISIBLE & & RSG : : texture_storage - > render_target_was_used ( vp - > render_target ) ) {
2020-03-14 17:06:39 +01:00
visible = true ;
}
2022-10-17 05:19:01 +02:00
if ( vp - > update_mode = = RS : : VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE ) {
Viewport * parent = viewport_owner . get_or_null ( vp - > parent ) ;
if ( parent & & parent - > last_pass = = draw_viewports_pass ) {
visible = true ;
}
}
2020-03-14 17:06:39 +01:00
}
2018-07-08 00:10:32 +02:00
visible = visible & & vp - > size . x > 1 & & vp - > size . y > 1 ;
2016-10-19 16:14:41 +02:00
2020-03-14 17:06:39 +01:00
if ( visible ) {
vp - > last_pass = draw_viewports_pass ;
}
}
2021-07-03 01:14:19 +02:00
int vertices_drawn = 0 ;
int objects_drawn = 0 ;
int draw_calls_used = 0 ;
2022-07-17 01:59:13 +02:00
for ( int i = 0 ; i < sorted_active_viewports . size ( ) ; i + + ) {
Viewport * vp = sorted_active_viewports [ i ] ;
2020-03-14 17:06:39 +01:00
if ( vp - > last_pass ! = draw_viewports_pass ) {
continue ; //should not draw
}
2016-10-19 16:14:41 +02:00
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " > Render Viewport " + itos ( i ) ) ;
2019-09-20 22:58:06 +02:00
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_set_as_unused ( vp - > render_target ) ;
2020-04-08 16:47:36 +02:00
if ( vp - > use_xr & & xr_interface . is_valid ( ) ) {
2022-10-17 05:19:01 +02:00
// Inform XR interface we're about to render its viewport,
// if this returns false we don't render.
// This usually is a result of the player taking off their headset and OpenXR telling us to skip
// rendering frames.
if ( xr_interface - > pre_draw_viewport ( vp - > render_target ) ) {
2022-11-03 14:47:28 +01:00
RSG : : texture_storage - > render_target_set_override ( vp - > render_target ,
xr_interface - > get_color_texture ( ) ,
xr_interface - > get_depth_texture ( ) ,
xr_interface - > get_velocity_texture ( ) ) ;
2022-10-17 05:19:01 +02:00
// render...
RSG : : scene - > set_debug_draw_mode ( vp - > debug_draw ) ;
// and draw viewport
_draw_viewport ( vp ) ;
// commit our eyes
Vector < BlitToScreen > blits = xr_interface - > post_draw_viewport ( vp - > render_target , vp - > viewport_to_screen_rect ) ;
if ( vp - > viewport_to_screen ! = DisplayServer : : INVALID_WINDOW_ID ) {
if ( OS : : get_singleton ( ) - > get_current_rendering_driver_name ( ) = = " opengl3 " ) {
if ( blits . size ( ) > 0 ) {
RSG : : rasterizer - > blit_render_targets_to_screen ( vp - > viewport_to_screen , blits . ptr ( ) , blits . size ( ) ) ;
}
RSG : : rasterizer - > end_frame ( true ) ;
} else if ( blits . size ( ) > 0 ) {
if ( ! blit_to_screen_list . has ( vp - > viewport_to_screen ) ) {
blit_to_screen_list [ vp - > viewport_to_screen ] = Vector < BlitToScreen > ( ) ;
}
2017-06-11 23:13:04 +02:00
2022-10-17 05:19:01 +02:00
for ( int b = 0 ; b < blits . size ( ) ; b + + ) {
blit_to_screen_list [ vp - > viewport_to_screen ] . push_back ( blits [ b ] ) ;
}
2022-08-16 23:54:55 +02:00
}
2021-05-07 15:19:04 +02:00
}
2017-04-23 14:10:41 +02:00
}
} else {
2022-11-03 14:47:28 +01:00
RSG : : texture_storage - > render_target_set_override ( vp - > render_target , RID ( ) , RID ( ) , RID ( ) ) ;
2017-04-23 14:10:41 +02:00
2020-12-03 22:09:47 +01:00
RSG : : scene - > set_debug_draw_mode ( vp - > debug_draw ) ;
2017-04-23 14:10:41 +02:00
// render standard mono camera
2021-08-19 03:52:06 +02:00
_draw_viewport ( vp ) ;
2017-04-23 14:10:41 +02:00
2020-03-27 19:21:27 +01:00
if ( vp - > viewport_to_screen ! = DisplayServer : : INVALID_WINDOW_ID & & ( ! vp - > viewport_render_direct_to_screen | | ! RSG : : rasterizer - > is_low_end ( ) ) ) {
2017-04-23 14:10:41 +02:00
//copy to screen if set as such
2021-05-07 15:19:04 +02:00
BlitToScreen blit ;
2019-06-16 04:45:24 +02:00
blit . render_target = vp - > render_target ;
2020-03-04 02:51:12 +01:00
if ( vp - > viewport_to_screen_rect ! = Rect2 ( ) ) {
2021-08-29 06:52:43 +02:00
blit . dst_rect = vp - > viewport_to_screen_rect ;
2020-03-04 02:51:12 +01:00
} else {
2021-08-29 06:52:43 +02:00
blit . dst_rect . position = Vector2 ( ) ;
blit . dst_rect . size = vp - > size ;
2020-03-04 02:51:12 +01:00
}
2019-06-16 04:45:24 +02:00
if ( ! blit_to_screen_list . has ( vp - > viewport_to_screen ) ) {
2021-05-07 15:19:04 +02:00
blit_to_screen_list [ vp - > viewport_to_screen ] = Vector < BlitToScreen > ( ) ;
2019-06-16 04:45:24 +02:00
}
2022-09-12 23:57:11 +02:00
if ( OS : : get_singleton ( ) - > get_current_rendering_driver_name ( ) = = " opengl3 " ) {
Vector < BlitToScreen > blit_to_screen_vec ;
blit_to_screen_vec . push_back ( blit ) ;
RSG : : rasterizer - > blit_render_targets_to_screen ( vp - > viewport_to_screen , blit_to_screen_vec . ptr ( ) , 1 ) ;
RSG : : rasterizer - > end_frame ( true ) ;
} else {
blit_to_screen_list [ vp - > viewport_to_screen ] . push_back ( blit ) ;
}
2017-04-23 14:10:41 +02:00
}
2016-10-03 21:33:42 +02:00
}
2020-03-27 19:21:27 +01:00
if ( vp - > update_mode = = RS : : VIEWPORT_UPDATE_ONCE ) {
vp - > update_mode = RS : : VIEWPORT_UPDATE_DISABLED ;
2016-10-03 21:33:42 +02:00
}
2019-09-20 22:58:06 +02:00
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " < Render Viewport " + itos ( i ) ) ;
2021-07-03 01:14:19 +02:00
objects_drawn + = vp - > render_info . info [ RS : : VIEWPORT_RENDER_INFO_TYPE_VISIBLE ] [ RS : : VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME ] + vp - > render_info . info [ RS : : VIEWPORT_RENDER_INFO_TYPE_SHADOW ] [ RS : : VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME ] ;
vertices_drawn + = vp - > render_info . info [ RS : : VIEWPORT_RENDER_INFO_TYPE_VISIBLE ] [ RS : : VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME ] + vp - > render_info . info [ RS : : VIEWPORT_RENDER_INFO_TYPE_SHADOW ] [ RS : : VIEWPORT_RENDER_INFO_PRIMITIVES_IN_FRAME ] ;
draw_calls_used + = vp - > render_info . info [ RS : : VIEWPORT_RENDER_INFO_TYPE_VISIBLE ] [ RS : : VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME ] + vp - > render_info . info [ RS : : VIEWPORT_RENDER_INFO_TYPE_SHADOW ] [ RS : : VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME ] ;
2019-06-16 04:45:24 +02:00
}
2020-12-03 22:09:47 +01:00
RSG : : scene - > set_debug_draw_mode ( RS : : VIEWPORT_DEBUG_DRAW_DISABLED ) ;
2019-06-16 04:45:24 +02:00
2021-07-03 01:14:19 +02:00
total_objects_drawn = objects_drawn ;
total_vertices_drawn = vertices_drawn ;
total_draw_calls_used = draw_calls_used ;
2022-03-04 08:44:29 +01:00
RENDER_TIMESTAMP ( " < Render Viewports " ) ;
2019-06-24 21:13:06 +02:00
//this needs to be called to make screen swapping more efficient
2020-03-27 19:21:27 +01:00
RSG : : rasterizer - > prepare_for_blitting_render_targets ( ) ;
2019-06-24 21:13:06 +02:00
2021-08-09 22:13:42 +02:00
for ( const KeyValue < int , Vector < BlitToScreen > > & E : blit_to_screen_list ) {
RSG : : rasterizer - > blit_render_targets_to_screen ( E . key , E . value . ptr ( ) , E . value . size ( ) ) ;
2016-10-03 21:33:42 +02:00
}
}
2021-02-09 17:19:03 +01:00
RID RendererViewport : : viewport_allocate ( ) {
return viewport_owner . allocate_rid ( ) ;
}
2016-10-03 21:33:42 +02:00
2021-02-09 17:19:03 +01:00
void RendererViewport : : viewport_initialize ( RID p_rid ) {
2021-06-29 15:58:28 +02:00
viewport_owner . initialize_rid ( p_rid ) ;
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_rid ) ;
2021-02-09 17:19:03 +01:00
viewport - > self = p_rid ;
2022-04-07 16:00:51 +02:00
viewport - > render_target = RSG : : texture_storage - > render_target_create ( ) ;
2022-09-12 11:44:48 +02:00
viewport - > shadow_atlas = RSG : : light_storage - > shadow_atlas_create ( ) ;
2019-05-08 20:25:34 +02:00
viewport - > viewport_render_direct_to_screen = false ;
2021-11-23 22:16:03 +01:00
viewport - > fsr_enabled = ! RSG : : rasterizer - > is_low_end ( ) & & ! viewport - > disable_3d ;
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_use_xr ( RID p_viewport , bool p_use_xr ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2017-04-23 14:10:41 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2021-05-07 15:19:04 +02:00
if ( viewport - > use_xr = = p_use_xr ) {
return ;
}
2020-04-08 16:47:36 +02:00
viewport - > use_xr = p_use_xr ;
2022-08-16 23:54:55 +02:00
// Re-configure the 3D render buffers when disabling XR. They'll get
// re-configured when enabling XR in draw_viewports().
if ( ! p_use_xr ) {
viewport - > view_count = 1 ;
_configure_3d_render_buffers ( viewport ) ;
}
2021-08-19 03:52:06 +02:00
}
2021-11-23 22:16:03 +01:00
void RendererViewport : : viewport_set_scaling_3d_mode ( RID p_viewport , RS : : ViewportScaling3DMode p_mode ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
viewport - > scaling_3d_mode = p_mode ;
_configure_3d_render_buffers ( viewport ) ;
}
void RendererViewport : : viewport_set_fsr_sharpness ( RID p_viewport , float p_sharpness ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
viewport - > fsr_sharpness = p_sharpness ;
2022-08-04 10:40:39 +02:00
if ( viewport - > render_buffers . is_valid ( ) ) {
viewport - > render_buffers - > set_fsr_sharpness ( p_sharpness ) ;
}
2021-11-23 22:16:03 +01:00
}
2022-06-12 01:49:59 +02:00
void RendererViewport : : viewport_set_texture_mipmap_bias ( RID p_viewport , float p_mipmap_bias ) {
2021-11-23 22:16:03 +01:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
2022-06-12 01:49:59 +02:00
viewport - > texture_mipmap_bias = p_mipmap_bias ;
2022-08-04 10:40:39 +02:00
if ( viewport - > render_buffers . is_valid ( ) ) {
viewport - > render_buffers - > set_texture_mipmap_bias ( p_mipmap_bias ) ;
}
2021-11-23 22:16:03 +01:00
}
void RendererViewport : : viewport_set_scaling_3d_scale ( RID p_viewport , float p_scaling_3d_scale ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2021-08-19 03:52:06 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2021-08-29 14:44:09 +02:00
// Clamp to reasonable values that are actually useful.
// Values above 2.0 don't serve a practical purpose since the viewport
// isn't displayed with mipmaps.
2021-11-23 22:16:03 +01:00
if ( viewport - > scaling_3d_scale = = CLAMP ( p_scaling_3d_scale , 0.1 , 2.0 ) ) {
2021-08-19 03:52:06 +02:00
return ;
2021-05-07 15:19:04 +02:00
}
2021-08-19 03:52:06 +02:00
2021-11-23 22:16:03 +01:00
viewport - > scaling_3d_scale = CLAMP ( p_scaling_3d_scale , 0.1 , 2.0 ) ;
2021-08-19 03:52:06 +02:00
_configure_3d_render_buffers ( viewport ) ;
2021-05-07 15:19:04 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_size ( RID p_viewport , int p_width , int p_height ) {
2023-02-09 23:14:46 +01:00
ERR_FAIL_COND ( p_width < 0 | | p_height < 0 ) ;
2016-10-03 21:33:42 +02:00
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2022-08-16 23:54:55 +02:00
ERR_FAIL_COND_MSG ( viewport - > use_xr , " Cannot set viewport size when using XR " ) ;
2016-10-03 21:33:42 +02:00
2022-08-16 23:54:55 +02:00
_viewport_set_size ( viewport , p_width , p_height , 1 ) ;
}
2021-11-23 22:16:03 +01:00
2022-08-16 23:54:55 +02:00
void RendererViewport : : _viewport_set_size ( Viewport * p_viewport , int p_width , int p_height , uint32_t p_view_count ) {
Size2i new_size ( p_width , p_height ) ;
if ( p_viewport - > size ! = new_size | | p_viewport - > view_count ! = p_view_count ) {
p_viewport - > size = new_size ;
p_viewport - > view_count = p_view_count ;
2021-04-20 18:40:24 +02:00
2022-08-16 23:54:55 +02:00
RSG : : texture_storage - > render_target_set_size ( p_viewport - > render_target , p_width , p_height , p_view_count ) ;
_configure_3d_render_buffers ( p_viewport ) ;
p_viewport - > occlusion_buffer_dirty = true ;
}
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_active ( RID p_viewport , bool p_active ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
if ( p_active ) {
2022-02-01 19:19:13 +01:00
ERR_FAIL_COND_MSG ( active_viewports . has ( viewport ) , " Can't make active a Viewport that is already active. " ) ;
2021-04-20 18:40:24 +02:00
viewport - > occlusion_buffer_dirty = true ;
2016-10-03 21:33:42 +02:00
active_viewports . push_back ( viewport ) ;
} else {
active_viewports . erase ( viewport ) ;
}
2022-07-17 01:59:13 +02:00
sorted_active_viewports_dirty = true ;
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_parent_viewport ( RID p_viewport , RID p_parent_viewport ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-05 06:26:35 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2017-03-05 16:44:50 +01:00
viewport - > parent = p_parent_viewport ;
2016-10-05 06:26:35 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_clear_mode ( RID p_viewport , RS : : ViewportClearMode p_clear_mode ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2017-03-05 16:44:50 +01:00
viewport - > clear_mode = p_clear_mode ;
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_attach_to_screen ( RID p_viewport , const Rect2 & p_rect , DisplayServer : : WindowID p_screen ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2020-03-04 02:51:12 +01:00
if ( p_screen ! = DisplayServer : : INVALID_WINDOW_ID ) {
2021-09-27 01:07:10 +02:00
// If using OpenGL we can optimize this operation by rendering directly to system_fbo
2020-03-04 02:51:12 +01:00
// instead of rendering to fbo and copying to system_fbo after
2020-03-27 19:21:27 +01:00
if ( RSG : : rasterizer - > is_low_end ( ) & & viewport - > viewport_render_direct_to_screen ) {
2022-08-16 23:54:55 +02:00
RSG : : texture_storage - > render_target_set_size ( viewport - > render_target , p_rect . size . x , p_rect . size . y , viewport - > view_count ) ;
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_set_position ( viewport - > render_target , p_rect . position . x , p_rect . position . y ) ;
2020-03-04 02:51:12 +01:00
}
2019-05-08 20:25:34 +02:00
2020-03-04 02:51:12 +01:00
viewport - > viewport_to_screen_rect = p_rect ;
viewport - > viewport_to_screen = p_screen ;
} else {
// if render_direct_to_screen was used, reset size and position
2020-03-27 19:21:27 +01:00
if ( RSG : : rasterizer - > is_low_end ( ) & & viewport - > viewport_render_direct_to_screen ) {
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_set_position ( viewport - > render_target , 0 , 0 ) ;
2022-08-16 23:54:55 +02:00
RSG : : texture_storage - > render_target_set_size ( viewport - > render_target , viewport - > size . x , viewport - > size . y , viewport - > view_count ) ;
2020-03-04 02:51:12 +01:00
}
viewport - > viewport_to_screen_rect = Rect2 ( ) ;
viewport - > viewport_to_screen = DisplayServer : : INVALID_WINDOW_ID ;
}
2016-10-03 21:33:42 +02:00
}
2019-05-08 20:25:34 +02:00
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_render_direct_to_screen ( RID p_viewport , bool p_enable ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2019-05-08 20:25:34 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2020-05-14 16:41:43 +02:00
if ( p_enable = = viewport - > viewport_render_direct_to_screen ) {
2019-05-08 20:25:34 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2019-05-08 20:25:34 +02:00
// if disabled, reset render_target size and position
if ( ! p_enable ) {
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_set_position ( viewport - > render_target , 0 , 0 ) ;
2022-08-16 23:54:55 +02:00
RSG : : texture_storage - > render_target_set_size ( viewport - > render_target , viewport - > size . x , viewport - > size . y , viewport - > view_count ) ;
2019-05-08 20:25:34 +02:00
}
2022-05-18 17:04:41 +02:00
RSG : : texture_storage - > render_target_set_direct_to_screen ( viewport - > render_target , p_enable ) ;
2019-05-08 20:25:34 +02:00
viewport - > viewport_render_direct_to_screen = p_enable ;
Fix misc. source comment typos
Found using `codespell -q 3 -S ./thirdparty,*.po -L ang,ba,cas,dof,doubleclick,fave,hist,leapyear,lod,nd,numer,ois,paket,seeked,sinc,switchs,te,uint -D ~/Projects/codespell/codespell_lib/data/dictionary.txt `
2019-09-19 20:36:39 +02:00
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
2020-03-27 19:21:27 +01:00
if ( RSG : : rasterizer - > is_low_end ( ) & & viewport - > viewport_to_screen_rect ! = Rect2 ( ) & & p_enable ) {
2022-08-16 23:54:55 +02:00
RSG : : texture_storage - > render_target_set_size ( viewport - > render_target , viewport - > viewport_to_screen_rect . size . x , viewport - > viewport_to_screen_rect . size . y , viewport - > view_count ) ;
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_set_position ( viewport - > render_target , viewport - > viewport_to_screen_rect . position . x , viewport - > viewport_to_screen_rect . position . y ) ;
2019-05-08 20:25:34 +02:00
}
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_update_mode ( RID p_viewport , RS : : ViewportUpdateMode p_mode ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2017-03-05 16:44:50 +01:00
viewport - > update_mode = p_mode ;
2016-10-03 21:33:42 +02:00
}
2023-03-31 02:28:53 +02:00
RID RendererViewport : : viewport_get_render_target ( RID p_viewport ) const {
const Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND_V ( ! viewport , RID ( ) ) ;
return viewport - > render_target ;
}
2020-12-04 19:26:24 +01:00
RID RendererViewport : : viewport_get_texture ( RID p_viewport ) const {
2021-09-29 19:08:41 +02:00
const Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2017-03-05 16:44:50 +01:00
ERR_FAIL_COND_V ( ! viewport , RID ( ) ) ;
2016-10-03 21:33:42 +02:00
2022-04-07 16:00:51 +02:00
return RSG : : texture_storage - > render_target_get_texture ( viewport - > render_target ) ;
2016-10-03 21:33:42 +02:00
}
2021-04-20 18:40:24 +02:00
RID RendererViewport : : viewport_get_occluder_debug_texture ( RID p_viewport ) const {
2021-09-29 19:08:41 +02:00
const Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2021-04-20 18:40:24 +02:00
ERR_FAIL_COND_V ( ! viewport , RID ( ) ) ;
if ( viewport - > use_occlusion_culling & & viewport - > debug_draw = = RenderingServer : : VIEWPORT_DEBUG_DRAW_OCCLUDERS ) {
return RendererSceneOcclusionCull : : get_singleton ( ) - > buffer_get_debug_texture ( p_viewport ) ;
}
return RID ( ) ;
}
2022-04-04 16:10:22 +02:00
void RendererViewport : : viewport_set_prev_camera_data ( RID p_viewport , const RendererSceneRender : : CameraData * p_camera_data ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
uint64_t frame = RSG : : rasterizer - > get_frame_number ( ) ;
if ( viewport - > prev_camera_data_frame ! = frame ) {
viewport - > prev_camera_data = * p_camera_data ;
viewport - > prev_camera_data_frame = frame ;
}
}
const RendererSceneRender : : CameraData * RendererViewport : : viewport_get_prev_camera_data ( RID p_viewport ) {
const Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND_V ( ! viewport , nullptr ) ;
return & viewport - > prev_camera_data ;
}
2021-07-01 04:17:47 +02:00
void RendererViewport : : viewport_set_disable_2d ( RID p_viewport , bool p_disable ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2021-07-01 04:17:47 +02:00
viewport - > disable_2d = p_disable ;
2016-10-03 21:33:42 +02:00
}
2020-05-14 14:29:06 +02:00
2023-01-30 01:04:39 +01:00
void RendererViewport : : viewport_set_environment_mode ( RID p_viewport , RS : : ViewportEnvironmentMode p_mode ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2023-01-30 01:04:39 +01:00
viewport - > disable_environment = p_mode ;
}
bool RendererViewport : : viewport_is_environment_disabled ( Viewport * viewport ) {
ERR_FAIL_COND_V ( ! viewport , false ) ;
if ( viewport - > parent . is_valid ( ) & & viewport - > disable_environment = = RS : : VIEWPORT_ENVIRONMENT_INHERIT ) {
Viewport * parent = viewport_owner . get_or_null ( viewport - > parent ) ;
return viewport_is_environment_disabled ( parent ) ;
}
return viewport - > disable_environment = = RS : : VIEWPORT_ENVIRONMENT_DISABLED ;
2016-10-03 21:33:42 +02:00
}
2021-06-29 18:36:32 +02:00
void RendererViewport : : viewport_set_disable_3d ( RID p_viewport , bool p_disable ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2021-06-29 18:36:32 +02:00
ERR_FAIL_COND ( ! viewport ) ;
viewport - > disable_3d = p_disable ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_attach_camera ( RID p_viewport , RID p_camera ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2017-03-05 16:44:50 +01:00
viewport - > camera = p_camera ;
2016-10-03 21:33:42 +02:00
}
2020-05-14 14:29:06 +02:00
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_scenario ( RID p_viewport , RID p_scenario ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2021-05-09 18:23:20 +02:00
if ( viewport - > scenario . is_valid ( ) ) {
RSG : : scene - > scenario_remove_viewport_visibility_mask ( viewport - > scenario , p_viewport ) ;
}
2017-03-05 16:44:50 +01:00
viewport - > scenario = p_scenario ;
2021-04-20 18:40:24 +02:00
if ( viewport - > use_occlusion_culling ) {
RendererSceneOcclusionCull : : get_singleton ( ) - > buffer_set_scenario ( p_viewport , p_scenario ) ;
}
2016-10-03 21:33:42 +02:00
}
2020-05-14 14:29:06 +02:00
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_attach_canvas ( RID p_viewport , RID p_canvas ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
ERR_FAIL_COND ( viewport - > canvas_map . has ( p_canvas ) ) ;
2021-09-29 19:08:41 +02:00
RendererCanvasCull : : Canvas * canvas = RSG : : canvas - > canvas_owner . get_or_null ( p_canvas ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! canvas ) ;
canvas - > viewports . insert ( p_viewport ) ;
2017-03-05 16:44:50 +01:00
viewport - > canvas_map [ p_canvas ] = Viewport : : CanvasData ( ) ;
viewport - > canvas_map [ p_canvas ] . layer = 0 ;
2018-10-30 21:53:00 +01:00
viewport - > canvas_map [ p_canvas ] . sublayer = 0 ;
2017-03-05 16:44:50 +01:00
viewport - > canvas_map [ p_canvas ] . canvas = canvas ;
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_remove_canvas ( RID p_viewport , RID p_canvas ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2021-09-29 19:08:41 +02:00
RendererCanvasCull : : Canvas * canvas = RSG : : canvas - > canvas_owner . get_or_null ( p_canvas ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! canvas ) ;
viewport - > canvas_map . erase ( p_canvas ) ;
canvas - > viewports . erase ( p_viewport ) ;
}
2020-05-14 14:29:06 +02:00
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_canvas_transform ( RID p_viewport , RID p_canvas , const Transform2D & p_offset ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
ERR_FAIL_COND ( ! viewport - > canvas_map . has ( p_canvas ) ) ;
2017-03-05 16:44:50 +01:00
viewport - > canvas_map [ p_canvas ] . transform = p_offset ;
2016-10-03 21:33:42 +02:00
}
2020-05-14 14:29:06 +02:00
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_transparent_background ( RID p_viewport , bool p_enabled ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2022-05-18 17:04:41 +02:00
RSG : : texture_storage - > render_target_set_transparent ( viewport - > render_target , p_enabled ) ;
2018-01-18 19:11:07 +01:00
viewport - > transparent_bg = p_enabled ;
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_global_canvas_transform ( RID p_viewport , const Transform2D & p_transform ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
2017-03-05 16:44:50 +01:00
viewport - > global_transform = p_transform ;
2016-10-03 21:33:42 +02:00
}
2020-05-14 14:29:06 +02:00
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_canvas_stacking ( RID p_viewport , RID p_canvas , int p_layer , int p_sublayer ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-10-03 21:33:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
ERR_FAIL_COND ( ! viewport - > canvas_map . has ( p_canvas ) ) ;
2017-03-05 16:44:50 +01:00
viewport - > canvas_map [ p_canvas ] . layer = p_layer ;
2018-10-30 21:53:00 +01:00
viewport - > canvas_map [ p_canvas ] . sublayer = p_sublayer ;
2016-10-03 21:33:42 +02:00
}
2022-05-01 01:40:30 +02:00
void RendererViewport : : viewport_set_positional_shadow_atlas_size ( RID p_viewport , int p_size , bool p_16_bits ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! viewport ) ;
2017-03-05 16:44:50 +01:00
viewport - > shadow_atlas_size = p_size ;
2021-01-24 20:00:20 +01:00
viewport - > shadow_atlas_16_bits = p_16_bits ;
2016-11-10 03:55:06 +01:00
2022-09-12 11:44:48 +02:00
RSG : : light_storage - > shadow_atlas_set_size ( viewport - > shadow_atlas , viewport - > shadow_atlas_size , viewport - > shadow_atlas_16_bits ) ;
2016-11-10 03:55:06 +01:00
}
2022-05-01 01:40:30 +02:00
void RendererViewport : : viewport_set_positional_shadow_atlas_quadrant_subdivision ( RID p_viewport , int p_quadrant , int p_subdiv ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2016-11-10 03:55:06 +01:00
ERR_FAIL_COND ( ! viewport ) ;
2022-09-12 11:44:48 +02:00
RSG : : light_storage - > shadow_atlas_set_quadrant_subdivision ( viewport - > shadow_atlas , p_quadrant , p_subdiv ) ;
2016-11-10 03:55:06 +01:00
}
2022-08-13 01:02:32 +02:00
void RendererViewport : : viewport_set_msaa_2d ( RID p_viewport , RS : : ViewportMSAA p_msaa ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2017-01-02 02:16:52 +01:00
ERR_FAIL_COND ( ! viewport ) ;
2022-08-13 01:02:32 +02:00
if ( viewport - > msaa_2d = = p_msaa ) {
2019-08-19 00:40:52 +02:00
return ;
}
2022-08-13 01:02:32 +02:00
viewport - > msaa_2d = p_msaa ;
RSG : : texture_storage - > render_target_set_msaa ( viewport - > render_target , p_msaa ) ;
}
void RendererViewport : : viewport_set_msaa_3d ( RID p_viewport , RS : : ViewportMSAA p_msaa ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
if ( viewport - > msaa_3d = = p_msaa ) {
return ;
}
viewport - > msaa_3d = p_msaa ;
2021-08-19 03:52:06 +02:00
_configure_3d_render_buffers ( viewport ) ;
2020-04-12 06:49:10 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_screen_space_aa ( RID p_viewport , RS : : ViewportScreenSpaceAA p_mode ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-04-12 06:49:10 +02:00
ERR_FAIL_COND ( ! viewport ) ;
if ( viewport - > screen_space_aa = = p_mode ) {
return ;
}
viewport - > screen_space_aa = p_mode ;
2021-08-19 03:52:06 +02:00
_configure_3d_render_buffers ( viewport ) ;
2020-04-20 23:34:47 +02:00
}
2022-04-04 16:10:22 +02:00
void RendererViewport : : viewport_set_use_taa ( RID p_viewport , bool p_use_taa ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
2023-01-16 19:38:37 +01:00
ERR_FAIL_COND_EDMSG ( OS : : get_singleton ( ) - > get_current_rendering_method ( ) ! = " forward_plus " , " TAA is only available when using the Forward+ renderer. " ) ;
2022-04-04 16:10:22 +02:00
if ( viewport - > use_taa = = p_use_taa ) {
return ;
}
viewport - > use_taa = p_use_taa ;
_configure_3d_render_buffers ( viewport ) ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_use_debanding ( RID p_viewport , bool p_use_debanding ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-04-20 23:34:47 +02:00
ERR_FAIL_COND ( ! viewport ) ;
if ( viewport - > use_debanding = = p_use_debanding ) {
return ;
}
viewport - > use_debanding = p_use_debanding ;
2022-08-04 10:40:39 +02:00
if ( viewport - > render_buffers . is_valid ( ) ) {
viewport - > render_buffers - > set_use_debanding ( p_use_debanding ) ;
}
2017-06-09 05:23:50 +02:00
}
2021-04-20 18:40:24 +02:00
void RendererViewport : : viewport_set_use_occlusion_culling ( RID p_viewport , bool p_use_occlusion_culling ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2021-04-20 18:40:24 +02:00
ERR_FAIL_COND ( ! viewport ) ;
if ( viewport - > use_occlusion_culling = = p_use_occlusion_culling ) {
return ;
}
viewport - > use_occlusion_culling = p_use_occlusion_culling ;
if ( viewport - > use_occlusion_culling ) {
RendererSceneOcclusionCull : : get_singleton ( ) - > add_buffer ( p_viewport ) ;
RendererSceneOcclusionCull : : get_singleton ( ) - > buffer_set_scenario ( p_viewport , viewport - > scenario ) ;
} else {
RendererSceneOcclusionCull : : get_singleton ( ) - > remove_buffer ( p_viewport ) ;
}
viewport - > occlusion_buffer_dirty = true ;
}
void RendererViewport : : viewport_set_occlusion_rays_per_thread ( int p_rays_per_thread ) {
if ( occlusion_rays_per_thread = = p_rays_per_thread ) {
return ;
}
occlusion_rays_per_thread = p_rays_per_thread ;
for ( int i = 0 ; i < active_viewports . size ( ) ; i + + ) {
active_viewports [ i ] - > occlusion_buffer_dirty = true ;
}
}
void RendererViewport : : viewport_set_occlusion_culling_build_quality ( RS : : ViewportOcclusionCullingBuildQuality p_quality ) {
RendererSceneOcclusionCull : : get_singleton ( ) - > set_build_quality ( p_quality ) ;
}
2021-12-29 00:10:41 +01:00
void RendererViewport : : viewport_set_mesh_lod_threshold ( RID p_viewport , float p_pixels ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-12-17 19:56:59 +01:00
ERR_FAIL_COND ( ! viewport ) ;
2021-12-29 00:10:41 +01:00
viewport - > mesh_lod_threshold = p_pixels ;
2020-12-17 19:56:59 +01:00
}
2021-07-03 01:14:19 +02:00
int RendererViewport : : viewport_get_render_info ( RID p_viewport , RS : : ViewportRenderInfoType p_type , RS : : ViewportRenderInfo p_info ) {
2021-10-18 16:58:38 +02:00
ERR_FAIL_INDEX_V ( p_type , RS : : VIEWPORT_RENDER_INFO_TYPE_MAX , - 1 ) ;
2020-03-27 19:21:27 +01:00
ERR_FAIL_INDEX_V ( p_info , RS : : VIEWPORT_RENDER_INFO_MAX , - 1 ) ;
2017-06-11 23:13:04 +02:00
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-05-14 16:41:43 +02:00
if ( ! viewport ) {
2017-06-11 23:13:04 +02:00
return 0 ; //there should be a lock here..
2020-05-14 16:41:43 +02:00
}
2017-06-11 20:52:03 +02:00
2021-07-03 01:14:19 +02:00
return viewport - > render_info . info [ p_type ] [ p_info ] ;
2017-06-11 20:52:03 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_debug_draw ( RID p_viewport , RS : : ViewportDebugDraw p_draw ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2017-06-11 20:52:03 +02:00
ERR_FAIL_COND ( ! viewport ) ;
viewport - > debug_draw = p_draw ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_measure_render_time ( RID p_viewport , bool p_enable ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-04-10 19:18:42 +02:00
ERR_FAIL_COND ( ! viewport ) ;
viewport - > measure_render_time = p_enable ;
}
2020-12-04 19:26:24 +01:00
float RendererViewport : : viewport_get_measured_render_time_cpu ( RID p_viewport ) const {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-04-10 19:18:42 +02:00
ERR_FAIL_COND_V ( ! viewport , 0 ) ;
return double ( viewport - > time_cpu_end - viewport - > time_cpu_begin ) / 1000.0 ;
}
2020-12-04 19:26:24 +01:00
float RendererViewport : : viewport_get_measured_render_time_gpu ( RID p_viewport ) const {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-04-10 19:18:42 +02:00
ERR_FAIL_COND_V ( ! viewport , 0 ) ;
return double ( ( viewport - > time_gpu_end - viewport - > time_gpu_begin ) / 1000 ) / 1000.0 ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_snap_2d_transforms_to_pixel ( RID p_viewport , bool p_enabled ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-10-29 22:09:16 +01:00
ERR_FAIL_COND ( ! viewport ) ;
viewport - > snap_2d_transforms_to_pixel = p_enabled ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_snap_2d_vertices_to_pixel ( RID p_viewport , bool p_enabled ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-10-29 22:09:16 +01:00
ERR_FAIL_COND ( ! viewport ) ;
viewport - > snap_2d_vertices_to_pixel = p_enabled ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_default_canvas_item_texture_filter ( RID p_viewport , RS : : CanvasItemTextureFilter p_filter ) {
2020-10-24 17:15:43 +02:00
ERR_FAIL_COND_MSG ( p_filter = = RS : : CANVAS_ITEM_TEXTURE_FILTER_DEFAULT , " Viewport does not accept DEFAULT as texture filter (it's the topmost choice already).) " ) ;
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-10-24 17:15:43 +02:00
ERR_FAIL_COND ( ! viewport ) ;
viewport - > texture_filter = p_filter ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_default_canvas_item_texture_repeat ( RID p_viewport , RS : : CanvasItemTextureRepeat p_repeat ) {
2020-10-24 17:15:43 +02:00
ERR_FAIL_COND_MSG ( p_repeat = = RS : : CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT , " Viewport does not accept DEFAULT as texture repeat (it's the topmost choice already).) " ) ;
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-10-24 17:15:43 +02:00
ERR_FAIL_COND ( ! viewport ) ;
viewport - > texture_repeat = p_repeat ;
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : viewport_set_sdf_oversize_and_scale ( RID p_viewport , RS : : ViewportSDFOversize p_size , RS : : ViewportSDFScale p_scale ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
2020-11-26 13:50:21 +01:00
ERR_FAIL_COND ( ! viewport ) ;
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_set_sdf_size_and_scale ( viewport - > render_target , p_size , p_scale ) ;
2020-11-26 13:50:21 +01:00
}
Implement Running Godot as Movie Writer
* Allows running the game in "movie writer" mode.
* It ensures entirely stable framerate, so your run can be saved stable and with proper sound (which is impossible if your CPU/GPU can't sustain doing this in real-time).
* If disabling vsync, it can save movies faster than the game is run, but if you want to control the interaction it can get difficult.
* Implements a simple, default MJPEG writer.
This new features has two main use cases, which have high demand:
* Saving game videos in high quality and ensuring the frame rate is *completely* stable, always.
* Using Godot as a tool to make movies and animations (which is ideal if you want interaction, or creating them procedurally. No other software is as good for this).
**Note**: This feature **IS NOT** for capturing real-time footage. Use something like OBS, SimpleScreenRecorder or FRAPS to achieve that, as they do a much better job at intercepting the compositor than Godot can probably do using Vulkan or OpenGL natively. If your game runs near real-time when capturing, you can still use this feature but it will play no sound (sound will be saved directly).
Usage:
$ godot --write-movie movie.avi [scene_file.tscn]
Missing:
* Options for configuring video writing via GLOBAL_DEF
* UI Menu for launching with this mode from the editor.
* Add to list of command line options.
* Add a feature tag to override configurations when movie writing (fantastic for saving videos with highest quality settings).
2022-06-17 00:55:19 +02:00
RID RendererViewport : : viewport_find_from_screen_attachment ( DisplayServer : : WindowID p_id ) const {
RID * rids = nullptr ;
uint32_t rid_count = viewport_owner . get_rid_count ( ) ;
rids = ( RID * ) alloca ( sizeof ( RID * ) * rid_count ) ;
viewport_owner . fill_owned_buffer ( rids ) ;
for ( uint32_t i = 0 ; i < rid_count ; i + + ) {
Viewport * viewport = viewport_owner . get_or_null ( rids [ i ] ) ;
if ( viewport - > viewport_to_screen = = p_id ) {
return rids [ i ] ;
}
}
return RID ( ) ;
}
2022-02-11 12:33:54 +01:00
void RendererViewport : : viewport_set_vrs_mode ( RID p_viewport , RS : : ViewportVRSMode p_mode ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
RSG : : texture_storage - > render_target_set_vrs_mode ( viewport - > render_target , p_mode ) ;
_configure_3d_render_buffers ( viewport ) ;
}
void RendererViewport : : viewport_set_vrs_texture ( RID p_viewport , RID p_texture ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
RSG : : texture_storage - > render_target_set_vrs_texture ( viewport - > render_target , p_texture ) ;
_configure_3d_render_buffers ( viewport ) ;
}
2020-12-04 19:26:24 +01:00
bool RendererViewport : : free ( RID p_rid ) {
2016-11-19 17:23:37 +01:00
if ( viewport_owner . owns ( p_rid ) ) {
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( p_rid ) ;
2016-10-03 21:33:42 +02:00
2022-04-07 16:00:51 +02:00
RSG : : texture_storage - > render_target_free ( viewport - > render_target ) ;
2022-09-12 11:44:48 +02:00
RSG : : light_storage - > shadow_atlas_free ( viewport - > shadow_atlas ) ;
2019-08-19 00:40:52 +02:00
if ( viewport - > render_buffers . is_valid ( ) ) {
2022-08-04 10:40:39 +02:00
viewport - > render_buffers . unref ( ) ;
2019-08-19 00:40:52 +02:00
}
2016-11-19 17:23:37 +01:00
2022-05-13 15:04:37 +02:00
while ( viewport - > canvas_map . begin ( ) ) {
viewport_remove_canvas ( p_rid , viewport - > canvas_map . begin ( ) - > key ) ;
2016-11-19 17:23:37 +01:00
}
2016-10-03 21:33:42 +02:00
2017-03-05 16:44:50 +01:00
viewport_set_scenario ( p_rid , RID ( ) ) ;
2016-11-19 17:23:37 +01:00
active_viewports . erase ( viewport ) ;
2022-07-17 01:59:13 +02:00
sorted_active_viewports_dirty = true ;
2016-11-19 17:23:37 +01:00
2021-04-20 18:40:24 +02:00
if ( viewport - > use_occlusion_culling ) {
RendererSceneOcclusionCull : : get_singleton ( ) - > remove_buffer ( p_rid ) ;
}
2016-11-19 17:23:37 +01:00
viewport_owner . free ( p_rid ) ;
2016-10-03 21:33:42 +02:00
2016-11-19 17:23:37 +01:00
return true ;
}
2016-10-03 21:33:42 +02:00
2016-11-19 17:23:37 +01:00
return false ;
2016-10-03 21:33:42 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : handle_timestamp ( String p_timestamp , uint64_t p_cpu_time , uint64_t p_gpu_time ) {
2020-04-10 19:18:42 +02:00
RID * vp = timestamp_vp_map . getptr ( p_timestamp ) ;
if ( ! vp ) {
return ;
}
2021-09-29 19:08:41 +02:00
Viewport * viewport = viewport_owner . get_or_null ( * vp ) ;
2020-04-10 19:18:42 +02:00
if ( ! viewport ) {
return ;
}
if ( p_timestamp . begins_with ( " vp_begin " ) ) {
viewport - > time_cpu_begin = p_cpu_time ;
viewport - > time_gpu_begin = p_gpu_time ;
}
if ( p_timestamp . begins_with ( " vp_end " ) ) {
viewport - > time_cpu_end = p_cpu_time ;
viewport - > time_gpu_end = p_gpu_time ;
}
}
2020-12-04 19:26:24 +01:00
void RendererViewport : : set_default_clear_color ( const Color & p_color ) {
2022-06-21 02:08:33 +02:00
RSG : : texture_storage - > set_default_clear_color ( p_color ) ;
2018-07-29 20:09:42 +02:00
}
2021-09-02 20:07:04 +02:00
void RendererViewport : : viewport_set_canvas_cull_mask ( RID p_viewport , uint32_t p_canvas_cull_mask ) {
Viewport * viewport = viewport_owner . get_or_null ( p_viewport ) ;
ERR_FAIL_COND ( ! viewport ) ;
viewport - > canvas_cull_mask = p_canvas_cull_mask ;
}
2021-06-19 17:44:59 +02:00
// Workaround for setting this on thread.
void RendererViewport : : call_set_vsync_mode ( DisplayServer : : VSyncMode p_mode , DisplayServer : : WindowID p_window ) {
DisplayServer : : get_singleton ( ) - > window_set_vsync_mode ( p_mode , p_window ) ;
2021-02-09 17:19:03 +01:00
}
2021-07-03 01:14:19 +02:00
int RendererViewport : : get_total_objects_drawn ( ) const {
return total_objects_drawn ;
}
int RendererViewport : : get_total_vertices_drawn ( ) const {
return total_vertices_drawn ;
}
int RendererViewport : : get_total_draw_calls_used ( ) const {
return total_draw_calls_used ;
}
2020-12-04 19:26:24 +01:00
RendererViewport : : RendererViewport ( ) {
2021-04-20 18:40:24 +02:00
occlusion_rays_per_thread = GLOBAL_GET ( " rendering/occlusion_culling/occlusion_rays_per_thread " ) ;
2016-10-03 21:33:42 +02:00
}