summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/SCsub2
-rw-r--r--servers/audio/audio_driver_dummy.cpp82
-rw-r--r--servers/audio/audio_driver_dummy.h30
-rw-r--r--servers/audio/audio_effect.cpp8
-rw-r--r--servers/audio/audio_effect.h6
-rw-r--r--servers/audio/audio_rb_resampler.cpp8
-rw-r--r--servers/audio/audio_stream.cpp179
-rw-r--r--servers/audio/audio_stream.h73
-rw-r--r--servers/audio/effects/audio_effect_amplify.cpp4
-rw-r--r--servers/audio/effects/audio_effect_amplify.h6
-rw-r--r--servers/audio/effects/audio_effect_capture.cpp2
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp50
-rw-r--r--servers/audio/effects/audio_effect_chorus.h8
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp18
-rw-r--r--servers/audio/effects/audio_effect_compressor.h8
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp59
-rw-r--r--servers/audio/effects/audio_effect_delay.h35
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp8
-rw-r--r--servers/audio/effects/audio_effect_distortion.h6
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp9
-rw-r--r--servers/audio/effects/audio_effect_eq.h8
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp14
-rw-r--r--servers/audio/effects/audio_effect_filter.h24
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp20
-rw-r--r--servers/audio/effects/audio_effect_panner.h6
-rw-r--r--servers/audio/effects/audio_effect_phaser.cpp6
-rw-r--r--servers/audio/effects/audio_effect_record.cpp32
-rw-r--r--servers/audio/effects/audio_effect_record.h17
-rw-r--r--servers/audio/effects/audio_effect_reverb.cpp2
-rw-r--r--servers/audio/effects/audio_effect_reverb.h8
-rw-r--r--servers/audio/effects/audio_effect_spectrum_analyzer.cpp2
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.cpp2
-rw-r--r--servers/audio/effects/audio_stream_generator.cpp20
-rw-r--r--servers/audio/effects/audio_stream_generator.h13
-rw-r--r--servers/audio/effects/eq_filter.cpp (renamed from servers/audio/effects/eq.cpp)6
-rw-r--r--servers/audio/effects/eq_filter.h (renamed from servers/audio/effects/eq.h)2
-rw-r--r--servers/audio/effects/reverb_filter.cpp (renamed from servers/audio/effects/reverb.cpp)12
-rw-r--r--servers/audio/effects/reverb_filter.h (renamed from servers/audio/effects/reverb.h)8
-rw-r--r--servers/audio_server.cpp36
-rw-r--r--servers/audio_server.h15
-rw-r--r--servers/camera_server.cpp15
-rw-r--r--servers/camera_server.h4
-rw-r--r--servers/debugger/servers_debugger.h4
-rw-r--r--servers/display_server.cpp122
-rw-r--r--servers/display_server.h59
-rw-r--r--servers/display_server_headless.h2
-rw-r--r--servers/extensions/physics_server_2d_extension.cpp341
-rw-r--r--servers/extensions/physics_server_2d_extension.h452
-rw-r--r--servers/extensions/physics_server_3d_extension.cpp134
-rw-r--r--servers/extensions/physics_server_3d_extension.h37
-rw-r--r--servers/movie_writer/SCsub5
-rw-r--r--servers/movie_writer/movie_writer.cpp227
-rw-r--r--servers/movie_writer/movie_writer.h90
-rw-r--r--servers/movie_writer/movie_writer_mjpeg.cpp263
-rw-r--r--servers/movie_writer/movie_writer_mjpeg.h73
-rw-r--r--servers/movie_writer/movie_writer_pngwav.cpp168
-rw-r--r--servers/movie_writer/movie_writer_pngwav.h71
-rw-r--r--servers/navigation/SCsub5
-rw-r--r--servers/navigation/navigation_path_query_parameters_2d.cpp144
-rw-r--r--servers/navigation/navigation_path_query_parameters_2d.h79
-rw-r--r--servers/navigation/navigation_path_query_parameters_3d.cpp144
-rw-r--r--servers/navigation/navigation_path_query_parameters_3d.h79
-rw-r--r--servers/navigation/navigation_path_query_result_2d.cpp52
-rw-r--r--servers/navigation/navigation_path_query_result_2d.h52
-rw-r--r--servers/navigation/navigation_path_query_result_3d.cpp52
-rw-r--r--servers/navigation/navigation_path_query_result_3d.h52
-rw-r--r--servers/navigation/navigation_utilities.h62
-rw-r--r--servers/navigation_server_2d.cpp147
-rw-r--r--servers/navigation_server_2d.h84
-rw-r--r--servers/navigation_server_3d.cpp382
-rw-r--r--servers/navigation_server_3d.h150
-rw-r--r--servers/physics_2d/godot_area_2d.cpp18
-rw-r--r--servers/physics_2d/godot_area_2d.h6
-rw-r--r--servers/physics_2d/godot_body_2d.cpp55
-rw-r--r--servers/physics_2d/godot_body_2d.h7
-rw-r--r--servers/physics_2d/godot_body_direct_state_2d.cpp2
-rw-r--r--servers/physics_2d/godot_body_pair_2d.cpp2
-rw-r--r--servers/physics_2d/godot_collision_object_2d.h8
-rw-r--r--servers/physics_2d/godot_collision_solver_2d.cpp13
-rw-r--r--servers/physics_2d/godot_collision_solver_2d.h2
-rw-r--r--servers/physics_2d/godot_collision_solver_2d_sat.cpp44
-rw-r--r--servers/physics_2d/godot_joints_2d.cpp6
-rw-r--r--servers/physics_2d/godot_physics_server_2d.cpp73
-rw-r--r--servers/physics_2d/godot_physics_server_2d.h11
-rw-r--r--servers/physics_2d/godot_shape_2d.cpp66
-rw-r--r--servers/physics_2d/godot_space_2d.cpp29
-rw-r--r--servers/physics_2d/godot_step_2d.cpp11
-rw-r--r--servers/physics_2d/godot_step_2d.h4
-rw-r--r--servers/physics_3d/gjk_epa.h2
-rw-r--r--servers/physics_3d/godot_area_3d.cpp18
-rw-r--r--servers/physics_3d/godot_area_3d.h6
-rw-r--r--servers/physics_3d/godot_body_3d.cpp71
-rw-r--r--servers/physics_3d/godot_body_3d.h7
-rw-r--r--servers/physics_3d/godot_body_direct_state_3d.cpp4
-rw-r--r--servers/physics_3d/godot_body_pair_3d.cpp2
-rw-r--r--servers/physics_3d/godot_collision_object_3d.h8
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.cpp29
-rw-r--r--servers/physics_3d/godot_collision_solver_3d.h2
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.cpp65
-rw-r--r--servers/physics_3d/godot_collision_solver_3d_sat.h6
-rw-r--r--servers/physics_3d/godot_physics_server_3d.cpp37
-rw-r--r--servers/physics_3d/godot_physics_server_3d.h10
-rw-r--r--servers/physics_3d/godot_shape_3d.cpp233
-rw-r--r--servers/physics_3d/godot_shape_3d.h2
-rw-r--r--servers/physics_3d/godot_soft_body_3d.cpp9
-rw-r--r--servers/physics_3d/godot_space_3d.cpp25
-rw-r--r--servers/physics_3d/godot_step_3d.cpp11
-rw-r--r--servers/physics_3d/godot_step_3d.h4
-rw-r--r--servers/physics_3d/joints/godot_cone_twist_joint_3d.h6
-rw-r--r--servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp2
-rw-r--r--servers/physics_3d/joints/godot_generic_6dof_joint_3d.h6
-rw-r--r--servers/physics_3d/joints/godot_hinge_joint_3d.h6
-rw-r--r--servers/physics_3d/joints/godot_jacobian_entry_3d.h6
-rw-r--r--servers/physics_3d/joints/godot_pin_joint_3d.h6
-rw-r--r--servers/physics_3d/joints/godot_slider_joint_3d.h6
-rw-r--r--servers/physics_server_2d.cpp130
-rw-r--r--servers/physics_server_2d.h87
-rw-r--r--servers/physics_server_2d_wrap_mt.h10
-rw-r--r--servers/physics_server_3d.cpp96
-rw-r--r--servers/physics_server_3d.h71
-rw-r--r--servers/physics_server_3d_wrap_mt.h10
-rw-r--r--servers/register_server_types.cpp50
-rw-r--r--servers/rendering/SCsub1
-rw-r--r--servers/rendering/dummy/SCsub7
-rw-r--r--servers/rendering/dummy/environment/fog.h55
-rw-r--r--servers/rendering/dummy/environment/gi.h85
-rw-r--r--servers/rendering/dummy/rasterizer_canvas_dummy.h3
-rw-r--r--servers/rendering/dummy/rasterizer_dummy.h15
-rw-r--r--servers/rendering/dummy/rasterizer_scene_dummy.h187
-rw-r--r--servers/rendering/dummy/rasterizer_storage_dummy.h147
-rw-r--r--servers/rendering/dummy/storage/SCsub5
-rw-r--r--servers/rendering/dummy/storage/light_storage.h50
-rw-r--r--servers/rendering/dummy/storage/material_storage.h41
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.cpp58
-rw-r--r--servers/rendering/dummy/storage/mesh_storage.h68
-rw-r--r--servers/rendering/dummy/storage/particles_storage.h2
-rw-r--r--servers/rendering/dummy/storage/texture_storage.cpp (renamed from servers/rendering/renderer_thread_pool.cpp)15
-rw-r--r--servers/rendering/dummy/storage/texture_storage.h42
-rw-r--r--servers/rendering/dummy/storage/utilities.cpp (renamed from servers/rendering/renderer_thread_pool.h)22
-rw-r--r--servers/rendering/dummy/storage/utilities.h118
-rw-r--r--servers/rendering/environment/renderer_fog.h53
-rw-r--r--servers/rendering/environment/renderer_gi.h84
-rw-r--r--servers/rendering/renderer_canvas_cull.cpp149
-rw-r--r--servers/rendering/renderer_canvas_cull.h21
-rw-r--r--servers/rendering/renderer_canvas_render.cpp6
-rw-r--r--servers/rendering/renderer_canvas_render.h20
-rw-r--r--servers/rendering/renderer_compositor.cpp7
-rw-r--r--servers/rendering/renderer_compositor.h18
-rw-r--r--servers/rendering/renderer_geometry_instance.cpp138
-rw-r--r--servers/rendering/renderer_geometry_instance.h150
-rw-r--r--servers/rendering/renderer_rd/SCsub1
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.cpp6
-rw-r--r--servers/rendering/renderer_rd/cluster_builder_rd.h20
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.cpp94
-rw-r--r--servers/rendering/renderer_rd/effects/bokeh_dof.h11
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.cpp553
-rw-r--r--servers/rendering/renderer_rd/effects/copy_effects.h142
-rw-r--r--servers/rendering/renderer_rd/effects/fsr.cpp128
-rw-r--r--servers/rendering/renderer_rd/effects/fsr.h72
-rw-r--r--servers/rendering/renderer_rd/effects/resolve.cpp130
-rw-r--r--servers/rendering/renderer_rd/effects/resolve.h74
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.cpp1876
-rw-r--r--servers/rendering/renderer_rd/effects/ss_effects.h552
-rw-r--r--servers/rendering/renderer_rd/effects/taa.cpp138
-rw-r--r--servers/rendering/renderer_rd/effects/taa.h68
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.cpp4
-rw-r--r--servers/rendering/renderer_rd/effects/tone_mapper.h6
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.cpp149
-rw-r--r--servers/rendering/renderer_rd/effects/vrs.h75
-rw-r--r--servers/rendering/renderer_rd/effects_rd.cpp1760
-rw-r--r--servers/rendering/renderer_rd/effects_rd.h565
-rw-r--r--servers/rendering/renderer_rd/environment/SCsub5
-rw-r--r--servers/rendering/renderer_rd/environment/fog.cpp1212
-rw-r--r--servers/rendering/renderer_rd/environment/fog.h360
-rw-r--r--servers/rendering/renderer_rd/environment/gi.cpp (renamed from servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp)1714
-rw-r--r--servers/rendering/renderer_rd/environment/gi.h (renamed from servers/rendering/renderer_rd/renderer_scene_gi_rd.h)404
-rw-r--r--servers/rendering/renderer_rd/environment/sky.cpp (renamed from servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp)466
-rw-r--r--servers/rendering/renderer_rd/environment/sky.h (renamed from servers/rendering/renderer_rd/renderer_scene_sky_rd.h)115
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp2398
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h408
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp85
-rw-r--r--servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h38
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp1527
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h360
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp69
-rw-r--r--servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h33
-rw-r--r--servers/rendering/renderer_rd/framebuffer_cache_rd.cpp64
-rw-r--r--servers/rendering/renderer_rd/framebuffer_cache_rd.h310
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.cpp5
-rw-r--r--servers/rendering/renderer_rd/pipeline_cache_rd.h2
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp275
-rw-r--r--servers/rendering/renderer_rd/renderer_canvas_render_rd.h38
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.cpp46
-rw-r--r--servers/rendering/renderer_rd/renderer_compositor_rd.h36
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp130
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_environment_rd.h167
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.cpp5453
-rw-r--r--servers/rendering/renderer_rd/renderer_scene_render_rd.h1417
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.cpp751
-rw-r--r--servers/rendering/renderer_rd/renderer_storage_rd.h306
-rw-r--r--servers/rendering/renderer_rd/shader_rd.cpp11
-rw-r--r--servers/rendering/renderer_rd/shaders/SCsub5
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas.glsl48
-rw-r--r--servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/cluster_render.glsl15
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/SCsub4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl2
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl25
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl5
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl29
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy.glsl4
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl (renamed from servers/rendering/renderer_rd/shaders/cube_to_dp.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_filter.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_filter.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl (renamed from servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl (renamed from servers/rendering/renderer_rd/shaders/fsr_upscale.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/resolve.glsl (renamed from servers/rendering/renderer_rd/shaders/resolve.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl)94
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl)20
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl28
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl (renamed from servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl)48
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl112
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl (renamed from servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_blur.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl (renamed from servers/rendering/renderer_rd/shaders/ssao_interleave.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_blur.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl (renamed from servers/rendering/renderer_rd/shaders/ssil_interleave.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl (renamed from servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl (renamed from servers/rendering/renderer_rd/shaders/taa_resolve.glsl)7
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/tonemap.glsl41
-rw-r--r--servers/rendering/renderer_rd/shaders/effects/vrs.glsl72
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/SCsub17
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/gi.glsl (renamed from servers/rendering/renderer_rd/shaders/gi.glsl)187
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl (renamed from servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl)27
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl (renamed from servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl)49
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl (renamed from servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl)1
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl (renamed from servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl)1
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl (renamed from servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/sky.glsl (renamed from servers/rendering/renderer_rd/shaders/sky.glsl)83
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl (renamed from servers/rendering/renderer_rd/shaders/volumetric_fog.glsl)8
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl (renamed from servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl)109
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl (renamed from servers/rendering/renderer_rd/shaders/voxel_gi.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl (renamed from servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/environment/voxel_gi_sdf.glsl (renamed from servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl)0
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/SCsub17
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl)320
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl)172
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/SCsub17
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl)208
-rw-r--r--servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl (renamed from servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl)93
-rw-r--r--servers/rendering/renderer_rd/shaders/light_data_inc.glsl12
-rw-r--r--servers/rendering/renderer_rd/shaders/particles.glsl10
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_data_inc.glsl69
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl8
-rw-r--r--servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl29
-rw-r--r--servers/rendering/renderer_rd/shaders/skeleton.glsl64
-rw-r--r--servers/rendering/renderer_rd/shaders/specular_merge.glsl53
-rw-r--r--servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp43
-rw-r--r--servers/rendering/renderer_rd/storage_rd/forward_id_storage.h68
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.cpp1712
-rw-r--r--servers/rendering/renderer_rd/storage_rd/light_storage.h871
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.cpp706
-rw-r--r--servers/rendering/renderer_rd/storage_rd/material_storage.h433
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp315
-rw-r--r--servers/rendering/renderer_rd/storage_rd/mesh_storage.h435
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.cpp159
-rw-r--r--servers/rendering/renderer_rd/storage_rd/particles_storage.h398
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h48
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp587
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h226
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp252
-rw-r--r--servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h156
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.cpp656
-rw-r--r--servers/rendering/renderer_rd/storage_rd/texture_storage.h620
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.cpp331
-rw-r--r--servers/rendering/renderer_rd/storage_rd/utilities.h124
-rw-r--r--servers/rendering/renderer_rd/uniform_set_cache_rd.h28
-rw-r--r--servers/rendering/renderer_scene_cull.cpp405
-rw-r--r--servers/rendering/renderer_scene_cull.h252
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.cpp2
-rw-r--r--servers/rendering/renderer_scene_occlusion_cull.h9
-rw-r--r--servers/rendering/renderer_scene_render.cpp487
-rw-r--r--servers/rendering/renderer_scene_render.h292
-rw-r--r--servers/rendering/renderer_storage.h240
-rw-r--r--servers/rendering/renderer_viewport.cpp312
-rw-r--r--servers/rendering/renderer_viewport.h86
-rw-r--r--servers/rendering/rendering_device.cpp12
-rw-r--r--servers/rendering/rendering_device.h77
-rw-r--r--servers/rendering/rendering_device_binds.h14
-rw-r--r--servers/rendering/rendering_method.cpp (renamed from servers/rendering/renderer_scene.cpp)8
-rw-r--r--servers/rendering/rendering_method.h (renamed from servers/rendering/renderer_scene.h)180
-rw-r--r--servers/rendering/rendering_server_default.cpp76
-rw-r--r--servers/rendering/rendering_server_default.h125
-rw-r--r--servers/rendering/rendering_server_globals.cpp7
-rw-r--r--servers/rendering/rendering_server_globals.h15
-rw-r--r--servers/rendering/shader_compiler.cpp150
-rw-r--r--servers/rendering/shader_compiler.h3
-rw-r--r--servers/rendering/shader_language.cpp1097
-rw-r--r--servers/rendering/shader_language.h39
-rw-r--r--servers/rendering/shader_preprocessor.cpp1277
-rw-r--r--servers/rendering/shader_preprocessor.h230
-rw-r--r--servers/rendering/shader_types.cpp24
-rw-r--r--servers/rendering/shader_types.h6
-rw-r--r--servers/rendering/shader_warnings.h6
-rw-r--r--servers/rendering/storage/camera_attributes_storage.cpp177
-rw-r--r--servers/rendering/storage/camera_attributes_storage.h129
-rw-r--r--servers/rendering/storage/environment_storage.cpp744
-rw-r--r--servers/rendering/storage/environment_storage.h288
-rw-r--r--servers/rendering/storage/light_storage.h55
-rw-r--r--servers/rendering/storage/material_storage.h41
-rw-r--r--servers/rendering/storage/mesh_storage.h6
-rw-r--r--servers/rendering/storage/particles_storage.h3
-rw-r--r--servers/rendering/storage/render_scene_buffers.cpp51
-rw-r--r--servers/rendering/storage/render_scene_buffers.h60
-rw-r--r--servers/rendering/storage/texture_storage.h49
-rw-r--r--servers/rendering/storage/utilities.cpp (renamed from servers/rendering/renderer_storage.cpp)16
-rw-r--r--servers/rendering/storage/utilities.h188
-rw-r--r--servers/rendering_server.cpp291
-rw-r--r--servers/rendering_server.h139
-rw-r--r--servers/server_wrap_mt_common.h5
-rw-r--r--servers/text/text_server_extension.cpp1341
-rw-r--r--servers/text/text_server_extension.h416
-rw-r--r--servers/text_server.cpp353
-rw-r--r--servers/text_server.h127
-rw-r--r--servers/xr/xr_interface.cpp103
-rw-r--r--servers/xr/xr_interface.h23
-rw-r--r--servers/xr/xr_interface_extension.cpp188
-rw-r--r--servers/xr/xr_interface_extension.h12
-rw-r--r--servers/xr/xr_pose.h2
-rw-r--r--servers/xr_server.cpp12
-rw-r--r--servers/xr_server.h13
342 files changed, 32971 insertions, 19589 deletions
diff --git a/servers/SCsub b/servers/SCsub
index 66a1b9b26f..788a368a4f 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -14,6 +14,8 @@ SConscript("audio/SCsub")
SConscript("text/SCsub")
SConscript("debugger/SCsub")
SConscript("extensions/SCsub")
+SConscript("movie_writer/SCsub")
+SConscript("navigation/SCsub")
lib = env.add_library("servers", env.servers_sources)
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index 635e4601c7..729f278d4b 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -33,22 +33,23 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
+AudioDriverDummy *AudioDriverDummy::singleton = nullptr;
+
Error AudioDriverDummy::init() {
- active = false;
- thread_exited = false;
- exit_thread = false;
+ active.clear();
+ exit_thread.clear();
samples_in = nullptr;
- mix_rate = GLOBAL_GET("audio/driver/mix_rate");
- speaker_mode = SPEAKER_MODE_STEREO;
- channels = 2;
-
- int latency = GLOBAL_GET("audio/driver/output_latency");
- buffer_frames = closest_power_of_2(latency * mix_rate / 1000);
+ if (mix_rate == -1) {
+ mix_rate = GLOBAL_GET("audio/driver/mix_rate");
+ }
+ channels = get_channels();
samples_in = memnew_arr(int32_t, (size_t)buffer_frames * channels);
- thread.start(AudioDriverDummy::thread_func, this);
+ if (use_threads) {
+ thread.start(AudioDriverDummy::thread_func, this);
+ }
return OK;
};
@@ -58,23 +59,23 @@ void AudioDriverDummy::thread_func(void *p_udata) {
uint64_t usdelay = (ad->buffer_frames / float(ad->mix_rate)) * 1000000;
- while (!ad->exit_thread) {
- if (ad->active) {
+ while (!ad->exit_thread.is_set()) {
+ if (ad->active.is_set()) {
ad->lock();
+ ad->start_counting_ticks();
ad->audio_server_process(ad->buffer_frames, ad->samples_in);
+ ad->stop_counting_ticks();
ad->unlock();
};
OS::get_singleton()->delay_usec(usdelay);
};
-
- ad->thread_exited = true;
};
void AudioDriverDummy::start() {
- active = true;
+ active.set();
};
int AudioDriverDummy::get_mix_rate() const {
@@ -93,11 +94,56 @@ void AudioDriverDummy::unlock() {
mutex.unlock();
};
+void AudioDriverDummy::set_use_threads(bool p_use_threads) {
+ use_threads = p_use_threads;
+}
+
+void AudioDriverDummy::set_speaker_mode(SpeakerMode p_mode) {
+ speaker_mode = p_mode;
+}
+
+void AudioDriverDummy::set_mix_rate(int p_rate) {
+ mix_rate = p_rate;
+}
+
+uint32_t AudioDriverDummy::get_channels() const {
+ static const int channels_for_mode[4] = { 2, 4, 8, 16 };
+ return channels_for_mode[speaker_mode];
+}
+
+void AudioDriverDummy::mix_audio(int p_frames, int32_t *p_buffer) {
+ ERR_FAIL_COND(!active.is_set()); // If not active, should not mix.
+ ERR_FAIL_COND(use_threads == true); // If using threads, this will not work well.
+
+ uint32_t todo = p_frames;
+ while (todo) {
+ uint32_t to_mix = MIN(buffer_frames, todo);
+ lock();
+ audio_server_process(to_mix, samples_in);
+ unlock();
+
+ uint32_t total_samples = to_mix * channels;
+
+ for (uint32_t i = 0; i < total_samples; i++) {
+ p_buffer[i] = samples_in[i];
+ }
+
+ todo -= to_mix;
+ p_buffer += total_samples;
+ }
+}
+
void AudioDriverDummy::finish() {
- exit_thread = true;
- thread.wait_to_finish();
+ if (use_threads) {
+ exit_thread.set();
+ thread.wait_to_finish();
+ }
if (samples_in) {
memdelete_arr(samples_in);
};
-};
+}
+
+AudioDriverDummy::AudioDriverDummy() {
+ singleton = this;
+}
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 68b523e086..46dd2e1439 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -35,6 +35,7 @@
#include "core/os/mutex.h"
#include "core/os/thread.h"
+#include "core/templates/safe_refcount.h"
class AudioDriverDummy : public AudioDriver {
Thread thread;
@@ -44,15 +45,18 @@ class AudioDriverDummy : public AudioDriver {
static void thread_func(void *p_udata);
- unsigned int buffer_frames;
- unsigned int mix_rate;
- SpeakerMode speaker_mode;
+ uint32_t buffer_frames = 4096;
+ int32_t mix_rate = -1;
+ SpeakerMode speaker_mode = SPEAKER_MODE_STEREO;
int channels;
- bool active;
- bool thread_exited;
- mutable bool exit_thread;
+ SafeFlag active;
+ SafeFlag exit_thread;
+
+ bool use_threads = true;
+
+ static AudioDriverDummy *singleton;
public:
const char *get_name() const {
@@ -67,8 +71,18 @@ public:
virtual void unlock();
virtual void finish();
- AudioDriverDummy() {}
+ void set_use_threads(bool p_use_threads);
+ void set_speaker_mode(SpeakerMode p_mode);
+ void set_mix_rate(int p_rate);
+
+ uint32_t get_channels() const;
+
+ void mix_audio(int p_frames, int32_t *p_buffer);
+
+ static AudioDriverDummy *get_dummy_singleton() { return singleton; }
+
+ AudioDriverDummy();
~AudioDriverDummy() {}
};
-#endif
+#endif // AUDIO_DRIVER_DUMMY_H
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
index f38d0adfb2..ef0e3197e1 100644
--- a/servers/audio/audio_effect.cpp
+++ b/servers/audio/audio_effect.cpp
@@ -36,11 +36,9 @@ void AudioEffectInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_
}
}
bool AudioEffectInstance::process_silence() const {
- bool ret;
- if (GDVIRTUAL_CALL(_process_silence, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_process_silence, ret);
+ return ret;
}
void AudioEffectInstance::_bind_methods() {
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
index 3a0578679d..653d04595e 100644
--- a/servers/audio/audio_effect.h
+++ b/servers/audio/audio_effect.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECT_H
-#define AUDIOEFFECT_H
+#ifndef AUDIO_EFFECT_H
+#define AUDIO_EFFECT_H
#include "core/io/resource.h"
#include "core/math/audio_frame.h"
@@ -62,4 +62,4 @@ public:
AudioEffect();
};
-#endif // AUDIOEFFECT_H
+#endif // AUDIO_EFFECT_H
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index 0cfba17563..adb0dc32ea 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -57,14 +57,14 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i
uint32_t pos_next = (pos + 1) & rb_mask;
// since this is a template with a known compile time value (C), conditionals go away when compiling.
- if (C == 1) {
+ if constexpr (C == 1) {
float v0 = rb[pos];
float v0n = rb[pos_next];
v0 += (v0n - v0) * frac;
p_dest[i] = AudioFrame(v0, v0);
}
- if (C == 2) {
+ if constexpr (C == 2) {
float v0 = rb[(pos << 1) + 0];
float v1 = rb[(pos << 1) + 1];
float v0n = rb[(pos_next << 1) + 0];
@@ -76,7 +76,7 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i
}
// This will probably never be used, but added anyway
- if (C == 4) {
+ if constexpr (C == 4) {
float v0 = rb[(pos << 2) + 0];
float v1 = rb[(pos << 2) + 1];
float v0n = rb[(pos_next << 2) + 0];
@@ -86,7 +86,7 @@ uint32_t AudioRBResampler::_resample(AudioFrame *p_dest, int p_todo, int32_t p_i
p_dest[i] = AudioFrame(v0, v1);
}
- if (C == 6) {
+ if constexpr (C == 6) {
float v0 = rb[(pos * 6) + 0];
float v1 = rb[(pos * 6) + 1];
float v0n = rb[(pos_next * 6) + 0];
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 8399a92be9..33d4c816f2 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -33,7 +33,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
-void AudioStreamPlayback::start(float p_from_pos) {
+void AudioStreamPlayback::start(double p_from_pos) {
if (GDVIRTUAL_CALL(_start, p_from_pos)) {
return;
}
@@ -54,24 +54,20 @@ bool AudioStreamPlayback::is_playing() const {
}
int AudioStreamPlayback::get_loop_count() const {
- int ret;
- if (GDVIRTUAL_CALL(_get_loop_count, ret)) {
- return ret;
- }
- return 0;
+ int ret = 0;
+ GDVIRTUAL_CALL(_get_loop_count, ret);
+ return ret;
}
-float AudioStreamPlayback::get_playback_position() const {
- float ret;
+double AudioStreamPlayback::get_playback_position() const {
+ double ret;
if (GDVIRTUAL_CALL(_get_playback_position, ret)) {
return ret;
}
ERR_FAIL_V_MSG(0, "AudioStreamPlayback::get_playback_position unimplemented!");
}
-void AudioStreamPlayback::seek(float p_time) {
- if (GDVIRTUAL_CALL(_seek, p_time)) {
- return;
- }
+void AudioStreamPlayback::seek(double p_time) {
+ GDVIRTUAL_CALL(_seek, p_time);
}
int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
@@ -83,6 +79,10 @@ int AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_fra
return 0;
}
+void AudioStreamPlayback::tag_used_streams() {
+ GDVIRTUAL_CALL(_tag_used_streams);
+}
+
void AudioStreamPlayback::_bind_methods() {
GDVIRTUAL_BIND(_start, "from_pos")
GDVIRTUAL_BIND(_stop)
@@ -91,6 +91,7 @@ void AudioStreamPlayback::_bind_methods() {
GDVIRTUAL_BIND(_get_playback_position)
GDVIRTUAL_BIND(_seek, "position")
GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames");
+ GDVIRTUAL_BIND(_tag_used_streams);
}
//////////////////////////////
@@ -135,9 +136,10 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
uint64_t mix_increment = uint64_t(((get_stream_sampling_rate() * p_rate_scale * playback_speed_scale) / double(target_rate)) * double(FP_LEN));
- int mixed_frames_total = p_frames;
+ int mixed_frames_total = -1;
- for (int i = 0; i < p_frames; i++) {
+ int i;
+ for (i = 0; i < p_frames; i++) {
uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS);
//standard cubic interpolation (great quality/performance ratio)
//this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory.
@@ -147,7 +149,7 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
AudioFrame y2 = internal_buffer[idx - 1];
AudioFrame y3 = internal_buffer[idx - 0];
- if (idx <= internal_buffer_end && idx >= internal_buffer_end && mixed_frames_total == p_frames) {
+ if (idx >= internal_buffer_end && mixed_frames_total == -1) {
// The internal buffer ends somewhere in this range, and we haven't yet recorded the number of good frames we have.
mixed_frames_total = i;
}
@@ -167,73 +169,110 @@ int AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
internal_buffer[1] = internal_buffer[INTERNAL_BUFFER_LEN + 1];
internal_buffer[2] = internal_buffer[INTERNAL_BUFFER_LEN + 2];
internal_buffer[3] = internal_buffer[INTERNAL_BUFFER_LEN + 3];
- if (is_playing()) {
- int mixed_frames = _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
- if (mixed_frames != INTERNAL_BUFFER_LEN) {
- // internal_buffer[mixed_frames] is the first frame of silence.
- internal_buffer_end = mixed_frames;
- } else {
- // The internal buffer does not contain the first frame of silence.
- internal_buffer_end = -1;
- }
+ int mixed_frames = _mix_internal(internal_buffer + 4, INTERNAL_BUFFER_LEN);
+ if (mixed_frames != INTERNAL_BUFFER_LEN) {
+ // internal_buffer[mixed_frames] is the first frame of silence.
+ internal_buffer_end = mixed_frames;
} else {
- //fill with silence, not playing
- for (int j = 0; j < INTERNAL_BUFFER_LEN; ++j) {
- internal_buffer[j + 4] = AudioFrame(0, 0);
- }
+ // The internal buffer does not contain the first frame of silence.
+ internal_buffer_end = -1;
}
mix_offset -= (INTERNAL_BUFFER_LEN << FP_BITS);
}
}
+ if (mixed_frames_total == -1 && i == p_frames) {
+ mixed_frames_total = p_frames;
+ }
return mixed_frames_total;
}
////////////////////////////////
-Ref<AudioStreamPlayback> AudioStream::instance_playback() {
+Ref<AudioStreamPlayback> AudioStream::instantiate_playback() {
Ref<AudioStreamPlayback> ret;
- if (GDVIRTUAL_CALL(_instance_playback, ret)) {
+ if (GDVIRTUAL_CALL(_instantiate_playback, ret)) {
return ret;
}
ERR_FAIL_V_MSG(Ref<AudioStreamPlayback>(), "Method must be implemented!");
}
String AudioStream::get_stream_name() const {
String ret;
- if (GDVIRTUAL_CALL(_get_stream_name, ret)) {
- return ret;
- }
- return String();
+ GDVIRTUAL_CALL(_get_stream_name, ret);
+ return ret;
}
-float AudioStream::get_length() const {
- float ret;
- if (GDVIRTUAL_CALL(_get_length, ret)) {
- return ret;
- }
- return 0;
+double AudioStream::get_length() const {
+ double ret = 0;
+ GDVIRTUAL_CALL(_get_length, ret);
+ return ret;
}
bool AudioStream::is_monophonic() const {
- bool ret;
- if (GDVIRTUAL_CALL(_is_monophonic, ret)) {
- return ret;
+ bool ret = true;
+ GDVIRTUAL_CALL(_is_monophonic, ret);
+ return ret;
+}
+
+double AudioStream::get_bpm() const {
+ double ret = 0;
+ GDVIRTUAL_CALL(_get_bpm, ret);
+ return ret;
+}
+
+bool AudioStream::has_loop() const {
+ bool ret = 0;
+ GDVIRTUAL_CALL(_has_loop, ret);
+ return ret;
+}
+
+int AudioStream::get_bar_beats() const {
+ int ret = 0;
+ GDVIRTUAL_CALL(_get_bar_beats, ret);
+ return ret;
+}
+
+int AudioStream::get_beat_count() const {
+ int ret = 0;
+ GDVIRTUAL_CALL(_get_beat_count, ret);
+ return ret;
+}
+
+void AudioStream::tag_used(float p_offset) {
+ if (tagged_frame != AudioServer::get_singleton()->get_mixed_frames()) {
+ offset_count = 0;
+ tagged_frame = AudioServer::get_singleton()->get_mixed_frames();
}
- return true;
+ if (offset_count < MAX_TAGGED_OFFSETS) {
+ tagged_offsets[offset_count++] = p_offset;
+ }
+}
+
+uint64_t AudioStream::get_tagged_frame() const {
+ return tagged_frame;
+}
+uint32_t AudioStream::get_tagged_frame_count() const {
+ return offset_count;
+}
+float AudioStream::get_tagged_frame_offset(int p_index) const {
+ ERR_FAIL_INDEX_V(p_index, MAX_TAGGED_OFFSETS, 0);
+ return tagged_offsets[p_index];
}
void AudioStream::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length);
ClassDB::bind_method(D_METHOD("is_monophonic"), &AudioStream::is_monophonic);
- ClassDB::bind_method(D_METHOD("instance_playback"), &AudioStream::instance_playback);
- GDVIRTUAL_BIND(_instance_playback);
+ ClassDB::bind_method(D_METHOD("instantiate_playback"), &AudioStream::instantiate_playback);
+ GDVIRTUAL_BIND(_instantiate_playback);
GDVIRTUAL_BIND(_get_stream_name);
GDVIRTUAL_BIND(_get_length);
GDVIRTUAL_BIND(_is_monophonic);
+ GDVIRTUAL_BIND(_get_bpm)
+ GDVIRTUAL_BIND(_get_beat_count)
}
////////////////////////////////
-Ref<AudioStreamPlayback> AudioStreamMicrophone::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamMicrophone::instantiate_playback() {
Ref<AudioStreamPlaybackMicrophone> playback;
playback.instantiate();
@@ -252,7 +291,7 @@ String AudioStreamMicrophone::get_stream_name() const {
return "Microphone";
}
-float AudioStreamMicrophone::get_length() const {
+double AudioStreamMicrophone::get_length() const {
return 0;
}
@@ -325,7 +364,7 @@ float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
return AudioDriver::get_singleton()->get_mix_rate();
}
-void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
+void AudioStreamPlaybackMicrophone::start(double p_from_pos) {
if (active) {
return;
}
@@ -358,14 +397,18 @@ int AudioStreamPlaybackMicrophone::get_loop_count() const {
return 0;
}
-float AudioStreamPlaybackMicrophone::get_playback_position() const {
+double AudioStreamPlaybackMicrophone::get_playback_position() const {
return 0;
}
-void AudioStreamPlaybackMicrophone::seek(float p_time) {
+void AudioStreamPlaybackMicrophone::seek(double p_time) {
// Can't seek a microphone input
}
+void AudioStreamPlaybackMicrophone::tag_used_streams() {
+ microphone->tag_used(0);
+}
+
AudioStreamPlaybackMicrophone::~AudioStreamPlaybackMicrophone() {
microphone->playbacks.erase(this);
stop();
@@ -493,7 +536,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() {
for (PoolEntry &entry : local_pool) {
cumulative_weight += entry.weight;
if (cumulative_weight > chosen_cumulative_weight) {
- playback->playback = entry.stream->instance_playback();
+ playback->playback = entry.stream->instantiate_playback();
last_playback = entry.stream;
break;
}
@@ -501,7 +544,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_random() {
if (playback->playback.is_null()) {
// This indicates a floating point error. Take the last element.
last_playback = local_pool[local_pool.size() - 1].stream;
- playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback();
+ playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback();
}
return playback;
}
@@ -535,14 +578,14 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_no_repeats() {
cumulative_weight += entry.weight;
if (cumulative_weight > chosen_cumulative_weight) {
last_playback = entry.stream;
- playback->playback = entry.stream->instance_playback();
+ playback->playback = entry.stream->instantiate_playback();
break;
}
}
if (playback->playback.is_null()) {
// This indicates a floating point error. Take the last element.
last_playback = local_pool[local_pool.size() - 1].stream;
- playback->playback = local_pool.write[local_pool.size() - 1].stream->instance_playback();
+ playback->playback = local_pool.write[local_pool.size() - 1].stream->instantiate_playback();
}
return playback;
}
@@ -571,7 +614,7 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() {
for (Ref<AudioStream> &entry : local_pool) {
if (found_last_stream) {
last_playback = entry;
- playback->playback = entry->instance_playback();
+ playback->playback = entry->instantiate_playback();
break;
}
if (entry == last_playback) {
@@ -581,12 +624,12 @@ Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback_sequential() {
if (playback->playback.is_null()) {
// Wrap around
last_playback = local_pool[0];
- playback->playback = local_pool.write[0]->instance_playback();
+ playback->playback = local_pool.write[0]->instantiate_playback();
}
return playback;
}
-Ref<AudioStreamPlayback> AudioStreamRandomizer::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamRandomizer::instantiate_playback() {
switch (playback_mode) {
case PLAYBACK_RANDOM:
return instance_playback_random();
@@ -603,7 +646,7 @@ String AudioStreamRandomizer::get_stream_name() const {
return "Randomizer";
}
-float AudioStreamRandomizer::get_length() const {
+double AudioStreamRandomizer::get_length() const {
return 0;
}
@@ -699,7 +742,7 @@ void AudioStreamRandomizer::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "streams_count", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR), "set_streams_count", "get_streams_count");
ADD_PROPERTY(PropertyInfo(Variant::INT, "playback_mode", PROPERTY_HINT_ENUM, "Random (Avoid Repeats),Random,Sequential"), "set_playback_mode", "get_playback_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_pitch", PROPERTY_HINT_RANGE, "1,16,0.01"), "set_random_pitch", "get_random_pitch");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0"), "set_random_volume_offset_db", "get_random_volume_offset_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "random_volume_offset_db", PROPERTY_HINT_RANGE, "0,40,0.01,suffix:dB"), "set_random_volume_offset_db", "get_random_volume_offset_db");
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM_NO_REPEATS);
BIND_ENUM_CONSTANT(PLAYBACK_RANDOM);
@@ -708,7 +751,7 @@ void AudioStreamRandomizer::_bind_methods() {
AudioStreamRandomizer::AudioStreamRandomizer() {}
-void AudioStreamPlaybackRandomizer::start(float p_from_pos) {
+void AudioStreamPlaybackRandomizer::start(double p_from_pos) {
playing = playback;
{
float range_from = 1.0 / randomizer->random_pitch_scale;
@@ -721,7 +764,7 @@ void AudioStreamPlaybackRandomizer::start(float p_from_pos) {
float range_to = randomizer->random_volume_offset_db;
float volume_offset_db = range_from + Math::randf() * (range_to - range_from);
- volume_scale = Math::db2linear(volume_offset_db);
+ volume_scale = Math::db_to_linear(volume_offset_db);
}
if (playing.is_valid()) {
@@ -751,7 +794,7 @@ int AudioStreamPlaybackRandomizer::get_loop_count() const {
return 0;
}
-float AudioStreamPlaybackRandomizer::get_playback_position() const {
+double AudioStreamPlaybackRandomizer::get_playback_position() const {
if (playing.is_valid()) {
return playing->get_playback_position();
}
@@ -759,12 +802,20 @@ float AudioStreamPlaybackRandomizer::get_playback_position() const {
return 0;
}
-void AudioStreamPlaybackRandomizer::seek(float p_time) {
+void AudioStreamPlaybackRandomizer::seek(double p_time) {
if (playing.is_valid()) {
playing->seek(p_time);
}
}
+void AudioStreamPlaybackRandomizer::tag_used_streams() {
+ Ref<AudioStreamPlayback> p = playing; // Thread safety
+ if (p.is_valid()) {
+ p->tag_used_streams();
+ }
+ randomizer->tag_used(0);
+}
+
int AudioStreamPlaybackRandomizer::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
if (playing.is_valid()) {
return playing->mix(p_buffer, p_rate_scale * pitch_scale, p_frames);
diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h
index bf200e7ecf..c41475010c 100644
--- a/servers/audio/audio_stream.h
+++ b/servers/audio/audio_stream.h
@@ -40,27 +40,32 @@
#include "core/object/script_language.h"
#include "core/variant/native_ptr.h"
+class AudioStream;
+
class AudioStreamPlayback : public RefCounted {
GDCLASS(AudioStreamPlayback, RefCounted);
protected:
static void _bind_methods();
- GDVIRTUAL1(_start, float)
+ GDVIRTUAL1(_start, double)
GDVIRTUAL0(_stop)
GDVIRTUAL0RC(bool, _is_playing)
GDVIRTUAL0RC(int, _get_loop_count)
- GDVIRTUAL0RC(float, _get_playback_position)
- GDVIRTUAL1(_seek, float)
+ GDVIRTUAL0RC(double, _get_playback_position)
+ GDVIRTUAL1(_seek, double)
GDVIRTUAL3R(int, _mix, GDNativePtr<AudioFrame>, float, int)
+ GDVIRTUAL0(_tag_used_streams)
public:
- virtual void start(float p_from_pos = 0.0);
+ virtual void start(double p_from_pos = 0.0);
virtual void stop();
virtual bool is_playing() const;
virtual int get_loop_count() const; //times it looped
- virtual float get_playback_position() const;
- virtual void seek(float p_time);
+ virtual double get_playback_position() const;
+ virtual void seek(double p_time);
+
+ virtual void tag_used_streams();
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
};
@@ -72,7 +77,7 @@ class AudioStreamPlaybackResampled : public AudioStreamPlayback {
FP_BITS = 16, //fixed point used for resampling
FP_LEN = (1 << FP_BITS),
FP_MASK = FP_LEN - 1,
- INTERNAL_BUFFER_LEN = 256,
+ INTERNAL_BUFFER_LEN = 128, // 128 warrants 3ms positional jitter at much at 44100hz
CUBIC_INTERP_HISTORY = 4
};
@@ -101,20 +106,42 @@ class AudioStream : public Resource {
GDCLASS(AudioStream, Resource);
OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged.
+ enum {
+ MAX_TAGGED_OFFSETS = 8
+ };
+
+ uint64_t tagged_frame = 0;
+ uint64_t offset_count = 0;
+ float tagged_offsets[MAX_TAGGED_OFFSETS];
+
protected:
static void _bind_methods();
- GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instance_playback)
+ GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instantiate_playback)
GDVIRTUAL0RC(String, _get_stream_name)
- GDVIRTUAL0RC(float, _get_length)
+ GDVIRTUAL0RC(double, _get_length)
GDVIRTUAL0RC(bool, _is_monophonic)
+ GDVIRTUAL0RC(double, _get_bpm)
+ GDVIRTUAL0RC(bool, _has_loop)
+ GDVIRTUAL0RC(int, _get_bar_beats)
+ GDVIRTUAL0RC(int, _get_beat_count)
public:
- virtual Ref<AudioStreamPlayback> instance_playback();
+ virtual Ref<AudioStreamPlayback> instantiate_playback();
virtual String get_stream_name() const;
- virtual float get_length() const;
+ virtual double get_bpm() const;
+ virtual bool has_loop() const;
+ virtual int get_bar_beats() const;
+ virtual int get_beat_count() const;
+
+ virtual double get_length() const;
virtual bool is_monophonic() const;
+
+ void tag_used(float p_offset);
+ uint64_t get_tagged_frame() const;
+ uint32_t get_tagged_frame_count() const;
+ float get_tagged_frame_offset(int p_index) const;
};
// Microphone
@@ -131,10 +158,10 @@ protected:
static void _bind_methods();
public:
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
- virtual float get_length() const override; //if supported, otherwise return 0
+ virtual double get_length() const override; //if supported, otherwise return 0
virtual bool is_monophonic() const override;
@@ -153,18 +180,20 @@ class AudioStreamPlaybackMicrophone : public AudioStreamPlaybackResampled {
protected:
virtual int _mix_internal(AudioFrame *p_buffer, int p_frames) override;
virtual float get_stream_sampling_rate() override;
+ virtual double get_playback_position() const override;
public:
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
- virtual void start(float p_from_pos = 0.0) override;
+ virtual void start(double p_from_pos = 0.0) override;
virtual void stop() override;
virtual bool is_playing() const override;
virtual int get_loop_count() const override; //times it looped
- virtual float get_playback_position() const override;
- virtual void seek(float p_time) override;
+ virtual void seek(double p_time) override;
+
+ virtual void tag_used_streams() override;
~AudioStreamPlaybackMicrophone();
AudioStreamPlaybackMicrophone();
@@ -233,10 +262,10 @@ public:
void set_playback_mode(PlaybackMode p_playback_mode);
PlaybackMode get_playback_mode() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
- virtual float get_length() const override; //if supported, otherwise return 0
+ virtual double get_length() const override; //if supported, otherwise return 0
virtual bool is_monophonic() const override;
AudioStreamRandomizer();
@@ -254,17 +283,19 @@ class AudioStreamPlaybackRandomizer : public AudioStreamPlayback {
float volume_scale;
public:
- virtual void start(float p_from_pos = 0.0) override;
+ virtual void start(double p_from_pos = 0.0) override;
virtual void stop() override;
virtual bool is_playing() const override;
virtual int get_loop_count() const override; //times it looped
- virtual float get_playback_position() const override;
- virtual void seek(float p_time) override;
+ virtual double get_playback_position() const override;
+ virtual void seek(double p_time) override;
virtual int mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) override;
+ virtual void tag_used_streams() override;
+
~AudioStreamPlaybackRandomizer();
};
diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp
index 87d46f8bbe..2889562173 100644
--- a/servers/audio/effects/audio_effect_amplify.cpp
+++ b/servers/audio/effects/audio_effect_amplify.cpp
@@ -33,8 +33,8 @@
void AudioEffectAmplifyInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
//multiply volume interpolating to avoid clicks if this changes
float volume_db = base->volume_db;
- float vol = Math::db2linear(mix_volume_db);
- float vol_inc = (Math::db2linear(volume_db) - vol) / float(p_frame_count);
+ float vol = Math::db_to_linear(mix_volume_db);
+ float vol_inc = (Math::db_to_linear(volume_db) - vol) / float(p_frame_count);
for (int i = 0; i < p_frame_count; i++) {
p_dst_frames[i] = p_src_frames[i] * vol;
diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h
index bd0fcaa94d..fd424cbe9a 100644
--- a/servers/audio/effects/audio_effect_amplify.h
+++ b/servers/audio/effects/audio_effect_amplify.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTAMPLIFY_H
-#define AUDIOEFFECTAMPLIFY_H
+#ifndef AUDIO_EFFECT_AMPLIFY_H
+#define AUDIO_EFFECT_AMPLIFY_H
#include "servers/audio/audio_effect.h"
@@ -63,4 +63,4 @@ public:
AudioEffectAmplify();
};
-#endif // AUDIOEFFECTAMPLIFY_H
+#endif // AUDIO_EFFECT_AMPLIFY_H
diff --git a/servers/audio/effects/audio_effect_capture.cpp b/servers/audio/effects/audio_effect_capture.cpp
index f605cfc9d4..1f5f5e259a 100644
--- a/servers/audio/effects/audio_effect_capture.cpp
+++ b/servers/audio/effects/audio_effect_capture.cpp
@@ -70,7 +70,7 @@ void AudioEffectCapture::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_buffer_length_frames"), &AudioEffectCapture::get_buffer_length_frames);
ClassDB::bind_method(D_METHOD("get_pushed_frames"), &AudioEffectCapture::get_pushed_frames);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_buffer_length", "get_buffer_length");
}
Ref<AudioEffectInstance> AudioEffectCapture::instantiate() {
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
index 8b1fe9cfd2..69b416f5f7 100644
--- a/servers/audio/effects/audio_effect_chorus.cpp
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -95,7 +95,7 @@ void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, A
//vol modifier
- AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db2linear(v.level);
+ AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db_to_linear(v.level);
vol_modifier.l *= CLAMP(1.0 - v.pan, 0, 1);
vol_modifier.r *= CLAMP(1.0 + v.pan, 0, 1);
@@ -272,11 +272,11 @@ float AudioEffectChorus::get_dry() const {
return dry;
}
-void AudioEffectChorus::_validate_property(PropertyInfo &property) const {
- if (property.name.begins_with("voice/")) {
- int voice_idx = property.name.get_slice("/", 1).to_int();
+void AudioEffectChorus::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name.begins_with("voice/")) {
+ int voice_idx = p_property.name.get_slice("/", 1).to_int();
if (voice_idx > voice_count) {
- property.usage = PROPERTY_USAGE_NONE;
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
}
@@ -313,32 +313,32 @@ void AudioEffectChorus::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wet", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_wet", "get_wet");
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 0);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 0);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 0);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 1);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 1);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 1);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 2);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 2);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/3/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 2);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_voice_delay_ms", "get_voice_delay_ms", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1"), "set_voice_rate_hz", "get_voice_rate_hz", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01"), "set_voice_depth_ms", "get_voice_depth_ms", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1"), "set_voice_level_db", "get_voice_level_db", 3);
- ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/delay_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_voice_delay_ms", "get_voice_delay_ms", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/rate_hz", PROPERTY_HINT_RANGE, "0.1,20,0.1,suffix:Hz"), "set_voice_rate_hz", "get_voice_rate_hz", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/depth_ms", PROPERTY_HINT_RANGE, "0,20,0.01,suffix:ms"), "set_voice_depth_ms", "get_voice_depth_ms", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/level_db", PROPERTY_HINT_RANGE, "-60,24,0.1,suffix:dB"), "set_voice_level_db", "get_voice_level_db", 3);
+ ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_voice_cutoff_hz", "get_voice_cutoff_hz", 3);
ADD_PROPERTYI(PropertyInfo(Variant::FLOAT, "voice/4/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_voice_pan", "get_voice_pan", 3);
}
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
index 19035222c5..dd4b431e7a 100644
--- a/servers/audio/effects/audio_effect_chorus.h
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTCHORUS_H
-#define AUDIOEFFECTCHORUS_H
+#ifndef AUDIO_EFFECT_CHORUS_H
+#define AUDIO_EFFECT_CHORUS_H
#include "servers/audio/audio_effect.h"
@@ -96,7 +96,7 @@ private:
float dry;
protected:
- void _validate_property(PropertyInfo &property) const override;
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
@@ -133,4 +133,4 @@ public:
AudioEffectChorus();
};
-#endif // AUDIOEFFECTCHORUS_H
+#endif // AUDIO_EFFECT_CHORUS_H
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
index f75d092dd3..43b210e450 100644
--- a/servers/audio/effects/audio_effect_compressor.cpp
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -32,7 +32,7 @@
#include "servers/audio_server.h"
void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
- float threshold = Math::db2linear(base->threshold);
+ float threshold = Math::db_to_linear(base->threshold);
float sample_rate = AudioServer::get_singleton()->get_mix_rate();
float ratatcoef = exp(-1 / (0.00001f * sample_rate));
@@ -42,7 +42,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi
float atcoef = exp(-1 / (attime * sample_rate));
float relcoef = exp(-1 / (reltime * sample_rate));
- float makeup = Math::db2linear(base->gain);
+ float makeup = Math::db_to_linear(base->gain);
float mix = base->mix;
float gr_meter_decay = exp(1 / (1 * sample_rate));
@@ -64,7 +64,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi
float peak = MAX(s.l, s.r);
- float overdb = 2.08136898f * Math::linear2db(peak / threshold);
+ float overdb = 2.08136898f * Math::linear_to_db(peak / threshold);
if (overdb < 0.0) { //we only care about what goes over to compress
overdb = 0.0;
@@ -94,7 +94,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi
}
float gr = -overdb * (cratio - 1) / cratio;
- float grv = Math::db2linear(gr);
+ float grv = Math::db_to_linear(gr);
runmax = maxover + relcoef * (runmax - maxover); // highest peak for setting att/rel decays in reltime
maxover = runmax;
@@ -184,15 +184,15 @@ StringName AudioEffectCompressor::get_sidechain() const {
return sidechain;
}
-void AudioEffectCompressor::_validate_property(PropertyInfo &property) const {
- if (property.name == "sidechain") {
+void AudioEffectCompressor::_validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "sidechain") {
String buses = "";
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
buses += ",";
buses += AudioServer::get_singleton()->get_bus_name(i);
}
- property.hint_string = buses;
+ p_property.hint_string = buses;
}
}
@@ -221,8 +221,8 @@ void AudioEffectCompressor::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold", PROPERTY_HINT_RANGE, "-60,0,0.1"), "set_threshold", "get_threshold");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ratio", PROPERTY_HINT_RANGE, "1,48,0.1"), "set_ratio", "get_ratio");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gain", PROPERTY_HINT_RANGE, "-20,20,0.1"), "set_gain", "get_gain");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attack_us", PROPERTY_HINT_RANGE, "20,2000,1"), "set_attack_us", "get_attack_us");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1"), "set_release_ms", "get_release_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "attack_us", PROPERTY_HINT_RANGE, U"20,2000,1,suffix:\u00B5s"), "set_attack_us", "get_attack_us");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "release_ms", PROPERTY_HINT_RANGE, "20,2000,1,suffix:ms"), "set_release_ms", "get_release_ms");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_mix", "get_mix");
ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "sidechain", PROPERTY_HINT_ENUM), "set_sidechain", "get_sidechain");
}
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
index 53c448e5db..886255b958 100644
--- a/servers/audio/effects/audio_effect_compressor.h
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTCOMPRESSOR_H
-#define AUDIOEFFECTCOMPRESSOR_H
+#ifndef AUDIO_EFFECT_COMPRESSOR_H
+#define AUDIO_EFFECT_COMPRESSOR_H
#include "servers/audio/audio_effect.h"
@@ -61,7 +61,7 @@ class AudioEffectCompressor : public AudioEffect {
StringName sidechain;
protected:
- void _validate_property(PropertyInfo &property) const override;
+ void _validate_property(PropertyInfo &p_property) const;
static void _bind_methods();
public:
@@ -91,4 +91,4 @@ public:
AudioEffectCompressor();
};
-#endif // AUDIOEFFECTCOMPRESSOR_H
+#endif // AUDIO_EFFECT_COMPRESSOR_H
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
index 1909ab6eae..69c62e3a13 100644
--- a/servers/audio/effects/audio_effect_delay.cpp
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "audio_effect_delay.h"
+
#include "core/math/math_funcs.h"
#include "servers/audio_server.h"
@@ -52,13 +53,13 @@ void AudioEffectDelayInstance::_process_chunk(const AudioFrame *p_src_frames, Au
float mix_rate = AudioServer::get_singleton()->get_mix_rate();
- float tap_1_level_f = base->tap_1_active ? Math::db2linear(base->tap_1_level) : 0.0;
+ float tap_1_level_f = base->tap_1_active ? Math::db_to_linear(base->tap_1_level) : 0.0;
int tap_1_delay_frames = int((base->tap_1_delay_ms / 1000.0) * mix_rate);
- float tap_2_level_f = base->tap_2_active ? Math::db2linear(base->tap_2_level) : 0.0;
+ float tap_2_level_f = base->tap_2_active ? Math::db_to_linear(base->tap_2_level) : 0.0;
int tap_2_delay_frames = int((base->tap_2_delay_ms / 1000.0) * mix_rate);
- float feedback_level_f = base->feedback_active ? Math::db2linear(base->feedback_level) : 0.0;
+ float feedback_level_f = base->feedback_active ? Math::db_to_linear(base->feedback_level) : 0.0;
unsigned int feedback_delay_frames = int((base->feedback_delay_ms / 1000.0) * mix_rate);
AudioFrame tap1_vol = AudioFrame(tap_1_level_f, tap_1_level_f);
@@ -93,7 +94,7 @@ void AudioEffectDelayInstance::_process_chunk(const AudioFrame *p_src_frames, Au
//apply lowpass and feedback gain
AudioFrame fb_in = out * feedback_level_f * lpf_ic + h * lpf_c;
- fb_in.undenormalise(); //avoid denormals
+ fb_in.undenormalize(); //avoid denormals
h = fb_in;
fb_buf[feedback_buffer_pos] = fb_in;
@@ -286,37 +287,21 @@ void AudioEffectDelay::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "dry", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_dry", "get_dry");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap1/active"), "set_tap1_active", "is_tap1_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_tap1_delay_ms", "get_tap1_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_tap1_level_db", "get_tap1_level_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap1_pan", "get_tap1_pan");
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap2/active"), "set_tap2_active", "is_tap2_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_tap2_delay_ms", "get_tap2_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_tap2_level_db", "get_tap2_level_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2/pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap2_pan", "get_tap2_pan");
-
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feedback/active"), "set_feedback_active", "is_feedback_active");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/delay_ms", PROPERTY_HINT_RANGE, "0,1500,1"), "set_feedback_delay_ms", "get_feedback_delay_ms");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/level_db", PROPERTY_HINT_RANGE, "-60,0,0.01"), "set_feedback_level_db", "get_feedback_level_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback/lowpass", PROPERTY_HINT_RANGE, "1,16000,1"), "set_feedback_lowpass", "get_feedback_lowpass");
-}
-
-AudioEffectDelay::AudioEffectDelay() {
- tap_1_active = true;
- tap_1_delay_ms = 250;
- tap_1_level = -6;
- tap_1_pan = 0.2;
-
- tap_2_active = true;
- tap_2_delay_ms = 500;
- tap_2_level = -12;
- tap_2_pan = -0.4;
-
- feedback_active = false;
- feedback_delay_ms = 340;
- feedback_level = -6;
- feedback_lowpass = 16000;
-
- dry = 1.0;
+ ADD_GROUP("Tap 1", "tap1_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap1_active"), "set_tap1_active", "is_tap1_active");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1_delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap1_delay_ms", "get_tap1_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1_level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap1_level_db", "get_tap1_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap1_pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap1_pan", "get_tap1_pan");
+
+ ADD_GROUP("Tap 2", "tap2_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tap2_active"), "set_tap2_active", "is_tap2_active");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2_delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_tap2_delay_ms", "get_tap2_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2_level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_tap2_level_db", "get_tap2_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap2_pan", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_tap2_pan", "get_tap2_pan");
+
+ ADD_GROUP("Feedback", "feedback_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "feedback_active"), "set_feedback_active", "is_feedback_active");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback_delay_ms", PROPERTY_HINT_RANGE, "0,1500,1,suffix:ms"), "set_feedback_delay_ms", "get_feedback_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback_level_db", PROPERTY_HINT_RANGE, "-60,0,0.01,suffix:dB"), "set_feedback_level_db", "get_feedback_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback_lowpass", PROPERTY_HINT_RANGE, "1,16000,1"), "set_feedback_lowpass", "get_feedback_lowpass");
}
diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h
index 5cc6d72c99..020d45e79b 100644
--- a/servers/audio/effects/audio_effect_delay.h
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTDELAY_H
-#define AUDIOEFFECTDELAY_H
+#ifndef AUDIO_EFFECT_DELAY_H
+#define AUDIO_EFFECT_DELAY_H
#include "servers/audio/audio_effect.h"
@@ -37,6 +37,7 @@ class AudioEffectDelay;
class AudioEffectDelayInstance : public AudioEffectInstance {
GDCLASS(AudioEffectDelayInstance, AudioEffectInstance);
+
friend class AudioEffectDelay;
Ref<AudioEffectDelay> base;
@@ -66,22 +67,22 @@ class AudioEffectDelay : public AudioEffect {
MAX_TAPS = 2
};
- float dry;
+ float dry = 1.0f;
- bool tap_1_active;
- float tap_1_delay_ms;
- float tap_1_level;
- float tap_1_pan;
+ bool tap_1_active = true;
+ float tap_1_delay_ms = 250.0f;
+ float tap_1_level = -6.0f;
+ float tap_1_pan = 0.2f;
- bool tap_2_active;
- float tap_2_delay_ms;
- float tap_2_level;
- float tap_2_pan;
+ bool tap_2_active = true;
+ float tap_2_delay_ms = 500.0f;
+ float tap_2_level = -12.0f;
+ float tap_2_pan = -0.4f;
- bool feedback_active;
- float feedback_delay_ms;
- float feedback_level;
- float feedback_lowpass;
+ bool feedback_active = false;
+ float feedback_delay_ms = 340.0f;
+ float feedback_level = -6.0f;
+ float feedback_lowpass = 16000.0f;
protected:
static void _bind_methods();
@@ -128,7 +129,7 @@ public:
Ref<AudioEffectInstance> instantiate() override;
- AudioEffectDelay();
+ AudioEffectDelay() {}
};
-#endif // AUDIOEFFECTDELAY_H
+#endif // AUDIO_EFFECT_DELAY_H
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
index afc4353bd7..95156d8d66 100644
--- a/servers/audio/effects/audio_effect_distortion.cpp
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -41,8 +41,8 @@ void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames, Audi
float lpf_ic = 1.0 - lpf_c;
float drive_f = base->drive;
- float pregain_f = Math::db2linear(base->pre_gain);
- float postgain_f = Math::db2linear(base->post_gain);
+ float pregain_f = Math::db_to_linear(base->pre_gain);
+ float postgain_f = Math::db_to_linear(base->post_gain);
float atan_mult = pow(10, drive_f * drive_f * 3.0) - 1.0 + 0.001;
float atan_div = 1.0 / (atanf(atan_mult) * (1.0 + drive_f * 8));
@@ -50,7 +50,7 @@ void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames, Audi
float lofi_mult = powf(2.0, 2.0 + (1.0 - drive_f) * 14); //goes from 16 to 2 bits
for (int i = 0; i < p_frame_count * 2; i++) {
- float out = undenormalise(src[i] * lpf_ic + lpf_c * h[i & 1]);
+ float out = undenormalize(src[i] * lpf_ic + lpf_c * h[i & 1]);
h[i & 1] = out;
float a = out;
float ha = src[i] - out; //high freqs
@@ -161,7 +161,7 @@ void AudioEffectDistortion::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Clip,ATan,LoFi,Overdrive,Wave Shape"), "set_mode", "get_mode");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pre_gain", PROPERTY_HINT_RANGE, "-60,60,0.01"), "set_pre_gain", "get_pre_gain");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_keep_hf_hz", "get_keep_hf_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "keep_hf_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_keep_hf_hz", "get_keep_hf_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "drive", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drive", "get_drive");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "post_gain", PROPERTY_HINT_RANGE, "-80,24,0.01"), "set_post_gain", "get_post_gain");
diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h
index 487babbdda..c845a0e53c 100644
--- a/servers/audio/effects/audio_effect_distortion.h
+++ b/servers/audio/effects/audio_effect_distortion.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTDISTORTION_H
-#define AUDIOEFFECTDISTORTION_H
+#ifndef AUDIO_EFFECT_DISTORTION_H
+#define AUDIO_EFFECT_DISTORTION_H
#include "servers/audio/audio_effect.h"
@@ -90,4 +90,4 @@ public:
VARIANT_ENUM_CAST(AudioEffectDistortion::Mode)
-#endif // AUDIOEFFECTDISTORTION_H
+#endif // AUDIO_EFFECT_DISTORTION_H
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
index b7c373479a..8a71ef0be7 100644
--- a/servers/audio/effects/audio_effect_eq.cpp
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "audio_effect_eq.h"
+
#include "servers/audio_server.h"
void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
@@ -37,7 +38,7 @@ void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame *
EQ::BandProcess *proc_r = bands[1].ptrw();
float *bgain = gains.ptrw();
for (int i = 0; i < band_count; i++) {
- bgain[i] = Math::db2linear(base->gain[i]);
+ bgain[i] = Math::db_to_linear(base->gain[i]);
}
for (int i = 0; i < p_frame_count; i++) {
@@ -127,8 +128,8 @@ AudioEffectEQ::AudioEffectEQ(EQ::Preset p_preset) {
gain.resize(eq.get_band_count());
for (int i = 0; i < gain.size(); i++) {
gain.write[i] = 0.0;
- String name = "band_db/" + itos(eq.get_band_frequency(i)) + "_hz";
- prop_band_map[name] = i;
- band_names.push_back(name);
+ String band_name = "band_db/" + itos(eq.get_band_frequency(i)) + "_hz";
+ prop_band_map[band_name] = i;
+ band_names.push_back(band_name);
}
}
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
index 9b0560223f..b80fb7c73c 100644
--- a/servers/audio/effects/audio_effect_eq.h
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTEQ_H
-#define AUDIOEFFECTEQ_H
+#ifndef AUDIO_EFFECT_EQ_H
+#define AUDIO_EFFECT_EQ_H
#include "servers/audio/audio_effect.h"
-#include "servers/audio/effects/eq.h"
+#include "servers/audio/effects/eq_filter.h"
class AudioEffectEQ;
@@ -98,4 +98,4 @@ public:
AudioEffectEQ(EQ::PRESET_21_BANDS) {}
};
-#endif // AUDIOEFFECTEQ_H
+#endif // AUDIO_EFFECT_EQ_H
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
index 06e66f22b1..68f8e334df 100644
--- a/servers/audio/effects/audio_effect_filter.cpp
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -36,13 +36,13 @@ void AudioEffectFilterInstance::_process_filter(const AudioFrame *p_src_frames,
for (int i = 0; i < p_frame_count; i++) {
float f = p_src_frames[i].l;
filter_process[0][0].process_one(f);
- if (S > 1) {
+ if constexpr (S > 1) {
filter_process[0][1].process_one(f);
}
- if (S > 2) {
+ if constexpr (S > 2) {
filter_process[0][2].process_one(f);
}
- if (S > 3) {
+ if constexpr (S > 3) {
filter_process[0][3].process_one(f);
}
@@ -52,13 +52,13 @@ void AudioEffectFilterInstance::_process_filter(const AudioFrame *p_src_frames,
for (int i = 0; i < p_frame_count; i++) {
float f = p_src_frames[i].r;
filter_process[1][0].process_one(f);
- if (S > 1) {
+ if constexpr (S > 1) {
filter_process[1][1].process_one(f);
}
- if (S > 2) {
+ if constexpr (S > 2) {
filter_process[1][2].process_one(f);
}
- if (S > 3) {
+ if constexpr (S > 3) {
filter_process[1][3].process_one(f);
}
@@ -153,7 +153,7 @@ void AudioEffectFilter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_db", "amount"), &AudioEffectFilter::set_db);
ClassDB::bind_method(D_METHOD("get_db"), &AudioEffectFilter::get_db);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1"), "set_cutoff", "get_cutoff");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "cutoff_hz", PROPERTY_HINT_RANGE, "1,20500,1,suffix:Hz"), "set_cutoff", "get_cutoff");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "resonance", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_resonance", "get_resonance");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gain", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_gain", "get_gain");
ADD_PROPERTY(PropertyInfo(Variant::INT, "db", PROPERTY_HINT_ENUM, "6 dB,12 dB,18 dB,24 dB"), "set_db", "get_db");
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
index d5d58ddaa3..1510ee2af7 100644
--- a/servers/audio/effects/audio_effect_filter.h
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTFILTER_H
-#define AUDIOEFFECTFILTER_H
+#ifndef AUDIO_EFFECT_FILTER_H
+#define AUDIO_EFFECT_FILTER_H
#include "servers/audio/audio_effect.h"
#include "servers/audio/audio_filter_sw.h"
@@ -98,9 +98,9 @@ VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB)
class AudioEffectLowPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectLowPassFilter, AudioEffectFilter);
- void _validate_property(PropertyInfo &property) const override {
- if (property.name == "gain") {
- property.usage = PROPERTY_USAGE_NONE;
+ void _validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "gain") {
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -111,9 +111,9 @@ public:
class AudioEffectHighPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectHighPassFilter, AudioEffectFilter);
- void _validate_property(PropertyInfo &property) const override {
- if (property.name == "gain") {
- property.usage = PROPERTY_USAGE_NONE;
+ void _validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "gain") {
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -124,9 +124,9 @@ public:
class AudioEffectBandPassFilter : public AudioEffectFilter {
GDCLASS(AudioEffectBandPassFilter, AudioEffectFilter);
- void _validate_property(PropertyInfo &property) const override {
- if (property.name == "gain") {
- property.usage = PROPERTY_USAGE_NONE;
+ void _validate_property(PropertyInfo &p_property) const {
+ if (p_property.name == "gain") {
+ p_property.usage = PROPERTY_USAGE_NONE;
}
}
@@ -167,4 +167,4 @@ public:
AudioEffectFilter(AudioFilterSW::HIGHSHELF) {}
};
-#endif // AUDIOEFFECTFILTER_H
+#endif // AUDIO_EFFECT_FILTER_H
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
index 5923cf8cf5..99653cf5b6 100644
--- a/servers/audio/effects/audio_effect_limiter.cpp
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -32,11 +32,11 @@
void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) {
float threshdb = base->threshold;
- float ceiling = Math::db2linear(base->ceiling);
+ float ceiling = Math::db_to_linear(base->ceiling);
float ceildb = base->ceiling;
- float makeup = Math::db2linear(ceildb - threshdb);
+ float makeup = Math::db_to_linear(ceildb - threshdb);
float sc = -base->soft_clip;
- float scv = Math::db2linear(sc);
+ float scv = Math::db_to_linear(sc);
float peakdb = ceildb + 25;
float scmult = Math::abs((ceildb - sc) / (peakdb - sc));
@@ -49,14 +49,14 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFr
float sign1 = (spl1 < 0.0 ? -1.0 : 1.0);
float abs0 = Math::abs(spl0);
float abs1 = Math::abs(spl1);
- float overdb0 = Math::linear2db(abs0) - ceildb;
- float overdb1 = Math::linear2db(abs1) - ceildb;
+ float overdb0 = Math::linear_to_db(abs0) - ceildb;
+ float overdb1 = Math::linear_to_db(abs1) - ceildb;
if (abs0 > scv) {
- spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult));
+ spl0 = sign0 * (scv + Math::db_to_linear(overdb0 * scmult));
}
if (abs1 > scv) {
- spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult));
+ spl1 = sign1 * (scv + Math::db_to_linear(overdb1 * scmult));
}
spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0);
@@ -120,9 +120,9 @@ void AudioEffectLimiter::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_soft_clip_ratio", "soft_clip"), &AudioEffectLimiter::set_soft_clip_ratio);
ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"), &AudioEffectLimiter::get_soft_clip_ratio);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1"), "set_ceiling_db", "get_ceiling_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1"), "set_threshold_db", "get_threshold_db");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1"), "set_soft_clip_db", "get_soft_clip_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "ceiling_db", PROPERTY_HINT_RANGE, "-20,-0.1,0.1,suffix:dB"), "set_ceiling_db", "get_ceiling_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "threshold_db", PROPERTY_HINT_RANGE, "-30,0,0.1,suffix:dB"), "set_threshold_db", "get_threshold_db");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_db", PROPERTY_HINT_RANGE, "0,6,0.1,suffix:dB"), "set_soft_clip_db", "get_soft_clip_db");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "soft_clip_ratio", PROPERTY_HINT_RANGE, "3,20,0.1"), "set_soft_clip_ratio", "get_soft_clip_ratio");
}
diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h
index d05c9902af..3eca71a926 100644
--- a/servers/audio/effects/audio_effect_panner.h
+++ b/servers/audio/effects/audio_effect_panner.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTPANNER_H
-#define AUDIOEFFECTPANNER_H
+#ifndef AUDIO_EFFECT_PANNER_H
+#define AUDIO_EFFECT_PANNER_H
#include "servers/audio/audio_effect.h"
@@ -61,4 +61,4 @@ public:
AudioEffectPanner();
};
-#endif // AUDIOEFFECTPANNER_H
+#endif // AUDIO_EFFECT_PANNER_H
diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp
index af5dce707e..2f86630ce9 100644
--- a/servers/audio/effects/audio_effect_phaser.cpp
+++ b/servers/audio/effects/audio_effect_phaser.cpp
@@ -144,9 +144,9 @@ void AudioEffectPhaser::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_depth", "depth"), &AudioEffectPhaser::set_depth);
ClassDB::bind_method(D_METHOD("get_depth"), &AudioEffectPhaser::get_depth);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_min_hz", PROPERTY_HINT_RANGE, "10,10000"), "set_range_min_hz", "get_range_min_hz");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_max_hz", PROPERTY_HINT_RANGE, "10,10000"), "set_range_max_hz", "get_range_max_hz");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rate_hz", PROPERTY_HINT_RANGE, "0.01,20"), "set_rate_hz", "get_rate_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_min_hz", PROPERTY_HINT_RANGE, "10,10000,suffix:Hz"), "set_range_min_hz", "get_range_min_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_max_hz", PROPERTY_HINT_RANGE, "10,10000,suffix:Hz"), "set_range_max_hz", "get_range_max_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "rate_hz", PROPERTY_HINT_RANGE, "0.01,20,suffix:Hz"), "set_rate_hz", "get_rate_hz");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "feedback", PROPERTY_HINT_RANGE, "0.1,0.9,0.1"), "set_feedback", "get_feedback");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_depth", "get_depth");
}
diff --git a/servers/audio/effects/audio_effect_record.cpp b/servers/audio/effects/audio_effect_record.cpp
index d68522e5b9..b2e57c9a01 100644
--- a/servers/audio/effects/audio_effect_record.cpp
+++ b/servers/audio/effects/audio_effect_record.cpp
@@ -71,8 +71,6 @@ bool AudioEffectRecordInstance::process_silence() const {
}
void AudioEffectRecordInstance::_io_thread_process() {
- thread_active = true;
-
while (is_recording) {
//Check: The current recording has been requested to stop
if (!base->recording_active) {
@@ -86,8 +84,6 @@ void AudioEffectRecordInstance::_io_thread_process() {
OS::get_singleton()->delay_usec(500);
}
}
-
- thread_active = false;
}
void AudioEffectRecordInstance::_io_store_buffer() {
@@ -120,19 +116,11 @@ void AudioEffectRecordInstance::init() {
recording_data.clear(); //Clear data completely and reset length
is_recording = true;
-#ifdef NO_THREADS
- AudioServer::get_singleton()->add_update_callback(&AudioEffectRecordInstance::_update, this);
-#else
io_thread.start(_thread_callback, this);
-#endif
}
void AudioEffectRecordInstance::finish() {
-#ifdef NO_THREADS
- AudioServer::get_singleton()->remove_update_callback(&AudioEffectRecordInstance::_update, this);
-#else
io_thread.wait_to_finish();
-#endif
}
AudioEffectRecordInstance::~AudioEffectRecordInstance() {
@@ -203,16 +191,16 @@ bool AudioEffectRecord::is_recording_active() const {
return recording_active;
}
-void AudioEffectRecord::set_format(AudioStreamSample::Format p_format) {
+void AudioEffectRecord::set_format(AudioStreamWAV::Format p_format) {
format = p_format;
}
-AudioStreamSample::Format AudioEffectRecord::get_format() const {
+AudioStreamWAV::Format AudioEffectRecord::get_format() const {
return format;
}
-Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
- AudioStreamSample::Format dst_format = format;
+Ref<AudioStreamWAV> AudioEffectRecord::get_recording() const {
+ AudioStreamWAV::Format dst_format = format;
bool stereo = true; //forcing mono is not implemented
Vector<uint8_t> dst_data;
@@ -220,7 +208,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
ERR_FAIL_COND_V(current_instance.is_null(), nullptr);
ERR_FAIL_COND_V(current_instance->recording_data.size() == 0, nullptr);
- if (dst_format == AudioStreamSample::FORMAT_8_BITS) {
+ if (dst_format == AudioStreamWAV::FORMAT_8_BITS) {
int data_size = current_instance->recording_data.size();
dst_data.resize(data_size);
uint8_t *w = dst_data.ptrw();
@@ -229,7 +217,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
int8_t v = CLAMP(current_instance->recording_data[i] * 128, -128, 127);
w[i] = v;
}
- } else if (dst_format == AudioStreamSample::FORMAT_16_BITS) {
+ } else if (dst_format == AudioStreamWAV::FORMAT_16_BITS) {
int data_size = current_instance->recording_data.size();
dst_data.resize(data_size * 2);
uint8_t *w = dst_data.ptrw();
@@ -238,7 +226,7 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
int16_t v = CLAMP(current_instance->recording_data[i] * 32768, -32768, 32767);
encode_uint16(v, &w[i * 2]);
}
- } else if (dst_format == AudioStreamSample::FORMAT_IMA_ADPCM) {
+ } else if (dst_format == AudioStreamWAV::FORMAT_IMA_ADPCM) {
//byte interleave
Vector<float> left;
Vector<float> right;
@@ -277,12 +265,12 @@ Ref<AudioStreamSample> AudioEffectRecord::get_recording() const {
ERR_PRINT("Format not implemented.");
}
- Ref<AudioStreamSample> sample;
+ Ref<AudioStreamWAV> sample;
sample.instantiate();
sample->set_data(dst_data);
sample->set_format(dst_format);
sample->set_mix_rate(AudioServer::get_singleton()->get_mix_rate());
- sample->set_loop_mode(AudioStreamSample::LOOP_DISABLED);
+ sample->set_loop_mode(AudioStreamWAV::LOOP_DISABLED);
sample->set_loop_begin(0);
sample->set_loop_end(0);
sample->set_stereo(stereo);
@@ -301,6 +289,6 @@ void AudioEffectRecord::_bind_methods() {
}
AudioEffectRecord::AudioEffectRecord() {
- format = AudioStreamSample::FORMAT_16_BITS;
+ format = AudioStreamWAV::FORMAT_16_BITS;
recording_active = false;
}
diff --git a/servers/audio/effects/audio_effect_record.h b/servers/audio/effects/audio_effect_record.h
index 305484d1cb..e89d8adbde 100644
--- a/servers/audio/effects/audio_effect_record.h
+++ b/servers/audio/effects/audio_effect_record.h
@@ -28,14 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTRECORD_H
-#define AUDIOEFFECTRECORD_H
+#ifndef AUDIO_EFFECT_RECORD_H
+#define AUDIO_EFFECT_RECORD_H
#include "core/io/file_access.h"
#include "core/io/marshalls.h"
#include "core/os/os.h"
#include "core/os/thread.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
#include "servers/audio/audio_effect.h"
#include "servers/audio_server.h"
@@ -48,7 +48,6 @@ class AudioEffectRecordInstance : public AudioEffectInstance {
bool is_recording;
Thread io_thread;
- bool thread_active = false;
Vector<AudioFrame> ring_buffer;
Vector<float> recording_data;
@@ -86,7 +85,7 @@ class AudioEffectRecord : public AudioEffect {
bool recording_active;
Ref<AudioEffectRecordInstance> current_instance;
- AudioStreamSample::Format format;
+ AudioStreamWAV::Format format;
void ensure_thread_stopped();
@@ -97,11 +96,11 @@ public:
Ref<AudioEffectInstance> instantiate() override;
void set_recording_active(bool p_record);
bool is_recording_active() const;
- void set_format(AudioStreamSample::Format p_format);
- AudioStreamSample::Format get_format() const;
- Ref<AudioStreamSample> get_recording() const;
+ void set_format(AudioStreamWAV::Format p_format);
+ AudioStreamWAV::Format get_format() const;
+ Ref<AudioStreamWAV> get_recording() const;
AudioEffectRecord();
};
-#endif // AUDIOEFFECTRECORD_H
+#endif // AUDIO_EFFECT_RECORD_H
diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp
index 0d4eb14e6a..bfc68152a4 100644
--- a/servers/audio/effects/audio_effect_reverb.cpp
+++ b/servers/audio/effects/audio_effect_reverb.cpp
@@ -176,7 +176,7 @@ void AudioEffectReverb::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_hpf"), &AudioEffectReverb::get_hpf);
ADD_GROUP("Predelay", "predelay_");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_msec", PROPERTY_HINT_RANGE, "20,500,1"), "set_predelay_msec", "get_predelay_msec");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_msec", PROPERTY_HINT_RANGE, "20,500,1,suffix:ms"), "set_predelay_msec", "get_predelay_msec");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "predelay_feedback", PROPERTY_HINT_RANGE, "0,0.98,0.01"), "set_predelay_feedback", "get_predelay_feedback");
ADD_GROUP("", "");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "room_size", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_room_size", "get_room_size");
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
index 90694c5492..a2c1fc5ea5 100644
--- a/servers/audio/effects/audio_effect_reverb.h
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef AUDIOEFFECTREVERB_H
-#define AUDIOEFFECTREVERB_H
+#ifndef AUDIO_EFFECT_REVERB_H
+#define AUDIO_EFFECT_REVERB_H
#include "servers/audio/audio_effect.h"
-#include "servers/audio/effects/reverb.h"
+#include "servers/audio/effects/reverb_filter.h"
class AudioEffectReverb;
@@ -94,4 +94,4 @@ public:
AudioEffectReverb();
};
-#endif // AUDIOEFFECTREVERB_H
+#endif // AUDIO_EFFECT_REVERB_H
diff --git a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
index 10627be74c..30ebf626ae 100644
--- a/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
+++ b/servers/audio/effects/audio_effect_spectrum_analyzer.cpp
@@ -264,7 +264,7 @@ void AudioEffectSpectrumAnalyzer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_fft_size", "size"), &AudioEffectSpectrumAnalyzer::set_fft_size);
ClassDB::bind_method(D_METHOD("get_fft_size"), &AudioEffectSpectrumAnalyzer::get_fft_size);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.1,4,0.1,suffix:s"), "set_buffer_length", "get_buffer_length");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "tap_back_pos", PROPERTY_HINT_RANGE, "0.1,4,0.1"), "set_tap_back_pos", "get_tap_back_pos");
ADD_PROPERTY(PropertyInfo(Variant::INT, "fft_size", PROPERTY_HINT_ENUM, "256,512,1024,2048,4096"), "set_fft_size", "get_fft_size");
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp
index 7bb62bcbed..e567add3e7 100644
--- a/servers/audio/effects/audio_effect_stereo_enhance.cpp
+++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp
@@ -138,7 +138,7 @@ void AudioEffectStereoEnhance::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_surround"), &AudioEffectStereoEnhance::get_surround);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pan_pullout", PROPERTY_HINT_RANGE, "0,4,0.01"), "set_pan_pullout", "get_pan_pullout");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_pullout_ms", PROPERTY_HINT_RANGE, "0,50,0.01"), "set_time_pullout", "get_time_pullout");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_pullout_ms", PROPERTY_HINT_RANGE, "0,50,0.01,suffix:ms"), "set_time_pullout", "get_time_pullout");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "surround", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_surround", "get_surround");
}
diff --git a/servers/audio/effects/audio_stream_generator.cpp b/servers/audio/effects/audio_stream_generator.cpp
index a3d615b925..547b60a317 100644
--- a/servers/audio/effects/audio_stream_generator.cpp
+++ b/servers/audio/effects/audio_stream_generator.cpp
@@ -46,7 +46,7 @@ float AudioStreamGenerator::get_buffer_length() const {
return buffer_len;
}
-Ref<AudioStreamPlayback> AudioStreamGenerator::instance_playback() {
+Ref<AudioStreamPlayback> AudioStreamGenerator::instantiate_playback() {
Ref<AudioStreamGeneratorPlayback> playback;
playback.instantiate();
playback->generator = this;
@@ -60,7 +60,7 @@ String AudioStreamGenerator::get_stream_name() const {
return "UserFeed";
}
-float AudioStreamGenerator::get_length() const {
+double AudioStreamGenerator::get_length() const {
return 0;
}
@@ -75,8 +75,8 @@ void AudioStreamGenerator::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_buffer_length", "seconds"), &AudioStreamGenerator::set_buffer_length);
ClassDB::bind_method(D_METHOD("get_buffer_length"), &AudioStreamGenerator::get_buffer_length);
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1"), "set_mix_rate", "get_mix_rate");
- ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01"), "set_buffer_length", "get_buffer_length");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "mix_rate", PROPERTY_HINT_RANGE, "20,192000,1,suffix:Hz"), "set_mix_rate", "get_mix_rate");
+ ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "buffer_length", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_buffer_length", "get_buffer_length");
}
AudioStreamGenerator::AudioStreamGenerator() {
@@ -108,7 +108,7 @@ bool AudioStreamGeneratorPlayback::push_buffer(const PackedVector2Array &p_frame
}
const Vector2 *r = p_frames.ptr();
- if (sizeof(real_t) == 4) {
+ if constexpr (sizeof(real_t) == 4) {
//write directly
buffer.write((const AudioFrame *)r, to_write);
} else {
@@ -167,7 +167,7 @@ float AudioStreamGeneratorPlayback::get_stream_sampling_rate() {
return generator->get_mix_rate();
}
-void AudioStreamGeneratorPlayback::start(float p_from_pos) {
+void AudioStreamGeneratorPlayback::start(double p_from_pos) {
if (mixed == 0.0) {
begin_resample();
}
@@ -188,14 +188,18 @@ int AudioStreamGeneratorPlayback::get_loop_count() const {
return 0;
}
-float AudioStreamGeneratorPlayback::get_playback_position() const {
+double AudioStreamGeneratorPlayback::get_playback_position() const {
return mixed;
}
-void AudioStreamGeneratorPlayback::seek(float p_time) {
+void AudioStreamGeneratorPlayback::seek(double p_time) {
//no seek possible
}
+void AudioStreamGeneratorPlayback::tag_used_streams() {
+ generator->tag_used(0);
+}
+
void AudioStreamGeneratorPlayback::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_frame", "frame"), &AudioStreamGeneratorPlayback::push_frame);
ClassDB::bind_method(D_METHOD("can_push_buffer", "amount"), &AudioStreamGeneratorPlayback::can_push_buffer);
diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h
index 2ce4b95fcf..21cb3954d3 100644
--- a/servers/audio/effects/audio_stream_generator.h
+++ b/servers/audio/effects/audio_stream_generator.h
@@ -50,10 +50,10 @@ public:
void set_buffer_length(float p_seconds);
float get_buffer_length() const;
- virtual Ref<AudioStreamPlayback> instance_playback() override;
+ virtual Ref<AudioStreamPlayback> instantiate_playback() override;
virtual String get_stream_name() const override;
- virtual float get_length() const override;
+ virtual double get_length() const override;
virtual bool is_monophonic() const override;
AudioStreamGenerator();
};
@@ -74,14 +74,14 @@ protected:
static void _bind_methods();
public:
- virtual void start(float p_from_pos = 0.0) override;
+ virtual void start(double p_from_pos = 0.0) override;
virtual void stop() override;
virtual bool is_playing() const override;
virtual int get_loop_count() const override; //times it looped
- virtual float get_playback_position() const override;
- virtual void seek(float p_time) override;
+ virtual double get_playback_position() const override;
+ virtual void seek(double p_time) override;
bool push_frame(const Vector2 &p_frame);
bool can_push_buffer(int p_frames) const;
@@ -89,8 +89,11 @@ public:
int get_frames_available() const;
int get_skips() const;
+ virtual void tag_used_streams() override;
+
void clear_buffer();
AudioStreamGeneratorPlayback();
};
+
#endif // AUDIO_STREAM_GENERATOR_H
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq_filter.cpp
index 2123284b3b..6807e81cc4 100644
--- a/servers/audio/effects/eq.cpp
+++ b/servers/audio/effects/eq_filter.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* eq.cpp */
+/* eq_filter.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-// Author: reduzio@gmail.com (C) 2006
+#include "eq_filter.h"
-#include "eq.h"
#include "core/error/error_macros.h"
#include "core/math/math_funcs.h"
+
#include <math.h>
#define POW2(v) ((v) * (v))
diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq_filter.h
index d6293bf875..9dcad4dcea 100644
--- a/servers/audio/effects/eq.h
+++ b/servers/audio/effects/eq_filter.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* eq.h */
+/* eq_filter.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb_filter.cpp
index adfd648514..2b60b73b7e 100644
--- a/servers/audio/effects/reverb.cpp
+++ b/servers/audio/effects/reverb_filter.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* reverb.cpp */
+/* reverb_filter.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,7 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "reverb.h"
+#include "reverb_filter.h"
#include "core/math/math_funcs.h"
@@ -77,7 +77,7 @@ void Reverb::process(float *p_src, float *p_dst, int p_frames) {
read_pos += echo_buffer_size;
}
- float in = undenormalise(echo_buffer[read_pos] * params.predelay_fb + p_src[i]);
+ float in = undenormalize(echo_buffer[read_pos] * params.predelay_fb + p_src[i]);
echo_buffer[echo_buffer_pos] = in;
@@ -111,7 +111,7 @@ void Reverb::process(float *p_src, float *p_dst, int p_frames) {
c.pos = 0;
}
- float out = undenormalise(c.buffer[c.pos] * c.feedback);
+ float out = undenormalize(c.buffer[c.pos] * c.feedback);
out = out * (1.0 - c.damp) + c.damp_h * c.damp; //lowpass
c.damp_h = out;
c.buffer[c.pos] = input_buffer[j] + out;
@@ -138,7 +138,7 @@ void Reverb::process(float *p_src, float *p_dst, int p_frames) {
ap=&allpass[m_ap]; \
if (ap->pos>=ap_size_limit[m_ap]) \
ap->pos=0; \
- aux=undenormalise(ap->buffer[ap->pos]); \
+ aux=undenormalize(ap->buffer[ap->pos]); \
in=sample; \
sample=-in+aux; \
ap->pos++;
@@ -163,7 +163,7 @@ void Reverb::process(float *p_src, float *p_dst, int p_frames) {
}
float aux = a.buffer[a.pos];
- a.buffer[a.pos] = undenormalise(allpass_feedback * aux + p_dst[j]);
+ a.buffer[a.pos] = undenormalize(allpass_feedback * aux + p_dst[j]);
p_dst[j] = aux - allpass_feedback * a.buffer[a.pos];
a.pos++;
}
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb_filter.h
index c9602c5b5a..fe846fe2e7 100644
--- a/servers/audio/effects/reverb.h
+++ b/servers/audio/effects/reverb_filter.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* reverb.h */
+/* reverb_filter.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef REVERB_H
-#define REVERB_H
+#ifndef REVERB_FILTER_H
+#define REVERB_FILTER_H
#include "core/math/audio_frame.h"
#include "core/os/memory.h"
@@ -119,4 +119,4 @@ public:
~Reverb();
};
-#endif // REVERB_H
+#endif // REVERB_FILTER_H
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 8ec3e469d3..e657570f9b 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -39,7 +39,7 @@
#include "core/os/os.h"
#include "core/string/string_name.h"
#include "core/templates/pair.h"
-#include "scene/resources/audio_stream_sample.h"
+#include "scene/resources/audio_stream_wav.h"
#include "servers/audio/audio_driver_dummy.h"
#include "servers/audio/effects/audio_effect_compressor.h"
@@ -144,8 +144,8 @@ int AudioDriver::get_total_channels_by_speaker_mode(AudioDriver::SpeakerMode p_m
ERR_FAIL_V(2);
}
-Array AudioDriver::get_device_list() {
- Array list;
+PackedStringArray AudioDriver::get_device_list() {
+ PackedStringArray list;
list.push_back("Default");
@@ -156,8 +156,8 @@ String AudioDriver::get_device() {
return "Default";
}
-Array AudioDriver::capture_get_device_list() {
- Array list;
+PackedStringArray AudioDriver::capture_get_device_list() {
+ PackedStringArray list;
list.push_back("Default");
@@ -350,6 +350,10 @@ void AudioServer::_mix_step() {
// Mix the audio stream
unsigned int mixed_frames = playback->stream_playback->mix(&buf[LOOKAHEAD_BUFFER_SIZE], playback->pitch_scale.get(), buffer_size);
+ if (tag_used_audio_streams && playback->stream_playback->is_playing()) {
+ playback->stream_playback->tag_used_streams();
+ }
+
if (mixed_frames != buffer_size) {
// We know we have at least the size of our lookahead buffer for fade-out purposes.
@@ -543,7 +547,7 @@ void AudioServer::_mix_step() {
AudioFrame peak = AudioFrame(0, 0);
- float volume = Math::db2linear(bus->volume_db);
+ float volume = Math::db_to_linear(bus->volume_db);
if (solo_mode) {
if (!bus->soloed) {
@@ -569,12 +573,12 @@ void AudioServer::_mix_step() {
}
}
- bus->channels.write[k].peak_volume = AudioFrame(Math::linear2db(peak.l + AUDIO_PEAK_OFFSET), Math::linear2db(peak.r + AUDIO_PEAK_OFFSET));
+ bus->channels.write[k].peak_volume = AudioFrame(Math::linear_to_db(peak.l + AUDIO_PEAK_OFFSET), Math::linear_to_db(peak.r + AUDIO_PEAK_OFFSET));
if (!bus->channels[k].used) {
//see if any audio is contained, because channel was not used
- if (MAX(peak.r, peak.l) > Math::db2linear(channel_disable_threshold_db)) {
+ if (MAX(peak.r, peak.l) > Math::db_to_linear(channel_disable_threshold_db)) {
bus->channels.write[k].last_mix_with_audio = mix_frames;
} else if (mix_frames - bus->channels[k].last_mix_with_audio > channel_disable_frames) {
bus->channels.write[k].active = false;
@@ -1312,6 +1316,10 @@ uint64_t AudioServer::get_mix_count() const {
return mix_count;
}
+uint64_t AudioServer::get_mixed_frames() const {
+ return mix_frames;
+}
+
void AudioServer::notify_listener_changed() {
for (CallbackItem *ci : listener_changed_callback_list) {
ci->callback(ci->userdata);
@@ -1446,7 +1454,7 @@ void AudioServer::update() {
}
void AudioServer::load_default_bus_layout() {
- String layout_path = ProjectSettings::get_singleton()->get("audio/buses/default_bus_layout");
+ String layout_path = GLOBAL_GET("audio/buses/default_bus_layout");
if (ResourceLoader::exists(layout_path)) {
Ref<AudioBusLayout> default_layout = ResourceLoader::load(layout_path);
@@ -1629,7 +1637,7 @@ Ref<AudioBusLayout> AudioServer::generate_bus_layout() const {
return state;
}
-Array AudioServer::get_device_list() {
+PackedStringArray AudioServer::get_device_list() {
return AudioDriver::get_singleton()->get_device_list();
}
@@ -1641,7 +1649,7 @@ void AudioServer::set_device(String device) {
AudioDriver::get_singleton()->set_device(device);
}
-Array AudioServer::capture_get_device_list() {
+PackedStringArray AudioServer::capture_get_device_list() {
return AudioDriver::get_singleton()->capture_get_device_list();
}
@@ -1653,6 +1661,10 @@ void AudioServer::capture_set_device(const String &p_name) {
AudioDriver::get_singleton()->capture_set_device(p_name);
}
+void AudioServer::set_enable_tagging_used_audio_streams(bool p_enable) {
+ tag_used_audio_streams = p_enable;
+}
+
void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_count", "amount"), &AudioServer::set_bus_count);
ClassDB::bind_method(D_METHOD("get_bus_count"), &AudioServer::get_bus_count);
@@ -1719,6 +1731,8 @@ void AudioServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_bus_layout", "bus_layout"), &AudioServer::set_bus_layout);
ClassDB::bind_method(D_METHOD("generate_bus_layout"), &AudioServer::generate_bus_layout);
+ ClassDB::bind_method(D_METHOD("set_enable_tagging_used_audio_streams", "enable"), &AudioServer::set_enable_tagging_used_audio_streams);
+
ADD_PROPERTY(PropertyInfo(Variant::INT, "bus_count"), "set_bus_count", "get_bus_count");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "device"), "set_device", "get_device");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "capture_device"), "capture_set_device", "capture_get_device");
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 18e173ff0b..588107c25d 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -43,7 +43,7 @@
class AudioDriverDummy;
class AudioStream;
-class AudioStreamSample;
+class AudioStreamWAV;
class AudioStreamPlayback;
class AudioDriver {
@@ -94,7 +94,7 @@ public:
virtual void start() = 0;
virtual int get_mix_rate() const = 0;
virtual SpeakerMode get_speaker_mode() const = 0;
- virtual Array get_device_list();
+ virtual PackedStringArray get_device_list();
virtual String get_device();
virtual void set_device(String device) {}
virtual void lock() = 0;
@@ -105,7 +105,7 @@ public:
virtual Error capture_stop() { return FAILED; }
virtual void capture_set_device(const String &p_name) {}
virtual String capture_get_device() { return "Default"; }
- virtual Array capture_get_device_list(); // TODO: convert this and get_device_list to PackedStringArray
+ virtual PackedStringArray capture_get_device_list();
virtual float get_latency() { return 0; }
@@ -187,6 +187,8 @@ private:
float playback_speed_scale = 1.0f;
+ bool tag_used_audio_streams = false;
+
struct Bus {
StringName name;
bool solo = false;
@@ -380,6 +382,7 @@ public:
bool is_playback_paused(Ref<AudioStreamPlayback> p_playback);
uint64_t get_mix_count() const;
+ uint64_t get_mixed_frames() const;
void notify_listener_changed();
@@ -416,14 +419,16 @@ public:
void set_bus_layout(const Ref<AudioBusLayout> &p_bus_layout);
Ref<AudioBusLayout> generate_bus_layout() const;
- Array get_device_list();
+ PackedStringArray get_device_list();
String get_device();
void set_device(String device);
- Array capture_get_device_list();
+ PackedStringArray capture_get_device_list();
String capture_get_device();
void capture_set_device(const String &p_name);
+ void set_enable_tagging_used_audio_streams(bool p_enable);
+
AudioServer();
virtual ~AudioServer();
};
diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp
index 91df3afadd..b87cdd6d9f 100644
--- a/servers/camera_server.cpp
+++ b/servers/camera_server.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "camera_server.h"
+#include "core/variant/typed_array.h"
#include "rendering_server.h"
#include "servers/camera/camera_feed.h"
@@ -104,10 +105,7 @@ void CameraServer::add_feed(const Ref<CameraFeed> &p_feed) {
// add our feed
feeds.push_back(p_feed);
-// record for debugging
-#ifdef DEBUG_ENABLED
- print_line("Registered camera " + p_feed->get_name() + " with id " + itos(p_feed->get_id()) + " position " + itos(p_feed->get_position()) + " at index " + itos(feeds.size() - 1));
-#endif
+ print_verbose("CameraServer: Registered camera " + p_feed->get_name() + " with ID " + itos(p_feed->get_id()) + " and position " + itos(p_feed->get_position()) + " at index " + itos(feeds.size() - 1));
// let whomever is interested know
emit_signal(SNAME("camera_feed_added"), p_feed->get_id());
@@ -118,10 +116,7 @@ void CameraServer::remove_feed(const Ref<CameraFeed> &p_feed) {
if (feeds[i] == p_feed) {
int feed_id = p_feed->get_id();
-// record for debugging
-#ifdef DEBUG_ENABLED
- print_line("Removed camera " + p_feed->get_name() + " with id " + itos(feed_id) + " position " + itos(p_feed->get_position()));
-#endif
+ print_verbose("CameraServer: Removed camera " + p_feed->get_name() + " with ID " + itos(feed_id) + " and position " + itos(p_feed->get_position()));
// remove it from our array, if this results in our feed being unreferenced it will be destroyed
feeds.remove_at(i);
@@ -143,8 +138,8 @@ int CameraServer::get_feed_count() {
return feeds.size();
};
-Array CameraServer::get_feeds() {
- Array return_feeds;
+TypedArray<CameraFeed> CameraServer::get_feeds() {
+ TypedArray<CameraFeed> return_feeds;
int cc = get_feed_count();
return_feeds.resize(cc);
diff --git a/servers/camera_server.h b/servers/camera_server.h
index b70938c34f..c6fb906b3c 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -43,6 +43,8 @@
**/
class CameraFeed;
+template <typename T>
+class TypedArray;
class CameraServer : public Object {
GDCLASS(CameraServer, Object);
@@ -100,7 +102,7 @@ public:
// Get our feeds.
Ref<CameraFeed> get_feed(int p_index);
int get_feed_count();
- Array get_feeds();
+ TypedArray<CameraFeed> get_feeds();
// Intended for use with custom CameraServer implementation.
RID feed_texture(int p_id, FeedImage p_texture);
diff --git a/servers/debugger/servers_debugger.h b/servers/debugger/servers_debugger.h
index f949c436e7..be0e64fbc0 100644
--- a/servers/debugger/servers_debugger.h
+++ b/servers/debugger/servers_debugger.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SERVER_DEBUGGER_H
-#define SERVER_DEBUGGER_H
+#ifndef SERVERS_DEBUGGER_H
+#define SERVERS_DEBUGGER_H
#include "core/debugger/debugger_marshalls.h"
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 59f88844e9..52d7f66203 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -44,40 +44,49 @@ DisplayServer::DisplayServerCreate DisplayServer::server_create_functions[Displa
int DisplayServer::server_create_count = 1;
-void DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+int DisplayServer::global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+int DisplayServer::global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+int DisplayServer::global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+int DisplayServer::global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+int DisplayServer::global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+int DisplayServer::global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Variant &p_tag, Key p_accel, int p_index) {
+int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback, const Callable &p_key_callback, const Variant &p_tag, Key p_accel, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
+int DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
-void DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) {
+int DisplayServer::global_menu_add_separator(const String &p_menu_root, int p_index) {
WARN_PRINT("Global menus not supported by this display server.");
+ return -1;
}
int DisplayServer::global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const {
@@ -94,6 +103,10 @@ void DisplayServer::global_menu_set_item_callback(const String &p_menu_root, int
WARN_PRINT("Global menus not supported by this display server.");
}
+void DisplayServer::global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
bool DisplayServer::global_menu_is_item_checked(const String &p_menu_root, int p_idx) const {
WARN_PRINT("Global menus not supported by this display server.");
return false;
@@ -114,6 +127,11 @@ Callable DisplayServer::global_menu_get_item_callback(const String &p_menu_root,
return Callable();
}
+Callable DisplayServer::global_menu_get_item_key_callback(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return Callable();
+}
+
Variant DisplayServer::global_menu_get_item_tag(const String &p_menu_root, int p_idx) const {
WARN_PRINT("Global menus not supported by this display server.");
return Variant();
@@ -159,6 +177,11 @@ Ref<Texture2D> DisplayServer::global_menu_get_item_icon(const String &p_menu_roo
return Ref<Texture2D>();
}
+int DisplayServer::global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const {
+ WARN_PRINT("Global menus not supported by this display server.");
+ return 0;
+}
+
void DisplayServer::global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) {
WARN_PRINT("Global menus not supported by this display server.");
}
@@ -207,6 +230,10 @@ void DisplayServer::global_menu_set_item_icon(const String &p_menu_root, int p_i
WARN_PRINT("Global menus not supported by this display server.");
}
+void DisplayServer::global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level) {
+ WARN_PRINT("Global menus not supported by this display server.");
+}
+
int DisplayServer::global_menu_get_item_count(const String &p_menu_root) const {
WARN_PRINT("Global menus not supported by this display server.");
return 0;
@@ -238,14 +265,14 @@ void DisplayServer::tts_resume() {
WARN_PRINT("TTS is not supported by this display server.");
}
-Array DisplayServer::tts_get_voices() const {
+TypedArray<Dictionary> DisplayServer::tts_get_voices() const {
WARN_PRINT("TTS is not supported by this display server.");
- return Array();
+ return TypedArray<Dictionary>();
}
PackedStringArray DisplayServer::tts_get_voices_for_language(const String &p_language) const {
PackedStringArray ret;
- Array voices = tts_get_voices();
+ TypedArray<Dictionary> voices = tts_get_voices();
for (int i = 0; i < voices.size(); i++) {
const Dictionary &voice = voices[i];
if (voice.has("id") && voice.has("language") && voice["language"].operator String().begins_with(p_language)) {
@@ -275,19 +302,12 @@ void DisplayServer::tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id
case DisplayServer::TTS_UTTERANCE_ENDED:
case DisplayServer::TTS_UTTERANCE_CANCELED: {
if (utterance_callback[p_event].is_valid()) {
- Variant args[1];
- args[0] = p_id;
- const Variant *argp[] = { &args[0] };
- utterance_callback[p_event].call_deferred(argp, 1); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
+ utterance_callback[p_event].call_deferred(p_id); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
}
} break;
case DisplayServer::TTS_UTTERANCE_BOUNDARY: {
if (utterance_callback[p_event].is_valid()) {
- Variant args[2];
- args[0] = p_pos;
- args[1] = p_id;
- const Variant *argp[] = { &args[0], &args[1] };
- utterance_callback[p_event].call_deferred(argp, 2); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
+ utterance_callback[p_event].call_deferred(p_pos, p_id); // Should be deferred, on some platforms utterance events can be called from different threads in a rapid succession.
}
} break;
default:
@@ -400,7 +420,7 @@ String DisplayServer::ime_get_text() const {
ERR_FAIL_V_MSG(String(), "IME or NOTIFICATION_WM_IME_UPDATEnot supported by this display server.");
}
-void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, bool p_multiline, int p_max_length, int p_cursor_start, int p_cursor_end) {
+void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, VirtualKeyboardType p_type, int p_max_length, int p_cursor_start, int p_cursor_end) {
WARN_PRINT("Virtual keyboard not supported by this display server.");
}
@@ -494,11 +514,11 @@ int64_t DisplayServer::window_get_native_handle(HandleType p_handle_type, Window
}
void DisplayServer::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
- WARN_PRINT("Changing the VSync mode is not supported by this display server.");
+ WARN_PRINT("Changing the V-Sync mode is not supported by this display server.");
}
DisplayServer::VSyncMode DisplayServer::window_get_vsync_mode(WindowID p_window) const {
- WARN_PRINT("Changing the VSync mode is not supported by this display server.");
+ WARN_PRINT("Changing the V-Sync mode is not supported by this display server.");
return VSyncMode::VSYNC_ENABLED;
}
@@ -509,14 +529,14 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature);
ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name);
- ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("global_menu_add_icon_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("global_menu_add_icon_check_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("global_menu_add_radio_check_item", "menu_root", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_radio_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("global_menu_add_icon_radio_check_item", "menu_root", "icon", "label", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_radio_check_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("global_menu_add_multistate_item", "menu_root", "labe", "max_states", "default_state", "callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_multistate_item, DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu", "index"), &DisplayServer::global_menu_add_submenu_item, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_icon_item", "menu_root", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_icon_check_item", "menu_root", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_radio_check_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_radio_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_icon_radio_check_item", "menu_root", "icon", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_icon_radio_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("global_menu_add_multistate_item", "menu_root", "labe", "max_states", "default_state", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_multistate_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_add_separator", "menu_root", "index"), &DisplayServer::global_menu_add_separator, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("global_menu_get_item_index_from_text", "menu_root", "text"), &DisplayServer::global_menu_get_item_index_from_text);
@@ -526,6 +546,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("global_menu_is_item_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_checkable);
ClassDB::bind_method(D_METHOD("global_menu_is_item_radio_checkable", "menu_root", "idx"), &DisplayServer::global_menu_is_item_radio_checkable);
ClassDB::bind_method(D_METHOD("global_menu_get_item_callback", "menu_root", "idx"), &DisplayServer::global_menu_get_item_callback);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_key_callback", "menu_root", "idx"), &DisplayServer::global_menu_get_item_key_callback);
ClassDB::bind_method(D_METHOD("global_menu_get_item_tag", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tag);
ClassDB::bind_method(D_METHOD("global_menu_get_item_text", "menu_root", "idx"), &DisplayServer::global_menu_get_item_text);
ClassDB::bind_method(D_METHOD("global_menu_get_item_submenu", "menu_root", "idx"), &DisplayServer::global_menu_get_item_submenu);
@@ -535,11 +556,13 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("global_menu_get_item_state", "menu_root", "idx"), &DisplayServer::global_menu_get_item_state);
ClassDB::bind_method(D_METHOD("global_menu_get_item_max_states", "menu_root", "idx"), &DisplayServer::global_menu_get_item_max_states);
ClassDB::bind_method(D_METHOD("global_menu_get_item_icon", "menu_root", "idx"), &DisplayServer::global_menu_get_item_icon);
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_indentation_level", "menu_root", "idx"), &DisplayServer::global_menu_get_item_indentation_level);
ClassDB::bind_method(D_METHOD("global_menu_set_item_checked", "menu_root", "idx", "checked"), &DisplayServer::global_menu_set_item_checked);
ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable);
ClassDB::bind_method(D_METHOD("global_menu_set_item_radio_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_radio_checkable);
ClassDB::bind_method(D_METHOD("global_menu_set_item_callback", "menu_root", "idx", "callback"), &DisplayServer::global_menu_set_item_callback);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_key_callback", "menu_root", "idx", "key_callback"), &DisplayServer::global_menu_set_item_key_callback);
ClassDB::bind_method(D_METHOD("global_menu_set_item_tag", "menu_root", "idx", "tag"), &DisplayServer::global_menu_set_item_tag);
ClassDB::bind_method(D_METHOD("global_menu_set_item_text", "menu_root", "idx", "text"), &DisplayServer::global_menu_set_item_text);
ClassDB::bind_method(D_METHOD("global_menu_set_item_submenu", "menu_root", "idx", "submenu"), &DisplayServer::global_menu_set_item_submenu);
@@ -549,6 +572,9 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("global_menu_set_item_state", "menu_root", "idx", "state"), &DisplayServer::global_menu_set_item_state);
ClassDB::bind_method(D_METHOD("global_menu_set_item_max_states", "menu_root", "idx", "max_states"), &DisplayServer::global_menu_set_item_max_states);
ClassDB::bind_method(D_METHOD("global_menu_set_item_icon", "menu_root", "idx", "icon"), &DisplayServer::global_menu_set_item_icon);
+ ClassDB::bind_method(D_METHOD("global_menu_set_item_indentation_level", "menu_root", "idx", "level"), &DisplayServer::global_menu_set_item_indentation_level);
+
+ ClassDB::bind_method(D_METHOD("global_menu_get_item_count", "menu_root"), &DisplayServer::global_menu_get_item_count);
ClassDB::bind_method(D_METHOD("global_menu_remove_item", "menu_root", "idx"), &DisplayServer::global_menu_remove_item);
ClassDB::bind_method(D_METHOD("global_menu_clear", "menu_root"), &DisplayServer::global_menu_clear);
@@ -566,6 +592,10 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("tts_set_utterance_callback", "event", "callable"), &DisplayServer::tts_set_utterance_callback);
ClassDB::bind_method(D_METHOD("_tts_post_utterance_event", "event", "id", "char_pos"), &DisplayServer::tts_post_utterance_event);
+ ClassDB::bind_method(D_METHOD("is_dark_mode_supported"), &DisplayServer::is_dark_mode_supported);
+ ClassDB::bind_method(D_METHOD("is_dark_mode"), &DisplayServer::is_dark_mode);
+ ClassDB::bind_method(D_METHOD("get_accent_color"), &DisplayServer::get_accent_color);
+
ClassDB::bind_method(D_METHOD("mouse_set_mode", "mouse_mode"), &DisplayServer::mouse_set_mode);
ClassDB::bind_method(D_METHOD("mouse_get_mode"), &DisplayServer::mouse_get_mode);
@@ -601,9 +631,6 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list);
ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position);
- ClassDB::bind_method(D_METHOD("create_sub_window", "mode", "vsync_mode", "flags", "rect"), &DisplayServer::create_sub_window, DEFVAL(Rect2i()));
- ClassDB::bind_method(D_METHOD("delete_sub_window", "window_id"), &DisplayServer::delete_sub_window);
-
ClassDB::bind_method(D_METHOD("window_get_native_handle", "handle_type", "window_id"), &DisplayServer::window_get_native_handle, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_active_popup"), &DisplayServer::window_get_active_popup);
ClassDB::bind_method(D_METHOD("window_set_popup_safe_rect", "window", "rect"), &DisplayServer::window_set_popup_safe_rect);
@@ -626,7 +653,6 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_input_text_callback", "callback", "window_id"), &DisplayServer::window_set_input_text_callback, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_drop_files_callback", "callback", "window_id"), &DisplayServer::window_set_drop_files_callback, DEFVAL(MAIN_WINDOW_ID));
- ClassDB::bind_method(D_METHOD("window_attach_instance_id", "instance_id", "window_id"), &DisplayServer::window_attach_instance_id, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_attached_instance_id", "window_id"), &DisplayServer::window_get_attached_instance_id, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_max_size", "window_id"), &DisplayServer::window_get_max_size, DEFVAL(MAIN_WINDOW_ID));
@@ -643,6 +669,9 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_flag", "flag", "enabled", "window_id"), &DisplayServer::window_set_flag, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_flag", "flag", "window_id"), &DisplayServer::window_get_flag, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_set_window_buttons_offset", "offset", "window_id"), &DisplayServer::window_set_window_buttons_offset, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_get_safe_title_margins", "window_id"), &DisplayServer::window_get_safe_title_margins, DEFVAL(MAIN_WINDOW_ID));
+
ClassDB::bind_method(D_METHOD("window_request_attention", "window_id"), &DisplayServer::window_request_attention, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_move_to_foreground", "window_id"), &DisplayServer::window_move_to_foreground, DEFVAL(MAIN_WINDOW_ID));
@@ -657,10 +686,14 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_set_vsync_mode", "vsync_mode", "window_id"), &DisplayServer::window_set_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_get_vsync_mode", "window_id"), &DisplayServer::window_get_vsync_mode, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_is_maximize_allowed", "window_id"), &DisplayServer::window_is_maximize_allowed, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_maximize_on_title_dbl_click"), &DisplayServer::window_maximize_on_title_dbl_click);
+ ClassDB::bind_method(D_METHOD("window_minimize_on_title_dbl_click"), &DisplayServer::window_minimize_on_title_dbl_click);
+
ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection);
ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text);
- ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "multiline", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(false), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("virtual_keyboard_show", "existing_text", "position", "type", "max_length", "cursor_start", "cursor_end"), &DisplayServer::virtual_keyboard_show, DEFVAL(Rect2()), DEFVAL(KEYBOARD_TYPE_DEFAULT), DEFVAL(-1), DEFVAL(-1), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("virtual_keyboard_hide"), &DisplayServer::virtual_keyboard_hide);
ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height);
@@ -713,6 +746,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS);
BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY);
BIND_ENUM_CONSTANT(FEATURE_TEXT_TO_SPEECH);
+ BIND_ENUM_CONSTANT(FEATURE_EXTEND_TO_TITLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE);
BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN);
@@ -732,6 +766,15 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(SCREEN_SENSOR_PORTRAIT);
BIND_ENUM_CONSTANT(SCREEN_SENSOR);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_DEFAULT);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_MULTILINE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_NUMBER_DECIMAL);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PHONE);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_EMAIL_ADDRESS);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_PASSWORD);
+ BIND_ENUM_CONSTANT(KEYBOARD_TYPE_URL);
+
BIND_ENUM_CONSTANT(CURSOR_ARROW);
BIND_ENUM_CONSTANT(CURSOR_IBEAM);
BIND_ENUM_CONSTANT(CURSOR_POINTING_HAND);
@@ -763,6 +806,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_FLAG_TRANSPARENT);
BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS);
BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP);
+ BIND_ENUM_CONSTANT(WINDOW_FLAG_EXTEND_TO_TITLE);
BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX);
BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER);
@@ -772,6 +816,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(WINDOW_EVENT_CLOSE_REQUEST);
BIND_ENUM_CONSTANT(WINDOW_EVENT_GO_BACK_REQUEST);
BIND_ENUM_CONSTANT(WINDOW_EVENT_DPI_CHANGE);
+ BIND_ENUM_CONSTANT(WINDOW_EVENT_TITLEBAR_CHANGE);
BIND_ENUM_CONSTANT(VSYNC_DISABLED);
BIND_ENUM_CONSTANT(VSYNC_ENABLED);
@@ -781,6 +826,7 @@ void DisplayServer::_bind_methods() {
BIND_ENUM_CONSTANT(DISPLAY_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_HANDLE);
BIND_ENUM_CONSTANT(WINDOW_VIEW);
+ BIND_ENUM_CONSTANT(OPENGL_CONTEXT);
BIND_ENUM_CONSTANT(TTS_UTTERANCE_STARTED);
BIND_ENUM_CONSTANT(TTS_UTTERANCE_ENDED);
@@ -812,9 +858,9 @@ Vector<String> DisplayServer::get_create_function_rendering_drivers(int p_index)
return server_create_functions[p_index].get_rendering_drivers_function();
}
-DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+DisplayServer *DisplayServer::create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
ERR_FAIL_INDEX_V(p_index, server_create_count, nullptr);
- return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error);
+ return server_create_functions[p_index].create_function(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_position, p_resolution, r_error);
}
void DisplayServer::_input_set_mouse_mode(Input::MouseMode p_mode) {
diff --git a/servers/display_server.h b/servers/display_server.h
index 7a15df2f92..a796377f88 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -70,9 +70,10 @@ public:
DISPLAY_HANDLE,
WINDOW_HANDLE,
WINDOW_VIEW,
+ OPENGL_CONTEXT,
};
- typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Size2i &, Error &r_error);
+ typedef DisplayServer *(*CreateFunction)(const String &, WindowMode, VSyncMode, uint32_t, const Point2i *, const Size2i &, Error &r_error);
typedef Vector<String> (*GetRenderingDriversFunction)();
private:
@@ -122,20 +123,21 @@ public:
FEATURE_KEEP_SCREEN_ON,
FEATURE_CLIPBOARD_PRIMARY,
FEATURE_TEXT_TO_SPEECH,
+ FEATURE_EXTEND_TO_TITLE,
};
virtual bool has_feature(Feature p_feature) const = 0;
virtual String get_name() const = 0;
- virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
- virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
- virtual void global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
- virtual void global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
- virtual void global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
- virtual void global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
- virtual void global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
- virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1);
- virtual void global_menu_add_separator(const String &p_menu_root, int p_index = -1);
+ virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1);
+ virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int global_menu_add_icon_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int global_menu_add_icon_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int global_menu_add_radio_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int global_menu_add_icon_radio_check_item(const String &p_menu_root, const Ref<Texture2D> &p_icon, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int global_menu_add_multistate_item(const String &p_menu_root, const String &p_label, int p_max_states, int p_default_state, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
+ virtual int global_menu_add_separator(const String &p_menu_root, int p_index = -1);
virtual int global_menu_get_item_index_from_text(const String &p_menu_root, const String &p_text) const;
virtual int global_menu_get_item_index_from_tag(const String &p_menu_root, const Variant &p_tag) const;
@@ -144,6 +146,7 @@ public:
virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const;
virtual bool global_menu_is_item_radio_checkable(const String &p_menu_root, int p_idx) const;
virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx) const;
+ virtual Callable global_menu_get_item_key_callback(const String &p_menu_root, int p_idx) const;
virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx) const;
virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx) const;
virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const;
@@ -153,11 +156,13 @@ public:
virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const;
virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const;
virtual Ref<Texture2D> global_menu_get_item_icon(const String &p_menu_root, int p_idx) const;
+ virtual int global_menu_get_item_indentation_level(const String &p_menu_root, int p_idx) const;
virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked);
virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable);
virtual void global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable);
virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback);
+ virtual void global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback);
virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag);
virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text);
virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu);
@@ -167,6 +172,7 @@ public:
virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state);
virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states);
virtual void global_menu_set_item_icon(const String &p_menu_root, int p_idx, const Ref<Texture2D> &p_icon);
+ virtual void global_menu_set_item_indentation_level(const String &p_menu_root, int p_idx, int p_level);
virtual int global_menu_get_item_count(const String &p_menu_root) const;
@@ -196,7 +202,7 @@ private:
public:
virtual bool tts_is_speaking() const;
virtual bool tts_is_paused() const;
- virtual Array tts_get_voices() const;
+ virtual TypedArray<Dictionary> tts_get_voices() const;
virtual PackedStringArray tts_get_voices_for_language(const String &p_language) const;
virtual void tts_speak(const String &p_text, const String &p_voice, int p_volume = 50, float p_pitch = 1.f, float p_rate = 1.f, int p_utterance_id = 0, bool p_interrupt = false);
@@ -207,6 +213,10 @@ public:
virtual void tts_set_utterance_callback(TTSUtteranceEvent p_event, const Callable &p_callable);
virtual void tts_post_utterance_event(TTSUtteranceEvent p_event, int p_id, int p_pos = 0);
+ virtual bool is_dark_mode_supported() const { return false; };
+ virtual bool is_dark_mode() const { return false; };
+ virtual Color get_accent_color() const { return Color(0, 0, 0, 0); };
+
enum MouseMode {
MOUSE_MODE_VISIBLE,
MOUSE_MODE_HIDDEN,
@@ -228,7 +238,7 @@ public:
virtual void clipboard_set_primary(const String &p_text);
virtual String clipboard_get_primary() const;
- virtual Array get_display_cutouts() const { return Array(); }
+ virtual TypedArray<Rect2> get_display_cutouts() const { return TypedArray<Rect2>(); }
virtual Rect2i get_display_safe_area() const { return screen_get_usable_rect(); }
enum {
@@ -287,6 +297,7 @@ public:
WINDOW_FLAG_TRANSPARENT,
WINDOW_FLAG_NO_FOCUS,
WINDOW_FLAG_POPUP,
+ WINDOW_FLAG_EXTEND_TO_TITLE,
WINDOW_FLAG_MAX,
};
@@ -298,6 +309,7 @@ public:
WINDOW_FLAG_TRANSPARENT_BIT = (1 << WINDOW_FLAG_TRANSPARENT),
WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS),
WINDOW_FLAG_POPUP_BIT = (1 << WINDOW_FLAG_POPUP),
+ WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE),
};
virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
@@ -325,6 +337,7 @@ public:
WINDOW_EVENT_CLOSE_REQUEST,
WINDOW_EVENT_GO_BACK_REQUEST,
WINDOW_EVENT_DPI_CHANGE,
+ WINDOW_EVENT_TITLEBAR_CHANGE,
};
virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0;
@@ -369,6 +382,9 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0;
+ virtual void window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window = MAIN_WINDOW_ID) {}
+ virtual Vector3i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const { return Vector3i(); }
+
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual bool can_any_window_draw() const = 0;
@@ -376,13 +392,27 @@ public:
virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ virtual bool window_maximize_on_title_dbl_click() const { return false; }
+ virtual bool window_minimize_on_title_dbl_click() const { return false; }
+
// necessary for GL focus, may be able to use one of the existing functions for this, not sure yet
virtual void gl_window_make_current(DisplayServer::WindowID p_window_id);
virtual Point2i ime_get_selection() const;
virtual String ime_get_text() const;
- virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), bool p_multiline = false, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
+ enum VirtualKeyboardType {
+ KEYBOARD_TYPE_DEFAULT,
+ KEYBOARD_TYPE_MULTILINE,
+ KEYBOARD_TYPE_NUMBER,
+ KEYBOARD_TYPE_NUMBER_DECIMAL,
+ KEYBOARD_TYPE_PHONE,
+ KEYBOARD_TYPE_EMAIL_ADDRESS,
+ KEYBOARD_TYPE_PASSWORD,
+ KEYBOARD_TYPE_URL
+ };
+
+ virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), VirtualKeyboardType p_type = KEYBOARD_TYPE_DEFAULT, int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
virtual void virtual_keyboard_hide();
// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
@@ -454,7 +484,7 @@ public:
static int get_create_function_count();
static const char *get_create_function_name(int p_index);
static Vector<String> get_create_function_rendering_drivers(int p_index);
- static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
+ static DisplayServer *create(int p_index, const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error);
DisplayServer();
~DisplayServer();
@@ -467,6 +497,7 @@ VARIANT_ENUM_CAST(DisplayServer::ScreenOrientation)
VARIANT_ENUM_CAST(DisplayServer::WindowMode)
VARIANT_ENUM_CAST(DisplayServer::WindowFlags)
VARIANT_ENUM_CAST(DisplayServer::HandleType)
+VARIANT_ENUM_CAST(DisplayServer::VirtualKeyboardType);
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
VARIANT_ENUM_CAST(DisplayServer::TTSUtteranceEvent)
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index 3853ff4fdc..e1a27b6137 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -45,7 +45,7 @@ private:
return drivers;
}
- static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
+ static DisplayServer *create_func(const String &p_rendering_driver, DisplayServer::WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, Error &r_error) {
r_error = OK;
RasterizerDummy::make_current();
return memnew(DisplayServerHeadless());
diff --git a/servers/extensions/physics_server_2d_extension.cpp b/servers/extensions/physics_server_2d_extension.cpp
new file mode 100644
index 0000000000..e5920c78d4
--- /dev/null
+++ b/servers/extensions/physics_server_2d_extension.cpp
@@ -0,0 +1,341 @@
+/*************************************************************************/
+/* physics_server_2d_extension.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "physics_server_2d_extension.h"
+
+bool PhysicsDirectSpaceState2DExtension::is_body_excluded_from_query(const RID &p_body) const {
+ return exclude && exclude->has(p_body);
+}
+
+thread_local const HashSet<RID> *PhysicsDirectSpaceState2DExtension::exclude = nullptr;
+
+void PhysicsDirectSpaceState2DExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_intersect_ray, "from", "to", "collision_mask", "collide_with_bodies", "collide_with_areas", "hit_from_inside", "result");
+ GDVIRTUAL_BIND(_intersect_point, "position", "canvas_instance_id", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results");
+ GDVIRTUAL_BIND(_intersect_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "result", "max_results");
+ GDVIRTUAL_BIND(_cast_motion, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "closest_safe", "closest_unsafe");
+ GDVIRTUAL_BIND(_collide_shape, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "results", "max_results", "result_count");
+ GDVIRTUAL_BIND(_rest_info, "shape_rid", "transform", "motion", "margin", "collision_mask", "collide_with_bodies", "collide_with_areas", "rest_info");
+}
+
+PhysicsDirectSpaceState2DExtension::PhysicsDirectSpaceState2DExtension() {
+}
+
+void PhysicsDirectBodyState2DExtension::_bind_methods() {
+ GDVIRTUAL_BIND(_get_total_gravity);
+ GDVIRTUAL_BIND(_get_total_linear_damp);
+ GDVIRTUAL_BIND(_get_total_angular_damp);
+
+ GDVIRTUAL_BIND(_get_center_of_mass);
+ GDVIRTUAL_BIND(_get_center_of_mass_local);
+ GDVIRTUAL_BIND(_get_inverse_mass);
+ GDVIRTUAL_BIND(_get_inverse_inertia);
+
+ GDVIRTUAL_BIND(_set_linear_velocity, "velocity");
+ GDVIRTUAL_BIND(_get_linear_velocity);
+
+ GDVIRTUAL_BIND(_set_angular_velocity, "velocity");
+ GDVIRTUAL_BIND(_get_angular_velocity);
+
+ GDVIRTUAL_BIND(_set_transform, "transform");
+ GDVIRTUAL_BIND(_get_transform);
+
+ GDVIRTUAL_BIND(_get_velocity_at_local_position, "local_position");
+
+ GDVIRTUAL_BIND(_apply_central_impulse, "impulse");
+ GDVIRTUAL_BIND(_apply_impulse, "impulse", "position");
+ GDVIRTUAL_BIND(_apply_torque_impulse, "impulse");
+
+ GDVIRTUAL_BIND(_apply_central_force, "force");
+ GDVIRTUAL_BIND(_apply_force, "force", "position");
+ GDVIRTUAL_BIND(_apply_torque, "torque");
+
+ GDVIRTUAL_BIND(_add_constant_central_force, "force");
+ GDVIRTUAL_BIND(_add_constant_force, "force", "position");
+ GDVIRTUAL_BIND(_add_constant_torque, "torque");
+
+ GDVIRTUAL_BIND(_set_constant_force, "force");
+ GDVIRTUAL_BIND(_get_constant_force);
+
+ GDVIRTUAL_BIND(_set_constant_torque, "torque");
+ GDVIRTUAL_BIND(_get_constant_torque);
+
+ GDVIRTUAL_BIND(_set_sleep_state, "enabled");
+ GDVIRTUAL_BIND(_is_sleeping);
+
+ GDVIRTUAL_BIND(_get_contact_count);
+
+ GDVIRTUAL_BIND(_get_contact_local_position, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_local_normal, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_local_shape, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_position, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_id, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_object, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_shape, "contact_idx");
+ GDVIRTUAL_BIND(_get_contact_collider_velocity_at_position, "contact_idx");
+
+ GDVIRTUAL_BIND(_get_step);
+ GDVIRTUAL_BIND(_integrate_forces);
+
+ GDVIRTUAL_BIND(_get_space_state);
+}
+
+PhysicsDirectBodyState2DExtension::PhysicsDirectBodyState2DExtension() {
+}
+
+thread_local const HashSet<RID> *PhysicsServer2DExtension::exclude_bodies = nullptr;
+thread_local const HashSet<ObjectID> *PhysicsServer2DExtension::exclude_objects = nullptr;
+
+bool PhysicsServer2DExtension::body_test_motion_is_excluding_body(RID p_body) const {
+ return exclude_bodies && exclude_bodies->has(p_body);
+}
+
+bool PhysicsServer2DExtension::body_test_motion_is_excluding_object(ObjectID p_object) const {
+ return exclude_objects && exclude_objects->has(p_object);
+}
+
+void PhysicsServer2DExtension::_bind_methods() {
+ /* SHAPE API */
+
+ GDVIRTUAL_BIND(_world_boundary_shape_create);
+ GDVIRTUAL_BIND(_separation_ray_shape_create);
+ GDVIRTUAL_BIND(_segment_shape_create);
+ GDVIRTUAL_BIND(_circle_shape_create);
+ GDVIRTUAL_BIND(_rectangle_shape_create);
+ GDVIRTUAL_BIND(_capsule_shape_create);
+ GDVIRTUAL_BIND(_convex_polygon_shape_create);
+ GDVIRTUAL_BIND(_concave_polygon_shape_create);
+
+ GDVIRTUAL_BIND(_shape_set_data, "shape", "data");
+ GDVIRTUAL_BIND(_shape_set_custom_solver_bias, "shape", "bias");
+
+ GDVIRTUAL_BIND(_shape_get_type, "shape");
+ GDVIRTUAL_BIND(_shape_get_data, "shape");
+ GDVIRTUAL_BIND(_shape_get_custom_solver_bias, "shape");
+ GDVIRTUAL_BIND(_shape_collide, "shape_A", "xform_A", "motion_A", "shape_B", "xform_B", "motion_B", "results", "result_max", "result_count");
+
+ /* SPACE API */
+
+ GDVIRTUAL_BIND(_space_create);
+ GDVIRTUAL_BIND(_space_set_active, "space", "active");
+ GDVIRTUAL_BIND(_space_is_active, "space");
+
+ GDVIRTUAL_BIND(_space_set_param, "space", "param", "value");
+ GDVIRTUAL_BIND(_space_get_param, "space", "param");
+
+ GDVIRTUAL_BIND(_space_get_direct_state, "space");
+
+ GDVIRTUAL_BIND(_space_set_debug_contacts, "space", "max_contacts");
+ GDVIRTUAL_BIND(_space_get_contacts, "space");
+ GDVIRTUAL_BIND(_space_get_contact_count, "space");
+
+ /* AREA API */
+
+ GDVIRTUAL_BIND(_area_create);
+
+ GDVIRTUAL_BIND(_area_set_space, "area", "space");
+ GDVIRTUAL_BIND(_area_get_space, "area");
+
+ GDVIRTUAL_BIND(_area_add_shape, "area", "shape", "transform", "disabled");
+ GDVIRTUAL_BIND(_area_set_shape, "area", "shape_idx", "shape");
+ GDVIRTUAL_BIND(_area_set_shape_transform, "area", "shape_idx", "transform");
+ GDVIRTUAL_BIND(_area_set_shape_disabled, "area", "shape_idx", "disabled");
+
+ GDVIRTUAL_BIND(_area_get_shape_count, "area");
+ GDVIRTUAL_BIND(_area_get_shape, "area", "shape_idx");
+ GDVIRTUAL_BIND(_area_get_shape_transform, "area", "shape_idx");
+
+ GDVIRTUAL_BIND(_area_remove_shape, "area", "shape_idx");
+ GDVIRTUAL_BIND(_area_clear_shapes, "area");
+
+ GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id");
+ GDVIRTUAL_BIND(_area_get_object_instance_id, "area");
+
+ GDVIRTUAL_BIND(_area_attach_canvas_instance_id, "area", "id");
+ GDVIRTUAL_BIND(_area_get_canvas_instance_id, "area");
+
+ GDVIRTUAL_BIND(_area_set_param, "area", "param", "value");
+ GDVIRTUAL_BIND(_area_set_transform, "area", "transform");
+
+ GDVIRTUAL_BIND(_area_get_param, "area", "param");
+ GDVIRTUAL_BIND(_area_get_transform, "area");
+
+ GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer");
+ GDVIRTUAL_BIND(_area_get_collision_layer, "area");
+
+ GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask");
+ GDVIRTUAL_BIND(_area_get_collision_mask, "area");
+
+ GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable");
+ GDVIRTUAL_BIND(_area_set_pickable, "area", "pickable");
+
+ GDVIRTUAL_BIND(_area_set_monitor_callback, "area", "callback");
+ GDVIRTUAL_BIND(_area_set_area_monitor_callback, "area", "callback");
+
+ /* BODY API */
+
+ GDVIRTUAL_BIND(_body_create);
+
+ GDVIRTUAL_BIND(_body_set_space, "body", "space");
+ GDVIRTUAL_BIND(_body_get_space, "body");
+
+ GDVIRTUAL_BIND(_body_set_mode, "body", "mode");
+ GDVIRTUAL_BIND(_body_get_mode, "body");
+
+ GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled");
+ GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape");
+ GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform");
+
+ GDVIRTUAL_BIND(_body_get_shape_count, "body");
+ GDVIRTUAL_BIND(_body_get_shape, "body", "shape_idx");
+ GDVIRTUAL_BIND(_body_get_shape_transform, "body", "shape_idx");
+
+ GDVIRTUAL_BIND(_body_set_shape_disabled, "body", "shape_idx", "disabled");
+ GDVIRTUAL_BIND(_body_set_shape_as_one_way_collision, "body", "shape_idx", "enable", "margin");
+
+ GDVIRTUAL_BIND(_body_remove_shape, "body", "shape_idx");
+ GDVIRTUAL_BIND(_body_clear_shapes, "body");
+
+ GDVIRTUAL_BIND(_body_attach_object_instance_id, "body", "id");
+ GDVIRTUAL_BIND(_body_get_object_instance_id, "body");
+
+ GDVIRTUAL_BIND(_body_attach_canvas_instance_id, "body", "id");
+ GDVIRTUAL_BIND(_body_get_canvas_instance_id, "body");
+
+ GDVIRTUAL_BIND(_body_set_continuous_collision_detection_mode, "body", "mode");
+ GDVIRTUAL_BIND(_body_get_continuous_collision_detection_mode, "body");
+
+ GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer");
+ GDVIRTUAL_BIND(_body_get_collision_layer, "body");
+
+ GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask");
+ GDVIRTUAL_BIND(_body_get_collision_mask, "body");
+
+ GDVIRTUAL_BIND(_body_set_collision_priority, "body", "priority");
+ GDVIRTUAL_BIND(_body_get_collision_priority, "body");
+
+ GDVIRTUAL_BIND(_body_set_param, "body", "param", "value");
+ GDVIRTUAL_BIND(_body_get_param, "body", "param");
+
+ GDVIRTUAL_BIND(_body_reset_mass_properties, "body");
+
+ GDVIRTUAL_BIND(_body_set_state, "body", "state", "value");
+ GDVIRTUAL_BIND(_body_get_state, "body", "state");
+
+ GDVIRTUAL_BIND(_body_apply_central_impulse, "body", "impulse");
+ GDVIRTUAL_BIND(_body_apply_torque_impulse, "body", "impulse");
+ GDVIRTUAL_BIND(_body_apply_impulse, "body", "impulse", "position");
+
+ GDVIRTUAL_BIND(_body_apply_central_force, "body", "force");
+ GDVIRTUAL_BIND(_body_apply_force, "body", "force", "position");
+ GDVIRTUAL_BIND(_body_apply_torque, "body", "torque");
+
+ GDVIRTUAL_BIND(_body_add_constant_central_force, "body", "force");
+ GDVIRTUAL_BIND(_body_add_constant_force, "body", "force", "position");
+ GDVIRTUAL_BIND(_body_add_constant_torque, "body", "torque");
+
+ GDVIRTUAL_BIND(_body_set_constant_force, "body", "force");
+ GDVIRTUAL_BIND(_body_get_constant_force, "body");
+
+ GDVIRTUAL_BIND(_body_set_constant_torque, "body", "torque");
+ GDVIRTUAL_BIND(_body_get_constant_torque, "body");
+
+ GDVIRTUAL_BIND(_body_set_axis_velocity, "body", "axis_velocity");
+
+ GDVIRTUAL_BIND(_body_add_collision_exception, "body", "excepted_body");
+ GDVIRTUAL_BIND(_body_remove_collision_exception, "body", "excepted_body");
+ GDVIRTUAL_BIND(_body_get_collision_exceptions, "body");
+
+ GDVIRTUAL_BIND(_body_set_max_contacts_reported, "body", "amount");
+ GDVIRTUAL_BIND(_body_get_max_contacts_reported, "body");
+
+ GDVIRTUAL_BIND(_body_set_contacts_reported_depth_threshold, "body", "threshold");
+ GDVIRTUAL_BIND(_body_get_contacts_reported_depth_threshold, "body");
+
+ GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable");
+ GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body");
+
+ GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callable");
+ GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata");
+
+ GDVIRTUAL_BIND(_body_collide_shape, "body", "body_shape", "shape", "shape_xform", "motion", "results", "result_max", "result_count");
+
+ GDVIRTUAL_BIND(_body_set_pickable, "body", "pickable");
+
+ GDVIRTUAL_BIND(_body_get_direct_state, "body");
+
+ GDVIRTUAL_BIND(_body_test_motion, "body", "from", "motion", "margin", "collide_separation_ray", "recovery_as_collision", "result");
+
+ /* JOINT API */
+
+ GDVIRTUAL_BIND(_joint_create);
+ GDVIRTUAL_BIND(_joint_clear, "joint");
+
+ GDVIRTUAL_BIND(_joint_set_param, "joint", "param", "value");
+ GDVIRTUAL_BIND(_joint_get_param, "joint", "param");
+
+ GDVIRTUAL_BIND(_joint_disable_collisions_between_bodies, "joint", "disable");
+ GDVIRTUAL_BIND(_joint_is_disabled_collisions_between_bodies, "joint");
+
+ GDVIRTUAL_BIND(_joint_make_pin, "joint", "anchor", "body_a", "body_b");
+ GDVIRTUAL_BIND(_joint_make_groove, "joint", "a_groove1", "a_groove2", "b_anchor", "body_a", "body_b");
+ GDVIRTUAL_BIND(_joint_make_damped_spring, "joint", "anchor_a", "anchor_b", "body_a", "body_b");
+
+ GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value");
+ GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param");
+
+ GDVIRTUAL_BIND(_damped_spring_joint_set_param, "joint", "param", "value");
+ GDVIRTUAL_BIND(_damped_spring_joint_get_param, "joint", "param");
+
+ GDVIRTUAL_BIND(_joint_get_type, "joint");
+
+ /* MISC */
+
+ GDVIRTUAL_BIND(_free_rid, "rid");
+
+ GDVIRTUAL_BIND(_set_active, "active");
+
+ GDVIRTUAL_BIND(_init);
+ GDVIRTUAL_BIND(_step, "step");
+ GDVIRTUAL_BIND(_sync);
+ GDVIRTUAL_BIND(_flush_queries);
+ GDVIRTUAL_BIND(_end_sync);
+ GDVIRTUAL_BIND(_finish);
+
+ GDVIRTUAL_BIND(_is_flushing_queries);
+ GDVIRTUAL_BIND(_get_process_info, "process_info");
+}
+
+PhysicsServer2DExtension::PhysicsServer2DExtension() {
+}
+
+PhysicsServer2DExtension::~PhysicsServer2DExtension() {
+}
diff --git a/servers/extensions/physics_server_2d_extension.h b/servers/extensions/physics_server_2d_extension.h
new file mode 100644
index 0000000000..573b51ee12
--- /dev/null
+++ b/servers/extensions/physics_server_2d_extension.h
@@ -0,0 +1,452 @@
+/*************************************************************************/
+/* physics_server_2d_extension.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef PHYSICS_SERVER_2D_EXTENSION_H
+#define PHYSICS_SERVER_2D_EXTENSION_H
+
+#include "core/extension/ext_wrappers.gen.inc"
+#include "core/object/gdvirtual.gen.inc"
+#include "core/object/script_language.h"
+#include "core/variant/native_ptr.h"
+#include "core/variant/type_info.h"
+#include "core/variant/typed_array.h"
+#include "servers/physics_server_2d.h"
+
+class PhysicsDirectBodyState2DExtension : public PhysicsDirectBodyState2D {
+ GDCLASS(PhysicsDirectBodyState2DExtension, PhysicsDirectBodyState2D);
+
+protected:
+ static void _bind_methods();
+
+public:
+ // The warning is valid, but unavoidable. If the function is not overridden it will error anyway.
+
+ EXBIND0RC(Vector2, get_total_gravity)
+ EXBIND0RC(real_t, get_total_angular_damp)
+ EXBIND0RC(real_t, get_total_linear_damp)
+
+ EXBIND0RC(Vector2, get_center_of_mass)
+ EXBIND0RC(Vector2, get_center_of_mass_local)
+ EXBIND0RC(real_t, get_inverse_mass)
+ EXBIND0RC(real_t, get_inverse_inertia)
+
+ EXBIND1(set_linear_velocity, const Vector2 &)
+ EXBIND0RC(Vector2, get_linear_velocity)
+
+ EXBIND1(set_angular_velocity, real_t)
+ EXBIND0RC(real_t, get_angular_velocity)
+
+ EXBIND1(set_transform, const Transform2D &)
+ EXBIND0RC(Transform2D, get_transform)
+
+ EXBIND1RC(Vector2, get_velocity_at_local_position, const Vector2 &)
+
+ EXBIND1(apply_central_impulse, const Vector2 &)
+ EXBIND1(apply_torque_impulse, real_t)
+ EXBIND2(apply_impulse, const Vector2 &, const Vector2 &)
+
+ EXBIND1(apply_central_force, const Vector2 &)
+ EXBIND2(apply_force, const Vector2 &, const Vector2 &)
+ EXBIND1(apply_torque, real_t)
+
+ EXBIND1(add_constant_central_force, const Vector2 &)
+ EXBIND2(add_constant_force, const Vector2 &, const Vector2 &)
+ EXBIND1(add_constant_torque, real_t)
+
+ EXBIND1(set_constant_force, const Vector2 &)
+ EXBIND0RC(Vector2, get_constant_force)
+
+ EXBIND1(set_constant_torque, real_t)
+ EXBIND0RC(real_t, get_constant_torque)
+
+ EXBIND1(set_sleep_state, bool)
+ EXBIND0RC(bool, is_sleeping)
+
+ EXBIND0RC(int, get_contact_count)
+
+ EXBIND1RC(Vector2, get_contact_local_position, int)
+ EXBIND1RC(Vector2, get_contact_local_normal, int)
+ EXBIND1RC(int, get_contact_local_shape, int)
+ EXBIND1RC(RID, get_contact_collider, int)
+ EXBIND1RC(Vector2, get_contact_collider_position, int)
+ EXBIND1RC(ObjectID, get_contact_collider_id, int)
+ EXBIND1RC(Object *, get_contact_collider_object, int)
+ EXBIND1RC(int, get_contact_collider_shape, int)
+ EXBIND1RC(Vector2, get_contact_collider_velocity_at_position, int)
+
+ EXBIND0RC(real_t, get_step)
+ EXBIND0(integrate_forces)
+
+ EXBIND0R(PhysicsDirectSpaceState2D *, get_space_state)
+
+ PhysicsDirectBodyState2DExtension();
+};
+
+typedef PhysicsDirectSpaceState2D::RayResult PhysicsServer2DExtensionRayResult;
+typedef PhysicsDirectSpaceState2D::ShapeResult PhysicsServer2DExtensionShapeResult;
+typedef PhysicsDirectSpaceState2D::ShapeRestInfo PhysicsServer2DExtensionShapeRestInfo;
+
+GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionRayResult)
+GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionShapeResult)
+GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionShapeRestInfo)
+
+class PhysicsDirectSpaceState2DExtension : public PhysicsDirectSpaceState2D {
+ GDCLASS(PhysicsDirectSpaceState2DExtension, PhysicsDirectSpaceState2D);
+
+ thread_local static const HashSet<RID> *exclude;
+
+protected:
+ static void _bind_methods();
+ bool is_body_excluded_from_query(const RID &p_body) const;
+
+ GDVIRTUAL7R(bool, _intersect_ray, const Vector2 &, const Vector2 &, uint32_t, bool, bool, bool, GDNativePtr<PhysicsServer2DExtensionRayResult>)
+ GDVIRTUAL7R(int, _intersect_point, const Vector2 &, ObjectID, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeResult>, int)
+ GDVIRTUAL9R(int, _intersect_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeResult>, int)
+ GDVIRTUAL9R(bool, _cast_motion, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<real_t>, GDNativePtr<real_t>)
+ GDVIRTUAL10R(bool, _collide_shape, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<Vector2>, int, GDNativePtr<int>)
+ GDVIRTUAL8R(bool, _rest_info, RID, const Transform2D &, const Vector2 &, real_t, uint32_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionShapeRestInfo>)
+
+public:
+ virtual bool intersect_ray(const RayParameters &p_parameters, RayResult &r_result) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_intersect_ray, p_parameters.from, p_parameters.to, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, p_parameters.hit_from_inside, &r_result, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual int intersect_point(const PointParameters &p_parameters, ShapeResult *r_results, int p_result_max) override {
+ exclude = &p_parameters.exclude;
+ int ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_intersect_point, p_parameters.position, p_parameters.canvas_instance_id, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual int intersect_shape(const ShapeParameters &p_parameters, ShapeResult *r_results, int p_result_max) override {
+ exclude = &p_parameters.exclude;
+ int ret = 0;
+ GDVIRTUAL_REQUIRED_CALL(_intersect_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual bool cast_motion(const ShapeParameters &p_parameters, real_t &p_closest_safe, real_t &p_closest_unsafe) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_cast_motion, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, &p_closest_safe, &p_closest_unsafe, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual bool collide_shape(const ShapeParameters &p_parameters, Vector2 *r_results, int p_result_max, int &r_result_count) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_collide_shape, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_results, p_result_max, &r_result_count, ret);
+ exclude = nullptr;
+ return ret;
+ }
+ virtual bool rest_info(const ShapeParameters &p_parameters, ShapeRestInfo *r_info) override {
+ exclude = &p_parameters.exclude;
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_rest_info, p_parameters.shape_rid, p_parameters.transform, p_parameters.motion, p_parameters.margin, p_parameters.collision_mask, p_parameters.collide_with_bodies, p_parameters.collide_with_areas, r_info, ret);
+ exclude = nullptr;
+ return ret;
+ }
+
+ PhysicsDirectSpaceState2DExtension();
+};
+
+typedef PhysicsServer2D::MotionResult PhysicsServer2DExtensionMotionResult;
+
+GDVIRTUAL_NATIVE_PTR(PhysicsServer2DExtensionMotionResult)
+
+class PhysicsServer2DExtension : public PhysicsServer2D {
+ GDCLASS(PhysicsServer2DExtension, PhysicsServer2D);
+
+protected:
+ static void _bind_methods();
+
+ GDVIRTUAL9R(bool, _shape_collide, RID, const Transform2D &, const Vector2 &, RID, const Transform2D &, const Vector2 &, GDNativePtr<Vector2>, int, GDNativePtr<int>)
+
+ GDVIRTUAL8R(bool, _body_collide_shape, RID, int, RID, const Transform2D &, const Vector2 &, GDNativePtr<Vector2>, int, GDNativePtr<int>)
+
+public:
+ // The warning is valid, but unavoidable. If the function is not overridden it will error anyway.
+
+ /* SHAPE API */
+
+ EXBIND0R(RID, world_boundary_shape_create)
+ EXBIND0R(RID, separation_ray_shape_create)
+ EXBIND0R(RID, segment_shape_create)
+ EXBIND0R(RID, circle_shape_create)
+ EXBIND0R(RID, rectangle_shape_create)
+ EXBIND0R(RID, capsule_shape_create)
+ EXBIND0R(RID, convex_polygon_shape_create)
+ EXBIND0R(RID, concave_polygon_shape_create)
+
+ EXBIND2(shape_set_data, RID, const Variant &)
+ EXBIND2(shape_set_custom_solver_bias, RID, real_t)
+
+ EXBIND1RC(ShapeType, shape_get_type, RID)
+ EXBIND1RC(Variant, shape_get_data, RID)
+ EXBIND1RC(real_t, shape_get_custom_solver_bias, RID)
+
+ virtual bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) override {
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_shape_collide, p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, &r_result_count, ret);
+ return ret;
+ }
+
+ /* SPACE API */
+
+ EXBIND0R(RID, space_create)
+ EXBIND2(space_set_active, RID, bool)
+ EXBIND1RC(bool, space_is_active, RID)
+
+ EXBIND3(space_set_param, RID, SpaceParameter, real_t)
+ EXBIND2RC(real_t, space_get_param, RID, SpaceParameter)
+
+ EXBIND1R(PhysicsDirectSpaceState2D *, space_get_direct_state, RID)
+
+ EXBIND2(space_set_debug_contacts, RID, int)
+ EXBIND1RC(Vector<Vector2>, space_get_contacts, RID)
+ EXBIND1RC(int, space_get_contact_count, RID)
+
+ /* AREA API */
+
+ //EXBIND0RID(area);
+ EXBIND0R(RID, area_create)
+
+ EXBIND2(area_set_space, RID, RID)
+ EXBIND1RC(RID, area_get_space, RID)
+
+ EXBIND4(area_add_shape, RID, RID, const Transform2D &, bool)
+ EXBIND3(area_set_shape, RID, int, RID)
+ EXBIND3(area_set_shape_transform, RID, int, const Transform2D &)
+ EXBIND3(area_set_shape_disabled, RID, int, bool)
+
+ EXBIND1RC(int, area_get_shape_count, RID)
+ EXBIND2RC(RID, area_get_shape, RID, int)
+ EXBIND2RC(Transform2D, area_get_shape_transform, RID, int)
+
+ EXBIND2(area_remove_shape, RID, int)
+ EXBIND1(area_clear_shapes, RID)
+
+ EXBIND2(area_attach_object_instance_id, RID, ObjectID)
+ EXBIND1RC(ObjectID, area_get_object_instance_id, RID)
+
+ EXBIND2(area_attach_canvas_instance_id, RID, ObjectID)
+ EXBIND1RC(ObjectID, area_get_canvas_instance_id, RID)
+
+ EXBIND3(area_set_param, RID, AreaParameter, const Variant &)
+ EXBIND2(area_set_transform, RID, const Transform2D &)
+
+ EXBIND2RC(Variant, area_get_param, RID, AreaParameter)
+ EXBIND1RC(Transform2D, area_get_transform, RID)
+
+ EXBIND2(area_set_collision_layer, RID, uint32_t)
+ EXBIND1RC(uint32_t, area_get_collision_layer, RID)
+
+ EXBIND2(area_set_collision_mask, RID, uint32_t)
+ EXBIND1RC(uint32_t, area_get_collision_mask, RID)
+
+ EXBIND2(area_set_monitorable, RID, bool)
+ EXBIND2(area_set_pickable, RID, bool)
+
+ EXBIND2(area_set_monitor_callback, RID, const Callable &)
+ EXBIND2(area_set_area_monitor_callback, RID, const Callable &)
+
+ /* BODY API */
+
+ //EXBIND2RID(body,BodyMode,bool);
+ EXBIND0R(RID, body_create)
+
+ EXBIND2(body_set_space, RID, RID)
+ EXBIND1RC(RID, body_get_space, RID)
+
+ EXBIND2(body_set_mode, RID, BodyMode)
+ EXBIND1RC(BodyMode, body_get_mode, RID)
+
+ EXBIND4(body_add_shape, RID, RID, const Transform2D &, bool)
+ EXBIND3(body_set_shape, RID, int, RID)
+ EXBIND3(body_set_shape_transform, RID, int, const Transform2D &)
+
+ EXBIND1RC(int, body_get_shape_count, RID)
+ EXBIND2RC(RID, body_get_shape, RID, int)
+ EXBIND2RC(Transform2D, body_get_shape_transform, RID, int)
+
+ EXBIND3(body_set_shape_disabled, RID, int, bool)
+ EXBIND4(body_set_shape_as_one_way_collision, RID, int, bool, real_t)
+
+ EXBIND2(body_remove_shape, RID, int)
+ EXBIND1(body_clear_shapes, RID)
+
+ EXBIND2(body_attach_object_instance_id, RID, ObjectID)
+ EXBIND1RC(ObjectID, body_get_object_instance_id, RID)
+
+ EXBIND2(body_attach_canvas_instance_id, RID, ObjectID)
+ EXBIND1RC(ObjectID, body_get_canvas_instance_id, RID)
+
+ EXBIND2(body_set_continuous_collision_detection_mode, RID, CCDMode)
+ EXBIND1RC(CCDMode, body_get_continuous_collision_detection_mode, RID)
+
+ EXBIND2(body_set_collision_layer, RID, uint32_t)
+ EXBIND1RC(uint32_t, body_get_collision_layer, RID)
+
+ EXBIND2(body_set_collision_mask, RID, uint32_t)
+ EXBIND1RC(uint32_t, body_get_collision_mask, RID)
+
+ EXBIND2(body_set_collision_priority, RID, real_t)
+ EXBIND1RC(real_t, body_get_collision_priority, RID)
+
+ EXBIND3(body_set_param, RID, BodyParameter, const Variant &)
+ EXBIND2RC(Variant, body_get_param, RID, BodyParameter)
+
+ EXBIND1(body_reset_mass_properties, RID)
+
+ EXBIND3(body_set_state, RID, BodyState, const Variant &)
+ EXBIND2RC(Variant, body_get_state, RID, BodyState)
+
+ EXBIND2(body_apply_central_impulse, RID, const Vector2 &)
+ EXBIND2(body_apply_torque_impulse, RID, real_t)
+ EXBIND3(body_apply_impulse, RID, const Vector2 &, const Vector2 &)
+
+ EXBIND2(body_apply_central_force, RID, const Vector2 &)
+ EXBIND3(body_apply_force, RID, const Vector2 &, const Vector2 &)
+ EXBIND2(body_apply_torque, RID, real_t)
+
+ EXBIND2(body_add_constant_central_force, RID, const Vector2 &)
+ EXBIND3(body_add_constant_force, RID, const Vector2 &, const Vector2 &)
+ EXBIND2(body_add_constant_torque, RID, real_t)
+
+ EXBIND2(body_set_constant_force, RID, const Vector2 &)
+ EXBIND1RC(Vector2, body_get_constant_force, RID)
+
+ EXBIND2(body_set_constant_torque, RID, real_t)
+ EXBIND1RC(real_t, body_get_constant_torque, RID)
+
+ EXBIND2(body_set_axis_velocity, RID, const Vector2 &)
+
+ EXBIND2(body_add_collision_exception, RID, RID)
+ EXBIND2(body_remove_collision_exception, RID, RID)
+ GDVIRTUAL1RC(TypedArray<RID>, _body_get_collision_exceptions, RID)
+
+ void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions) override {
+ TypedArray<RID> ret;
+ GDVIRTUAL_REQUIRED_CALL(_body_get_collision_exceptions, p_body, ret);
+ for (int i = 0; i < ret.size(); i++) {
+ p_exceptions->push_back(ret[i]);
+ }
+ }
+
+ EXBIND2(body_set_max_contacts_reported, RID, int)
+ EXBIND1RC(int, body_get_max_contacts_reported, RID)
+
+ EXBIND2(body_set_contacts_reported_depth_threshold, RID, real_t)
+ EXBIND1RC(real_t, body_get_contacts_reported_depth_threshold, RID)
+
+ EXBIND2(body_set_omit_force_integration, RID, bool)
+ EXBIND1RC(bool, body_is_omitting_force_integration, RID)
+
+ EXBIND2(body_set_state_sync_callback, RID, const Callable &)
+ EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &)
+
+ virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
+ bool ret = false;
+ GDVIRTUAL_REQUIRED_CALL(_body_collide_shape, p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, &r_result_count, ret);
+ return ret;
+ }
+
+ EXBIND2(body_set_pickable, RID, bool)
+
+ EXBIND1R(PhysicsDirectBodyState2D *, body_get_direct_state, RID)
+
+ GDVIRTUAL7RC(bool, _body_test_motion, RID, const Transform2D &, const Vector2 &, real_t, bool, bool, GDNativePtr<PhysicsServer2DExtensionMotionResult>)
+
+ thread_local static const HashSet<RID> *exclude_bodies;
+ thread_local static const HashSet<ObjectID> *exclude_objects;
+
+ bool body_test_motion_is_excluding_body(RID p_body) const;
+ bool body_test_motion_is_excluding_object(ObjectID p_object) const;
+
+ bool body_test_motion(RID p_body, const MotionParameters &p_parameters, MotionResult *r_result = nullptr) override {
+ bool ret = false;
+ exclude_bodies = &p_parameters.exclude_bodies;
+ exclude_objects = &p_parameters.exclude_objects;
+ GDVIRTUAL_REQUIRED_CALL(_body_test_motion, p_body, p_parameters.from, p_parameters.motion, p_parameters.margin, p_parameters.collide_separation_ray, p_parameters.recovery_as_collision, r_result, ret);
+ exclude_bodies = nullptr;
+ exclude_objects = nullptr;
+ return ret;
+ }
+
+ /* JOINT API */
+
+ EXBIND0R(RID, joint_create)
+ EXBIND1(joint_clear, RID)
+
+ EXBIND3(joint_set_param, RID, JointParam, real_t)
+ EXBIND2RC(real_t, joint_get_param, RID, JointParam)
+
+ EXBIND2(joint_disable_collisions_between_bodies, RID, bool)
+ EXBIND1RC(bool, joint_is_disabled_collisions_between_bodies, RID)
+
+ EXBIND4(joint_make_pin, RID, const Vector2 &, RID, RID)
+ EXBIND6(joint_make_groove, RID, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID)
+ EXBIND5(joint_make_damped_spring, RID, const Vector2 &, const Vector2 &, RID, RID)
+
+ EXBIND3(pin_joint_set_param, RID, PinJointParam, real_t)
+ EXBIND2RC(real_t, pin_joint_get_param, RID, PinJointParam)
+
+ EXBIND3(damped_spring_joint_set_param, RID, DampedSpringParam, real_t)
+ EXBIND2RC(real_t, damped_spring_joint_get_param, RID, DampedSpringParam)
+
+ EXBIND1RC(JointType, joint_get_type, RID)
+
+ /* MISC */
+
+ GDVIRTUAL1(_free_rid, RID)
+ virtual void free(RID p_rid) override {
+ GDVIRTUAL_REQUIRED_CALL(_free_rid, p_rid);
+ }
+
+ EXBIND1(set_active, bool)
+
+ EXBIND0(init)
+ EXBIND1(step, real_t)
+ EXBIND0(sync)
+ EXBIND0(flush_queries)
+ EXBIND0(end_sync)
+ EXBIND0(finish)
+
+ EXBIND0RC(bool, is_flushing_queries)
+ EXBIND1R(int, get_process_info, ProcessInfo)
+
+ PhysicsServer2DExtension();
+ ~PhysicsServer2DExtension();
+};
+
+#endif // PHYSICS_SERVER_2D_EXTENSION_H
diff --git a/servers/extensions/physics_server_3d_extension.cpp b/servers/extensions/physics_server_3d_extension.cpp
index 3694dcdb9a..811ff231fc 100644
--- a/servers/extensions/physics_server_3d_extension.cpp
+++ b/servers/extensions/physics_server_3d_extension.cpp
@@ -60,6 +60,7 @@ void PhysicsDirectBodyState3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_get_inverse_mass);
GDVIRTUAL_BIND(_get_inverse_inertia);
+ GDVIRTUAL_BIND(_get_inverse_inertia_tensor);
GDVIRTUAL_BIND(_set_linear_velocity, "velocity");
GDVIRTUAL_BIND(_get_linear_velocity);
@@ -125,6 +126,8 @@ bool PhysicsServer3DExtension::body_test_motion_is_excluding_object(ObjectID p_o
}
void PhysicsServer3DExtension::_bind_methods() {
+ /* SHAPE API */
+
GDVIRTUAL_BIND(_world_boundary_shape_create);
GDVIRTUAL_BIND(_separation_ray_shape_create);
GDVIRTUAL_BIND(_sphere_shape_create);
@@ -137,18 +140,34 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_custom_shape_create);
GDVIRTUAL_BIND(_shape_set_data, "shape", "data");
+ GDVIRTUAL_BIND(_shape_set_custom_solver_bias, "shape", "bias");
+
+ GDVIRTUAL_BIND(_shape_set_margin, "shape", "margin");
+ GDVIRTUAL_BIND(_shape_get_margin, "shape");
GDVIRTUAL_BIND(_shape_get_type, "shape");
GDVIRTUAL_BIND(_shape_get_data, "shape");
+ GDVIRTUAL_BIND(_shape_get_custom_solver_bias, "shape");
+
+ /* SPACE API */
GDVIRTUAL_BIND(_space_create);
GDVIRTUAL_BIND(_space_set_active, "space", "active");
GDVIRTUAL_BIND(_space_is_active, "space");
+
GDVIRTUAL_BIND(_space_set_param, "space", "param", "value");
GDVIRTUAL_BIND(_space_get_param, "space", "param");
+
GDVIRTUAL_BIND(_space_get_direct_state, "space");
+ GDVIRTUAL_BIND(_space_set_debug_contacts, "space", "max_contacts");
+ GDVIRTUAL_BIND(_space_get_contacts, "space");
+ GDVIRTUAL_BIND(_space_get_contact_count, "space");
+
+ /* AREA API */
+
GDVIRTUAL_BIND(_area_create);
+
GDVIRTUAL_BIND(_area_set_space, "area", "space");
GDVIRTUAL_BIND(_area_get_space, "area");
@@ -164,8 +183,8 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_area_remove_shape, "area", "shape_idx");
GDVIRTUAL_BIND(_area_clear_shapes, "area");
- GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer");
- GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask");
+ GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id");
+ GDVIRTUAL_BIND(_area_get_object_instance_id, "area");
GDVIRTUAL_BIND(_area_set_param, "area", "param", "value");
GDVIRTUAL_BIND(_area_set_transform, "area", "transform");
@@ -173,14 +192,19 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_area_get_param, "area", "param");
GDVIRTUAL_BIND(_area_get_transform, "area");
- GDVIRTUAL_BIND(_area_attach_object_instance_id, "area", "id");
- GDVIRTUAL_BIND(_area_get_object_instance_id, "area");
+ GDVIRTUAL_BIND(_area_set_collision_layer, "area", "layer");
+ GDVIRTUAL_BIND(_area_get_collision_layer, "area");
+
+ GDVIRTUAL_BIND(_area_set_collision_mask, "area", "mask");
+ GDVIRTUAL_BIND(_area_get_collision_mask, "area");
+
+ GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable");
+ GDVIRTUAL_BIND(_area_set_ray_pickable, "area", "enable");
GDVIRTUAL_BIND(_area_set_monitor_callback, "area", "callback");
GDVIRTUAL_BIND(_area_set_area_monitor_callback, "area", "callback");
- GDVIRTUAL_BIND(_area_set_monitorable, "area", "monitorable");
- GDVIRTUAL_BIND(_area_set_ray_pickable, "area", "enable");
+ /* BODY API */
GDVIRTUAL_BIND(_body_create);
@@ -190,12 +214,6 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_body_set_mode, "body", "mode");
GDVIRTUAL_BIND(_body_get_mode, "body");
- GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer");
- GDVIRTUAL_BIND(_body_get_collision_layer, "body");
-
- GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask");
- GDVIRTUAL_BIND(_body_get_collision_mask, "body");
-
GDVIRTUAL_BIND(_body_add_shape, "body", "shape", "transform", "disabled");
GDVIRTUAL_BIND(_body_set_shape, "body", "shape_idx", "shape");
GDVIRTUAL_BIND(_body_set_shape_transform, "body", "shape_idx", "transform");
@@ -214,6 +232,18 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_body_set_enable_continuous_collision_detection, "body", "enable");
GDVIRTUAL_BIND(_body_is_continuous_collision_detection_enabled, "body");
+ GDVIRTUAL_BIND(_body_set_collision_layer, "body", "layer");
+ GDVIRTUAL_BIND(_body_get_collision_layer, "body");
+
+ GDVIRTUAL_BIND(_body_set_collision_mask, "body", "mask");
+ GDVIRTUAL_BIND(_body_get_collision_mask, "body");
+
+ GDVIRTUAL_BIND(_body_set_collision_priority, "body", "priority");
+ GDVIRTUAL_BIND(_body_get_collision_priority, "body");
+
+ GDVIRTUAL_BIND(_body_set_user_flags, "body", "flags");
+ GDVIRTUAL_BIND(_body_get_user_flags, "body");
+
GDVIRTUAL_BIND(_body_set_param, "body", "param", "value");
GDVIRTUAL_BIND(_body_get_param, "body", "param");
@@ -247,13 +277,18 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_body_add_collision_exception, "body", "excepted_body");
GDVIRTUAL_BIND(_body_remove_collision_exception, "body", "excepted_body");
+ GDVIRTUAL_BIND(_body_get_collision_exceptions, "body");
GDVIRTUAL_BIND(_body_set_max_contacts_reported, "body", "amount");
GDVIRTUAL_BIND(_body_get_max_contacts_reported, "body");
+ GDVIRTUAL_BIND(_body_set_contacts_reported_depth_threshold, "body", "threshold");
+ GDVIRTUAL_BIND(_body_get_contacts_reported_depth_threshold, "body");
+
GDVIRTUAL_BIND(_body_set_omit_force_integration, "body", "enable");
GDVIRTUAL_BIND(_body_is_omitting_force_integration, "body");
+ GDVIRTUAL_BIND(_body_set_state_sync_callback, "body", "callable");
GDVIRTUAL_BIND(_body_set_force_integration_callback, "body", "callable", "userdata");
GDVIRTUAL_BIND(_body_set_ray_pickable, "body", "enable");
@@ -262,12 +297,68 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_body_get_direct_state, "body");
+ /* SOFT BODY API */
+
+ GDVIRTUAL_BIND(_soft_body_create);
+
+ GDVIRTUAL_BIND(_soft_body_update_rendering_server, "body", "rendering_server_handler");
+
+ GDVIRTUAL_BIND(_soft_body_set_space, "body", "space");
+ GDVIRTUAL_BIND(_soft_body_get_space, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_ray_pickable, "body", "enable");
+
+ GDVIRTUAL_BIND(_soft_body_set_collision_layer, "body", "layer");
+ GDVIRTUAL_BIND(_soft_body_get_collision_layer, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_collision_mask, "body", "mask");
+ GDVIRTUAL_BIND(_soft_body_get_collision_mask, "body");
+
+ GDVIRTUAL_BIND(_soft_body_add_collision_exception, "body", "body_b");
+ GDVIRTUAL_BIND(_soft_body_remove_collision_exception, "body", "body_b");
+ GDVIRTUAL_BIND(_soft_body_get_collision_exceptions, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_state, "body", "state", "variant");
+ GDVIRTUAL_BIND(_soft_body_get_state, "body", "state");
+
+ GDVIRTUAL_BIND(_soft_body_set_transform, "body", "transform");
+
+ GDVIRTUAL_BIND(_soft_body_set_simulation_precision, "body", "simulation_precision");
+ GDVIRTUAL_BIND(_soft_body_get_simulation_precision, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_total_mass, "body", "total_mass");
+ GDVIRTUAL_BIND(_soft_body_get_total_mass, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_linear_stiffness, "body", "linear_stiffness");
+ GDVIRTUAL_BIND(_soft_body_get_linear_stiffness, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_pressure_coefficient, "body", "pressure_coefficient");
+ GDVIRTUAL_BIND(_soft_body_get_pressure_coefficient, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_damping_coefficient, "body", "damping_coefficient");
+ GDVIRTUAL_BIND(_soft_body_get_damping_coefficient, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_drag_coefficient, "body", "drag_coefficient");
+ GDVIRTUAL_BIND(_soft_body_get_drag_coefficient, "body");
+
+ GDVIRTUAL_BIND(_soft_body_set_mesh, "body", "mesh");
+
GDVIRTUAL_BIND(_soft_body_get_bounds, "body");
+ GDVIRTUAL_BIND(_soft_body_move_point, "body", "point_index", "global_position");
+ GDVIRTUAL_BIND(_soft_body_get_point_global_position, "body", "point_index");
+
+ GDVIRTUAL_BIND(_soft_body_remove_all_pinned_points, "body");
+ GDVIRTUAL_BIND(_soft_body_pin_point, "body", "point_index", "pin");
+ GDVIRTUAL_BIND(_soft_body_is_point_pinned, "body", "point_index");
+
+ /* JOINT API */
+
GDVIRTUAL_BIND(_joint_create);
GDVIRTUAL_BIND(_joint_clear, "joint");
GDVIRTUAL_BIND(_joint_make_pin, "joint", "body_A", "local_A", "body_B", "local_B");
+
GDVIRTUAL_BIND(_pin_joint_set_param, "joint", "param", "value");
GDVIRTUAL_BIND(_pin_joint_get_param, "joint", "param");
@@ -278,6 +369,7 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_pin_joint_get_local_b, "joint");
GDVIRTUAL_BIND(_joint_make_hinge, "joint", "body_A", "hinge_A", "body_B", "hinge_B");
+ GDVIRTUAL_BIND(_joint_make_hinge_simple, "joint", "body_A", "pivot_A", "axis_A", "body_B", "pivot_B", "axis_B");
GDVIRTUAL_BIND(_hinge_joint_set_param, "joint", "param", "value");
GDVIRTUAL_BIND(_hinge_joint_get_param, "joint", "param");
@@ -295,11 +387,6 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_cone_twist_joint_set_param, "joint", "param", "value");
GDVIRTUAL_BIND(_cone_twist_joint_get_param, "joint", "param");
- GDVIRTUAL_BIND(_joint_get_type, "joint");
-
- GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority");
- GDVIRTUAL_BIND(_joint_get_solver_priority, "joint");
-
GDVIRTUAL_BIND(_joint_make_generic_6dof, "joint", "body_A", "local_ref_A", "body_B", "local_ref_B");
GDVIRTUAL_BIND(_generic_6dof_joint_set_param, "joint", "axis", "param", "value");
@@ -308,10 +395,23 @@ void PhysicsServer3DExtension::_bind_methods() {
GDVIRTUAL_BIND(_generic_6dof_joint_set_flag, "joint", "axis", "flag", "enable");
GDVIRTUAL_BIND(_generic_6dof_joint_get_flag, "joint", "axis", "flag");
+ GDVIRTUAL_BIND(_joint_get_type, "joint");
+
+ GDVIRTUAL_BIND(_joint_set_solver_priority, "joint", "priority");
+ GDVIRTUAL_BIND(_joint_get_solver_priority, "joint");
+
GDVIRTUAL_BIND(_free_rid, "rid");
GDVIRTUAL_BIND(_set_active, "active");
+ GDVIRTUAL_BIND(_init);
+ GDVIRTUAL_BIND(_step, "step");
+ GDVIRTUAL_BIND(_sync);
+ GDVIRTUAL_BIND(_flush_queries);
+ GDVIRTUAL_BIND(_end_sync);
+ GDVIRTUAL_BIND(_finish);
+
+ GDVIRTUAL_BIND(_is_flushing_queries);
GDVIRTUAL_BIND(_get_process_info, "process_info");
}
diff --git a/servers/extensions/physics_server_3d_extension.h b/servers/extensions/physics_server_3d_extension.h
index 663af1ae6c..57f2a2d790 100644
--- a/servers/extensions/physics_server_3d_extension.h
+++ b/servers/extensions/physics_server_3d_extension.h
@@ -192,14 +192,8 @@ public:
typedef PhysicsServer3D::MotionCollision PhysicsServer3DExtensionMotionCollision;
typedef PhysicsServer3D::MotionResult PhysicsServer3DExtensionMotionResult;
-struct PhysicsServer3DExtensionStateCallback {
- void *instance = nullptr;
- void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state);
-};
-
GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionCollision)
GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionMotionResult)
-GDVIRTUAL_NATIVE_PTR(PhysicsServer3DExtensionStateCallback)
class PhysicsServer3DExtension : public PhysicsServer3D {
GDCLASS(PhysicsServer3DExtension, PhysicsServer3D);
@@ -210,6 +204,8 @@ protected:
public:
// The warning is valid, but unavoidable. If the function is not overridden it will error anyway.
+ /* SHAPE API */
+
EXBIND0R(RID, world_boundary_shape_create)
EXBIND0R(RID, separation_ray_shape_create)
EXBIND0R(RID, sphere_shape_create)
@@ -262,6 +258,7 @@ public:
EXBIND1RC(int, area_get_shape_count, RID)
EXBIND2RC(RID, area_get_shape, RID, int)
EXBIND2RC(Transform3D, area_get_shape_transform, RID, int)
+
EXBIND2(area_remove_shape, RID, int)
EXBIND1(area_clear_shapes, RID)
@@ -274,8 +271,11 @@ public:
EXBIND2RC(Variant, area_get_param, RID, AreaParameter)
EXBIND1RC(Transform3D, area_get_transform, RID)
- EXBIND2(area_set_collision_mask, RID, uint32_t)
EXBIND2(area_set_collision_layer, RID, uint32_t)
+ EXBIND1RC(uint32_t, area_get_collision_layer, RID)
+
+ EXBIND2(area_set_collision_mask, RID, uint32_t)
+ EXBIND1RC(uint32_t, area_get_collision_mask, RID)
EXBIND2(area_set_monitorable, RID, bool)
EXBIND2(area_set_ray_pickable, RID, bool)
@@ -297,12 +297,11 @@ public:
EXBIND4(body_add_shape, RID, RID, const Transform3D &, bool)
EXBIND3(body_set_shape, RID, int, RID)
EXBIND3(body_set_shape_transform, RID, int, const Transform3D &)
+ EXBIND3(body_set_shape_disabled, RID, int, bool)
EXBIND1RC(int, body_get_shape_count, RID)
- EXBIND2RC(Transform3D, body_get_shape_transform, RID, int)
EXBIND2RC(RID, body_get_shape, RID, int)
-
- EXBIND3(body_set_shape_disabled, RID, int, bool)
+ EXBIND2RC(Transform3D, body_get_shape_transform, RID, int)
EXBIND2(body_remove_shape, RID, int)
EXBIND1(body_clear_shapes, RID)
@@ -319,6 +318,9 @@ public:
EXBIND2(body_set_collision_mask, RID, uint32_t)
EXBIND1RC(uint32_t, body_get_collision_mask, RID)
+ EXBIND2(body_set_collision_priority, RID, real_t)
+ EXBIND1RC(real_t, body_get_collision_priority, RID)
+
EXBIND2(body_set_user_flags, RID, uint32_t)
EXBIND1RC(uint32_t, body_get_user_flags, RID)
@@ -330,9 +332,9 @@ public:
EXBIND3(body_set_state, RID, BodyState, const Variant &)
EXBIND2RC(Variant, body_get_state, RID, BodyState)
- EXBIND2(body_apply_torque_impulse, RID, const Vector3 &)
EXBIND2(body_apply_central_impulse, RID, const Vector3 &)
EXBIND3(body_apply_impulse, RID, const Vector3 &, const Vector3 &)
+ EXBIND2(body_apply_torque_impulse, RID, const Vector3 &)
EXBIND2(body_apply_central_force, RID, const Vector3 &)
EXBIND3(body_apply_force, RID, const Vector3 &, const Vector3 &)
@@ -375,13 +377,7 @@ public:
EXBIND2(body_set_omit_force_integration, RID, bool)
EXBIND1RC(bool, body_is_omitting_force_integration, RID)
- GDVIRTUAL2(_body_set_state_sync_callback, RID, GDNativePtr<PhysicsServer3DExtensionStateCallback>)
- void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override {
- PhysicsServer3DExtensionStateCallback callback;
- callback.callback = p_callback;
- callback.instance = p_instance;
- GDVIRTUAL_REQUIRED_CALL(_body_set_state_sync_callback, p_body, &callback);
- }
+ EXBIND2(body_set_state_sync_callback, RID, const Callable &)
EXBIND3(body_set_force_integration_callback, RID, const Callable &, const Variant &)
EXBIND2(body_set_ray_pickable, RID, bool)
@@ -473,7 +469,6 @@ public:
/* JOINT API */
EXBIND0R(RID, joint_create)
-
EXBIND1(joint_clear, RID)
EXBIND5(joint_make_pin, RID, RID, const Vector3 &, RID, const Vector3 &)
@@ -534,8 +529,8 @@ public:
EXBIND0(init)
EXBIND1(step, real_t)
EXBIND0(sync)
- EXBIND0(end_sync)
EXBIND0(flush_queries)
+ EXBIND0(end_sync)
EXBIND0(finish)
EXBIND0RC(bool, is_flushing_queries)
@@ -545,4 +540,4 @@ public:
~PhysicsServer3DExtension();
};
-#endif // PHYSICSSERVER3DEXTENSION_H
+#endif // PHYSICS_SERVER_3D_EXTENSION_H
diff --git a/servers/movie_writer/SCsub b/servers/movie_writer/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/movie_writer/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/movie_writer/movie_writer.cpp b/servers/movie_writer/movie_writer.cpp
new file mode 100644
index 0000000000..0edce4ced6
--- /dev/null
+++ b/servers/movie_writer/movie_writer.cpp
@@ -0,0 +1,227 @@
+/*************************************************************************/
+/* movie_writer.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "movie_writer.h"
+#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+#include "core/os/time.h"
+#include "servers/display_server.h"
+
+MovieWriter *MovieWriter::writers[MovieWriter::MAX_WRITERS];
+uint32_t MovieWriter::writer_count = 0;
+
+void MovieWriter::add_writer(MovieWriter *p_writer) {
+ ERR_FAIL_COND(writer_count == MAX_WRITERS);
+ writers[writer_count++] = p_writer;
+}
+
+MovieWriter *MovieWriter::find_writer_for_file(const String &p_file) {
+ for (int32_t i = writer_count - 1; i >= 0; i--) { // More recent last, to have override ability.
+ if (writers[i]->handles_file(p_file)) {
+ return writers[i];
+ }
+ }
+ return nullptr;
+}
+
+uint32_t MovieWriter::get_audio_mix_rate() const {
+ uint32_t ret = 0;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_audio_mix_rate, ret)) {
+ return ret;
+ }
+ return 48000;
+}
+AudioServer::SpeakerMode MovieWriter::get_audio_speaker_mode() const {
+ AudioServer::SpeakerMode ret = AudioServer::SPEAKER_MODE_STEREO;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_audio_speaker_mode, ret)) {
+ return ret;
+ }
+ return AudioServer::SPEAKER_MODE_STEREO;
+}
+
+Error MovieWriter::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
+ Error ret = OK;
+ if (GDVIRTUAL_REQUIRED_CALL(_write_begin, p_movie_size, p_fps, p_base_path, ret)) {
+ return ret;
+ }
+ return ERR_UNCONFIGURED;
+}
+
+Error MovieWriter::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) {
+ Error ret = OK;
+ if (GDVIRTUAL_REQUIRED_CALL(_write_frame, p_image, p_audio_data, ret)) {
+ return ret;
+ }
+ return ERR_UNCONFIGURED;
+}
+
+void MovieWriter::write_end() {
+ GDVIRTUAL_REQUIRED_CALL(_write_end);
+}
+
+bool MovieWriter::handles_file(const String &p_path) const {
+ bool ret = false;
+ if (GDVIRTUAL_REQUIRED_CALL(_handles_file, p_path, ret)) {
+ return ret;
+ }
+ return false;
+}
+
+void MovieWriter::get_supported_extensions(List<String> *r_extensions) const {
+ Vector<String> exts;
+ if (GDVIRTUAL_REQUIRED_CALL(_get_supported_extensions, exts)) {
+ for (int i = 0; i < exts.size(); i++) {
+ r_extensions->push_back(exts[i]);
+ }
+ }
+}
+
+void MovieWriter::begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
+ project_name = GLOBAL_GET("application/config/name");
+
+ print_line(vformat("Movie Maker mode enabled, recording movie at %d FPS...", p_fps));
+
+ // Check for available disk space and warn the user if needed.
+ Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ String path = p_base_path.get_basename();
+ if (path.is_relative_path()) {
+ path = "res://" + path;
+ }
+ dir->open(path);
+ if (dir->get_space_left() < 10 * Math::pow(1024.0, 3.0)) {
+ // Less than 10 GiB available.
+ WARN_PRINT(vformat("Current available space on disk is low (%s). MovieWriter will fail during movie recording if the disk runs out of available space.", String::humanize_size(dir->get_space_left())));
+ }
+
+ mix_rate = get_audio_mix_rate();
+ AudioDriverDummy::get_dummy_singleton()->set_mix_rate(mix_rate);
+ AudioDriverDummy::get_dummy_singleton()->set_speaker_mode(AudioDriver::SpeakerMode(get_audio_speaker_mode()));
+ fps = p_fps;
+ if ((mix_rate % fps) != 0) {
+ WARN_PRINT("MovieWriter's audio mix rate (" + itos(mix_rate) + ") can not be divided by the recording FPS (" + itos(fps) + "). Audio may go out of sync over time.");
+ }
+
+ audio_channels = AudioDriverDummy::get_dummy_singleton()->get_channels();
+ audio_mix_buffer.resize(mix_rate * audio_channels / fps);
+
+ write_begin(p_movie_size, p_fps, p_base_path);
+}
+
+void MovieWriter::_bind_methods() {
+ ClassDB::bind_static_method("MovieWriter", D_METHOD("add_writer", "writer"), &MovieWriter::add_writer);
+
+ GDVIRTUAL_BIND(_get_audio_mix_rate)
+ GDVIRTUAL_BIND(_get_audio_speaker_mode)
+
+ GDVIRTUAL_BIND(_handles_file, "path")
+
+ GDVIRTUAL_BIND(_write_begin, "movie_size", "fps", "base_path")
+ GDVIRTUAL_BIND(_write_frame, "frame_image", "audio_frame_block")
+ GDVIRTUAL_BIND(_write_end)
+
+ GLOBAL_DEF("editor/movie_writer/mix_rate", 48000);
+ ProjectSettings::get_singleton()->set_custom_property_info("editor/movie_writer/mix_rate", PropertyInfo(Variant::INT, "editor/movie_writer/mix_rate", PROPERTY_HINT_RANGE, "8000,192000,1,suffix:Hz"));
+ GLOBAL_DEF("editor/movie_writer/speaker_mode", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("editor/movie_writer/speaker_mode", PropertyInfo(Variant::INT, "editor/movie_writer/speaker_mode", PROPERTY_HINT_ENUM, "Stereo,3.1,5.1,7.1"));
+ GLOBAL_DEF("editor/movie_writer/mjpeg_quality", 0.75);
+ ProjectSettings::get_singleton()->set_custom_property_info("editor/movie_writer/mjpeg_quality", PropertyInfo(Variant::FLOAT, "editor/movie_writer/mjpeg_quality", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
+ // used by the editor
+ GLOBAL_DEF_BASIC("editor/movie_writer/movie_file", "");
+ GLOBAL_DEF_BASIC("editor/movie_writer/disable_vsync", false);
+ GLOBAL_DEF_BASIC("editor/movie_writer/fps", 60);
+ ProjectSettings::get_singleton()->set_custom_property_info("editor/movie_writer/fps", PropertyInfo(Variant::INT, "editor/movie_writer/fps", PROPERTY_HINT_RANGE, "1,300,1,suffix:FPS"));
+}
+
+void MovieWriter::set_extensions_hint() {
+ RBSet<String> found;
+ for (uint32_t i = 0; i < writer_count; i++) {
+ List<String> extensions;
+ writers[i]->get_supported_extensions(&extensions);
+ for (const String &ext : extensions) {
+ found.insert(ext);
+ }
+ }
+
+ String ext_hint;
+
+ for (const String &S : found) {
+ if (ext_hint != "") {
+ ext_hint += ",";
+ }
+ ext_hint += "*." + S;
+ }
+ ProjectSettings::get_singleton()->set_custom_property_info("editor/movie_writer/movie_file", PropertyInfo(Variant::STRING, "editor/movie_writer/movie_file", PROPERTY_HINT_GLOBAL_SAVE_FILE, ext_hint));
+}
+
+void MovieWriter::add_frame(const Ref<Image> &p_image) {
+ const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps;
+ const String movie_time = vformat("%s:%s:%s",
+ String::num(movie_time_seconds / 3600).pad_zeros(2),
+ String::num((movie_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(movie_time_seconds % 60).pad_zeros(2));
+
+#ifdef DEBUG_ENABLED
+ DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s (DEBUG)", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name));
+#else
+ DisplayServer::get_singleton()->window_set_title(vformat("MovieWriter: Frame %d (time: %s) - %s", Engine::get_singleton()->get_frames_drawn(), movie_time, project_name));
+#endif
+
+ AudioDriverDummy::get_dummy_singleton()->mix_audio(mix_rate / fps, audio_mix_buffer.ptr());
+ write_frame(p_image, audio_mix_buffer.ptr());
+}
+
+void MovieWriter::end() {
+ write_end();
+
+ // Print a report with various statistics.
+ print_line("----------------");
+ String movie_path = Engine::get_singleton()->get_write_movie_path();
+ if (movie_path.is_relative_path()) {
+ // Print absolute path to make finding the file easier,
+ // and to make it clickable in terminal emulators that support this.
+ movie_path = ProjectSettings::get_singleton()->globalize_path("res://").path_join(movie_path);
+ }
+ print_line(vformat("Done recording movie at path: %s", movie_path));
+
+ const int movie_time_seconds = Engine::get_singleton()->get_frames_drawn() / fps;
+ const String movie_time = vformat("%s:%s:%s",
+ String::num(movie_time_seconds / 3600).pad_zeros(2),
+ String::num((movie_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(movie_time_seconds % 60).pad_zeros(2));
+
+ const int real_time_seconds = Time::get_singleton()->get_ticks_msec() / 1000;
+ const String real_time = vformat("%s:%s:%s",
+ String::num(real_time_seconds / 3600).pad_zeros(2),
+ String::num((real_time_seconds % 3600) / 60).pad_zeros(2),
+ String::num(real_time_seconds % 60).pad_zeros(2));
+
+ print_line(vformat("%d frames at %d FPS (movie length: %s), recorded in %s (%d%% of real-time speed).", Engine::get_singleton()->get_frames_drawn(), fps, movie_time, real_time, (float(movie_time_seconds) / real_time_seconds) * 100));
+ print_line("----------------");
+}
diff --git a/servers/movie_writer/movie_writer.h b/servers/movie_writer/movie_writer.h
new file mode 100644
index 0000000000..7877a60715
--- /dev/null
+++ b/servers/movie_writer/movie_writer.h
@@ -0,0 +1,90 @@
+/*************************************************************************/
+/* movie_writer.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef MOVIE_WRITER_H
+#define MOVIE_WRITER_H
+
+#include "core/templates/local_vector.h"
+#include "servers/audio/audio_driver_dummy.h"
+#include "servers/audio_server.h"
+
+class MovieWriter : public Object {
+ GDCLASS(MovieWriter, Object);
+
+ uint64_t fps = 0;
+ uint64_t mix_rate = 0;
+ uint32_t audio_channels = 0;
+
+ String project_name;
+
+ LocalVector<int32_t> audio_mix_buffer;
+
+ enum {
+ MAX_WRITERS = 8
+ };
+ static MovieWriter *writers[];
+ static uint32_t writer_count;
+
+protected:
+ virtual uint32_t get_audio_mix_rate() const;
+ virtual AudioServer::SpeakerMode get_audio_speaker_mode() const;
+
+ virtual Error write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path);
+ virtual Error write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data);
+ virtual void write_end();
+
+ GDVIRTUAL0RC(uint32_t, _get_audio_mix_rate)
+ GDVIRTUAL0RC(AudioServer::SpeakerMode, _get_audio_speaker_mode)
+
+ GDVIRTUAL1RC(bool, _handles_file, const String &)
+ GDVIRTUAL0RC(Vector<String>, _get_supported_extensions)
+
+ GDVIRTUAL3R(Error, _write_begin, const Size2i &, uint32_t, const String &)
+ GDVIRTUAL2R(Error, _write_frame, const Ref<Image> &, GDNativeConstPtr<int32_t>)
+ GDVIRTUAL0(_write_end)
+
+ static void _bind_methods();
+
+public:
+ virtual bool handles_file(const String &p_path) const;
+ virtual void get_supported_extensions(List<String> *r_extensions) const;
+
+ static void add_writer(MovieWriter *p_writer);
+ static MovieWriter *find_writer_for_file(const String &p_file);
+
+ void begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path);
+ void add_frame(const Ref<Image> &p_image);
+
+ static void set_extensions_hint();
+
+ void end();
+};
+
+#endif // MOVIE_WRITER_H
diff --git a/servers/movie_writer/movie_writer_mjpeg.cpp b/servers/movie_writer/movie_writer_mjpeg.cpp
new file mode 100644
index 0000000000..7d9e6e3b87
--- /dev/null
+++ b/servers/movie_writer/movie_writer_mjpeg.cpp
@@ -0,0 +1,263 @@
+/*************************************************************************/
+/* movie_writer_mjpeg.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "movie_writer_mjpeg.h"
+#include "core/config/project_settings.h"
+
+uint32_t MovieWriterMJPEG::get_audio_mix_rate() const {
+ return mix_rate;
+}
+AudioServer::SpeakerMode MovieWriterMJPEG::get_audio_speaker_mode() const {
+ return speaker_mode;
+}
+
+bool MovieWriterMJPEG::handles_file(const String &p_path) const {
+ return p_path.get_extension().to_lower() == "avi";
+}
+
+void MovieWriterMJPEG::get_supported_extensions(List<String> *r_extensions) const {
+ r_extensions->push_back("avi");
+}
+
+Error MovieWriterMJPEG::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
+ // Quick & Dirty MJPEG Code based on - https://docs.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference
+
+ base_path = p_base_path.get_basename();
+ if (base_path.is_relative_path()) {
+ base_path = "res://" + base_path;
+ }
+
+ base_path += ".avi";
+
+ f = FileAccess::open(base_path, FileAccess::WRITE_READ);
+
+ fps = p_fps;
+
+ ERR_FAIL_COND_V(f.is_null(), ERR_CANT_OPEN);
+
+ f->store_buffer((const uint8_t *)"RIFF", 4);
+ f->store_32(0); // Total length (update later)
+ f->store_buffer((const uint8_t *)"AVI ", 4);
+ f->store_buffer((const uint8_t *)"LIST", 4);
+ f->store_32(300); // 4 + 4 + 4 + 56 + 4 + 4 + 132 + 4 + 4 + 84
+ f->store_buffer((const uint8_t *)"hdrl", 4);
+ f->store_buffer((const uint8_t *)"avih", 4);
+ f->store_32(56);
+
+ f->store_32(1000000 / p_fps); // Microsecs per frame.
+ f->store_32(7000); // Max bytes per second
+ f->store_32(0); // Padding Granularity
+ f->store_32(16);
+ total_frames_ofs = f->get_position();
+ f->store_32(0); // Total frames (update later)
+ f->store_32(0); // Initial frames
+ f->store_32(1); // Streams
+ f->store_32(0); // Suggested buffer size
+ f->store_32(p_movie_size.width); // Movie Width
+ f->store_32(p_movie_size.height); // Movie Height
+ for (uint32_t i = 0; i < 4; i++) {
+ f->store_32(0); // Reserved.
+ }
+ f->store_buffer((const uint8_t *)"LIST", 4);
+ f->store_32(132); // 4 + 4 + 4 + 48 + 4 + 4 + 40 + 4 + 4 + 16
+ f->store_buffer((const uint8_t *)"strl", 4);
+ f->store_buffer((const uint8_t *)"strh", 4);
+ f->store_32(48);
+ f->store_buffer((const uint8_t *)"vids", 4);
+ f->store_buffer((const uint8_t *)"MJPG", 4);
+ f->store_32(0); // Flags
+ f->store_16(0); // Priority
+ f->store_16(0); // Language
+ f->store_32(0); // Initial Frames
+ f->store_32(1); // Scale
+ f->store_32(p_fps); // FPS
+ f->store_32(0); // Start
+ total_frames_ofs2 = f->get_position();
+ f->store_32(0); // Number of frames (to be updated later)
+ f->store_32(0); // Suggested Buffer Size
+ f->store_32(0); // Quality
+ f->store_32(0); // Sample Size
+
+ f->store_buffer((const uint8_t *)"strf", 4);
+ f->store_32(40); // Size.
+ f->store_32(40); // Size.
+
+ f->store_32(p_movie_size.width); // Width
+ f->store_32(p_movie_size.height); // Width
+ f->store_16(1); // Planes
+ f->store_16(24); // Bitcount
+ f->store_buffer((const uint8_t *)"MJPG", 4); // Compression
+
+ f->store_32(((p_movie_size.width * 24 / 8 + 3) & 0xFFFFFFFC) * p_movie_size.height); // SizeImage
+ f->store_32(0); // XPelsXMeter
+ f->store_32(0); // YPelsXMeter
+ f->store_32(0); // ClrUsed
+ f->store_32(0); // ClrImportant
+
+ f->store_buffer((const uint8_t *)"LIST", 4);
+ f->store_32(16);
+
+ f->store_buffer((const uint8_t *)"odml", 4);
+ f->store_buffer((const uint8_t *)"dmlh", 4);
+ f->store_32(4); // sizes
+
+ total_frames_ofs3 = f->get_position();
+ f->store_32(0); // Number of frames (to be updated later)
+
+ // Audio //
+
+ const uint32_t bit_depth = 32;
+ uint32_t channels = 2;
+ switch (speaker_mode) {
+ case AudioServer::SPEAKER_MODE_STEREO:
+ channels = 2;
+ break;
+ case AudioServer::SPEAKER_SURROUND_31:
+ channels = 4;
+ break;
+ case AudioServer::SPEAKER_SURROUND_51:
+ channels = 6;
+ break;
+ case AudioServer::SPEAKER_SURROUND_71:
+ channels = 8;
+ break;
+ }
+ uint32_t blockalign = bit_depth / 8 * channels;
+
+ f->store_buffer((const uint8_t *)"LIST", 4);
+ f->store_32(84); // 4 + 4 + 4 + 48 + 4 + 4 + 16
+ f->store_buffer((const uint8_t *)"strl", 4);
+ f->store_buffer((const uint8_t *)"strh", 4);
+ f->store_32(48);
+ f->store_buffer((const uint8_t *)"auds", 4);
+ f->store_32(0); // Handler
+ f->store_32(0); // Flags
+ f->store_16(0); // Priority
+ f->store_16(0); // Language
+ f->store_32(0); // Initial Frames
+ f->store_32(blockalign); // Scale
+ f->store_32(mix_rate * blockalign); // mix rate
+ f->store_32(0); // Start
+ total_audio_frames_ofs4 = f->get_position();
+ f->store_32(0); // Number of frames (to be updated later)
+ f->store_32(12288); // Suggested Buffer Size
+ f->store_32(0xFFFFFFFF); // Quality
+ f->store_32(blockalign); // Block Align to 32 bits
+
+ audio_block_size = (mix_rate / fps) * blockalign;
+
+ f->store_buffer((const uint8_t *)"strf", 4);
+ f->store_32(16); // Standard format, no extra fields
+ f->store_16(1); // Compression code, standard PCM
+ f->store_16(channels);
+ f->store_32(mix_rate); // Samples (frames) / Sec
+ f->store_32(mix_rate * blockalign); // Bytes / sec
+ f->store_16(blockalign); // Bytes / sec
+ f->store_16(bit_depth); // Bytes / sec
+
+ f->store_buffer((const uint8_t *)"LIST", 4);
+ movi_data_ofs = f->get_position();
+ f->store_32(0); // Number of frames (to be updated later)
+ f->store_buffer((const uint8_t *)"movi", 4);
+
+ return OK;
+}
+
+Error MovieWriterMJPEG::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) {
+ ERR_FAIL_COND_V(!f.is_valid(), ERR_UNCONFIGURED);
+
+ Vector<uint8_t> jpg_buffer = p_image->save_jpg_to_buffer(quality);
+ uint32_t s = jpg_buffer.size();
+
+ f->store_buffer((const uint8_t *)"00db", 4); // Stream 0, Video
+ f->store_32(jpg_buffer.size()); // sizes
+ f->store_buffer(jpg_buffer.ptr(), jpg_buffer.size());
+ if (jpg_buffer.size() & 1) {
+ f->store_8(0);
+ s++;
+ }
+ jpg_frame_sizes.push_back(s);
+
+ f->store_buffer((const uint8_t *)"01wb", 4); // Stream 1, Audio.
+ f->store_32(audio_block_size);
+ f->store_buffer((const uint8_t *)p_audio_data, audio_block_size);
+
+ frame_count++;
+
+ return OK;
+}
+
+void MovieWriterMJPEG::write_end() {
+ if (f.is_valid()) {
+ // Finalize the file (frame indices)
+ f->store_buffer((const uint8_t *)"idx1", 4);
+ f->store_32(8 * 4 * frame_count);
+ uint32_t ofs = 4;
+ uint32_t all_data_size = 0;
+ for (uint32_t i = 0; i < frame_count; i++) {
+ f->store_buffer((const uint8_t *)"00db", 4);
+ f->store_32(16); // AVI_KEYFRAME
+ f->store_32(ofs);
+ f->store_32(jpg_frame_sizes[i]);
+
+ ofs += jpg_frame_sizes[i] + 8;
+
+ f->store_buffer((const uint8_t *)"01wb", 4);
+ f->store_32(16); // AVI_KEYFRAME
+ f->store_32(ofs);
+ f->store_32(audio_block_size);
+
+ ofs += audio_block_size + 8;
+ all_data_size += jpg_frame_sizes[i] + audio_block_size;
+ }
+
+ uint32_t file_size = f->get_position();
+ f->seek(4);
+ f->store_32(file_size - 78);
+ f->seek(total_frames_ofs);
+ f->store_32(frame_count);
+ f->seek(total_frames_ofs2);
+ f->store_32(frame_count);
+ f->seek(total_frames_ofs3);
+ f->store_32(frame_count);
+ f->seek(total_audio_frames_ofs4);
+ f->store_32(frame_count * mix_rate / fps);
+ f->seek(movi_data_ofs);
+ f->store_32(all_data_size + 4 + 16 * frame_count);
+
+ f.unref();
+ }
+}
+
+MovieWriterMJPEG::MovieWriterMJPEG() {
+ mix_rate = GLOBAL_GET("editor/movie_writer/mix_rate");
+ speaker_mode = AudioServer::SpeakerMode(int(GLOBAL_GET("editor/movie_writer/speaker_mode")));
+ quality = GLOBAL_GET("editor/movie_writer/mjpeg_quality");
+}
diff --git a/servers/movie_writer/movie_writer_mjpeg.h b/servers/movie_writer/movie_writer_mjpeg.h
new file mode 100644
index 0000000000..233267df30
--- /dev/null
+++ b/servers/movie_writer/movie_writer_mjpeg.h
@@ -0,0 +1,73 @@
+/*************************************************************************/
+/* movie_writer_mjpeg.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef MOVIE_WRITER_MJPEG_H
+#define MOVIE_WRITER_MJPEG_H
+
+#include "servers/movie_writer/movie_writer.h"
+
+class MovieWriterMJPEG : public MovieWriter {
+ GDCLASS(MovieWriterMJPEG, MovieWriter)
+
+ uint32_t mix_rate = 48000;
+ AudioServer::SpeakerMode speaker_mode = AudioServer::SPEAKER_MODE_STEREO;
+ String base_path;
+ uint32_t frame_count = 0;
+ uint32_t fps = 0;
+ float quality = 0.75;
+
+ uint32_t audio_block_size = 0;
+
+ Vector<uint32_t> jpg_frame_sizes;
+
+ uint64_t total_frames_ofs = 0;
+ uint64_t total_frames_ofs2 = 0;
+ uint64_t total_frames_ofs3 = 0;
+ uint64_t total_audio_frames_ofs4 = 0;
+ uint64_t movi_data_ofs = 0;
+
+ Ref<FileAccess> f;
+
+protected:
+ virtual uint32_t get_audio_mix_rate() const override;
+ virtual AudioServer::SpeakerMode get_audio_speaker_mode() const override;
+ virtual void get_supported_extensions(List<String> *r_extensions) const override;
+
+ virtual Error write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) override;
+ virtual Error write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) override;
+ virtual void write_end() override;
+
+ virtual bool handles_file(const String &p_path) const override;
+
+public:
+ MovieWriterMJPEG();
+};
+
+#endif // MOVIE_WRITER_MJPEG_H
diff --git a/servers/movie_writer/movie_writer_pngwav.cpp b/servers/movie_writer/movie_writer_pngwav.cpp
new file mode 100644
index 0000000000..bd79b0bd98
--- /dev/null
+++ b/servers/movie_writer/movie_writer_pngwav.cpp
@@ -0,0 +1,168 @@
+/*************************************************************************/
+/* movie_writer_pngwav.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "movie_writer_pngwav.h"
+#include "core/config/project_settings.h"
+#include "core/io/dir_access.h"
+
+uint32_t MovieWriterPNGWAV::get_audio_mix_rate() const {
+ return mix_rate;
+}
+AudioServer::SpeakerMode MovieWriterPNGWAV::get_audio_speaker_mode() const {
+ return speaker_mode;
+}
+
+void MovieWriterPNGWAV::get_supported_extensions(List<String> *r_extensions) const {
+ r_extensions->push_back("png");
+}
+
+bool MovieWriterPNGWAV::handles_file(const String &p_path) const {
+ return p_path.get_extension().to_lower() == "png";
+}
+
+String MovieWriterPNGWAV::zeros_str(uint32_t p_index) {
+ char zeros[MAX_TRAILING_ZEROS + 1];
+ for (uint32_t i = 0; i < MAX_TRAILING_ZEROS; i++) {
+ uint32_t idx = MAX_TRAILING_ZEROS - i - 1;
+ uint32_t digit = (p_index / uint32_t(Math::pow(double(10), double(idx)))) % 10;
+ zeros[i] = '0' + digit;
+ }
+ zeros[MAX_TRAILING_ZEROS] = 0;
+ return zeros;
+}
+
+Error MovieWriterPNGWAV::write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) {
+ // Quick & Dirty PNGWAV Code based on - https://docs.microsoft.com/en-us/windows/win32/directshow/avi-riff-file-reference
+
+ base_path = p_base_path.get_basename();
+ if (base_path.is_relative_path()) {
+ base_path = "res://" + base_path;
+ }
+
+ {
+ //Remove existing files before writing anew
+ uint32_t idx = 0;
+ Ref<DirAccess> d = DirAccess::open(base_path.get_base_dir());
+ String file = base_path.get_file();
+ while (true) {
+ String path = file + zeros_str(idx) + ".png";
+ if (d->remove(path) != OK) {
+ break;
+ }
+ }
+ }
+
+ f_wav = FileAccess::open(base_path + ".wav", FileAccess::WRITE_READ);
+ ERR_FAIL_COND_V(f_wav.is_null(), ERR_CANT_OPEN);
+
+ fps = p_fps;
+
+ f_wav->store_buffer((const uint8_t *)"RIFF", 4);
+ int total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */;
+ f_wav->store_32(total_size); //will store final later
+ f_wav->store_buffer((const uint8_t *)"WAVE", 4);
+
+ /* FORMAT CHUNK */
+
+ f_wav->store_buffer((const uint8_t *)"fmt ", 4);
+
+ uint32_t channels = 2;
+ switch (speaker_mode) {
+ case AudioServer::SPEAKER_MODE_STEREO:
+ channels = 2;
+ break;
+ case AudioServer::SPEAKER_SURROUND_31:
+ channels = 4;
+ break;
+ case AudioServer::SPEAKER_SURROUND_51:
+ channels = 6;
+ break;
+ case AudioServer::SPEAKER_SURROUND_71:
+ channels = 8;
+ break;
+ }
+
+ f_wav->store_32(16); //standard format, no extra fields
+ f_wav->store_16(1); // compression code, standard PCM
+ f_wav->store_16(channels); //CHANNELS: 2
+
+ f_wav->store_32(mix_rate);
+
+ /* useless stuff the format asks for */
+
+ int bits_per_sample = 32;
+ int blockalign = bits_per_sample / 8 * channels;
+ int bytes_per_sec = mix_rate * blockalign;
+
+ audio_block_size = (mix_rate / fps) * blockalign;
+
+ f_wav->store_32(bytes_per_sec);
+ f_wav->store_16(blockalign); // block align (unused)
+ f_wav->store_16(bits_per_sample);
+
+ /* DATA CHUNK */
+
+ f_wav->store_buffer((const uint8_t *)"data", 4);
+
+ f_wav->store_32(0); //data size... wooh
+ wav_data_size_pos = f_wav->get_position();
+
+ return OK;
+}
+
+Error MovieWriterPNGWAV::write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) {
+ ERR_FAIL_COND_V(!f_wav.is_valid(), ERR_UNCONFIGURED);
+
+ Vector<uint8_t> png_buffer = p_image->save_png_to_buffer();
+
+ Ref<FileAccess> fi = FileAccess::open(base_path + zeros_str(frame_count) + ".png", FileAccess::WRITE);
+ fi->store_buffer(png_buffer.ptr(), png_buffer.size());
+ f_wav->store_buffer((const uint8_t *)p_audio_data, audio_block_size);
+
+ frame_count++;
+
+ return OK;
+}
+
+void MovieWriterPNGWAV::write_end() {
+ if (f_wav.is_valid()) {
+ uint32_t total_size = 4 /* WAVE */ + 8 /* fmt+size */ + 16 /* format */ + 8 /* data+size */;
+ uint32_t datasize = f_wav->get_position() - wav_data_size_pos;
+ f_wav->seek(4);
+ f_wav->store_32(total_size + datasize);
+ f_wav->seek(0x28);
+ f_wav->store_32(datasize);
+ }
+}
+
+MovieWriterPNGWAV::MovieWriterPNGWAV() {
+ mix_rate = GLOBAL_GET("editor/movie_writer/mix_rate");
+ speaker_mode = AudioServer::SpeakerMode(int(GLOBAL_GET("editor/movie_writer/speaker_mode")));
+}
diff --git a/servers/movie_writer/movie_writer_pngwav.h b/servers/movie_writer/movie_writer_pngwav.h
new file mode 100644
index 0000000000..64608ce387
--- /dev/null
+++ b/servers/movie_writer/movie_writer_pngwav.h
@@ -0,0 +1,71 @@
+/*************************************************************************/
+/* movie_writer_pngwav.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef MOVIE_WRITER_PNGWAV_H
+#define MOVIE_WRITER_PNGWAV_H
+
+#include "servers/movie_writer/movie_writer.h"
+
+class MovieWriterPNGWAV : public MovieWriter {
+ GDCLASS(MovieWriterPNGWAV, MovieWriter)
+
+ enum {
+ MAX_TRAILING_ZEROS = 8 // more than 10 days at 60fps, no hard drive can put up with this anyway :)
+ };
+
+ uint32_t mix_rate = 48000;
+ AudioServer::SpeakerMode speaker_mode = AudioServer::SPEAKER_MODE_STEREO;
+ String base_path;
+ uint32_t frame_count = 0;
+ uint32_t fps = 0;
+
+ uint32_t audio_block_size = 0;
+
+ Ref<FileAccess> f_wav;
+ uint32_t wav_data_size_pos = 0;
+
+ String zeros_str(uint32_t p_index);
+
+protected:
+ virtual uint32_t get_audio_mix_rate() const override;
+ virtual AudioServer::SpeakerMode get_audio_speaker_mode() const override;
+ virtual void get_supported_extensions(List<String> *r_extensions) const override;
+
+ virtual Error write_begin(const Size2i &p_movie_size, uint32_t p_fps, const String &p_base_path) override;
+ virtual Error write_frame(const Ref<Image> &p_image, const int32_t *p_audio_data) override;
+ virtual void write_end() override;
+
+ virtual bool handles_file(const String &p_path) const override;
+
+public:
+ MovieWriterPNGWAV();
+};
+
+#endif // MOVIE_WRITER_PNGWAV_H
diff --git a/servers/navigation/SCsub b/servers/navigation/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/navigation/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/navigation/navigation_path_query_parameters_2d.cpp b/servers/navigation/navigation_path_query_parameters_2d.cpp
new file mode 100644
index 0000000000..574af90be1
--- /dev/null
+++ b/servers/navigation/navigation_path_query_parameters_2d.cpp
@@ -0,0 +1,144 @@
+/*************************************************************************/
+/* navigation_path_query_parameters_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "navigation_path_query_parameters_2d.h"
+
+void NavigationPathQueryParameters2D::set_pathfinding_algorithm(const NavigationPathQueryParameters2D::PathfindingAlgorithm p_pathfinding_algorithm) {
+ switch (p_pathfinding_algorithm) {
+ case PATHFINDING_ALGORITHM_ASTAR: {
+ parameters.pathfinding_algorithm = NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR;
+ } break;
+ default: {
+ WARN_PRINT_ONCE("No match for used PathfindingAlgorithm - fallback to default");
+ parameters.pathfinding_algorithm = NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR;
+ } break;
+ }
+}
+
+NavigationPathQueryParameters2D::PathfindingAlgorithm NavigationPathQueryParameters2D::get_pathfinding_algorithm() const {
+ switch (parameters.pathfinding_algorithm) {
+ case NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR:
+ return PATHFINDING_ALGORITHM_ASTAR;
+ default:
+ WARN_PRINT_ONCE("No match for used PathfindingAlgorithm - fallback to default");
+ return PATHFINDING_ALGORITHM_ASTAR;
+ }
+}
+
+void NavigationPathQueryParameters2D::set_path_postprocessing(const NavigationPathQueryParameters2D::PathPostProcessing p_path_postprocessing) {
+ switch (p_path_postprocessing) {
+ case PATH_POSTPROCESSING_CORRIDORFUNNEL: {
+ parameters.path_postprocessing = NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ } break;
+ case PATH_POSTPROCESSING_EDGECENTERED: {
+ parameters.path_postprocessing = NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED;
+ } break;
+ default: {
+ WARN_PRINT_ONCE("No match for used PathPostProcessing - fallback to default");
+ parameters.path_postprocessing = NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ } break;
+ }
+}
+
+NavigationPathQueryParameters2D::PathPostProcessing NavigationPathQueryParameters2D::get_path_postprocessing() const {
+ switch (parameters.path_postprocessing) {
+ case NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL:
+ return PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ case NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED:
+ return PATH_POSTPROCESSING_EDGECENTERED;
+ default:
+ WARN_PRINT_ONCE("No match for used PathPostProcessing - fallback to default");
+ return PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ }
+}
+
+void NavigationPathQueryParameters2D::set_map(const RID &p_map) {
+ parameters.map = p_map;
+}
+
+const RID &NavigationPathQueryParameters2D::get_map() const {
+ return parameters.map;
+}
+
+void NavigationPathQueryParameters2D::set_start_position(const Vector2 p_start_position) {
+ parameters.start_position = Vector3(p_start_position.x, 0.0, p_start_position.y);
+}
+
+Vector2 NavigationPathQueryParameters2D::get_start_position() const {
+ return Vector2(parameters.start_position.x, parameters.start_position.z);
+}
+
+void NavigationPathQueryParameters2D::set_target_position(const Vector2 p_target_position) {
+ parameters.target_position = Vector3(p_target_position.x, 0.0, p_target_position.y);
+}
+
+Vector2 NavigationPathQueryParameters2D::get_target_position() const {
+ return Vector2(parameters.target_position.x, parameters.target_position.z);
+}
+
+void NavigationPathQueryParameters2D::set_navigation_layers(uint32_t p_navigation_layers) {
+ parameters.navigation_layers = p_navigation_layers;
+};
+
+uint32_t NavigationPathQueryParameters2D::get_navigation_layers() const {
+ return parameters.navigation_layers;
+};
+
+void NavigationPathQueryParameters2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters2D::set_pathfinding_algorithm);
+ ClassDB::bind_method(D_METHOD("get_pathfinding_algorithm"), &NavigationPathQueryParameters2D::get_pathfinding_algorithm);
+
+ ClassDB::bind_method(D_METHOD("set_path_postprocessing", "path_postprocessing"), &NavigationPathQueryParameters2D::set_path_postprocessing);
+ ClassDB::bind_method(D_METHOD("get_path_postprocessing"), &NavigationPathQueryParameters2D::get_path_postprocessing);
+
+ ClassDB::bind_method(D_METHOD("set_map", "map"), &NavigationPathQueryParameters2D::set_map);
+ ClassDB::bind_method(D_METHOD("get_map"), &NavigationPathQueryParameters2D::get_map);
+
+ ClassDB::bind_method(D_METHOD("set_start_position", "start_position"), &NavigationPathQueryParameters2D::set_start_position);
+ ClassDB::bind_method(D_METHOD("get_start_position"), &NavigationPathQueryParameters2D::get_start_position);
+
+ ClassDB::bind_method(D_METHOD("set_target_position", "target_position"), &NavigationPathQueryParameters2D::set_target_position);
+ ClassDB::bind_method(D_METHOD("get_target_position"), &NavigationPathQueryParameters2D::get_target_position);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationPathQueryParameters2D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationPathQueryParameters2D::get_navigation_layers);
+
+ ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "start_position"), "set_start_position", "get_start_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "target_position"), "set_target_position", "get_target_position");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "pathfinding_algorithm", PROPERTY_HINT_ENUM, "AStar"), "set_pathfinding_algorithm", "get_pathfinding_algorithm");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "path_postprocessing", PROPERTY_HINT_ENUM, "Corridorfunnel,Edgecentered"), "set_path_postprocessing", "get_path_postprocessing");
+
+ BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR);
+
+ BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_CORRIDORFUNNEL);
+ BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_EDGECENTERED);
+}
diff --git a/servers/navigation/navigation_path_query_parameters_2d.h b/servers/navigation/navigation_path_query_parameters_2d.h
new file mode 100644
index 0000000000..c0ef337a27
--- /dev/null
+++ b/servers/navigation/navigation_path_query_parameters_2d.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* navigation_path_query_parameters_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_PATH_QUERY_PARAMETERS_2D_H
+#define NAVIGATION_PATH_QUERY_PARAMETERS_2D_H
+
+#include "core/object/ref_counted.h"
+#include "servers/navigation/navigation_utilities.h"
+
+class NavigationPathQueryParameters2D : public RefCounted {
+ GDCLASS(NavigationPathQueryParameters2D, RefCounted);
+
+ NavigationUtilities::PathQueryParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ enum PathfindingAlgorithm {
+ PATHFINDING_ALGORITHM_ASTAR = 0,
+ };
+
+ enum PathPostProcessing {
+ PATH_POSTPROCESSING_CORRIDORFUNNEL = 0,
+ PATH_POSTPROCESSING_EDGECENTERED,
+ };
+
+ const NavigationUtilities::PathQueryParameters &get_parameters() const { return parameters; }
+
+ void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm);
+ PathfindingAlgorithm get_pathfinding_algorithm() const;
+
+ void set_path_postprocessing(const PathPostProcessing p_path_postprocessing);
+ PathPostProcessing get_path_postprocessing() const;
+
+ void set_map(const RID &p_map);
+ const RID &get_map() const;
+
+ void set_start_position(const Vector2 p_start_position);
+ Vector2 get_start_position() const;
+
+ void set_target_position(const Vector2 p_target_position);
+ Vector2 get_target_position() const;
+
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
+};
+
+VARIANT_ENUM_CAST(NavigationPathQueryParameters2D::PathfindingAlgorithm);
+VARIANT_ENUM_CAST(NavigationPathQueryParameters2D::PathPostProcessing);
+
+#endif // NAVIGATION_PATH_QUERY_PARAMETERS_2D_H
diff --git a/servers/navigation/navigation_path_query_parameters_3d.cpp b/servers/navigation/navigation_path_query_parameters_3d.cpp
new file mode 100644
index 0000000000..b09448e82e
--- /dev/null
+++ b/servers/navigation/navigation_path_query_parameters_3d.cpp
@@ -0,0 +1,144 @@
+/*************************************************************************/
+/* navigation_path_query_parameters_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "navigation_path_query_parameters_3d.h"
+
+void NavigationPathQueryParameters3D::set_pathfinding_algorithm(const NavigationPathQueryParameters3D::PathfindingAlgorithm p_pathfinding_algorithm) {
+ switch (p_pathfinding_algorithm) {
+ case PATHFINDING_ALGORITHM_ASTAR: {
+ parameters.pathfinding_algorithm = NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR;
+ } break;
+ default: {
+ WARN_PRINT_ONCE("No match for used PathfindingAlgorithm - fallback to default");
+ parameters.pathfinding_algorithm = NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR;
+ } break;
+ }
+}
+
+NavigationPathQueryParameters3D::PathfindingAlgorithm NavigationPathQueryParameters3D::get_pathfinding_algorithm() const {
+ switch (parameters.pathfinding_algorithm) {
+ case NavigationUtilities::PathfindingAlgorithm::PATHFINDING_ALGORITHM_ASTAR:
+ return PATHFINDING_ALGORITHM_ASTAR;
+ default:
+ WARN_PRINT_ONCE("No match for used PathfindingAlgorithm - fallback to default");
+ return PATHFINDING_ALGORITHM_ASTAR;
+ }
+}
+
+void NavigationPathQueryParameters3D::set_path_postprocessing(const NavigationPathQueryParameters3D::PathPostProcessing p_path_postprocessing) {
+ switch (p_path_postprocessing) {
+ case PATH_POSTPROCESSING_CORRIDORFUNNEL: {
+ parameters.path_postprocessing = NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ } break;
+ case PATH_POSTPROCESSING_EDGECENTERED: {
+ parameters.path_postprocessing = NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED;
+ } break;
+ default: {
+ WARN_PRINT_ONCE("No match for used PathPostProcessing - fallback to default");
+ parameters.path_postprocessing = NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ } break;
+ }
+}
+
+NavigationPathQueryParameters3D::PathPostProcessing NavigationPathQueryParameters3D::get_path_postprocessing() const {
+ switch (parameters.path_postprocessing) {
+ case NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_CORRIDORFUNNEL:
+ return PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ case NavigationUtilities::PathPostProcessing::PATH_POSTPROCESSING_EDGECENTERED:
+ return PATH_POSTPROCESSING_EDGECENTERED;
+ default:
+ WARN_PRINT_ONCE("No match for used PathPostProcessing - fallback to default");
+ return PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ }
+}
+
+void NavigationPathQueryParameters3D::set_map(const RID &p_map) {
+ parameters.map = p_map;
+}
+
+const RID &NavigationPathQueryParameters3D::get_map() const {
+ return parameters.map;
+}
+
+void NavigationPathQueryParameters3D::set_start_position(const Vector3 &p_start_position) {
+ parameters.start_position = p_start_position;
+}
+
+const Vector3 &NavigationPathQueryParameters3D::get_start_position() const {
+ return parameters.start_position;
+}
+
+void NavigationPathQueryParameters3D::set_target_position(const Vector3 &p_target_position) {
+ parameters.target_position = p_target_position;
+}
+
+const Vector3 &NavigationPathQueryParameters3D::get_target_position() const {
+ return parameters.target_position;
+}
+
+void NavigationPathQueryParameters3D::set_navigation_layers(uint32_t p_navigation_layers) {
+ parameters.navigation_layers = p_navigation_layers;
+}
+
+uint32_t NavigationPathQueryParameters3D::get_navigation_layers() const {
+ return parameters.navigation_layers;
+}
+
+void NavigationPathQueryParameters3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_pathfinding_algorithm", "pathfinding_algorithm"), &NavigationPathQueryParameters3D::set_pathfinding_algorithm);
+ ClassDB::bind_method(D_METHOD("get_pathfinding_algorithm"), &NavigationPathQueryParameters3D::get_pathfinding_algorithm);
+
+ ClassDB::bind_method(D_METHOD("set_path_postprocessing", "path_postprocessing"), &NavigationPathQueryParameters3D::set_path_postprocessing);
+ ClassDB::bind_method(D_METHOD("get_path_postprocessing"), &NavigationPathQueryParameters3D::get_path_postprocessing);
+
+ ClassDB::bind_method(D_METHOD("set_map", "map"), &NavigationPathQueryParameters3D::set_map);
+ ClassDB::bind_method(D_METHOD("get_map"), &NavigationPathQueryParameters3D::get_map);
+
+ ClassDB::bind_method(D_METHOD("set_start_position", "start_position"), &NavigationPathQueryParameters3D::set_start_position);
+ ClassDB::bind_method(D_METHOD("get_start_position"), &NavigationPathQueryParameters3D::get_start_position);
+
+ ClassDB::bind_method(D_METHOD("set_target_position", "target_position"), &NavigationPathQueryParameters3D::set_target_position);
+ ClassDB::bind_method(D_METHOD("get_target_position"), &NavigationPathQueryParameters3D::get_target_position);
+
+ ClassDB::bind_method(D_METHOD("set_navigation_layers", "navigation_layers"), &NavigationPathQueryParameters3D::set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("get_navigation_layers"), &NavigationPathQueryParameters3D::get_navigation_layers);
+
+ ADD_PROPERTY(PropertyInfo(Variant::RID, "map"), "set_map", "get_map");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "start_position"), "set_start_position", "get_start_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "target_position"), "set_target_position", "get_target_position");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "navigation_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigation_layers", "get_navigation_layers");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "pathfinding_algorithm", PROPERTY_HINT_ENUM, "AStar"), "set_pathfinding_algorithm", "get_pathfinding_algorithm");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "path_postprocessing", PROPERTY_HINT_ENUM, "Corridorfunnel,Edgecentered"), "set_path_postprocessing", "get_path_postprocessing");
+
+ BIND_ENUM_CONSTANT(PATHFINDING_ALGORITHM_ASTAR);
+
+ BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_CORRIDORFUNNEL);
+ BIND_ENUM_CONSTANT(PATH_POSTPROCESSING_EDGECENTERED);
+}
diff --git a/servers/navigation/navigation_path_query_parameters_3d.h b/servers/navigation/navigation_path_query_parameters_3d.h
new file mode 100644
index 0000000000..b4cf02fc79
--- /dev/null
+++ b/servers/navigation/navigation_path_query_parameters_3d.h
@@ -0,0 +1,79 @@
+/*************************************************************************/
+/* navigation_path_query_parameters_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_PATH_QUERY_PARAMETERS_3D_H
+#define NAVIGATION_PATH_QUERY_PARAMETERS_3D_H
+
+#include "core/object/ref_counted.h"
+#include "servers/navigation/navigation_utilities.h"
+
+class NavigationPathQueryParameters3D : public RefCounted {
+ GDCLASS(NavigationPathQueryParameters3D, RefCounted);
+
+ NavigationUtilities::PathQueryParameters parameters;
+
+protected:
+ static void _bind_methods();
+
+public:
+ enum PathfindingAlgorithm {
+ PATHFINDING_ALGORITHM_ASTAR = 0,
+ };
+
+ enum PathPostProcessing {
+ PATH_POSTPROCESSING_CORRIDORFUNNEL = 0,
+ PATH_POSTPROCESSING_EDGECENTERED,
+ };
+
+ const NavigationUtilities::PathQueryParameters &get_parameters() const { return parameters; }
+
+ void set_pathfinding_algorithm(const PathfindingAlgorithm p_pathfinding_algorithm);
+ PathfindingAlgorithm get_pathfinding_algorithm() const;
+
+ void set_path_postprocessing(const PathPostProcessing p_path_postprocessing);
+ PathPostProcessing get_path_postprocessing() const;
+
+ void set_map(const RID &p_map);
+ const RID &get_map() const;
+
+ void set_start_position(const Vector3 &p_start_position);
+ const Vector3 &get_start_position() const;
+
+ void set_target_position(const Vector3 &p_target_position);
+ const Vector3 &get_target_position() const;
+
+ void set_navigation_layers(uint32_t p_navigation_layers);
+ uint32_t get_navigation_layers() const;
+};
+
+VARIANT_ENUM_CAST(NavigationPathQueryParameters3D::PathfindingAlgorithm);
+VARIANT_ENUM_CAST(NavigationPathQueryParameters3D::PathPostProcessing);
+
+#endif // NAVIGATION_PATH_QUERY_PARAMETERS_3D_H
diff --git a/servers/navigation/navigation_path_query_result_2d.cpp b/servers/navigation/navigation_path_query_result_2d.cpp
new file mode 100644
index 0000000000..8a55451e40
--- /dev/null
+++ b/servers/navigation/navigation_path_query_result_2d.cpp
@@ -0,0 +1,52 @@
+/*************************************************************************/
+/* navigation_path_query_result_2d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "navigation_path_query_result_2d.h"
+
+void NavigationPathQueryResult2D::set_path(const Vector<Vector2> &p_path) {
+ path = p_path;
+}
+
+const Vector<Vector2> &NavigationPathQueryResult2D::get_path() const {
+ return path;
+}
+
+void NavigationPathQueryResult2D::reset() {
+ path.clear();
+}
+
+void NavigationPathQueryResult2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult2D::set_path);
+ ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult2D::get_path);
+
+ ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult2D::reset);
+
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "path"), "set_path", "get_path");
+}
diff --git a/servers/navigation/navigation_path_query_result_2d.h b/servers/navigation/navigation_path_query_result_2d.h
new file mode 100644
index 0000000000..da251ef32d
--- /dev/null
+++ b/servers/navigation/navigation_path_query_result_2d.h
@@ -0,0 +1,52 @@
+/*************************************************************************/
+/* navigation_path_query_result_2d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_PATH_QUERY_RESULT_2D_H
+#define NAVIGATION_PATH_QUERY_RESULT_2D_H
+
+#include "core/object/ref_counted.h"
+#include "servers/navigation/navigation_utilities.h"
+
+class NavigationPathQueryResult2D : public RefCounted {
+ GDCLASS(NavigationPathQueryResult2D, RefCounted);
+
+ Vector<Vector2> path;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_path(const Vector<Vector2> &p_path);
+ const Vector<Vector2> &get_path() const;
+
+ void reset();
+};
+
+#endif // NAVIGATION_PATH_QUERY_RESULT_2D_H
diff --git a/servers/navigation/navigation_path_query_result_3d.cpp b/servers/navigation/navigation_path_query_result_3d.cpp
new file mode 100644
index 0000000000..1e28352995
--- /dev/null
+++ b/servers/navigation/navigation_path_query_result_3d.cpp
@@ -0,0 +1,52 @@
+/*************************************************************************/
+/* navigation_path_query_result_3d.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "navigation_path_query_result_3d.h"
+
+void NavigationPathQueryResult3D::set_path(const Vector<Vector3> &p_path) {
+ path = p_path;
+}
+
+const Vector<Vector3> &NavigationPathQueryResult3D::get_path() const {
+ return path;
+}
+
+void NavigationPathQueryResult3D::reset() {
+ path.clear();
+}
+
+void NavigationPathQueryResult3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_path", "path"), &NavigationPathQueryResult3D::set_path);
+ ClassDB::bind_method(D_METHOD("get_path"), &NavigationPathQueryResult3D::get_path);
+
+ ClassDB::bind_method(D_METHOD("reset"), &NavigationPathQueryResult3D::reset);
+
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR3_ARRAY, "path"), "set_path", "get_path");
+}
diff --git a/servers/navigation/navigation_path_query_result_3d.h b/servers/navigation/navigation_path_query_result_3d.h
new file mode 100644
index 0000000000..fc143ac389
--- /dev/null
+++ b/servers/navigation/navigation_path_query_result_3d.h
@@ -0,0 +1,52 @@
+/*************************************************************************/
+/* navigation_path_query_result_3d.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_PATH_QUERY_RESULT_3D_H
+#define NAVIGATION_PATH_QUERY_RESULT_3D_H
+
+#include "core/object/ref_counted.h"
+#include "servers/navigation/navigation_utilities.h"
+
+class NavigationPathQueryResult3D : public RefCounted {
+ GDCLASS(NavigationPathQueryResult3D, RefCounted);
+
+ Vector<Vector3> path;
+
+protected:
+ static void _bind_methods();
+
+public:
+ void set_path(const Vector<Vector3> &p_path);
+ const Vector<Vector3> &get_path() const;
+
+ void reset();
+};
+
+#endif // NAVIGATION_PATH_QUERY_RESULT_3D_H
diff --git a/servers/navigation/navigation_utilities.h b/servers/navigation/navigation_utilities.h
new file mode 100644
index 0000000000..bedcc16a67
--- /dev/null
+++ b/servers/navigation/navigation_utilities.h
@@ -0,0 +1,62 @@
+/*************************************************************************/
+/* navigation_utilities.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef NAVIGATION_UTILITIES_H
+#define NAVIGATION_UTILITIES_H
+
+#include "core/math/vector3.h"
+
+namespace NavigationUtilities {
+
+enum PathfindingAlgorithm {
+ PATHFINDING_ALGORITHM_ASTAR = 0,
+};
+
+enum PathPostProcessing {
+ PATH_POSTPROCESSING_CORRIDORFUNNEL = 0,
+ PATH_POSTPROCESSING_EDGECENTERED,
+};
+
+struct PathQueryParameters {
+ PathfindingAlgorithm pathfinding_algorithm = PATHFINDING_ALGORITHM_ASTAR;
+ PathPostProcessing path_postprocessing = PATH_POSTPROCESSING_CORRIDORFUNNEL;
+ RID map;
+ Vector3 start_position = Vector3();
+ Vector3 target_position = Vector3();
+ uint32_t navigation_layers = 1;
+};
+
+struct PathQueryResult {
+ Vector<Vector3> path;
+};
+
+} //namespace NavigationUtilities
+
+#endif // NAVIGATION_UTILITIES_H
diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp
index ab323e76e8..04e5d2f6a1 100644
--- a/servers/navigation_server_2d.cpp
+++ b/servers/navigation_server_2d.cpp
@@ -53,6 +53,12 @@ NavigationServer2D *NavigationServer2D::singleton = nullptr;
return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0)); \
}
+#define FORWARD_1_R_C(CONV_R, FUNC_NAME, T_0, D_0, CONV_0) \
+ NavigationServer2D::FUNC_NAME(T_0 D_0) \
+ const { \
+ return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0))); \
+ }
+
#define FORWARD_2_C(FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \
NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1) \
const { \
@@ -158,40 +164,123 @@ void NavigationServer2D::_emit_map_changed(RID p_map) {
emit_signal(SNAME("map_changed"), p_map);
}
+#ifdef DEBUG_ENABLED
+void NavigationServer2D::set_debug_enabled(bool p_enabled) {
+ NavigationServer3D::get_singleton_mut()->set_debug_enabled(p_enabled);
+}
+bool NavigationServer2D::get_debug_enabled() const {
+ return NavigationServer3D::get_singleton()->get_debug_enabled();
+}
+
+void NavigationServer2D::set_debug_navigation_edge_connection_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_edge_connection_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_edge_connection_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_edge_connection_color();
+}
+
+void NavigationServer2D::set_debug_navigation_geometry_face_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_geometry_face_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_color();
+}
+
+void NavigationServer2D::set_debug_navigation_geometry_face_disabled_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_geometry_face_disabled_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_geometry_face_disabled_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_geometry_face_disabled_color();
+}
+
+void NavigationServer2D::set_debug_navigation_link_connection_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_link_connection_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_link_connection_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_color();
+}
+
+void NavigationServer2D::set_debug_navigation_link_connection_disabled_color(const Color &p_color) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_link_connection_disabled_color(p_color);
+}
+
+Color NavigationServer2D::get_debug_navigation_link_connection_disabled_color() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_link_connection_disabled_color();
+}
+
+void NavigationServer2D::set_debug_navigation_enable_edge_connections(const bool p_value) {
+ NavigationServer3D::get_singleton_mut()->set_debug_navigation_enable_edge_connections(p_value);
+}
+
+bool NavigationServer2D::get_debug_navigation_enable_edge_connections() const {
+ return NavigationServer3D::get_singleton()->get_debug_navigation_enable_edge_connections();
+}
+#endif // DEBUG_ENABLED
+
void NavigationServer2D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_maps"), &NavigationServer2D::get_maps);
+
ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create);
ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active);
- ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer2D::map_is_active);
+ ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer2D::map_is_active);
ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer2D::map_set_cell_size);
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer2D::map_set_link_connection_radius);
+ ClassDB::bind_method(D_METHOD("map_get_link_connection_radius", "map"), &NavigationServer2D::map_get_link_connection_radius);
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer2D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner);
+ ClassDB::bind_method(D_METHOD("map_get_links", "map"), &NavigationServer2D::map_get_links);
ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer2D::map_get_regions);
ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer2D::map_get_agents);
+ ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer2D::map_force_update);
+
+ ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer2D::query_path);
+
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create);
ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer2D::region_set_enter_cost);
ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer2D::region_get_enter_cost);
ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer2D::region_set_travel_cost);
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer2D::region_get_travel_cost);
+ ClassDB::bind_method(D_METHOD("region_owns_point", "region", "point"), &NavigationServer2D::region_owns_point);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer2D::region_get_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer2D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer2D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer2D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer2D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly);
ClassDB::bind_method(D_METHOD("region_get_connections_count", "region"), &NavigationServer2D::region_get_connections_count);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer2D::region_get_connection_pathway_end);
+ ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer2D::link_create);
+ ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer2D::link_set_map);
+ ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer2D::link_get_map);
+ ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer2D::link_set_bidirectional);
+ ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer2D::link_is_bidirectional);
+ ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer2D::link_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("link_get_navigation_layers", "link"), &NavigationServer2D::link_get_navigation_layers);
+ ClassDB::bind_method(D_METHOD("link_set_start_location", "link", "location"), &NavigationServer2D::link_set_start_location);
+ ClassDB::bind_method(D_METHOD("link_get_start_location", "link"), &NavigationServer2D::link_get_start_location);
+ ClassDB::bind_method(D_METHOD("link_set_end_location", "link", "location"), &NavigationServer2D::link_set_end_location);
+ ClassDB::bind_method(D_METHOD("link_get_end_location", "link"), &NavigationServer2D::link_get_end_location);
+ ClassDB::bind_method(D_METHOD("link_set_enter_cost", "link", "enter_cost"), &NavigationServer2D::link_set_enter_cost);
+ ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer2D::link_get_enter_cost);
+ ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer2D::link_set_travel_cost);
+ ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer2D::link_get_travel_cost);
+
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map);
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map);
- ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer2D::agent_set_neighbor_dist);
+ ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer2D::agent_set_neighbor_distance);
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors);
ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer2D::agent_set_time_horizon);
ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer2D::agent_set_radius);
@@ -217,9 +306,13 @@ NavigationServer2D::~NavigationServer2D() {
singleton = nullptr;
}
-Array FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid);
+TypedArray<RID> FORWARD_0_C(get_maps);
-Array FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid);
+TypedArray<RID> FORWARD_1_C(map_get_links, RID, p_map, rid_to_rid);
+
+TypedArray<RID> FORWARD_1_C(map_get_regions, RID, p_map, rid_to_rid);
+
+TypedArray<RID> FORWARD_1_C(map_get_agents, RID, p_map, rid_to_rid);
RID FORWARD_1_C(region_get_map, RID, p_region, rid_to_rid);
@@ -231,12 +324,19 @@ void FORWARD_2_C(map_set_active, RID, p_map, bool, p_active, rid_to_rid, bool_to
bool FORWARD_1_C(map_is_active, RID, p_map, rid_to_rid);
+void NavigationServer2D::map_force_update(RID p_map) {
+ NavigationServer3D::get_singleton_mut()->map_force_update(p_map);
+}
+
void FORWARD_2_C(map_set_cell_size, RID, p_map, real_t, p_cell_size, rid_to_rid, real_to_real);
real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid);
void FORWARD_2_C(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real);
real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid);
+void FORWARD_2_C(map_set_link_connection_radius, RID, p_map, real_t, p_connection_radius, rid_to_rid, real_to_real);
+real_t FORWARD_1_C(map_get_link_connection_radius, RID, p_map, rid_to_rid);
+
Vector<Vector2> FORWARD_5_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, uint32_t, p_layers, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool, uint32_to_uint32);
Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3);
@@ -248,10 +348,11 @@ void FORWARD_2_C(region_set_enter_cost, RID, p_region, real_t, p_enter_cost, rid
real_t FORWARD_1_C(region_get_enter_cost, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_travel_cost, RID, p_region, real_t, p_travel_cost, rid_to_rid, real_to_real);
real_t FORWARD_1_C(region_get_travel_cost, RID, p_region, rid_to_rid);
+bool FORWARD_2_C(region_owns_point, RID, p_region, const Vector2 &, p_point, rid_to_rid, v2_to_v3);
void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid);
-void FORWARD_2_C(region_set_layers, RID, p_region, uint32_t, p_layers, rid_to_rid, uint32_to_uint32);
-uint32_t FORWARD_1_C(region_get_layers, RID, p_region, rid_to_rid);
+void FORWARD_2_C(region_set_navigation_layers, RID, p_region, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
+uint32_t FORWARD_1_C(region_get_navigation_layers, RID, p_region, rid_to_rid);
void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3);
void NavigationServer2D::region_set_navpoly(RID p_region, Ref<NavigationPolygon> p_nav_mesh) const {
@@ -262,6 +363,23 @@ int FORWARD_1_C(region_get_connections_count, RID, p_region, rid_to_rid);
Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_start, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
Vector2 FORWARD_2_R_C(v3_to_v2, region_get_connection_pathway_end, RID, p_region, int, p_connection_id, rid_to_rid, int_to_int);
+RID FORWARD_0_C(link_create);
+
+void FORWARD_2_C(link_set_map, RID, p_link, RID, p_map, rid_to_rid, rid_to_rid);
+RID FORWARD_1_C(link_get_map, RID, p_link, rid_to_rid);
+void FORWARD_2_C(link_set_bidirectional, RID, p_link, bool, p_bidirectional, rid_to_rid, bool_to_bool);
+bool FORWARD_1_C(link_is_bidirectional, RID, p_link, rid_to_rid);
+void FORWARD_2_C(link_set_navigation_layers, RID, p_link, uint32_t, p_navigation_layers, rid_to_rid, uint32_to_uint32);
+uint32_t FORWARD_1_C(link_get_navigation_layers, RID, p_link, rid_to_rid);
+void FORWARD_2_C(link_set_start_location, RID, p_link, Vector2, p_location, rid_to_rid, v2_to_v3);
+Vector2 FORWARD_1_R_C(v3_to_v2, link_get_start_location, RID, p_link, rid_to_rid);
+void FORWARD_2_C(link_set_end_location, RID, p_link, Vector2, p_location, rid_to_rid, v2_to_v3);
+Vector2 FORWARD_1_R_C(v3_to_v2, link_get_end_location, RID, p_link, rid_to_rid);
+void FORWARD_2_C(link_set_enter_cost, RID, p_link, real_t, p_enter_cost, rid_to_rid, real_to_real);
+real_t FORWARD_1_C(link_get_enter_cost, RID, p_link, rid_to_rid);
+void FORWARD_2_C(link_set_travel_cost, RID, p_link, real_t, p_travel_cost, rid_to_rid, real_to_real);
+real_t FORWARD_1_C(link_get_travel_cost, RID, p_link, rid_to_rid);
+
RID NavigationServer2D::agent_create() const {
RID agent = NavigationServer3D::get_singleton()->agent_create();
NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true);
@@ -270,7 +388,7 @@ RID NavigationServer2D::agent_create() const {
void FORWARD_2_C(agent_set_map, RID, p_agent, RID, p_map, rid_to_rid, rid_to_rid);
-void FORWARD_2_C(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real);
+void FORWARD_2_C(agent_set_neighbor_distance, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real);
void FORWARD_2_C(agent_set_max_neighbors, RID, p_agent, int, p_count, rid_to_rid, int_to_int);
@@ -293,3 +411,12 @@ bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
void FORWARD_4_C(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, rid_to_rid, obj_to_obj, sn_to_sn, var_to_var);
void FORWARD_1_C(free, RID, p_object, rid_to_rid);
+
+void NavigationServer2D::query_path(const Ref<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result) const {
+ ERR_FAIL_COND(!p_query_parameters.is_valid());
+ ERR_FAIL_COND(!p_query_result.is_valid());
+
+ const NavigationUtilities::PathQueryResult _query_result = NavigationServer3D::get_singleton()->_query_path(p_query_parameters->get_parameters());
+
+ p_query_result->set_path(vector_v3_to_v2(_query_result.path));
+}
diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h
index 8e285147b1..54cfc6b14e 100644
--- a/servers/navigation_server_2d.h
+++ b/servers/navigation_server_2d.h
@@ -33,7 +33,10 @@
#include "core/object/class_db.h"
#include "core/templates/rid.h"
+
#include "scene/2d/navigation_region_2d.h"
+#include "servers/navigation/navigation_path_query_parameters_2d.h"
+#include "servers/navigation/navigation_path_query_result_2d.h"
// This server exposes the `NavigationServer3D` features in the 2D world.
class NavigationServer2D : public Object {
@@ -53,6 +56,8 @@ public:
/// MUST be used in single thread!
static NavigationServer2D *get_singleton_mut() { return singleton; }
+ virtual TypedArray<RID> get_maps() const;
+
/// Create a new map.
virtual RID map_create() const;
@@ -74,14 +79,23 @@ public:
/// Returns the edge connection margin of this map.
virtual real_t map_get_edge_connection_margin(RID p_map) const;
+ /// Set the map link connection radius used to attach links to the nav mesh.
+ virtual void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) const;
+
+ /// Returns the link connection radius of this map.
+ virtual real_t map_get_link_connection_radius(RID p_map) const;
+
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_layers = 1) const;
+ virtual Vector<Vector2> map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const;
virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const;
virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const;
- virtual Array map_get_regions(RID p_map) const;
- virtual Array map_get_agents(RID p_map) const;
+ virtual TypedArray<RID> map_get_links(RID p_map) const;
+ virtual TypedArray<RID> map_get_regions(RID p_map) const;
+ virtual TypedArray<RID> map_get_agents(RID p_map) const;
+
+ virtual void map_force_update(RID p_map);
/// Creates a new region.
virtual RID region_create() const;
@@ -94,13 +108,15 @@ public:
virtual void region_set_travel_cost(RID p_region, real_t p_travel_cost) const;
virtual real_t region_get_travel_cost(RID p_region) const;
+ virtual bool region_owns_point(RID p_region, const Vector2 &p_point) const;
+
/// Set the map of this region.
virtual void region_set_map(RID p_region, RID p_map) const;
virtual RID region_get_map(RID p_region) const;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const;
- virtual uint32_t region_get_layers(RID p_region) const;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform2D p_transform) const;
@@ -113,6 +129,37 @@ public:
virtual Vector2 region_get_connection_pathway_start(RID p_region, int p_connection_id) const;
virtual Vector2 region_get_connection_pathway_end(RID p_region, int p_connection_id) const;
+ /// Creates a new link between locations in the nav map.
+ virtual RID link_create() const;
+
+ /// Set the map of this link.
+ virtual void link_set_map(RID p_link, RID p_map) const;
+ virtual RID link_get_map(RID p_link) const;
+
+ /// Set whether this link travels in both directions.
+ virtual void link_set_bidirectional(RID p_link, bool p_bidirectional) const;
+ virtual bool link_is_bidirectional(RID p_link) const;
+
+ /// Set the link's layers.
+ virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) const;
+ virtual uint32_t link_get_navigation_layers(RID p_link) const;
+
+ /// Set the start location of the link.
+ virtual void link_set_start_location(RID p_link, Vector2 p_location) const;
+ virtual Vector2 link_get_start_location(RID p_link) const;
+
+ /// Set the end location of the link.
+ virtual void link_set_end_location(RID p_link, Vector2 p_location) const;
+ virtual Vector2 link_get_end_location(RID p_link) const;
+
+ /// Set the enter cost of the link.
+ virtual void link_set_enter_cost(RID p_link, real_t p_enter_cost) const;
+ virtual real_t link_get_enter_cost(RID p_link) const;
+
+ /// Set the travel cost of the link.
+ virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const;
+ virtual real_t link_get_travel_cost(RID p_link) const;
+
/// Creates the agent.
virtual RID agent_create() const;
@@ -127,7 +174,7 @@ public:
/// time of the simulation. If the number is too
/// low, the simulation will not be safe.
/// Must be non-negative.
- virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const;
+ virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const;
/// The maximum number of other agents this
/// agent takes into account in the navigation.
@@ -173,11 +220,36 @@ public:
/// Callback called at the end of the RVO process
virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const;
+ virtual void query_path(const Ref<NavigationPathQueryParameters2D> &p_query_parameters, Ref<NavigationPathQueryResult2D> p_query_result) const;
+
/// Destroy the `RID`
virtual void free(RID p_object) const;
NavigationServer2D();
virtual ~NavigationServer2D();
+
+#ifdef DEBUG_ENABLED
+ void set_debug_enabled(bool p_enabled);
+ bool get_debug_enabled() const;
+
+ void set_debug_navigation_edge_connection_color(const Color &p_color);
+ Color get_debug_navigation_edge_connection_color() const;
+
+ void set_debug_navigation_geometry_face_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_color() const;
+
+ void set_debug_navigation_geometry_face_disabled_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_disabled_color() const;
+
+ void set_debug_navigation_link_connection_color(const Color &p_color);
+ Color get_debug_navigation_link_connection_color() const;
+
+ void set_debug_navigation_link_connection_disabled_color(const Color &p_color);
+ Color get_debug_navigation_link_connection_disabled_color() const;
+
+ void set_debug_navigation_enable_edge_connections(const bool p_value);
+ bool get_debug_navigation_enable_edge_connections() const;
+#endif // DEBUG_ENABLED
};
#endif // NAVIGATION_SERVER_2D_H
diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp
index 6d99f6dfbb..cab8816747 100644
--- a/servers/navigation_server_3d.cpp
+++ b/servers/navigation_server_3d.cpp
@@ -30,36 +30,50 @@
#include "navigation_server_3d.h"
+#ifdef DEBUG_ENABLED
+#include "core/config/project_settings.h"
+#endif // DEBUG_ENABLED
+
NavigationServer3D *NavigationServer3D::singleton = nullptr;
void NavigationServer3D::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("get_maps"), &NavigationServer3D::get_maps);
+
ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer3D::map_create);
ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer3D::map_set_active);
- ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer3D::map_is_active);
+ ClassDB::bind_method(D_METHOD("map_is_active", "map"), &NavigationServer3D::map_is_active);
ClassDB::bind_method(D_METHOD("map_set_up", "map", "up"), &NavigationServer3D::map_set_up);
ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up);
ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size);
ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size);
ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin);
ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin);
- ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
+ ClassDB::bind_method(D_METHOD("map_set_link_connection_radius", "map", "radius"), &NavigationServer3D::map_set_link_connection_radius);
+ ClassDB::bind_method(D_METHOD("map_get_link_connection_radius", "map"), &NavigationServer3D::map_get_link_connection_radius);
+ ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize", "navigation_layers"), &NavigationServer3D::map_get_path, DEFVAL(1));
ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false));
ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point);
ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal);
ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner);
+ ClassDB::bind_method(D_METHOD("map_get_links", "map"), &NavigationServer3D::map_get_links);
ClassDB::bind_method(D_METHOD("map_get_regions", "map"), &NavigationServer3D::map_get_regions);
ClassDB::bind_method(D_METHOD("map_get_agents", "map"), &NavigationServer3D::map_get_agents);
+ ClassDB::bind_method(D_METHOD("map_force_update", "map"), &NavigationServer3D::map_force_update);
+
+ ClassDB::bind_method(D_METHOD("query_path", "parameters", "result"), &NavigationServer3D::query_path);
+
ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create);
ClassDB::bind_method(D_METHOD("region_set_enter_cost", "region", "enter_cost"), &NavigationServer3D::region_set_enter_cost);
ClassDB::bind_method(D_METHOD("region_get_enter_cost", "region"), &NavigationServer3D::region_get_enter_cost);
ClassDB::bind_method(D_METHOD("region_set_travel_cost", "region", "travel_cost"), &NavigationServer3D::region_set_travel_cost);
ClassDB::bind_method(D_METHOD("region_get_travel_cost", "region"), &NavigationServer3D::region_get_travel_cost);
+ ClassDB::bind_method(D_METHOD("region_owns_point", "region", "point"), &NavigationServer3D::region_owns_point);
ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map);
ClassDB::bind_method(D_METHOD("region_get_map", "region"), &NavigationServer3D::region_get_map);
- ClassDB::bind_method(D_METHOD("region_set_layers", "region", "layers"), &NavigationServer3D::region_set_layers);
- ClassDB::bind_method(D_METHOD("region_get_layers", "region"), &NavigationServer3D::region_get_layers);
+ ClassDB::bind_method(D_METHOD("region_set_navigation_layers", "region", "navigation_layers"), &NavigationServer3D::region_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("region_get_navigation_layers", "region"), &NavigationServer3D::region_get_navigation_layers);
ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform);
ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh);
ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh);
@@ -67,10 +81,26 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_start", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_start);
ClassDB::bind_method(D_METHOD("region_get_connection_pathway_end", "region", "connection"), &NavigationServer3D::region_get_connection_pathway_end);
+ ClassDB::bind_method(D_METHOD("link_create"), &NavigationServer3D::link_create);
+ ClassDB::bind_method(D_METHOD("link_set_map", "link", "map"), &NavigationServer3D::link_set_map);
+ ClassDB::bind_method(D_METHOD("link_get_map", "link"), &NavigationServer3D::link_get_map);
+ ClassDB::bind_method(D_METHOD("link_set_bidirectional", "link", "bidirectional"), &NavigationServer3D::link_set_bidirectional);
+ ClassDB::bind_method(D_METHOD("link_is_bidirectional", "link"), &NavigationServer3D::link_is_bidirectional);
+ ClassDB::bind_method(D_METHOD("link_set_navigation_layers", "link", "navigation_layers"), &NavigationServer3D::link_set_navigation_layers);
+ ClassDB::bind_method(D_METHOD("link_get_navigation_layers", "link"), &NavigationServer3D::link_get_navigation_layers);
+ ClassDB::bind_method(D_METHOD("link_set_start_location", "link", "location"), &NavigationServer3D::link_set_start_location);
+ ClassDB::bind_method(D_METHOD("link_get_start_location", "link"), &NavigationServer3D::link_get_start_location);
+ ClassDB::bind_method(D_METHOD("link_set_end_location", "link", "location"), &NavigationServer3D::link_set_end_location);
+ ClassDB::bind_method(D_METHOD("link_get_end_location", "link"), &NavigationServer3D::link_get_end_location);
+ ClassDB::bind_method(D_METHOD("link_set_enter_cost", "link", "enter_cost"), &NavigationServer3D::link_set_enter_cost);
+ ClassDB::bind_method(D_METHOD("link_get_enter_cost", "link"), &NavigationServer3D::link_get_enter_cost);
+ ClassDB::bind_method(D_METHOD("link_set_travel_cost", "link", "travel_cost"), &NavigationServer3D::link_set_travel_cost);
+ ClassDB::bind_method(D_METHOD("link_get_travel_cost", "link"), &NavigationServer3D::link_get_travel_cost);
+
ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map);
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map);
- ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer3D::agent_set_neighbor_dist);
+ ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer3D::agent_set_neighbor_distance);
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors);
ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer3D::agent_set_time_horizon);
ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer3D::agent_set_radius);
@@ -87,6 +117,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process);
ADD_SIGNAL(MethodInfo("map_changed", PropertyInfo(Variant::RID, "map")));
+
+ ADD_SIGNAL(MethodInfo("navigation_debug_changed"));
}
const NavigationServer3D *NavigationServer3D::get_singleton() {
@@ -100,6 +132,30 @@ NavigationServer3D *NavigationServer3D::get_singleton_mut() {
NavigationServer3D::NavigationServer3D() {
ERR_FAIL_COND(singleton != nullptr);
singleton = this;
+
+#ifdef DEBUG_ENABLED
+ debug_navigation_edge_connection_color = GLOBAL_DEF("debug/shapes/navigation/edge_connection_color", Color(1.0, 0.0, 1.0, 1.0));
+ debug_navigation_geometry_edge_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_color", Color(0.5, 1.0, 1.0, 1.0));
+ debug_navigation_geometry_face_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_color", Color(0.5, 1.0, 1.0, 0.4));
+ debug_navigation_geometry_edge_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_edge_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
+ debug_navigation_geometry_face_disabled_color = GLOBAL_DEF("debug/shapes/navigation/geometry_face_disabled_color", Color(0.5, 0.5, 0.5, 0.4));
+ debug_navigation_link_connection_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_color", Color(1.0, 0.5, 1.0, 1.0));
+ debug_navigation_link_connection_disabled_color = GLOBAL_DEF("debug/shapes/navigation/link_connection_disabled_color", Color(0.5, 0.5, 0.5, 1.0));
+
+ debug_navigation_enable_edge_connections = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections", true);
+ debug_navigation_enable_edge_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_connections_xray", true);
+ debug_navigation_enable_edge_lines = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines", true);
+ debug_navigation_enable_edge_lines_xray = GLOBAL_DEF("debug/shapes/navigation/enable_edge_lines_xray", true);
+ debug_navigation_enable_geometry_face_random_color = GLOBAL_DEF("debug/shapes/navigation/enable_geometry_face_random_color", true);
+ debug_navigation_enable_link_connections = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections", true);
+ debug_navigation_enable_link_connections_xray = GLOBAL_DEF("debug/shapes/navigation/enable_link_connections_xray", true);
+
+ if (Engine::get_singleton()->is_editor_hint()) {
+ // enable NavigationServer3D when in Editor or else navmesh edge connections are invisible
+ // on runtime tests SceneTree has "Visible Navigation" set and main iteration takes care of this
+ set_debug_enabled(true);
+ }
+#endif // DEBUG_ENABLED
}
NavigationServer3D::~NavigationServer3D() {
@@ -116,3 +172,319 @@ NavigationServer3D *NavigationServer3DManager::new_default_server() {
ERR_FAIL_COND_V(create_callback == nullptr, nullptr);
return create_callback();
}
+
+#ifdef DEBUG_ENABLED
+void NavigationServer3D::_emit_navigation_debug_changed_signal() {
+ if (debug_dirty) {
+ debug_dirty = false;
+ emit_signal(SNAME("navigation_debug_changed"));
+ }
+}
+#endif // DEBUG_ENABLED
+
+#ifdef DEBUG_ENABLED
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_face_material() {
+ if (debug_navigation_geometry_face_material.is_valid()) {
+ return debug_navigation_geometry_face_material;
+ }
+
+ bool enabled_geometry_face_random_color = get_debug_navigation_enable_geometry_face_random_color();
+
+ Ref<StandardMaterial3D> face_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ face_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ face_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ face_material->set_albedo(get_debug_navigation_geometry_face_color());
+ if (enabled_geometry_face_random_color) {
+ face_material->set_flag(StandardMaterial3D::FLAG_SRGB_VERTEX_COLOR, true);
+ face_material->set_flag(StandardMaterial3D::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
+ }
+
+ debug_navigation_geometry_face_material = face_material;
+
+ return debug_navigation_geometry_face_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_edge_material() {
+ if (debug_navigation_geometry_edge_material.is_valid()) {
+ return debug_navigation_geometry_edge_material;
+ }
+
+ bool enabled_edge_lines_xray = get_debug_navigation_enable_edge_lines_xray();
+
+ Ref<StandardMaterial3D> line_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ line_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ line_material->set_albedo(get_debug_navigation_geometry_edge_color());
+ if (enabled_edge_lines_xray) {
+ line_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+
+ debug_navigation_geometry_edge_material = line_material;
+
+ return debug_navigation_geometry_edge_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_face_disabled_material() {
+ if (debug_navigation_geometry_face_disabled_material.is_valid()) {
+ return debug_navigation_geometry_face_disabled_material;
+ }
+
+ Ref<StandardMaterial3D> face_disabled_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ face_disabled_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ face_disabled_material->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
+ face_disabled_material->set_albedo(get_debug_navigation_geometry_face_disabled_color());
+
+ debug_navigation_geometry_face_disabled_material = face_disabled_material;
+
+ return debug_navigation_geometry_face_disabled_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_geometry_edge_disabled_material() {
+ if (debug_navigation_geometry_edge_disabled_material.is_valid()) {
+ return debug_navigation_geometry_edge_disabled_material;
+ }
+
+ bool enabled_edge_lines_xray = get_debug_navigation_enable_edge_lines_xray();
+
+ Ref<StandardMaterial3D> line_disabled_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ line_disabled_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ line_disabled_material->set_albedo(get_debug_navigation_geometry_edge_disabled_color());
+ if (enabled_edge_lines_xray) {
+ line_disabled_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+
+ debug_navigation_geometry_edge_disabled_material = line_disabled_material;
+
+ return debug_navigation_geometry_edge_disabled_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_edge_connections_material() {
+ if (debug_navigation_edge_connections_material.is_valid()) {
+ return debug_navigation_edge_connections_material;
+ }
+
+ bool enabled_edge_connections_xray = get_debug_navigation_enable_edge_connections_xray();
+
+ Ref<StandardMaterial3D> edge_connections_material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ edge_connections_material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ edge_connections_material->set_albedo(get_debug_navigation_edge_connection_color());
+ if (enabled_edge_connections_xray) {
+ edge_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+ edge_connections_material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
+
+ debug_navigation_edge_connections_material = edge_connections_material;
+
+ return debug_navigation_edge_connections_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connections_material() {
+ if (debug_navigation_link_connections_material.is_valid()) {
+ return debug_navigation_link_connections_material;
+ }
+
+ Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ material->set_albedo(debug_navigation_link_connection_color);
+ if (debug_navigation_enable_link_connections_xray) {
+ material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+ material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
+
+ debug_navigation_link_connections_material = material;
+ return debug_navigation_link_connections_material;
+}
+
+Ref<StandardMaterial3D> NavigationServer3D::get_debug_navigation_link_connections_disabled_material() {
+ if (debug_navigation_link_connections_disabled_material.is_valid()) {
+ return debug_navigation_link_connections_disabled_material;
+ }
+
+ Ref<StandardMaterial3D> material = Ref<StandardMaterial3D>(memnew(StandardMaterial3D));
+ material->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
+ material->set_albedo(debug_navigation_link_connection_disabled_color);
+ if (debug_navigation_enable_link_connections_xray) {
+ material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
+ }
+ material->set_render_priority(StandardMaterial3D::RENDER_PRIORITY_MAX - 2);
+
+ debug_navigation_link_connections_disabled_material = material;
+ return debug_navigation_link_connections_disabled_material;
+}
+
+void NavigationServer3D::set_debug_navigation_edge_connection_color(const Color &p_color) {
+ debug_navigation_edge_connection_color = p_color;
+ if (debug_navigation_edge_connections_material.is_valid()) {
+ debug_navigation_edge_connections_material->set_albedo(debug_navigation_edge_connection_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_edge_connection_color() const {
+ return debug_navigation_edge_connection_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_edge_color(const Color &p_color) {
+ debug_navigation_geometry_edge_color = p_color;
+ if (debug_navigation_geometry_edge_material.is_valid()) {
+ debug_navigation_geometry_edge_material->set_albedo(debug_navigation_geometry_edge_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_edge_color() const {
+ return debug_navigation_geometry_edge_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_face_color(const Color &p_color) {
+ debug_navigation_geometry_face_color = p_color;
+ if (debug_navigation_geometry_face_material.is_valid()) {
+ debug_navigation_geometry_face_material->set_albedo(debug_navigation_geometry_face_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_face_color() const {
+ return debug_navigation_geometry_face_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_edge_disabled_color(const Color &p_color) {
+ debug_navigation_geometry_edge_disabled_color = p_color;
+ if (debug_navigation_geometry_edge_disabled_material.is_valid()) {
+ debug_navigation_geometry_edge_disabled_material->set_albedo(debug_navigation_geometry_edge_disabled_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_edge_disabled_color() const {
+ return debug_navigation_geometry_edge_disabled_color;
+}
+
+void NavigationServer3D::set_debug_navigation_geometry_face_disabled_color(const Color &p_color) {
+ debug_navigation_geometry_face_disabled_color = p_color;
+ if (debug_navigation_geometry_face_disabled_material.is_valid()) {
+ debug_navigation_geometry_face_disabled_material->set_albedo(debug_navigation_geometry_face_disabled_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_geometry_face_disabled_color() const {
+ return debug_navigation_geometry_face_disabled_color;
+}
+
+void NavigationServer3D::set_debug_navigation_link_connection_color(const Color &p_color) {
+ debug_navigation_link_connection_color = p_color;
+ if (debug_navigation_link_connections_material.is_valid()) {
+ debug_navigation_link_connections_material->set_albedo(debug_navigation_link_connection_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_link_connection_color() const {
+ return debug_navigation_link_connection_color;
+}
+
+void NavigationServer3D::set_debug_navigation_link_connection_disabled_color(const Color &p_color) {
+ debug_navigation_link_connection_disabled_color = p_color;
+ if (debug_navigation_link_connections_disabled_material.is_valid()) {
+ debug_navigation_link_connections_disabled_material->set_albedo(debug_navigation_link_connection_disabled_color);
+ }
+}
+
+Color NavigationServer3D::get_debug_navigation_link_connection_disabled_color() const {
+ return debug_navigation_link_connection_disabled_color;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_connections(const bool p_value) {
+ debug_navigation_enable_edge_connections = p_value;
+ debug_dirty = true;
+ call_deferred("_emit_navigation_debug_changed_signal");
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_connections() const {
+ return debug_navigation_enable_edge_connections;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_connections_xray(const bool p_value) {
+ debug_navigation_enable_edge_connections_xray = p_value;
+ if (debug_navigation_edge_connections_material.is_valid()) {
+ debug_navigation_edge_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_edge_connections_xray);
+ }
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_connections_xray() const {
+ return debug_navigation_enable_edge_connections_xray;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_lines(const bool p_value) {
+ debug_navigation_enable_edge_lines = p_value;
+ debug_dirty = true;
+ call_deferred("_emit_navigation_debug_changed_signal");
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_lines() const {
+ return debug_navigation_enable_edge_lines;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_edge_lines_xray(const bool p_value) {
+ debug_navigation_enable_edge_lines_xray = p_value;
+ if (debug_navigation_geometry_edge_material.is_valid()) {
+ debug_navigation_geometry_edge_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_edge_lines_xray);
+ }
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_edge_lines_xray() const {
+ return debug_navigation_enable_edge_lines_xray;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_geometry_face_random_color(const bool p_value) {
+ debug_navigation_enable_geometry_face_random_color = p_value;
+ debug_dirty = true;
+ call_deferred("_emit_navigation_debug_changed_signal");
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_geometry_face_random_color() const {
+ return debug_navigation_enable_geometry_face_random_color;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_link_connections(const bool p_value) {
+ debug_navigation_enable_link_connections = p_value;
+ debug_dirty = true;
+ call_deferred("_emit_navigation_debug_changed_signal");
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_link_connections() const {
+ return debug_navigation_enable_link_connections;
+}
+
+void NavigationServer3D::set_debug_navigation_enable_link_connections_xray(const bool p_value) {
+ debug_navigation_enable_link_connections_xray = p_value;
+ if (debug_navigation_link_connections_material.is_valid()) {
+ debug_navigation_link_connections_material->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, debug_navigation_enable_link_connections_xray);
+ }
+}
+
+bool NavigationServer3D::get_debug_navigation_enable_link_connections_xray() const {
+ return debug_navigation_enable_link_connections_xray;
+}
+
+void NavigationServer3D::set_debug_enabled(bool p_enabled) {
+ if (debug_enabled != p_enabled) {
+ debug_dirty = true;
+ }
+
+ debug_enabled = p_enabled;
+
+ if (debug_dirty) {
+ call_deferred("_emit_navigation_debug_changed_signal");
+ }
+}
+
+bool NavigationServer3D::get_debug_enabled() const {
+ return debug_enabled;
+}
+#endif // DEBUG_ENABLED
+
+///////////////////////////////////////////////////////
+
+void NavigationServer3D::query_path(const Ref<NavigationPathQueryParameters3D> &p_query_parameters, Ref<NavigationPathQueryResult3D> p_query_result) const {
+ ERR_FAIL_COND(!p_query_parameters.is_valid());
+ ERR_FAIL_COND(!p_query_result.is_valid());
+
+ const NavigationUtilities::PathQueryResult _query_result = _query_path(p_query_parameters->get_parameters());
+
+ p_query_result->set_path(_query_result.path);
+}
diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h
index 9b7e48e8d1..0f537383a2 100644
--- a/servers/navigation_server_3d.h
+++ b/servers/navigation_server_3d.h
@@ -33,7 +33,10 @@
#include "core/object/class_db.h"
#include "core/templates/rid.h"
+
#include "scene/3d/navigation_region_3d.h"
+#include "servers/navigation/navigation_path_query_parameters_3d.h"
+#include "servers/navigation/navigation_path_query_result_3d.h"
/// This server uses the concept of internal mutability.
/// All the constant functions can be called in multithread because internally
@@ -41,6 +44,7 @@
///
/// Note: All the `set` functions are commands executed during the `sync` phase,
/// don't expect that a change is immediately propagated.
+
class NavigationServer3D : public Object {
GDCLASS(NavigationServer3D, Object);
@@ -56,6 +60,8 @@ public:
/// MUST be used in single thread!
static NavigationServer3D *get_singleton_mut();
+ virtual TypedArray<RID> get_maps() const = 0;
+
/// Create a new map.
virtual RID map_create() const = 0;
@@ -83,16 +89,25 @@ public:
/// Returns the edge connection margin of this map.
virtual real_t map_get_edge_connection_margin(RID p_map) const = 0;
+ /// Set the map link connection radius used to attach links to the nav mesh.
+ virtual void map_set_link_connection_radius(RID p_map, real_t p_connection_radius) const = 0;
+
+ /// Returns the link connection radius of this map.
+ virtual real_t map_get_link_connection_radius(RID p_map) const = 0;
+
/// Returns the navigation path to reach the destination from the origin.
- virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigable_layers = 1) const = 0;
+ virtual Vector<Vector3> map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize, uint32_t p_navigation_layers = 1) const = 0;
virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0;
virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0;
virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0;
virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0;
- virtual Array map_get_regions(RID p_map) const = 0;
- virtual Array map_get_agents(RID p_map) const = 0;
+ virtual TypedArray<RID> map_get_links(RID p_map) const = 0;
+ virtual TypedArray<RID> map_get_regions(RID p_map) const = 0;
+ virtual TypedArray<RID> map_get_agents(RID p_map) const = 0;
+
+ virtual void map_force_update(RID p_map) = 0;
/// Creates a new region.
virtual RID region_create() const = 0;
@@ -105,13 +120,15 @@ public:
virtual void region_set_travel_cost(RID p_region, real_t p_travel_cost) const = 0;
virtual real_t region_get_travel_cost(RID p_region) const = 0;
+ virtual bool region_owns_point(RID p_region, const Vector3 &p_point) const = 0;
+
/// Set the map of this region.
virtual void region_set_map(RID p_region, RID p_map) const = 0;
virtual RID region_get_map(RID p_region) const = 0;
/// Set the region's layers
- virtual void region_set_layers(RID p_region, uint32_t p_layers) const = 0;
- virtual uint32_t region_get_layers(RID p_region) const = 0;
+ virtual void region_set_navigation_layers(RID p_region, uint32_t p_navigation_layers) const = 0;
+ virtual uint32_t region_get_navigation_layers(RID p_region) const = 0;
/// Set the global transformation of this region.
virtual void region_set_transform(RID p_region, Transform3D p_transform) const = 0;
@@ -127,6 +144,37 @@ public:
virtual Vector3 region_get_connection_pathway_start(RID p_region, int p_connection_id) const = 0;
virtual Vector3 region_get_connection_pathway_end(RID p_region, int p_connection_id) const = 0;
+ /// Creates a new link between locations in the nav map.
+ virtual RID link_create() const = 0;
+
+ /// Set the map of this link.
+ virtual void link_set_map(RID p_link, RID p_map) const = 0;
+ virtual RID link_get_map(RID p_link) const = 0;
+
+ /// Set whether this link travels in both directions.
+ virtual void link_set_bidirectional(RID p_link, bool p_bidirectional) const = 0;
+ virtual bool link_is_bidirectional(RID p_link) const = 0;
+
+ /// Set the link's layers.
+ virtual void link_set_navigation_layers(RID p_link, uint32_t p_navigation_layers) const = 0;
+ virtual uint32_t link_get_navigation_layers(RID p_link) const = 0;
+
+ /// Set the start location of the link.
+ virtual void link_set_start_location(RID p_link, Vector3 p_location) const = 0;
+ virtual Vector3 link_get_start_location(RID p_link) const = 0;
+
+ /// Set the end location of the link.
+ virtual void link_set_end_location(RID p_link, Vector3 p_location) const = 0;
+ virtual Vector3 link_get_end_location(RID p_link) const = 0;
+
+ /// Set the enter cost of the link.
+ virtual void link_set_enter_cost(RID p_link, real_t p_enter_cost) const = 0;
+ virtual real_t link_get_enter_cost(RID p_link) const = 0;
+
+ /// Set the travel cost of the link.
+ virtual void link_set_travel_cost(RID p_link, real_t p_travel_cost) const = 0;
+ virtual real_t link_get_travel_cost(RID p_link) const = 0;
+
/// Creates the agent.
virtual RID agent_create() const = 0;
@@ -141,7 +189,7 @@ public:
/// time of the simulation. If the number is too
/// low, the simulation will not be safe.
/// Must be non-negative.
- virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const = 0;
+ virtual void agent_set_neighbor_distance(RID p_agent, real_t p_distance) const = 0;
/// The maximum number of other agents this
/// agent takes into account in the navigation.
@@ -199,8 +247,98 @@ public:
/// Note: This function is not thread safe.
virtual void process(real_t delta_time) = 0;
+ /// Returns a customized navigation path using a query parameters object
+ void query_path(const Ref<NavigationPathQueryParameters3D> &p_query_parameters, Ref<NavigationPathQueryResult3D> p_query_result) const;
+
+ virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const = 0;
+
NavigationServer3D();
virtual ~NavigationServer3D();
+
+#ifdef DEBUG_ENABLED
+private:
+ bool debug_enabled = false;
+ bool debug_dirty = true;
+ void _emit_navigation_debug_changed_signal();
+
+ Color debug_navigation_edge_connection_color = Color(1.0, 0.0, 1.0, 1.0);
+ Color debug_navigation_geometry_edge_color = Color(0.5, 1.0, 1.0, 1.0);
+ Color debug_navigation_geometry_face_color = Color(0.5, 1.0, 1.0, 0.4);
+ Color debug_navigation_geometry_edge_disabled_color = Color(0.5, 0.5, 0.5, 1.0);
+ Color debug_navigation_geometry_face_disabled_color = Color(0.5, 0.5, 0.5, 0.4);
+ Color debug_navigation_link_connection_color = Color(1.0, 0.5, 1.0, 1.0);
+ Color debug_navigation_link_connection_disabled_color = Color(0.5, 0.5, 0.5, 1.0);
+
+ bool debug_navigation_enable_edge_connections = true;
+ bool debug_navigation_enable_edge_connections_xray = true;
+ bool debug_navigation_enable_edge_lines = true;
+ bool debug_navigation_enable_edge_lines_xray = true;
+ bool debug_navigation_enable_geometry_face_random_color = true;
+ bool debug_navigation_enable_link_connections = true;
+ bool debug_navigation_enable_link_connections_xray = true;
+
+ Ref<StandardMaterial3D> debug_navigation_geometry_edge_material;
+ Ref<StandardMaterial3D> debug_navigation_geometry_face_material;
+ Ref<StandardMaterial3D> debug_navigation_geometry_edge_disabled_material;
+ Ref<StandardMaterial3D> debug_navigation_geometry_face_disabled_material;
+ Ref<StandardMaterial3D> debug_navigation_edge_connections_material;
+ Ref<StandardMaterial3D> debug_navigation_link_connections_material;
+ Ref<StandardMaterial3D> debug_navigation_link_connections_disabled_material;
+
+public:
+ void set_debug_enabled(bool p_enabled);
+ bool get_debug_enabled() const;
+
+ void set_debug_navigation_edge_connection_color(const Color &p_color);
+ Color get_debug_navigation_edge_connection_color() const;
+
+ void set_debug_navigation_geometry_edge_color(const Color &p_color);
+ Color get_debug_navigation_geometry_edge_color() const;
+
+ void set_debug_navigation_geometry_face_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_color() const;
+
+ void set_debug_navigation_geometry_edge_disabled_color(const Color &p_color);
+ Color get_debug_navigation_geometry_edge_disabled_color() const;
+
+ void set_debug_navigation_geometry_face_disabled_color(const Color &p_color);
+ Color get_debug_navigation_geometry_face_disabled_color() const;
+
+ void set_debug_navigation_link_connection_color(const Color &p_color);
+ Color get_debug_navigation_link_connection_color() const;
+
+ void set_debug_navigation_link_connection_disabled_color(const Color &p_color);
+ Color get_debug_navigation_link_connection_disabled_color() const;
+
+ void set_debug_navigation_enable_edge_connections(const bool p_value);
+ bool get_debug_navigation_enable_edge_connections() const;
+
+ void set_debug_navigation_enable_edge_connections_xray(const bool p_value);
+ bool get_debug_navigation_enable_edge_connections_xray() const;
+
+ void set_debug_navigation_enable_edge_lines(const bool p_value);
+ bool get_debug_navigation_enable_edge_lines() const;
+
+ void set_debug_navigation_enable_edge_lines_xray(const bool p_value);
+ bool get_debug_navigation_enable_edge_lines_xray() const;
+
+ void set_debug_navigation_enable_geometry_face_random_color(const bool p_value);
+ bool get_debug_navigation_enable_geometry_face_random_color() const;
+
+ void set_debug_navigation_enable_link_connections(const bool p_value);
+ bool get_debug_navigation_enable_link_connections() const;
+
+ void set_debug_navigation_enable_link_connections_xray(const bool p_value);
+ bool get_debug_navigation_enable_link_connections_xray() const;
+
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_face_material();
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_material();
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_face_disabled_material();
+ Ref<StandardMaterial3D> get_debug_navigation_geometry_edge_disabled_material();
+ Ref<StandardMaterial3D> get_debug_navigation_edge_connections_material();
+ Ref<StandardMaterial3D> get_debug_navigation_link_connections_material();
+ Ref<StandardMaterial3D> get_debug_navigation_link_connections_disabled_material();
+#endif // DEBUG_ENABLED
};
typedef NavigationServer3D *(*NavigationServer3DCallback)();
diff --git a/servers/physics_2d/godot_area_2d.cpp b/servers/physics_2d/godot_area_2d.cpp
index 11208f2d5b..3fe062de57 100644
--- a/servers/physics_2d/godot_area_2d.cpp
+++ b/servers/physics_2d/godot_area_2d.cpp
@@ -247,7 +247,11 @@ void GodotArea2D::call_queries() {
Callable::CallError ce;
Variant ret;
- monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling event callback method " + Variant::get_callable_error_text(monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_bodies.clear();
@@ -285,7 +289,11 @@ void GodotArea2D::call_queries() {
Callable::CallError ce;
Variant ret;
- area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling event callback method " + Variant::get_callable_error_text(area_monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_areas.clear();
@@ -296,12 +304,12 @@ void GodotArea2D::call_queries() {
void GodotArea2D::compute_gravity(const Vector2 &p_position, Vector2 &r_gravity) const {
if (is_gravity_point()) {
- const real_t gravity_distance_scale = get_gravity_distance_scale();
+ const real_t gr_distance_scale = get_gravity_distance_scale();
Vector2 v = get_transform().xform(get_gravity_vector()) - p_position;
- if (gravity_distance_scale > 0) {
+ if (gr_distance_scale > 0) {
const real_t v_length = v.length();
if (v_length > 0) {
- const real_t v_scaled = v_length * gravity_distance_scale;
+ const real_t v_scaled = v_length * gr_distance_scale;
r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled)));
} else {
r_gravity = Vector2();
diff --git a/servers/physics_2d/godot_area_2d.h b/servers/physics_2d/godot_area_2d.h
index 35dad9d2c3..221982cf78 100644
--- a/servers/physics_2d/godot_area_2d.h
+++ b/servers/physics_2d/godot_area_2d.h
@@ -70,9 +70,9 @@ class GodotArea2D : public GodotCollisionObject2D {
static uint32_t hash(const BodyKey &p_key) {
uint32_t h = hash_one_uint64(p_key.rid.get_id());
- h = hash_djb2_one_64(p_key.instance_id, h);
- h = hash_djb2_one_32(p_key.area_shape, h);
- return hash_djb2_one_32(p_key.body_shape, h);
+ h = hash_murmur3_one_64(p_key.instance_id, h);
+ h = hash_murmur3_one_32(p_key.area_shape, h);
+ return hash_fmix32(hash_murmur3_one_32(p_key.body_shape, h));
}
_FORCE_INLINE_ bool operator==(const BodyKey &p_key) const {
diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp
index 6873504f70..4422be959a 100644
--- a/servers/physics_2d/godot_body_2d.cpp
+++ b/servers/physics_2d/godot_body_2d.cpp
@@ -44,7 +44,7 @@ void GodotBody2D::update_mass_properties() {
//update shapes and motions
switch (mode) {
- case PhysicsServer2D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer2D::BODY_MODE_RIGID: {
real_t total_area = 0;
for (int i = 0; i < get_shape_count(); i++) {
if (is_shape_disabled(i)) {
@@ -65,10 +65,10 @@ void GodotBody2D::update_mass_properties() {
real_t area = get_shape_aabb(i).get_area();
- real_t mass = area * this->mass / total_area;
+ real_t mass_new = area * mass / total_area;
// NOTE: we assume that the shape origin is also its center of mass.
- center_of_mass_local += mass * get_shape_transform(i).get_origin();
+ center_of_mass_local += mass_new * get_shape_transform(i).get_origin();
}
center_of_mass_local /= mass;
@@ -90,12 +90,12 @@ void GodotBody2D::update_mass_properties() {
continue;
}
- real_t mass = area * this->mass / total_area;
+ real_t mass_new = area * mass / total_area;
Transform2D mtx = get_shape_transform(i);
Vector2 scale = mtx.get_scale();
Vector2 shape_origin = mtx.get_origin() - center_of_mass_local;
- inertia += shape->get_moment_of_inertia(mass, scale) + mass * shape_origin.length_squared();
+ inertia += shape->get_moment_of_inertia(mass_new, scale) + mass_new * shape_origin.length_squared();
}
}
@@ -113,7 +113,7 @@ void GodotBody2D::update_mass_properties() {
_inv_inertia = 0;
_inv_mass = 0;
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: {
_inv_inertia = 0;
_inv_mass = 1.0 / mass;
@@ -160,7 +160,7 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian
real_t mass_value = p_value;
ERR_FAIL_COND(mass_value <= 0);
mass = mass_value;
- if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (mode >= PhysicsServer2D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} break;
@@ -168,13 +168,13 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian
real_t inertia_value = p_value;
if (inertia_value <= 0.0) {
calculate_inertia = true;
- if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer2D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} else {
calculate_inertia = false;
inertia = inertia_value;
- if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer2D::BODY_MODE_RIGID) {
_inv_inertia = 1.0 / inertia;
}
}
@@ -267,7 +267,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) {
first_time_kinematic = true;
}
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer2D::BODY_MODE_RIGID: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
if (!calculate_inertia) {
_inv_inertia = 1.0 / inertia;
@@ -277,7 +277,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) {
set_active(true);
} break;
- case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = 0;
angular_velocity = 0;
@@ -358,7 +358,7 @@ void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p
} break;
case PhysicsServer2D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
+ if (mode >= PhysicsServer2D::BODY_MODE_RIGID && !active && !can_sleep) {
set_active(true);
}
@@ -578,14 +578,14 @@ void GodotBody2D::integrate_forces(real_t p_step) {
damp = 0;
}
- real_t angular_damp = 1.0 - p_step * total_angular_damp;
+ real_t angular_damp_new = 1.0 - p_step * total_angular_damp;
- if (angular_damp < 0) { // reached zero in the given time
- angular_damp = 0;
+ if (angular_damp_new < 0) { // reached zero in the given time
+ angular_damp_new = 0;
}
linear_velocity *= damp;
- angular_velocity *= angular_damp;
+ angular_velocity *= angular_damp_new;
linear_velocity += _inv_mass * force * p_step;
angular_velocity += _inv_inertia * torque * p_step;
@@ -615,7 +615,7 @@ void GodotBody2D::integrate_velocities(real_t p_step) {
return;
}
- if (fi_callback_data || body_state_callback) {
+ if (fi_callback_data || body_state_callback.get_object()) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@@ -661,7 +661,7 @@ void GodotBody2D::wakeup_neighbours() {
continue;
}
GodotBody2D *b = n[i];
- if (b->mode < PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (b->mode < PhysicsServer2D::BODY_MODE_RIGID) {
continue;
}
@@ -673,26 +673,30 @@ void GodotBody2D::wakeup_neighbours() {
}
void GodotBody2D::call_queries() {
+ Variant direct_state_variant = get_direct_state();
+
if (fi_callback_data) {
if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
} else {
- Variant direct_state_variant = get_direct_state();
const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
Callable::CallError ce;
Variant rv;
if (fi_callback_data->udata.get_type() != Variant::NIL) {
- fi_callback_data->callable.call(vp, 2, rv, ce);
+ fi_callback_data->callable.callp(vp, 2, rv, ce);
} else {
- fi_callback_data->callable.call(vp, 1, rv, ce);
+ fi_callback_data->callable.callp(vp, 1, rv, ce);
}
}
}
- if (body_state_callback) {
- (body_state_callback)(body_state_callback_instance, get_direct_state());
+ if (body_state_callback.get_object()) {
+ const Variant *vp[1] = { &direct_state_variant };
+ Callable::CallError ce;
+ Variant rv;
+ body_state_callback.callp(vp, 1, rv, ce);
}
}
@@ -713,9 +717,8 @@ bool GodotBody2D::sleep_test(real_t p_step) {
}
}
-void GodotBody2D::set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback) {
- body_state_callback_instance = p_instance;
- body_state_callback = p_callback;
+void GodotBody2D::set_state_sync_callback(const Callable &p_callable) {
+ body_state_callback = p_callable;
}
void GodotBody2D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h
index 4b87a69d5c..86d42ae7f8 100644
--- a/servers/physics_2d/godot_body_2d.h
+++ b/servers/physics_2d/godot_body_2d.h
@@ -42,7 +42,7 @@ class GodotConstraint2D;
class GodotPhysicsDirectBodyState2D;
class GodotBody2D : public GodotCollisionObject2D {
- PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_DYNAMIC;
+ PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_RIGID;
Vector2 biased_linear_velocity;
real_t biased_angular_velocity = 0.0;
@@ -137,8 +137,7 @@ class GodotBody2D : public GodotCollisionObject2D {
Vector<Contact> contacts; //no contacts by default
int contact_count = 0;
- void *body_state_callback_instance = nullptr;
- PhysicsServer2D::BodyStateCallback body_state_callback = nullptr;
+ Callable body_state_callback;
struct ForceIntegrationCallbackData {
Callable callable;
@@ -156,7 +155,7 @@ class GodotBody2D : public GodotCollisionObject2D {
friend class GodotPhysicsDirectBodyState2D; // i give up, too many functions to expose
public:
- void set_state_sync_callback(void *p_instance, PhysicsServer2D::BodyStateCallback p_callback);
+ void set_state_sync_callback(const Callable &p_callable);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
GodotPhysicsDirectBodyState2D *get_direct_state();
diff --git a/servers/physics_2d/godot_body_direct_state_2d.cpp b/servers/physics_2d/godot_body_direct_state_2d.cpp
index cde6e8c991..d413e03be6 100644
--- a/servers/physics_2d/godot_body_direct_state_2d.cpp
+++ b/servers/physics_2d/godot_body_direct_state_2d.cpp
@@ -138,7 +138,7 @@ void GodotPhysicsDirectBodyState2D::add_constant_torque(real_t p_torque) {
}
void GodotPhysicsDirectBodyState2D::set_constant_force(const Vector2 &p_force) {
- if (!p_force.is_equal_approx(Vector2())) {
+ if (!p_force.is_zero_approx()) {
body->wakeup();
}
body->set_constant_force(p_force);
diff --git a/servers/physics_2d/godot_body_pair_2d.cpp b/servers/physics_2d/godot_body_pair_2d.cpp
index 2f2af15da7..7b7c67bbc2 100644
--- a/servers/physics_2d/godot_body_pair_2d.cpp
+++ b/servers/physics_2d/godot_body_pair_2d.cpp
@@ -170,7 +170,7 @@ bool GodotBodyPair2D::_test_ccd(real_t p_step, GodotBody2D *p_A, int p_shape_A,
Vector2 mnormal = motion / mlen;
- real_t min, max;
+ real_t min = 0.0, max = 0.0;
p_A->get_shape(p_shape_A)->project_rangev(mnormal, p_xform_A, min, max);
// Did it move enough in this direction to even attempt raycast?
diff --git a/servers/physics_2d/godot_collision_object_2d.h b/servers/physics_2d/godot_collision_object_2d.h
index 1a683a7b0f..7965e8a94d 100644
--- a/servers/physics_2d/godot_collision_object_2d.h
+++ b/servers/physics_2d/godot_collision_object_2d.h
@@ -70,6 +70,7 @@ private:
Transform2D inv_transform;
uint32_t collision_mask = 1;
uint32_t collision_layer = 1;
+ real_t collision_priority = 1.0;
bool _static = true;
SelfList<GodotCollisionObject2D> pending_shape_update_list;
@@ -166,6 +167,13 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; }
+ _FORCE_INLINE_ void set_collision_priority(real_t p_priority) {
+ ERR_FAIL_COND_MSG(p_priority <= 0, "Priority must be greater than 0.");
+ collision_priority = p_priority;
+ _shape_changed();
+ }
+ _FORCE_INLINE_ real_t get_collision_priority() const { return collision_priority; }
+
void remove_shape(GodotShape2D *p_shape) override;
void remove_shape(int p_index);
diff --git a/servers/physics_2d/godot_collision_solver_2d.cpp b/servers/physics_2d/godot_collision_solver_2d.cpp
index 0d7b42b80d..9c7b8fbe53 100644
--- a/servers/physics_2d/godot_collision_solver_2d.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d.cpp
@@ -34,7 +34,7 @@
#define collision_solver sat_2d_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) {
const GodotWorldBoundaryShape2D *world_boundary = static_cast<const GodotWorldBoundaryShape2D *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) {
return false;
@@ -52,7 +52,9 @@ bool GodotCollisionSolver2D::solve_static_world_boundary(const GodotShape2D *p_s
bool found = false;
for (int i = 0; i < support_count; i++) {
+ supports[i] += p_margin * supports[i].normalized();
supports[i] = p_transform_B.xform(supports[i]);
+ supports[i] += p_motion_B;
real_t pd = n.dot(supports[i]);
if (pd >= d) {
continue;
@@ -195,7 +197,7 @@ bool GodotCollisionSolver2D::solve_concave(const GodotShape2D *p_shape_A, const
real_t axis_scale = 1.0 / axis.length();
axis *= axis_scale;
- real_t smin, smax;
+ real_t smin = 0.0, smax = 0.0;
p_shape_A->project_rangev(axis, rel_transform, smin, smax);
smin *= axis_scale;
smax *= axis_scale;
@@ -227,17 +229,19 @@ bool GodotCollisionSolver2D::solve(const GodotShape2D *p_shape_A, const Transfor
if (type_A == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) {
if (type_B == PhysicsServer2D::SHAPE_WORLD_BOUNDARY) {
+ WARN_PRINT_ONCE("Collisions between world boundaries are not supported.");
return false;
}
if (swap) {
- return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_motion_A, p_result_callback, p_userdata, true, p_margin_A);
} else {
- return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_motion_B, p_result_callback, p_userdata, false, p_margin_B);
}
} else if (type_A == PhysicsServer2D::SHAPE_SEPARATION_RAY) {
if (type_B == PhysicsServer2D::SHAPE_SEPARATION_RAY) {
+ WARN_PRINT_ONCE("Collisions between two rays are not supported.");
return false; //no ray-ray
}
@@ -249,6 +253,7 @@ bool GodotCollisionSolver2D::solve(const GodotShape2D *p_shape_A, const Transfor
} else if (concave_B) {
if (concave_A) {
+ WARN_PRINT_ONCE("Collisions between two concave shapes are not supported.");
return false;
}
diff --git a/servers/physics_2d/godot_collision_solver_2d.h b/servers/physics_2d/godot_collision_solver_2d.h
index bd90641f04..3aac2751e0 100644
--- a/servers/physics_2d/godot_collision_solver_2d.h
+++ b/servers/physics_2d/godot_collision_solver_2d.h
@@ -38,7 +38,7 @@ public:
typedef void (*CallbackResult)(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata);
private:
- static bool solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_static_world_boundary(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
static bool concave_callback(void *p_userdata, GodotShape2D *p_convex);
static bool solve_concave(const GodotShape2D *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin_A = 0, real_t p_margin_B = 0);
static bool solve_separation_ray(const GodotShape2D *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const GodotShape2D *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *r_sep_axis = nullptr, real_t p_margin = 0);
diff --git a/servers/physics_2d/godot_collision_solver_2d_sat.cpp b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
index 77186d3810..f8924239ea 100644
--- a/servers/physics_2d/godot_collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/godot_collision_solver_2d_sat.cpp
@@ -234,7 +234,7 @@ public:
axis = Vector2(0.0, 1.0);
}
- real_t min_A, max_A, min_B, max_B;
+ real_t min_A = 0.0, max_A = 0.0, min_B = 0.0, max_B = 0.0;
if (castA) {
shape_A->project_range_cast(motion_A, axis, *transform_A, min_A, max_A);
@@ -498,7 +498,7 @@ static void _collision_segment_rectangle(const GodotShape2D *p_a, const Transfor
return;
}
- if (castA) {
+ if constexpr (castA) {
if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a + p_motion_a))) {
return;
}
@@ -507,7 +507,7 @@ static void _collision_segment_rectangle(const GodotShape2D *p_a, const Transfor
}
}
- if (castB) {
+ if constexpr (castB) {
if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a - p_motion_b))) {
return;
}
@@ -516,7 +516,7 @@ static void _collision_segment_rectangle(const GodotShape2D *p_a, const Transfor
}
}
- if (castA && castB) {
+ if constexpr (castA && castB) {
if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a - p_motion_b + p_motion_a))) {
return;
}
@@ -665,21 +665,21 @@ static void _collision_circle_rectangle(const GodotShape2D *p_a, const Transform
}
}
- if (castA) {
+ if constexpr (castA) {
Vector2 sphereofs = sphere + p_motion_a;
if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs))) {
return;
}
}
- if (castB) {
+ if constexpr (castB) {
Vector2 sphereofs = sphere - p_motion_b;
if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs))) {
return;
}
}
- if (castA && castB) {
+ if constexpr (castA && castB) {
Vector2 sphereofs = sphere - p_motion_b + p_motion_a;
if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs))) {
return;
@@ -786,7 +786,7 @@ static void _collision_rectangle_rectangle(const GodotShape2D *p_a, const Transf
return;
}
- if (withMargin) {
+ if constexpr (withMargin) {
Transform2D invA = p_transform_a.affine_inverse();
Transform2D invB = p_transform_b.affine_inverse();
@@ -794,29 +794,29 @@ static void _collision_rectangle_rectangle(const GodotShape2D *p_a, const Transf
return;
}
- if (castA || castB) {
+ if constexpr (castA || castB) {
Transform2D aofs = p_transform_a;
aofs.columns[2] += p_motion_a;
Transform2D bofs = p_transform_b;
bofs.columns[2] += p_motion_b;
- Transform2D aofsinv = aofs.affine_inverse();
- Transform2D bofsinv = bofs.affine_inverse();
+ [[maybe_unused]] Transform2D aofsinv = aofs.affine_inverse();
+ [[maybe_unused]] Transform2D bofsinv = bofs.affine_inverse();
- if (castA) {
+ if constexpr (castA) {
if (!separator.test_axis(rectangle_A->get_box_axis(aofs, aofsinv, rectangle_B, p_transform_b, invB))) {
return;
}
}
- if (castB) {
+ if constexpr (castB) {
if (!separator.test_axis(rectangle_A->get_box_axis(p_transform_a, invA, rectangle_B, bofs, bofsinv))) {
return;
}
}
- if (castA && castB) {
+ if constexpr (castA && castB) {
if (!separator.test_axis(rectangle_A->get_box_axis(aofs, aofsinv, rectangle_B, bofs, bofsinv))) {
return;
}
@@ -871,7 +871,7 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
}
}
- if (castA) {
+ if constexpr (castA) {
Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir;
capsule_endpoint -= p_motion_a;
@@ -880,7 +880,7 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
}
}
- if (castB) {
+ if constexpr (castB) {
Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir;
capsule_endpoint += p_motion_b;
@@ -889,7 +889,7 @@ static void _collision_rectangle_capsule(const GodotShape2D *p_a, const Transfor
}
}
- if (castA && castB) {
+ if constexpr (castA && castB) {
Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.columns[1] * capsule_dir;
capsule_endpoint -= p_motion_a;
capsule_endpoint += p_motion_b;
@@ -931,7 +931,7 @@ static void _collision_rectangle_convex_polygon(const GodotShape2D *p_a, const T
//convex faces
Transform2D boxinv;
- if (withMargin) {
+ if constexpr (withMargin) {
boxinv = p_transform_a.affine_inverse();
}
for (int i = 0; i < convex_B->get_point_count(); i++) {
@@ -939,22 +939,22 @@ static void _collision_rectangle_convex_polygon(const GodotShape2D *p_a, const T
return;
}
- if (withMargin) {
+ if constexpr (withMargin) {
//all points vs all points need to be tested if margin exist
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i))))) {
return;
}
- if (castA) {
+ if constexpr (castA) {
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)) - p_motion_a))) {
return;
}
}
- if (castB) {
+ if constexpr (castB) {
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)) + p_motion_b))) {
return;
}
}
- if (castA && castB) {
+ if constexpr (castA && castB) {
if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)) + p_motion_b - p_motion_a))) {
return;
}
diff --git a/servers/physics_2d/godot_joints_2d.cpp b/servers/physics_2d/godot_joints_2d.cpp
index 0c21b08ea9..34eb66500d 100644
--- a/servers/physics_2d/godot_joints_2d.cpp
+++ b/servers/physics_2d/godot_joints_2d.cpp
@@ -436,13 +436,13 @@ void GodotDampedSpringJoint2D::solve(real_t p_step) {
// not 100% certain this is derived correctly, though it makes sense
real_t v_damp = -vrn * v_coef;
target_vrn = vrn + v_damp;
- Vector2 j = n * v_damp * n_mass;
+ Vector2 j_new = n * v_damp * n_mass;
if (dynamic_A) {
- A->apply_impulse(-j, rA);
+ A->apply_impulse(-j_new, rA);
}
if (dynamic_B) {
- B->apply_impulse(j, rB);
+ B->apply_impulse(j_new, rB);
}
}
diff --git a/servers/physics_2d/godot_physics_server_2d.cpp b/servers/physics_2d/godot_physics_server_2d.cpp
index 99e68de07c..f1551df2e3 100644
--- a/servers/physics_2d/godot_physics_server_2d.cpp
+++ b/servers/physics_2d/godot_physics_server_2d.cpp
@@ -485,6 +485,20 @@ void GodotPhysicsServer2D::area_set_monitorable(RID p_area, bool p_monitorable)
area->set_monitorable(p_monitorable);
}
+void GodotPhysicsServer2D::area_set_collision_layer(RID p_area, uint32_t p_layer) {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND(!area);
+
+ area->set_collision_layer(p_layer);
+}
+
+uint32_t GodotPhysicsServer2D::area_get_collision_layer(RID p_area) const {
+ GodotArea2D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, 0);
+
+ return area->get_collision_layer();
+}
+
void GodotPhysicsServer2D::area_set_collision_mask(RID p_area, uint32_t p_mask) {
GodotArea2D *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
@@ -492,11 +506,11 @@ void GodotPhysicsServer2D::area_set_collision_mask(RID p_area, uint32_t p_mask)
area->set_collision_mask(p_mask);
}
-void GodotPhysicsServer2D::area_set_collision_layer(RID p_area, uint32_t p_layer) {
+uint32_t GodotPhysicsServer2D::area_get_collision_mask(RID p_area) const {
GodotArea2D *area = area_owner.get_or_null(p_area);
- ERR_FAIL_COND(!area);
+ ERR_FAIL_COND_V(!area, 0);
- area->set_collision_layer(p_layer);
+ return area->get_collision_mask();
}
void GodotPhysicsServer2D::area_set_monitor_callback(RID p_area, const Callable &p_callback) {
@@ -718,6 +732,20 @@ uint32_t GodotPhysicsServer2D::body_get_collision_mask(RID p_body) const {
return body->get_collision_mask();
}
+void GodotPhysicsServer2D::body_set_collision_priority(RID p_body, real_t p_priority) {
+ GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_priority(p_priority);
+}
+
+real_t GodotPhysicsServer2D::body_get_collision_priority(RID p_body) const {
+ const GodotBody2D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_priority();
+}
+
void GodotPhysicsServer2D::body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) {
GodotBody2D *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
@@ -834,7 +862,7 @@ void GodotPhysicsServer2D::body_set_constant_force(RID p_body, const Vector2 &p_
ERR_FAIL_COND(!body);
body->set_constant_force(p_force);
- if (!p_force.is_equal_approx(Vector2())) {
+ if (!p_force.is_zero_approx()) {
body->wakeup();
}
}
@@ -937,10 +965,10 @@ int GodotPhysicsServer2D::body_get_max_contacts_reported(RID p_body) const {
return body->get_max_contacts_reported();
}
-void GodotPhysicsServer2D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
+void GodotPhysicsServer2D::body_set_state_sync_callback(RID p_body, const Callable &p_callable) {
GodotBody2D *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
- body->set_state_sync_callback(p_instance, p_callback);
+ body->set_state_sync_callback(p_callable);
}
void GodotPhysicsServer2D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
@@ -1004,6 +1032,7 @@ RID GodotPhysicsServer2D::joint_create() {
void GodotPhysicsServer2D::joint_clear(RID p_joint) {
GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL(joint);
if (joint->get_type() != JOINT_TYPE_MAX) {
GodotJoint2D *empty_joint = memnew(GodotJoint2D);
empty_joint->copy_settings_from(joint);
@@ -1130,38 +1159,38 @@ void GodotPhysicsServer2D::joint_make_damped_spring(RID p_joint, const Vector2 &
}
void GodotPhysicsServer2D::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) {
- GodotJoint2D *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!j);
- ERR_FAIL_COND(j->get_type() != JOINT_TYPE_PIN);
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL(joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_PIN);
- GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(j);
+ GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(joint);
pin_joint->set_param(p_param, p_value);
}
real_t GodotPhysicsServer2D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const {
- GodotJoint2D *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!j, 0);
- ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_PIN, 0);
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL_V(joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_PIN, 0);
- GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(j);
+ GodotPinJoint2D *pin_joint = static_cast<GodotPinJoint2D *>(joint);
return pin_joint->get_param(p_param);
}
void GodotPhysicsServer2D::damped_spring_joint_set_param(RID p_joint, DampedSpringParam p_param, real_t p_value) {
- GodotJoint2D *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND(!j);
- ERR_FAIL_COND(j->get_type() != JOINT_TYPE_DAMPED_SPRING);
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL(joint);
+ ERR_FAIL_COND(joint->get_type() != JOINT_TYPE_DAMPED_SPRING);
- GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(j);
+ GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(joint);
dsj->set_param(p_param, p_value);
}
real_t GodotPhysicsServer2D::damped_spring_joint_get_param(RID p_joint, DampedSpringParam p_param) const {
- GodotJoint2D *j = joint_owner.get_or_null(p_joint);
- ERR_FAIL_COND_V(!j, 0);
- ERR_FAIL_COND_V(j->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
+ GodotJoint2D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL_V(joint, 0);
+ ERR_FAIL_COND_V(joint->get_type() != JOINT_TYPE_DAMPED_SPRING, 0);
- GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(j);
+ GodotDampedSpringJoint2D *dsj = static_cast<GodotDampedSpringJoint2D *>(joint);
return dsj->get_param(p_param);
}
diff --git a/servers/physics_2d/godot_physics_server_2d.h b/servers/physics_2d/godot_physics_server_2d.h
index 2af6e5c97c..b96677700c 100644
--- a/servers/physics_2d/godot_physics_server_2d.h
+++ b/servers/physics_2d/godot_physics_server_2d.h
@@ -151,8 +151,12 @@ public:
virtual Variant area_get_param(RID p_area, AreaParameter p_param) const override;
virtual Transform2D area_get_transform(RID p_area) const override;
virtual void area_set_monitorable(RID p_area, bool p_monitorable) override;
- virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
+
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
+ virtual uint32_t area_get_collision_layer(RID p_area) const override;
+
+ virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
+ virtual uint32_t area_get_collision_mask(RID p_area) const override;
virtual void area_set_monitor_callback(RID p_area, const Callable &p_callback) override;
virtual void area_set_area_monitor_callback(RID p_area, const Callable &p_callback) override;
@@ -199,6 +203,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override;
virtual uint32_t body_get_collision_mask(RID p_body) const override;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) override;
+ virtual real_t body_get_collision_priority(RID p_body) const override;
+
virtual void body_set_param(RID p_body, BodyParameter p_param, const Variant &p_value) override;
virtual Variant body_get_param(RID p_body, BodyParameter p_param) const override;
@@ -240,7 +247,7 @@ public:
virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
virtual int body_get_max_contacts_reported(RID p_body) const override;
- virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override;
+ virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) override;
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override;
virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override;
diff --git a/servers/physics_2d/godot_shape_2d.cpp b/servers/physics_2d/godot_shape_2d.cpp
index 72ade3757b..da414ae233 100644
--- a/servers/physics_2d/godot_shape_2d.cpp
+++ b/servers/physics_2d/godot_shape_2d.cpp
@@ -225,16 +225,16 @@ void GodotSegmentShape2D::set_data(const Variant &p_data) {
b = r.size;
n = (b - a).orthogonal();
- Rect2 aabb;
- aabb.position = a;
- aabb.expand_to(b);
- if (aabb.size.x == 0) {
- aabb.size.x = 0.001;
+ Rect2 aabb_new;
+ aabb_new.position = a;
+ aabb_new.expand_to(b);
+ if (aabb_new.size.x == 0) {
+ aabb_new.size.x = 0.001;
}
- if (aabb.size.y == 0) {
- aabb.size.y = 0.001;
+ if (aabb_new.size.y == 0) {
+ aabb_new.size.y = 0.001;
}
- configure(aabb);
+ configure(aabb_new);
}
Variant GodotSegmentShape2D::get_data() const {
@@ -564,13 +564,13 @@ bool GodotConvexPolygonShape2D::intersect_segment(const Vector2 &p_begin, const
real_t GodotConvexPolygonShape2D::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
ERR_FAIL_COND_V_MSG(point_count == 0, 0, "Convex polygon shape has no points.");
- Rect2 aabb;
- aabb.position = points[0].pos * p_scale;
+ Rect2 aabb_new;
+ aabb_new.position = points[0].pos * p_scale;
for (int i = 0; i < point_count; i++) {
- aabb.expand_to(points[i].pos * p_scale);
+ aabb_new.expand_to(points[i].pos * p_scale);
}
- return p_mass * aabb.size.dot(aabb.size) / 12.0;
+ return p_mass * aabb_new.size.dot(aabb_new.size) / 12.0;
}
void GodotConvexPolygonShape2D::set_data(const Variant &p_data) {
@@ -620,13 +620,13 @@ void GodotConvexPolygonShape2D::set_data(const Variant &p_data) {
}
ERR_FAIL_COND(point_count == 0);
- Rect2 aabb;
- aabb.position = points[0].pos;
+ Rect2 aabb_new;
+ aabb_new.position = points[0].pos;
for (int i = 1; i < point_count; i++) {
- aabb.expand_to(points[i].pos);
+ aabb_new.expand_to(points[i].pos);
}
- configure(aabb);
+ configure(aabb_new);
}
Variant GodotConvexPolygonShape2D::get_data() const {
@@ -705,18 +705,18 @@ bool GodotConcavePolygonShape2D::intersect_segment(const Vector2 &p_begin, const
stack[0] = 0;
while (true) {
uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &bvh = bvhptr[node];
+ const BVH &bvh2 = bvhptr[node];
bool done = false;
switch (stack[level] >> VISITED_BIT_SHIFT) {
case TEST_AABB_BIT: {
- bool valid = bvh.aabb.intersects_segment(p_begin, p_end);
+ bool valid = bvh2.aabb.intersects_segment(p_begin, p_end);
if (!valid) {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
} else {
- if (bvh.left < 0) {
- const Segment &s = segmentptr[bvh.right];
+ if (bvh2.left < 0) {
+ const Segment &s = segmentptr[bvh2.right];
Vector2 a = pointptr[s.points[0]];
Vector2 b = pointptr[s.points[1]];
@@ -742,13 +742,13 @@ bool GodotConcavePolygonShape2D::intersect_segment(const Vector2 &p_begin, const
continue;
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = bvh.left | TEST_AABB_BIT;
+ stack[level + 1] = bvh2.left | TEST_AABB_BIT;
level++;
}
continue;
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = bvh.right | TEST_AABB_BIT;
+ stack[level + 1] = bvh2.right | TEST_AABB_BIT;
level++;
}
continue;
@@ -822,7 +822,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) {
ERR_FAIL_COND(p_data.get_type() != Variant::PACKED_VECTOR2_ARRAY && p_data.get_type() != Variant::PACKED_FLOAT32_ARRAY);
#endif
- Rect2 aabb;
+ Rect2 aabb_new;
if (p_data.get_type() == Variant::PACKED_VECTOR2_ARRAY) {
Vector<Vector2> p2arr = p_data;
@@ -835,7 +835,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) {
bvh_depth = 1;
if (len == 0) {
- configure(aabb);
+ configure(aabb_new);
return;
}
@@ -868,9 +868,9 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) {
}
points.resize(pointmap.size());
- aabb.position = pointmap.begin()->key;
+ aabb_new.position = pointmap.begin()->key;
for (const KeyValue<Point2, int> &E : pointmap) {
- aabb.expand_to(E.key);
+ aabb_new.expand_to(E.key);
points.write[E.value] = E.key;
}
@@ -889,7 +889,7 @@ void GodotConcavePolygonShape2D::set_data(const Variant &p_data) {
//dictionary with arrays
}
- configure(aabb);
+ configure(aabb_new);
}
Variant GodotConcavePolygonShape2D::get_data() const {
@@ -937,17 +937,17 @@ void GodotConcavePolygonShape2D::cull(const Rect2 &p_local_aabb, QueryCallback p
stack[0] = 0;
while (true) {
uint32_t node = stack[level] & NODE_IDX_MASK;
- const BVH &bvh = bvhptr[node];
+ const BVH &bvh2 = bvhptr[node];
switch (stack[level] >> VISITED_BIT_SHIFT) {
case TEST_AABB_BIT: {
- bool valid = p_local_aabb.intersects(bvh.aabb);
+ bool valid = p_local_aabb.intersects(bvh2.aabb);
if (!valid) {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
} else {
- if (bvh.left < 0) {
- const Segment &s = segmentptr[bvh.right];
+ if (bvh2.left < 0) {
+ const Segment &s = segmentptr[bvh2.right];
Vector2 a = pointptr[s.points[0]];
Vector2 b = pointptr[s.points[1]];
@@ -966,13 +966,13 @@ void GodotConcavePolygonShape2D::cull(const Rect2 &p_local_aabb, QueryCallback p
continue;
case VISIT_LEFT_BIT: {
stack[level] = (VISIT_RIGHT_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = bvh.left | TEST_AABB_BIT;
+ stack[level + 1] = bvh2.left | TEST_AABB_BIT;
level++;
}
continue;
case VISIT_RIGHT_BIT: {
stack[level] = (VISIT_DONE_BIT << VISITED_BIT_SHIFT) | node;
- stack[level + 1] = bvh.right | TEST_AABB_BIT;
+ stack[level + 1] = bvh2.right | TEST_AABB_BIT;
level++;
}
continue;
diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp
index 166ec3049e..89afb0e2a0 100644
--- a/servers/physics_2d/godot_space_2d.cpp
+++ b/servers/physics_2d/godot_space_2d.cpp
@@ -129,8 +129,8 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parame
bool collided = false;
Vector2 res_point, res_normal;
- int res_shape;
- const GodotCollisionObject2D *res_obj;
+ int res_shape = -1;
+ const GodotCollisionObject2D *res_obj = nullptr;
real_t min_d = 1e10;
for (int i = 0; i < amount; i++) {
@@ -190,6 +190,7 @@ bool GodotPhysicsDirectSpaceState2D::intersect_ray(const RayParameters &p_parame
if (!collided) {
return false;
}
+ ERR_FAIL_NULL_V(res_obj, false); // Shouldn't happen but silences warning.
r_result.collider_id = res_obj->get_instance_id();
if (r_result.collider_id.is_valid()) {
@@ -594,6 +595,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
const int max_results = 32;
int recover_attempts = 4;
Vector2 sr[max_results * 2];
+ real_t priorities[max_results];
do {
GodotPhysicsServer2D::CollCbkData cbk;
@@ -606,6 +608,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
GodotPhysicsServer2D::CollCbkData *cbkptr = &cbk;
GodotCollisionSolver2D::CallbackResult cbkres = GodotPhysicsServer2D::_shape_col_cbk;
+ int priority_amount = 0;
bool collided = false;
@@ -641,7 +644,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) {
const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj);
- if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
@@ -664,6 +667,10 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
if (GodotCollisionSolver2D::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, nullptr, margin)) {
did_collide = cbk.passed > current_passed; //more passed, so collision actually existed
}
+ while (cbk.amount > priority_amount) {
+ priorities[priority_amount] = col_obj->get_collision_priority();
+ priority_amount++;
+ }
if (!did_collide && cbk.invalid_by_dir > 0) {
//this shape must be excluded
@@ -686,6 +693,12 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
break;
}
+ real_t inv_total_weight = 0.0;
+ for (int i = 0; i < cbk.amount; i++) {
+ inv_total_weight += priorities[i];
+ }
+ inv_total_weight = Math::is_zero_approx(inv_total_weight) ? 1.0 : (real_t)cbk.amount / inv_total_weight;
+
recovered = true;
Vector2 recover_motion;
@@ -701,7 +714,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
real_t depth = n.dot(a + recover_motion) - d;
if (depth > min_contact_depth + CMP_EPSILON) {
// Only recover if there is penetration.
- recover_motion -= n * (depth - min_contact_depth) * 0.4;
+ recover_motion -= n * (depth - min_contact_depth) * 0.4 * priorities[i] * inv_total_weight;
}
}
@@ -936,7 +949,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) {
const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj);
- if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) {
+ if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
@@ -1024,8 +1037,6 @@ void *GodotSpace2D::_broadphase_pair(GodotCollisionObject2D *A, int p_subindex_A
GodotBodyPair2D *b = memnew(GodotBodyPair2D(static_cast<GodotBody2D *>(A), p_subindex_A, static_cast<GodotBody2D *>(B), p_subindex_B));
return b;
}
-
- return nullptr;
}
void GodotSpace2D::_broadphase_unpair(GodotCollisionObject2D *A, int p_subindex_A, GodotCollisionObject2D *B, int p_subindex_B, void *p_data, void *p_self) {
@@ -1206,7 +1217,7 @@ GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() {
GodotSpace2D::GodotSpace2D() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0);
- body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg2rad(8.0));
+ body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
@@ -1214,7 +1225,7 @@ GodotSpace2D::GodotSpace2D() {
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/solver_iterations", PropertyInfo(Variant::INT, "physics/2d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"));
contact_recycle_radius = GLOBAL_DEF("physics/2d/solver/contact_recycle_radius", 1.0);
- ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"));
contact_max_separation = GLOBAL_DEF("physics/2d/solver/contact_max_separation", 1.5);
ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/solver/contact_max_separation", PropertyInfo(Variant::FLOAT, "physics/2d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"));
diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp
index 551fd9329f..46718c8819 100644
--- a/servers/physics_2d/godot_step_2d.cpp
+++ b/servers/physics_2d/godot_step_2d.cpp
@@ -42,7 +42,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D
p_body->set_island_step(_step);
if (p_body->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) {
- // Only dynamic bodies are tested for activation.
+ // Only rigid bodies are tested for activation.
p_body_island.push_back(p_body);
}
@@ -239,7 +239,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &GodotStep2D::_setup_contraint, nullptr);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics2DConstraintSetup"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -258,7 +259,8 @@ void GodotStep2D::step(GodotSpace2D *p_space, real_t p_delta) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- work_pool.do_work(island_count, this, &GodotStep2D::_solve_island, nullptr);
+ group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep2D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics2DConstraintSolveIslands"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -297,10 +299,7 @@ GodotStep2D::GodotStep2D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
-
- work_pool.init();
}
GodotStep2D::~GodotStep2D() {
- work_pool.finish();
}
diff --git a/servers/physics_2d/godot_step_2d.h b/servers/physics_2d/godot_step_2d.h
index 9a6d8caf9b..9f8fdd6ce3 100644
--- a/servers/physics_2d/godot_step_2d.h
+++ b/servers/physics_2d/godot_step_2d.h
@@ -33,8 +33,8 @@
#include "godot_space_2d.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/local_vector.h"
-#include "core/templates/thread_work_pool.h"
class GodotStep2D {
uint64_t _step = 1;
@@ -42,8 +42,6 @@ class GodotStep2D {
int iterations = 0;
real_t delta = 0.0;
- ThreadWorkPool work_pool;
-
LocalVector<LocalVector<GodotBody2D *>> body_islands;
LocalVector<LocalVector<GodotConstraint2D *>> constraint_islands;
LocalVector<GodotConstraint2D *> all_constraints;
diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h
index 01a47f222e..309af76561 100644
--- a/servers/physics_3d/gjk_epa.h
+++ b/servers/physics_3d/gjk_epa.h
@@ -37,4 +37,4 @@
bool gjk_epa_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, real_t p_margin_A = 0.0, real_t p_margin_B = 0.0);
bool gjk_epa_calculate_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B);
-#endif
+#endif // GJK_EPA_H
diff --git a/servers/physics_3d/godot_area_3d.cpp b/servers/physics_3d/godot_area_3d.cpp
index e2ad765d62..d4d3b3e6aa 100644
--- a/servers/physics_3d/godot_area_3d.cpp
+++ b/servers/physics_3d/godot_area_3d.cpp
@@ -276,7 +276,11 @@ void GodotArea3D::call_queries() {
Callable::CallError ce;
Variant ret;
- monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling monitor callback method " + Variant::get_callable_error_text(monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_bodies.clear();
@@ -314,7 +318,11 @@ void GodotArea3D::call_queries() {
Callable::CallError ce;
Variant ret;
- area_monitor_callback.call((const Variant **)resptr, 5, ret, ce);
+ area_monitor_callback.callp((const Variant **)resptr, 5, ret, ce);
+
+ if (ce.error != Callable::CallError::CALL_OK) {
+ ERR_PRINT_ONCE("Error calling area monitor callback method " + Variant::get_callable_error_text(area_monitor_callback, (const Variant **)resptr, 5, ce));
+ }
}
} else {
monitored_areas.clear();
@@ -325,12 +333,12 @@ void GodotArea3D::call_queries() {
void GodotArea3D::compute_gravity(const Vector3 &p_position, Vector3 &r_gravity) const {
if (is_gravity_point()) {
- const real_t gravity_distance_scale = get_gravity_distance_scale();
+ const real_t gr_distance_scale = get_gravity_distance_scale();
Vector3 v = get_transform().xform(get_gravity_vector()) - p_position;
- if (gravity_distance_scale > 0) {
+ if (gr_distance_scale > 0) {
const real_t v_length = v.length();
if (v_length > 0) {
- const real_t v_scaled = v_length * gravity_distance_scale;
+ const real_t v_scaled = v_length * gr_distance_scale;
r_gravity = (v.normalized() * (get_gravity() / (v_scaled * v_scaled)));
} else {
r_gravity = Vector3();
diff --git a/servers/physics_3d/godot_area_3d.h b/servers/physics_3d/godot_area_3d.h
index a00451f602..51b435eb00 100644
--- a/servers/physics_3d/godot_area_3d.h
+++ b/servers/physics_3d/godot_area_3d.h
@@ -74,9 +74,9 @@ class GodotArea3D : public GodotCollisionObject3D {
static uint32_t hash(const BodyKey &p_key) {
uint32_t h = hash_one_uint64(p_key.rid.get_id());
- h = hash_djb2_one_64(p_key.instance_id, h);
- h = hash_djb2_one_32(p_key.area_shape, h);
- return hash_djb2_one_32(p_key.body_shape, h);
+ h = hash_murmur3_one_64(p_key.instance_id, h);
+ h = hash_murmur3_one_32(p_key.area_shape, h);
+ return hash_fmix32(hash_murmur3_one_32(p_key.body_shape, h));
}
_FORCE_INLINE_ bool operator==(const BodyKey &p_key) const {
diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp
index ad97533f44..53f4ab86f9 100644
--- a/servers/physics_3d/godot_body_3d.cpp
+++ b/servers/physics_3d/godot_body_3d.cpp
@@ -56,7 +56,7 @@ void GodotBody3D::update_mass_properties() {
// Update shapes and motions.
switch (mode) {
- case PhysicsServer3D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer3D::BODY_MODE_RIGID: {
real_t total_area = 0;
for (int i = 0; i < get_shape_count(); i++) {
if (is_shape_disabled(i)) {
@@ -78,10 +78,10 @@ void GodotBody3D::update_mass_properties() {
real_t area = get_shape_area(i);
- real_t mass = area * this->mass / total_area;
+ real_t mass_new = area * mass / total_area;
// NOTE: we assume that the shape origin is also its center of mass.
- center_of_mass_local += mass * get_shape_transform(i).origin;
+ center_of_mass_local += mass_new * get_shape_transform(i).origin;
}
center_of_mass_local /= mass;
@@ -108,9 +108,9 @@ void GodotBody3D::update_mass_properties() {
const GodotShape3D *shape = get_shape(i);
- real_t mass = area * this->mass / total_area;
+ real_t mass_new = area * mass / total_area;
- Basis shape_inertia_tensor = Basis::from_scale(shape->get_moment_of_inertia(mass));
+ Basis shape_inertia_tensor = Basis::from_scale(shape->get_moment_of_inertia(mass_new));
Transform3D shape_transform = get_shape_transform(i);
Basis shape_basis = shape_transform.basis.orthonormalized();
@@ -118,7 +118,7 @@ void GodotBody3D::update_mass_properties() {
shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed();
Vector3 shape_origin = shape_transform.origin - center_of_mass_local;
- inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass;
+ inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass_new;
}
// Set the inertia to a valid value when there are no valid shapes.
@@ -154,7 +154,7 @@ void GodotBody3D::update_mass_properties() {
_inv_inertia = Vector3();
_inv_mass = 0;
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: {
_inv_inertia_tensor.set_zero();
_inv_mass = 1.0 / mass;
@@ -201,7 +201,7 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian
real_t mass_value = p_value;
ERR_FAIL_COND(mass_value <= 0);
mass = mass_value;
- if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode >= PhysicsServer3D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} break;
@@ -209,12 +209,12 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian
inertia = p_value;
if ((inertia.x <= 0.0) || (inertia.y <= 0.0) || (inertia.z <= 0.0)) {
calculate_inertia = true;
- if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer3D::BODY_MODE_RIGID) {
_mass_properties_changed();
}
} else {
calculate_inertia = false;
- if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer3D::BODY_MODE_RIGID) {
principal_inertia_axes_local = Basis();
_inv_inertia = inertia.inverse();
_update_transform_dependent();
@@ -263,7 +263,7 @@ Variant GodotBody3D::get_param(PhysicsServer3D::BodyParameter p_param) const {
return mass;
} break;
case PhysicsServer3D::BODY_PARAM_INERTIA: {
- if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (mode == PhysicsServer3D::BODY_MODE_RIGID) {
return _inv_inertia.inverse();
} else {
return Vector3();
@@ -315,7 +315,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
_update_transform_dependent();
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC: {
+ case PhysicsServer3D::BODY_MODE_RIGID: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
if (!calculate_inertia) {
principal_inertia_axes_local = Basis();
@@ -327,7 +327,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) {
set_active(true);
} break;
- case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: {
+ case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: {
_inv_mass = mass > 0 ? (1.0 / mass) : 0;
_inv_inertia = Vector3();
angular_velocity = Vector3();
@@ -407,7 +407,7 @@ void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p
} break;
case PhysicsServer3D::BODY_STATE_CAN_SLEEP: {
can_sleep = p_variant;
- if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC && !active && !can_sleep) {
+ if (mode >= PhysicsServer3D::BODY_MODE_RIGID && !active && !can_sleep) {
set_active(true);
}
@@ -637,14 +637,14 @@ void GodotBody3D::integrate_forces(real_t p_step) {
damp = 0;
}
- real_t angular_damp = 1.0 - p_step * total_angular_damp;
+ real_t angular_damp_new = 1.0 - p_step * total_angular_damp;
- if (angular_damp < 0) { // reached zero in the given time
- angular_damp = 0;
+ if (angular_damp_new < 0) { // reached zero in the given time
+ angular_damp_new = 0;
}
linear_velocity *= damp;
- angular_velocity *= angular_damp;
+ angular_velocity *= angular_damp_new;
linear_velocity += _inv_mass * force * p_step;
angular_velocity += _inv_inertia_tensor.xform(torque) * p_step;
@@ -674,7 +674,7 @@ void GodotBody3D::integrate_velocities(real_t p_step) {
return;
}
- if (fi_callback_data || body_state_callback) {
+ if (fi_callback_data || body_state_callback.get_object()) {
get_space()->body_add_to_state_query_list(&direct_state_query_list);
}
@@ -707,27 +707,27 @@ void GodotBody3D::integrate_velocities(real_t p_step) {
Vector3 total_angular_velocity = angular_velocity + biased_angular_velocity;
real_t ang_vel = total_angular_velocity.length();
- Transform3D transform = get_transform();
+ Transform3D transform_new = get_transform();
if (!Math::is_zero_approx(ang_vel)) {
Vector3 ang_vel_axis = total_angular_velocity / ang_vel;
Basis rot(ang_vel_axis, ang_vel * p_step);
Basis identity3(1, 0, 0, 0, 1, 0, 0, 0, 1);
- transform.origin += ((identity3 - rot) * transform.basis).xform(center_of_mass_local);
- transform.basis = rot * transform.basis;
- transform.orthonormalize();
+ transform_new.origin += ((identity3 - rot) * transform_new.basis).xform(center_of_mass_local);
+ transform_new.basis = rot * transform_new.basis;
+ transform_new.orthonormalize();
}
Vector3 total_linear_velocity = linear_velocity + biased_linear_velocity;
/*for(int i=0;i<3;i++) {
if (axis_lock&(1<<i)) {
- transform.origin[i]=0.0;
+ transform_new.origin[i]=0.0;
}
}*/
- transform.origin += total_linear_velocity * p_step;
+ transform_new.origin += total_linear_velocity * p_step;
- _set_transform(transform);
+ _set_transform(transform_new);
_set_inv_transform(get_transform().inverse());
_update_transform_dependent();
@@ -744,7 +744,7 @@ void GodotBody3D::wakeup_neighbours() {
continue;
}
GodotBody3D *b = n[i];
- if (b->mode < PhysicsServer3D::BODY_MODE_DYNAMIC) {
+ if (b->mode < PhysicsServer3D::BODY_MODE_RIGID) {
continue;
}
@@ -756,22 +756,26 @@ void GodotBody3D::wakeup_neighbours() {
}
void GodotBody3D::call_queries() {
+ Variant direct_state_variant = get_direct_state();
+
if (fi_callback_data) {
if (!fi_callback_data->callable.get_object()) {
set_force_integration_callback(Callable());
} else {
- Variant direct_state_variant = get_direct_state();
const Variant *vp[2] = { &direct_state_variant, &fi_callback_data->udata };
Callable::CallError ce;
int argc = (fi_callback_data->udata.get_type() == Variant::NIL) ? 1 : 2;
Variant rv;
- fi_callback_data->callable.call(vp, argc, rv, ce);
+ fi_callback_data->callable.callp(vp, argc, rv, ce);
}
}
- if (body_state_callback_instance) {
- (body_state_callback)(body_state_callback_instance, get_direct_state());
+ if (body_state_callback.get_object()) {
+ const Variant *vp[1] = { &direct_state_variant };
+ Callable::CallError ce;
+ Variant rv;
+ body_state_callback.callp(vp, 1, rv, ce);
}
}
@@ -792,9 +796,8 @@ bool GodotBody3D::sleep_test(real_t p_step) {
}
}
-void GodotBody3D::set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback) {
- body_state_callback_instance = p_instance;
- body_state_callback = p_callback;
+void GodotBody3D::set_state_sync_callback(const Callable &p_callable) {
+ body_state_callback = p_callable;
}
void GodotBody3D::set_force_integration_callback(const Callable &p_callable, const Variant &p_udata) {
diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h
index 93bd5a0071..412cbebc7d 100644
--- a/servers/physics_3d/godot_body_3d.h
+++ b/servers/physics_3d/godot_body_3d.h
@@ -40,7 +40,7 @@ class GodotConstraint3D;
class GodotPhysicsDirectBodyState3D;
class GodotBody3D : public GodotCollisionObject3D {
- PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_DYNAMIC;
+ PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_RIGID;
Vector3 linear_velocity;
Vector3 angular_velocity;
@@ -131,8 +131,7 @@ class GodotBody3D : public GodotCollisionObject3D {
Vector<Contact> contacts; //no contacts by default
int contact_count = 0;
- void *body_state_callback_instance = nullptr;
- PhysicsServer3D::BodyStateCallback body_state_callback = nullptr;
+ Callable body_state_callback;
struct ForceIntegrationCallbackData {
Callable callable;
@@ -150,7 +149,7 @@ class GodotBody3D : public GodotCollisionObject3D {
friend class GodotPhysicsDirectBodyState3D; // i give up, too many functions to expose
public:
- void set_state_sync_callback(void *p_instance, PhysicsServer3D::BodyStateCallback p_callback);
+ void set_state_sync_callback(const Callable &p_callable);
void set_force_integration_callback(const Callable &p_callable, const Variant &p_udata = Variant());
GodotPhysicsDirectBodyState3D *get_direct_state();
diff --git a/servers/physics_3d/godot_body_direct_state_3d.cpp b/servers/physics_3d/godot_body_direct_state_3d.cpp
index a8c6086e1c..25088d33f3 100644
--- a/servers/physics_3d/godot_body_direct_state_3d.cpp
+++ b/servers/physics_3d/godot_body_direct_state_3d.cpp
@@ -145,7 +145,7 @@ void GodotPhysicsDirectBodyState3D::add_constant_torque(const Vector3 &p_torque)
}
void GodotPhysicsDirectBodyState3D::set_constant_force(const Vector3 &p_force) {
- if (!p_force.is_equal_approx(Vector3())) {
+ if (!p_force.is_zero_approx()) {
body->wakeup();
}
body->set_constant_force(p_force);
@@ -156,7 +156,7 @@ Vector3 GodotPhysicsDirectBodyState3D::get_constant_force() const {
}
void GodotPhysicsDirectBodyState3D::set_constant_torque(const Vector3 &p_torque) {
- if (!p_torque.is_equal_approx(Vector3())) {
+ if (!p_torque.is_zero_approx()) {
body->wakeup();
}
body->set_constant_torque(p_torque);
diff --git a/servers/physics_3d/godot_body_pair_3d.cpp b/servers/physics_3d/godot_body_pair_3d.cpp
index eebbe0196d..7e6cc6f834 100644
--- a/servers/physics_3d/godot_body_pair_3d.cpp
+++ b/servers/physics_3d/godot_body_pair_3d.cpp
@@ -170,7 +170,7 @@ bool GodotBodyPair3D::_test_ccd(real_t p_step, GodotBody3D *p_A, int p_shape_A,
Vector3 mnormal = motion / mlen;
- real_t min, max;
+ real_t min = 0.0, max = 0.0;
p_A->get_shape(p_shape_A)->project_range(mnormal, p_xform_A, min, max);
// Did it move enough in this direction to even attempt raycast?
diff --git a/servers/physics_3d/godot_collision_object_3d.h b/servers/physics_3d/godot_collision_object_3d.h
index 0f09f21962..2d342f65f3 100644
--- a/servers/physics_3d/godot_collision_object_3d.h
+++ b/servers/physics_3d/godot_collision_object_3d.h
@@ -59,6 +59,7 @@ private:
ObjectID instance_id;
uint32_t collision_layer = 1;
uint32_t collision_mask = 1;
+ real_t collision_priority = 1.0;
struct Shape {
Transform3D xform;
@@ -165,6 +166,13 @@ public:
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }
+ _FORCE_INLINE_ void set_collision_priority(real_t p_priority) {
+ ERR_FAIL_COND_MSG(p_priority <= 0, "Priority must be greater than 0.");
+ collision_priority = p_priority;
+ _shape_changed();
+ }
+ _FORCE_INLINE_ real_t get_collision_priority() const { return collision_priority; }
+
_FORCE_INLINE_ bool collides_with(GodotCollisionObject3D *p_other) const {
return p_other->collision_layer & collision_mask;
}
diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp
index b2d3e4d876..ca76a819ec 100644
--- a/servers/physics_3d/godot_collision_solver_3d.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d.cpp
@@ -38,7 +38,7 @@
#define collision_solver sat_calculate_penetration
//#define collision_solver gjk_epa_calculate_penetration
-bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) {
+bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) {
const GodotWorldBoundaryShape3D *world_boundary = static_cast<const GodotWorldBoundaryShape3D *>(p_shape_A);
if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
return false;
@@ -48,7 +48,7 @@ bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_s
static const int max_supports = 16;
Vector3 supports[max_supports];
int support_count;
- GodotShape3D::FeatureType support_type;
+ GodotShape3D::FeatureType support_type = GodotShape3D::FeatureType::FEATURE_POINT;
p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type);
if (support_type == GodotShape3D::FEATURE_CIRCLE) {
@@ -70,6 +70,7 @@ bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_s
bool found = false;
for (int i = 0; i < support_count; i++) {
+ supports[i] += p_margin * supports[i].normalized();
supports[i] = p_transform_B.xform(supports[i]);
if (p.distance_to(supports[i]) >= 0) {
continue;
@@ -337,7 +338,7 @@ bool GodotCollisionSolver3D::solve_concave(const GodotShape3D *p_shape_A, const
real_t axis_scale = 1.0 / axis.length();
axis *= axis_scale;
- real_t smin, smax;
+ real_t smin = 0.0, smax = 0.0;
p_shape_A->project_range(axis, rel_transform, smin, smax);
smin -= p_margin_A;
smax += p_margin_A;
@@ -369,23 +370,27 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T
if (type_A == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
if (type_B == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) {
+ WARN_PRINT_ONCE("Collisions between world boundaries are not supported.");
return false;
}
if (type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY) {
+ WARN_PRINT_ONCE("Collisions between world boundaries and rays are not supported.");
return false;
}
if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
+ WARN_PRINT_ONCE("Collisions between world boundaries and soft bodies are not supported.");
return false;
}
if (swap) {
- return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true);
+ return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_A);
} else {
- return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false);
+ return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_B);
}
} else if (type_A == PhysicsServer3D::SHAPE_SEPARATION_RAY) {
if (type_B == PhysicsServer3D::SHAPE_SEPARATION_RAY) {
+ WARN_PRINT_ONCE("Collisions between rays are not supported.");
return false;
}
@@ -397,7 +402,7 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T
} else if (type_B == PhysicsServer3D::SHAPE_SOFT_BODY) {
if (type_A == PhysicsServer3D::SHAPE_SOFT_BODY) {
- // Soft Body / Soft Body not supported.
+ WARN_PRINT_ONCE("Collisions between soft bodies are not supported.");
return false;
}
@@ -409,6 +414,7 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T
} else if (concave_B) {
if (concave_A) {
+ WARN_PRINT_ONCE("Collisions between two concave shapes are not supported.");
return false;
}
@@ -456,8 +462,17 @@ bool GodotCollisionSolver3D::solve_distance_world_boundary(const GodotShape3D *p
Vector3 supports[max_supports];
int support_count;
GodotShape3D::FeatureType support_type;
+ Vector3 support_direction = p_transform_B.basis.xform_inv(-p.normal).normalized();
- p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type);
+ p_shape_B->get_supports(support_direction, max_supports, supports, support_count, support_type);
+
+ if (support_count == 0) { // This is a poor man's way to detect shapes that don't implement get_supports, such as GodotMotionShape3D.
+ Vector3 support_B = p_transform_B.xform(p_shape_B->get_support(support_direction));
+ r_point_A = p.project(support_B);
+ r_point_B = support_B;
+ bool collided = p.distance_to(support_B) <= 0;
+ return collided;
+ }
if (support_type == GodotShape3D::FEATURE_CIRCLE) {
ERR_FAIL_COND_V(support_count != 3, false);
diff --git a/servers/physics_3d/godot_collision_solver_3d.h b/servers/physics_3d/godot_collision_solver_3d.h
index a6a0ebfead..e7d67903e9 100644
--- a/servers/physics_3d/godot_collision_solver_3d.h
+++ b/servers/physics_3d/godot_collision_solver_3d.h
@@ -42,7 +42,7 @@ private:
static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata);
static bool soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex);
static bool concave_callback(void *p_userdata, GodotShape3D *p_convex);
- static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
+ static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
static bool solve_separation_ray(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0);
static bool solve_soft_body(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result);
static bool solve_concave(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0);
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.cpp b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
index 20e9300778..96253cb452 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.cpp
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.cpp
@@ -629,12 +629,12 @@ public:
_FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) {
Vector3 axis = p_axis;
- if (axis.is_equal_approx(Vector3())) {
+ if (axis.is_zero_approx()) {
// strange case, try an upwards separator
axis = Vector3(0.0, 1.0, 0.0);
}
- real_t min_A, max_A, min_B, max_B;
+ real_t min_A = 0.0, max_A = 0.0, min_B = 0.0, max_B = 0.0;
shape_A->project_range(axis, *transform_A, min_A, max_A);
shape_B->project_range(axis, *transform_B, min_B, max_B);
@@ -964,8 +964,8 @@ static void _collision_sphere_convex_polygon(const GodotShape3D *p_a, const Tran
// edges of B
for (int i = 0; i < edge_count; i++) {
- Vector3 v1 = p_transform_b.xform(vertices[edges[i].a]);
- Vector3 v2 = p_transform_b.xform(vertices[edges[i].b]);
+ Vector3 v1 = p_transform_b.xform(vertices[edges[i].vertex_a]);
+ Vector3 v2 = p_transform_b.xform(vertices[edges[i].vertex_b]);
Vector3 v3 = p_transform_a.origin;
Vector3 n1 = v2 - v1;
@@ -1404,7 +1404,7 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
Vector3 e1 = p_transform_a.basis.get_column(i);
for (int j = 0; j < edge_count; j++) {
- Vector3 e2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]);
+ Vector3 e2 = p_transform_b.basis.xform(vertices[edges[j].vertex_a]) - p_transform_b.basis.xform(vertices[edges[j].vertex_b]);
Vector3 axis = e1.cross(e2).normalized();
@@ -1460,8 +1460,8 @@ static void _collision_box_convex_polygon(const GodotShape3D *p_a, const Transfo
}
for (int e = 0; e < edge_count; e++) {
- Vector3 p1 = p_transform_b.xform(vertices[edges[e].a]);
- Vector3 p2 = p_transform_b.xform(vertices[edges[e].b]);
+ Vector3 p1 = p_transform_b.xform(vertices[edges[e].vertex_a]);
+ Vector3 p2 = p_transform_b.xform(vertices[edges[e].vertex_b]);
Vector3 n = (p2 - p1);
if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) {
@@ -1771,7 +1771,7 @@ static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Tra
for (int i = 0; i < edge_count; i++) {
// cylinder
- Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].a]) - p_transform_b.basis.xform(vertices[edges[i].b]);
+ Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].vertex_a]) - p_transform_b.basis.xform(vertices[edges[i].vertex_b]);
Vector3 axis = edge_axis.cross(p_transform_a.basis.get_column(1)).normalized();
if (!separator.test_axis(axis)) {
@@ -1789,8 +1789,8 @@ static void _collision_capsule_convex_polygon(const GodotShape3D *p_a, const Tra
Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis);
for (int j = 0; j < edge_count; j++) {
- Vector3 n1 = sphere_pos - p_transform_b.xform(vertices[edges[j].a]);
- Vector3 n2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]);
+ Vector3 n1 = sphere_pos - p_transform_b.xform(vertices[edges[j].vertex_a]);
+ Vector3 n2 = p_transform_b.basis.xform(vertices[edges[j].vertex_a]) - p_transform_b.basis.xform(vertices[edges[j].vertex_b]);
Vector3 axis = n1.cross(n2).cross(n2).normalized();
@@ -2075,6 +2075,16 @@ static void _collision_cylinder_face(const GodotShape3D *p_a, const Transform3D
separator.generate_contacts();
}
+static _FORCE_INLINE_ bool is_minkowski_face(const Vector3 &A, const Vector3 &B, const Vector3 &B_x_A, const Vector3 &C, const Vector3 &D, const Vector3 &D_x_C) {
+ // Test if arcs AB and CD intersect on the unit sphere
+ real_t CBA = C.dot(B_x_A);
+ real_t DBA = D.dot(B_x_A);
+ real_t ADC = A.dot(D_x_C);
+ real_t BDC = B.dot(D_x_C);
+
+ return (CBA * DBA < 0.0f) && (ADC * BDC < 0.0f) && (CBA * BDC > 0.0f);
+}
+
template <bool withMargin>
static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, const Transform3D &p_transform_a, const GodotShape3D *p_b, const Transform3D &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) {
const GodotConvexPolygonShape3D *convex_polygon_A = static_cast<const GodotConvexPolygonShape3D *>(p_a);
@@ -2129,16 +2139,27 @@ static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, co
}
// A<->B edges
+
for (int i = 0; i < edge_count_A; i++) {
- Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]) - p_transform_a.basis.xform(vertices_A[edges_A[i].b]);
+ Vector3 p1 = p_transform_a.xform(vertices_A[edges_A[i].vertex_a]);
+ Vector3 q1 = p_transform_a.xform(vertices_A[edges_A[i].vertex_b]);
+ Vector3 e1 = q1 - p1;
+ Vector3 u1 = p_transform_a.basis.xform(faces_A[edges_A[i].face_a].plane.normal).normalized();
+ Vector3 v1 = p_transform_a.basis.xform(faces_A[edges_A[i].face_b].plane.normal).normalized();
for (int j = 0; j < edge_count_B; j++) {
- Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[j].a]) - p_transform_b.basis.xform(vertices_B[edges_B[j].b]);
+ Vector3 p2 = p_transform_b.xform(vertices_B[edges_B[j].vertex_a]);
+ Vector3 q2 = p_transform_b.xform(vertices_B[edges_B[j].vertex_b]);
+ Vector3 e2 = q2 - p2;
+ Vector3 u2 = p_transform_b.basis.xform(faces_B[edges_B[j].face_a].plane.normal).normalized();
+ Vector3 v2 = p_transform_b.basis.xform(faces_B[edges_B[j].face_b].plane.normal).normalized();
- Vector3 axis = e1.cross(e2).normalized();
+ if (is_minkowski_face(u1, v1, -e1, -u2, -v2, -e2)) {
+ Vector3 axis = e1.cross(e2).normalized();
- if (!separator.test_axis(axis)) {
- return;
+ if (!separator.test_axis(axis)) {
+ return;
+ }
}
}
}
@@ -2157,8 +2178,8 @@ static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, co
//edge-vertex (shell)
for (int i = 0; i < edge_count_A; i++) {
- Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]);
- Vector3 e2 = p_transform_a.basis.xform(vertices_A[edges_A[i].b]);
+ Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].vertex_a]);
+ Vector3 e2 = p_transform_a.basis.xform(vertices_A[edges_A[i].vertex_b]);
Vector3 n = (e2 - e1);
for (int j = 0; j < vertex_count_B; j++) {
@@ -2171,8 +2192,8 @@ static void _collision_convex_polygon_convex_polygon(const GodotShape3D *p_a, co
}
for (int i = 0; i < edge_count_B; i++) {
- Vector3 e1 = p_transform_b.basis.xform(vertices_B[edges_B[i].a]);
- Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[i].b]);
+ Vector3 e1 = p_transform_b.basis.xform(vertices_B[edges_B[i].vertex_a]);
+ Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[i].vertex_b]);
Vector3 n = (e2 - e1);
for (int j = 0; j < vertex_count_A; j++) {
@@ -2231,7 +2252,7 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf
// A<->B edges
for (int i = 0; i < edge_count; i++) {
- Vector3 e1 = p_transform_a.xform(vertices[edges[i].a]) - p_transform_a.xform(vertices[edges[i].b]);
+ Vector3 e1 = p_transform_a.xform(vertices[edges[i].vertex_a]) - p_transform_a.xform(vertices[edges[i].vertex_b]);
for (int j = 0; j < 3; j++) {
Vector3 e2 = vertex[j] - vertex[(j + 1) % 3];
@@ -2266,8 +2287,8 @@ static void _collision_convex_polygon_face(const GodotShape3D *p_a, const Transf
//edge-vertex (shell)
for (int i = 0; i < edge_count; i++) {
- Vector3 e1 = p_transform_a.basis.xform(vertices[edges[i].a]);
- Vector3 e2 = p_transform_a.basis.xform(vertices[edges[i].b]);
+ Vector3 e1 = p_transform_a.basis.xform(vertices[edges[i].vertex_a]);
+ Vector3 e2 = p_transform_a.basis.xform(vertices[edges[i].vertex_b]);
Vector3 n = (e2 - e1);
for (int j = 0; j < 3; j++) {
diff --git a/servers/physics_3d/godot_collision_solver_3d_sat.h b/servers/physics_3d/godot_collision_solver_3d_sat.h
index 3eb7aa4c9e..46c5ec3254 100644
--- a/servers/physics_3d/godot_collision_solver_3d_sat.h
+++ b/servers/physics_3d/godot_collision_solver_3d_sat.h
@@ -28,11 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef GODOT_COLLISION_SOLVER_SAT_H
-#define GODOT_COLLISION_SOLVER_SAT_H
+#ifndef GODOT_COLLISION_SOLVER_3D_SAT_H
+#define GODOT_COLLISION_SOLVER_3D_SAT_H
#include "godot_collision_solver_3d.h"
bool sat_calculate_penetration(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, GodotCollisionSolver3D::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = nullptr, real_t p_margin_a = 0, real_t p_margin_b = 0);
-#endif // GODOT_COLLISION_SOLVER_SAT_H
+#endif // GODOT_COLLISION_SOLVER_3D_SAT_H
diff --git a/servers/physics_3d/godot_physics_server_3d.cpp b/servers/physics_3d/godot_physics_server_3d.cpp
index b735283ebe..68db5df144 100644
--- a/servers/physics_3d/godot_physics_server_3d.cpp
+++ b/servers/physics_3d/godot_physics_server_3d.cpp
@@ -387,6 +387,13 @@ void GodotPhysicsServer3D::area_set_collision_layer(RID p_area, uint32_t p_layer
area->set_collision_layer(p_layer);
}
+uint32_t GodotPhysicsServer3D::area_get_collision_layer(RID p_area) const {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, 0);
+
+ return area->get_collision_layer();
+}
+
void GodotPhysicsServer3D::area_set_collision_mask(RID p_area, uint32_t p_mask) {
GodotArea3D *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
@@ -394,6 +401,13 @@ void GodotPhysicsServer3D::area_set_collision_mask(RID p_area, uint32_t p_mask)
area->set_collision_mask(p_mask);
}
+uint32_t GodotPhysicsServer3D::area_get_collision_mask(RID p_area) const {
+ GodotArea3D *area = area_owner.get_or_null(p_area);
+ ERR_FAIL_COND_V(!area, 0);
+
+ return area->get_collision_mask();
+}
+
void GodotPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable) {
GodotArea3D *area = area_owner.get_or_null(p_area);
ERR_FAIL_COND(!area);
@@ -593,6 +607,20 @@ uint32_t GodotPhysicsServer3D::body_get_collision_mask(RID p_body) const {
return body->get_collision_mask();
}
+void GodotPhysicsServer3D::body_set_collision_priority(RID p_body, real_t p_priority) {
+ GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->set_collision_priority(p_priority);
+}
+
+real_t GodotPhysicsServer3D::body_get_collision_priority(RID p_body) const {
+ const GodotBody3D *body = body_owner.get_or_null(p_body);
+ ERR_FAIL_COND_V(!body, 0);
+
+ return body->get_collision_priority();
+}
+
void GodotPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) {
GodotBody3D *body = body_owner.get_or_null(p_body);
if (body) {
@@ -746,7 +774,7 @@ void GodotPhysicsServer3D::body_set_constant_force(RID p_body, const Vector3 &p_
ERR_FAIL_COND(!body);
body->set_constant_force(p_force);
- if (!p_force.is_equal_approx(Vector3())) {
+ if (!p_force.is_zero_approx()) {
body->wakeup();
}
}
@@ -762,7 +790,7 @@ void GodotPhysicsServer3D::body_set_constant_torque(RID p_body, const Vector3 &p
ERR_FAIL_COND(!body);
body->set_constant_torque(p_torque);
- if (!p_torque.is_equal_approx(Vector3())) {
+ if (!p_torque.is_zero_approx()) {
body->wakeup();
}
}
@@ -863,10 +891,10 @@ int GodotPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const {
return body->get_max_contacts_reported();
}
-void GodotPhysicsServer3D::body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) {
+void GodotPhysicsServer3D::body_set_state_sync_callback(RID p_body, const Callable &p_callable) {
GodotBody3D *body = body_owner.get_or_null(p_body);
ERR_FAIL_COND(!body);
- body->set_state_sync_callback(p_instance, p_callback);
+ body->set_state_sync_callback(p_callable);
}
void GodotPhysicsServer3D::body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata) {
@@ -1182,6 +1210,7 @@ RID GodotPhysicsServer3D::joint_create() {
void GodotPhysicsServer3D::joint_clear(RID p_joint) {
GodotJoint3D *joint = joint_owner.get_or_null(p_joint);
+ ERR_FAIL_NULL(joint);
if (joint->get_type() != JOINT_TYPE_MAX) {
GodotJoint3D *empty_joint = memnew(GodotJoint3D);
empty_joint->copy_settings_from(joint);
diff --git a/servers/physics_3d/godot_physics_server_3d.h b/servers/physics_3d/godot_physics_server_3d.h
index 1d57451925..e3e649da57 100644
--- a/servers/physics_3d/godot_physics_server_3d.h
+++ b/servers/physics_3d/godot_physics_server_3d.h
@@ -148,8 +148,11 @@ public:
virtual void area_set_ray_pickable(RID p_area, bool p_enable) override;
- virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) override;
+ virtual uint32_t area_get_collision_layer(RID p_area) const override;
+
+ virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) override;
+ virtual uint32_t area_get_collision_mask(RID p_area) const override;
virtual void area_set_monitorable(RID p_area, bool p_monitorable) override;
@@ -192,6 +195,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) override;
virtual uint32_t body_get_collision_mask(RID p_body) const override;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) override;
+ virtual real_t body_get_collision_priority(RID p_body) const override;
+
virtual void body_set_user_flags(RID p_body, uint32_t p_flags) override;
virtual uint32_t body_get_user_flags(RID p_body) const override;
@@ -239,7 +245,7 @@ public:
virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) override;
virtual int body_get_max_contacts_reported(RID p_body) const override;
- virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) override;
+ virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) override;
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) override;
virtual void body_set_ray_pickable(RID p_body, bool p_enable) override;
diff --git a/servers/physics_3d/godot_shape_3d.cpp b/servers/physics_3d/godot_shape_3d.cpp
index 5e310670a5..1443cd166b 100644
--- a/servers/physics_3d/godot_shape_3d.cpp
+++ b/servers/physics_3d/godot_shape_3d.cpp
@@ -411,9 +411,9 @@ void GodotBoxShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *
}
bool GodotBoxShape3D::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal, bool p_hit_back_faces) const {
- AABB aabb(-half_extents, half_extents * 2.0);
+ AABB aabb_ext(-half_extents, half_extents * 2.0);
- return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal);
+ return aabb_ext.intersects_segment(p_begin, p_end, &r_result, &r_normal);
}
bool GodotBoxShape3D::intersect_point(const Vector3 &p_point) const {
@@ -735,29 +735,6 @@ void GodotCylinderShape3D::get_supports(const Vector3 &p_normal, int p_max, Vect
r_amount = 1;
r_type = FEATURE_POINT;
r_supports[0] = get_support(p_normal);
- return;
-
- Vector3 n = p_normal;
- real_t h = n.y * Math::sqrt(0.25 * height * height + radius * radius);
- if (Math::abs(h) > 1.0) {
- // Top or bottom surface.
- n.y = (n.y > 0.0) ? height * 0.5 : -height * 0.5;
- } else {
- // Lateral surface.
- n.y = height * 0.5 * h;
- }
-
- real_t s = Math::sqrt(n.x * n.x + n.z * n.z);
- if (Math::is_zero_approx(s)) {
- n.x = 0.0;
- n.z = 0.0;
- } else {
- real_t scaled_radius = radius / s;
- n.x = n.x * scaled_radius;
- n.z = n.z * scaled_radius;
- }
-
- r_supports[0] = n;
}
}
@@ -840,48 +817,78 @@ GodotCylinderShape3D::GodotCylinderShape3D() {}
/********** CONVEX POLYGON *************/
void GodotConvexPolygonShape3D::project_range(const Vector3 &p_normal, const Transform3D &p_transform, real_t &r_min, real_t &r_max) const {
- int vertex_count = mesh.vertices.size();
+ uint32_t vertex_count = mesh.vertices.size();
if (vertex_count == 0) {
return;
}
const Vector3 *vrts = &mesh.vertices[0];
- for (int i = 0; i < vertex_count; i++) {
- real_t d = p_normal.dot(p_transform.xform(vrts[i]));
+ if (vertex_count > 3 * extreme_vertices.size()) {
+ // For a large mesh, two calls to get_support() is faster than a full
+ // scan over all vertices.
- if (i == 0 || d > r_max) {
- r_max = d;
- }
- if (i == 0 || d < r_min) {
- r_min = d;
+ Vector3 n = p_transform.basis.xform_inv(p_normal).normalized();
+ r_min = p_normal.dot(p_transform.xform(get_support(-n)));
+ r_max = p_normal.dot(p_transform.xform(get_support(n)));
+ } else {
+ for (uint32_t i = 0; i < vertex_count; i++) {
+ real_t d = p_normal.dot(p_transform.xform(vrts[i]));
+
+ if (i == 0 || d > r_max) {
+ r_max = d;
+ }
+ if (i == 0 || d < r_min) {
+ r_min = d;
+ }
}
}
}
Vector3 GodotConvexPolygonShape3D::get_support(const Vector3 &p_normal) const {
- Vector3 n = p_normal;
-
- int vert_support_idx = -1;
- real_t support_max = 0;
-
- int vertex_count = mesh.vertices.size();
- if (vertex_count == 0) {
+ if (mesh.vertices.size() == 0) {
return Vector3();
}
- const Vector3 *vrts = &mesh.vertices[0];
+ // Find an initial guess for the support vertex by checking the ones we
+ // found in _setup().
- for (int i = 0; i < vertex_count; i++) {
- real_t d = n.dot(vrts[i]);
-
- if (i == 0 || d > support_max) {
- support_max = d;
- vert_support_idx = i;
+ int best_vertex = -1;
+ real_t max_support = 0.0;
+ for (uint32_t i = 0; i < extreme_vertices.size(); i++) {
+ real_t s = p_normal.dot(mesh.vertices[extreme_vertices[i]]);
+ if (best_vertex == -1 || s > max_support) {
+ best_vertex = extreme_vertices[i];
+ max_support = s;
}
}
+ if (extreme_vertices.size() == mesh.vertices.size()) {
+ // We've already checked every vertex, so we can return now.
+ return mesh.vertices[best_vertex];
+ }
+
+ // Move along the surface until we reach the true support vertex.
- return vrts[vert_support_idx];
+ int last_vertex = -1;
+ while (true) {
+ int next_vertex = -1;
+ for (uint32_t i = 0; i < vertex_neighbors[best_vertex].size(); i++) {
+ int vert = vertex_neighbors[best_vertex][i];
+ if (vert != last_vertex) {
+ real_t s = p_normal.dot(mesh.vertices[vert]);
+ if (s > max_support) {
+ next_vertex = vert;
+ max_support = s;
+ break;
+ }
+ }
+ }
+ if (next_vertex == -1) {
+ return mesh.vertices[best_vertex];
+ }
+ last_vertex = best_vertex;
+ best_vertex = next_vertex;
+ }
}
void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount, FeatureType &r_type) const {
@@ -938,13 +945,13 @@ void GodotConvexPolygonShape3D::get_supports(const Vector3 &p_normal, int p_max,
}
for (int i = 0; i < ec; i++) {
- real_t dot = (vertices[edges[i].a] - vertices[edges[i].b]).normalized().dot(p_normal);
+ real_t dot = (vertices[edges[i].vertex_a] - vertices[edges[i].vertex_b]).normalized().dot(p_normal);
dot = ABS(dot);
- if (dot < edge_support_threshold && (edges[i].a == vtx || edges[i].b == vtx)) {
+ if (dot < edge_support_threshold && (edges[i].vertex_a == vtx || edges[i].vertex_b == vtx)) {
r_amount = 2;
r_type = FEATURE_EDGE;
- r_supports[0] = vertices[edges[i].a];
- r_supports[1] = vertices[edges[i].b];
+ r_supports[0] = vertices[edges[i].vertex_a];
+ r_supports[1] = vertices[edges[i].vertex_b];
return;
}
}
@@ -1048,8 +1055,8 @@ Vector3 GodotConvexPolygonShape3D::get_closest_point_to(const Vector3 &p_point)
int ec = mesh.edges.size();
for (int i = 0; i < ec; i++) {
Vector3 s[2] = {
- vertices[edges[i].a],
- vertices[edges[i].b]
+ vertices[edges[i].vertex_a],
+ vertices[edges[i].vertex_b]
};
Vector3 closest = Geometry3D::get_closest_point_to_segment(p_point, s);
@@ -1081,7 +1088,7 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) {
AABB _aabb;
- for (int i = 0; i < mesh.vertices.size(); i++) {
+ for (uint32_t i = 0; i < mesh.vertices.size(); i++) {
if (i == 0) {
_aabb.position = mesh.vertices[i];
} else {
@@ -1090,6 +1097,43 @@ void GodotConvexPolygonShape3D::_setup(const Vector<Vector3> &p_vertices) {
}
configure(_aabb);
+
+ // Pre-compute the extreme vertices in 26 directions. This will be used
+ // to speed up get_support() by letting us quickly get a good guess for
+ // the support vertex.
+
+ for (int x = -1; x < 2; x++) {
+ for (int y = -1; y < 2; y++) {
+ for (int z = -1; z < 2; z++) {
+ if (x != 0 || y != 0 || z != 0) {
+ Vector3 dir(x, y, z);
+ dir.normalize();
+ real_t max_support = 0.0;
+ int best_vertex = -1;
+ for (uint32_t i = 0; i < mesh.vertices.size(); i++) {
+ real_t s = dir.dot(mesh.vertices[i]);
+ if (best_vertex == -1 || s > max_support) {
+ best_vertex = i;
+ max_support = s;
+ }
+ }
+ if (extreme_vertices.find(best_vertex) == -1)
+ extreme_vertices.push_back(best_vertex);
+ }
+ }
+ }
+ }
+
+ // Record all the neighbors of each vertex. This is used in get_support().
+
+ if (extreme_vertices.size() < mesh.vertices.size()) {
+ vertex_neighbors.resize(mesh.vertices.size());
+ for (uint32_t i = 0; i < mesh.edges.size(); i++) {
+ Geometry3D::MeshData::Edge &edge = mesh.edges[i];
+ vertex_neighbors[edge.vertex_a].push_back(edge.vertex_b);
+ vertex_neighbors[edge.vertex_b].push_back(edge.vertex_a);
+ }
+ }
}
void GodotConvexPolygonShape3D::set_data(const Variant &p_data) {
@@ -1097,7 +1141,12 @@ void GodotConvexPolygonShape3D::set_data(const Variant &p_data) {
}
Variant GodotConvexPolygonShape3D::get_data() const {
- return mesh.vertices;
+ Vector<Vector3> vertices;
+ vertices.resize(mesh.vertices.size());
+ for (uint32_t i = 0; i < mesh.vertices.size(); i++) {
+ vertices.write[i] = mesh.vertices[i];
+ }
+ return vertices;
}
GodotConvexPolygonShape3D::GodotConvexPolygonShape3D() {
@@ -1282,14 +1331,14 @@ Vector3 GodotConcavePolygonShape3D::get_support(const Vector3 &p_normal) const {
}
void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_params) const {
- const BVH *bvh = &p_params->bvh[p_idx];
+ const BVH *params_bvh = &p_params->bvh[p_idx];
- if (!bvh->aabb.intersects_segment(p_params->from, p_params->to)) {
+ if (!params_bvh->aabb.intersects_segment(p_params->from, p_params->to)) {
return;
}
- if (bvh->face_index >= 0) {
- const Face *f = &p_params->faces[bvh->face_index];
+ if (params_bvh->face_index >= 0) {
+ const Face *f = &p_params->faces[params_bvh->face_index];
GodotFaceShape3D *face = p_params->face;
face->normal = f->normal;
face->vertex[0] = p_params->vertices[f->indices[0]];
@@ -1308,11 +1357,11 @@ void GodotConcavePolygonShape3D::_cull_segment(int p_idx, _SegmentCullParams *p_
}
}
} else {
- if (bvh->left >= 0) {
- _cull_segment(bvh->left, p_params);
+ if (params_bvh->left >= 0) {
+ _cull_segment(params_bvh->left, p_params);
}
- if (bvh->right >= 0) {
- _cull_segment(bvh->right, p_params);
+ if (params_bvh->right >= 0) {
+ _cull_segment(params_bvh->right, p_params);
}
}
}
@@ -1362,14 +1411,14 @@ Vector3 GodotConcavePolygonShape3D::get_closest_point_to(const Vector3 &p_point)
}
bool GodotConcavePolygonShape3D::_cull(int p_idx, _CullParams *p_params) const {
- const BVH *bvh = &p_params->bvh[p_idx];
+ const BVH *params_bvh = &p_params->bvh[p_idx];
- if (!p_params->aabb.intersects(bvh->aabb)) {
+ if (!p_params->aabb.intersects(params_bvh->aabb)) {
return false;
}
- if (bvh->face_index >= 0) {
- const Face *f = &p_params->faces[bvh->face_index];
+ if (params_bvh->face_index >= 0) {
+ const Face *f = &p_params->faces[params_bvh->face_index];
GodotFaceShape3D *face = p_params->face;
face->normal = f->normal;
face->vertex[0] = p_params->vertices[f->indices[0]];
@@ -1379,14 +1428,14 @@ bool GodotConcavePolygonShape3D::_cull(int p_idx, _CullParams *p_params) const {
return true;
}
} else {
- if (bvh->left >= 0) {
- if (_cull(bvh->left, p_params)) {
+ if (params_bvh->left >= 0) {
+ if (_cull(params_bvh->left, p_params)) {
return true;
}
}
- if (bvh->right >= 0) {
- if (_cull(bvh->right, p_params)) {
+ if (params_bvh->right >= 0) {
+ if (_cull(params_bvh->right, p_params)) {
return true;
}
}
@@ -1942,14 +1991,14 @@ Vector3 GodotHeightMapShape3D::get_closest_point_to(const Vector3 &p_point) cons
}
void GodotHeightMapShape3D::_get_cell(const Vector3 &p_point, int &r_x, int &r_y, int &r_z) const {
- const AABB &aabb = get_aabb();
+ const AABB &shape_aabb = get_aabb();
- Vector3 pos_local = aabb.position + local_origin;
+ Vector3 pos_local = shape_aabb.position + local_origin;
Vector3 clamped_point(p_point);
- clamped_point.x = CLAMP(p_point.x, pos_local.x, pos_local.x + aabb.size.x);
- clamped_point.y = CLAMP(p_point.y, pos_local.y, pos_local.y + aabb.size.y);
- clamped_point.z = CLAMP(p_point.z, pos_local.z, pos_local.x + aabb.size.z);
+ clamped_point.x = CLAMP(p_point.x, pos_local.x, pos_local.x + shape_aabb.size.x);
+ clamped_point.y = CLAMP(p_point.y, pos_local.y, pos_local.y + shape_aabb.size.y);
+ clamped_point.z = CLAMP(p_point.z, pos_local.z, pos_local.x + shape_aabb.size.z);
r_x = (clamped_point.x < 0.0) ? (clamped_point.x - 0.5) : (clamped_point.x + 0.5);
r_y = (clamped_point.y < 0.0) ? (clamped_point.y - 0.5) : (clamped_point.y + 0.5);
@@ -2093,19 +2142,19 @@ void GodotHeightMapShape3D::_setup(const Vector<real_t> &p_heights, int p_width,
depth = p_depth;
// Initialize aabb.
- AABB aabb;
- aabb.position = Vector3(0.0, p_min_height, 0.0);
- aabb.size = Vector3(p_width - 1, p_max_height - p_min_height, p_depth - 1);
+ AABB aabb_new;
+ aabb_new.position = Vector3(0.0, p_min_height, 0.0);
+ aabb_new.size = Vector3(p_width - 1, p_max_height - p_min_height, p_depth - 1);
// Initialize origin as the aabb center.
- local_origin = aabb.position + 0.5 * aabb.size;
+ local_origin = aabb_new.position + 0.5 * aabb_new.size;
local_origin.y = 0.0;
- aabb.position -= local_origin;
+ aabb_new.position -= local_origin;
_build_accelerator();
- configure(aabb);
+ configure(aabb_new);
}
void GodotHeightMapShape3D::set_data(const Variant &p_data) {
@@ -2116,11 +2165,11 @@ void GodotHeightMapShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(!d.has("depth"));
ERR_FAIL_COND(!d.has("heights"));
- int width = d["width"];
- int depth = d["depth"];
+ int width_new = d["width"];
+ int depth_new = d["depth"];
- ERR_FAIL_COND(width <= 0.0);
- ERR_FAIL_COND(depth <= 0.0);
+ ERR_FAIL_COND(width_new <= 0.0);
+ ERR_FAIL_COND(depth_new <= 0.0);
Variant heights_variant = d["heights"];
Vector<real_t> heights_buffer;
@@ -2174,10 +2223,10 @@ void GodotHeightMapShape3D::set_data(const Variant &p_data) {
ERR_FAIL_COND(min_height > max_height);
- ERR_FAIL_COND(heights_buffer.size() != (width * depth));
+ ERR_FAIL_COND(heights_buffer.size() != (width_new * depth_new));
// If specified, min and max height will be used as precomputed values.
- _setup(heights_buffer, width, depth, min_height, max_height);
+ _setup(heights_buffer, width_new, depth_new, min_height, max_height);
}
Variant GodotHeightMapShape3D::get_data() const {
@@ -2185,9 +2234,9 @@ Variant GodotHeightMapShape3D::get_data() const {
d["width"] = width;
d["depth"] = depth;
- const AABB &aabb = get_aabb();
- d["min_height"] = aabb.position.y;
- d["max_height"] = aabb.position.y + aabb.size.y;
+ const AABB &shape_aabb = get_aabb();
+ d["min_height"] = shape_aabb.position.y;
+ d["max_height"] = shape_aabb.position.y + shape_aabb.size.y;
d["heights"] = heights;
diff --git a/servers/physics_3d/godot_shape_3d.h b/servers/physics_3d/godot_shape_3d.h
index 1fc8f7c711..dc8e34e2bc 100644
--- a/servers/physics_3d/godot_shape_3d.h
+++ b/servers/physics_3d/godot_shape_3d.h
@@ -277,6 +277,8 @@ public:
struct GodotConvexPolygonShape3D : public GodotShape3D {
Geometry3D::MeshData mesh;
+ LocalVector<int> extreme_vertices;
+ LocalVector<LocalVector<int>> vertex_neighbors;
void _setup(const Vector<Vector3> &p_vertices);
diff --git a/servers/physics_3d/godot_soft_body_3d.cpp b/servers/physics_3d/godot_soft_body_3d.cpp
index 173843072a..77110c5fbc 100644
--- a/servers/physics_3d/godot_soft_body_3d.cpp
+++ b/servers/physics_3d/godot_soft_body_3d.cpp
@@ -722,7 +722,14 @@ void GodotSoftBody3D::reoptimize_link_order() {
const int reop_not_dependent = -1;
const int reop_node_complete = -2;
- uint32_t i, link_count = links.size(), node_count = nodes.size();
+ uint32_t link_count = links.size();
+ uint32_t node_count = nodes.size();
+
+ if (link_count < 1 || node_count < 2) {
+ return;
+ }
+
+ uint32_t i;
Link *lr;
int ar, br;
Node *node0 = &(nodes[0]);
diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp
index 533d7605ce..c98409e2c4 100644
--- a/servers/physics_3d/godot_space_3d.cpp
+++ b/servers/physics_3d/godot_space_3d.cpp
@@ -120,8 +120,8 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
bool collided = false;
Vector3 res_point, res_normal;
- int res_shape;
- const GodotCollisionObject3D *res_obj;
+ int res_shape = -1;
+ const GodotCollisionObject3D *res_obj = nullptr;
real_t min_d = 1e10;
for (int i = 0; i < amount; i++) {
@@ -185,6 +185,7 @@ bool GodotPhysicsDirectSpaceState3D::intersect_ray(const RayParameters &p_parame
if (!collided) {
return false;
}
+ ERR_FAIL_NULL_V(res_obj, false); // Shouldn't happen but silences warning.
r_result.collider_id = res_obj->get_instance_id();
if (r_result.collider_id.is_valid()) {
@@ -701,6 +702,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
const int max_results = 32;
int recover_attempts = 4;
Vector3 sr[max_results * 2];
+ real_t priorities[max_results];
do {
GodotPhysicsServer3D::CollCbkData cbk;
@@ -710,6 +712,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
GodotPhysicsServer3D::CollCbkData *cbkptr = &cbk;
GodotCollisionSolver3D::CallbackResult cbkres = GodotPhysicsServer3D::_shape_col_cbk;
+ int priority_amount = 0;
bool collided = false;
@@ -737,6 +740,10 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
if (GodotCollisionSolver3D::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, nullptr, margin)) {
collided = cbk.amount > 0;
}
+ while (cbk.amount > priority_amount) {
+ priorities[priority_amount] = col_obj->get_collision_priority();
+ priority_amount++;
+ }
}
}
@@ -744,6 +751,12 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
break;
}
+ real_t inv_total_weight = 0.0;
+ for (int i = 0; i < cbk.amount; i++) {
+ inv_total_weight += priorities[i];
+ }
+ inv_total_weight = Math::is_zero_approx(inv_total_weight) ? 1.0 : (real_t)cbk.amount / inv_total_weight;
+
recovered = true;
Vector3 recover_motion;
@@ -759,7 +772,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
real_t depth = n.dot(a + recover_motion) - d;
if (depth > min_contact_depth + CMP_EPSILON) {
// Only recover if there is penetration.
- recover_motion -= n * (depth - min_contact_depth) * 0.4;
+ recover_motion -= n * (depth - min_contact_depth) * 0.4 * priorities[i] * inv_total_weight;
}
}
@@ -989,6 +1002,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
r_result->collision_unsafe_fraction = unsafe;
r_result->collision_count = rcd.result_count;
+ r_result->collision_depth = rcd.best_result.len;
}
collided = true;
@@ -1002,6 +1016,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
r_result->collision_safe_fraction = 1.0;
r_result->collision_unsafe_fraction = 1.0;
+ r_result->collision_depth = 0.0;
}
return collided;
@@ -1235,7 +1250,7 @@ GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() {
GodotSpace3D::GodotSpace3D() {
body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1);
- body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg2rad(8.0));
+ body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0));
body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater"));
@@ -1243,7 +1258,7 @@ GodotSpace3D::GodotSpace3D() {
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/solver_iterations", PropertyInfo(Variant::INT, "physics/3d/solver/solver_iterations", PROPERTY_HINT_RANGE, "1,32,1,or_greater"));
contact_recycle_radius = GLOBAL_DEF("physics/3d/solver/contact_recycle_radius", 0.01);
- ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"));
+ ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_recycle_radius", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_recycle_radius", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"));
contact_max_separation = GLOBAL_DEF("physics/3d/solver/contact_max_separation", 0.05);
ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/solver/contact_max_separation", PropertyInfo(Variant::FLOAT, "physics/3d/solver/contact_max_separation", PROPERTY_HINT_RANGE, "0,0.1,0.01,or_greater"));
diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp
index 99656d01a0..bfedcd29c0 100644
--- a/servers/physics_3d/godot_step_3d.cpp
+++ b/servers/physics_3d/godot_step_3d.cpp
@@ -44,7 +44,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D
p_body->set_island_step(_step);
if (p_body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) {
- // Only dynamic bodies are tested for activation.
+ // Only rigid bodies are tested for activation.
p_body_island.push_back(p_body);
}
@@ -343,7 +343,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
/* SETUP CONSTRAINTS / PROCESS COLLISIONS */
uint32_t total_contraint_count = all_constraints.size();
- work_pool.do_work(total_contraint_count, this, &GodotStep3D::_setup_contraint, nullptr);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_setup_contraint, nullptr, total_contraint_count, -1, true, SNAME("Physics3DConstraintSetup"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -362,7 +363,8 @@ void GodotStep3D::step(GodotSpace3D *p_space, real_t p_delta) {
// Warning: _solve_island modifies the constraint islands for optimization purpose,
// their content is not reliable after these calls and shouldn't be used anymore.
- work_pool.do_work(island_count, this, &GodotStep3D::_solve_island, nullptr);
+ group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &GodotStep3D::_solve_island, nullptr, island_count, -1, true, SNAME("Physics3DConstraintSolveIslands"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
{ //profile
profile_endtime = OS::get_singleton()->get_ticks_usec();
@@ -409,10 +411,7 @@ GodotStep3D::GodotStep3D() {
body_islands.reserve(BODY_ISLAND_COUNT_RESERVE);
constraint_islands.reserve(ISLAND_COUNT_RESERVE);
all_constraints.reserve(CONSTRAINT_COUNT_RESERVE);
-
- work_pool.init();
}
GodotStep3D::~GodotStep3D() {
- work_pool.finish();
}
diff --git a/servers/physics_3d/godot_step_3d.h b/servers/physics_3d/godot_step_3d.h
index 6d975b0dd3..189487757f 100644
--- a/servers/physics_3d/godot_step_3d.h
+++ b/servers/physics_3d/godot_step_3d.h
@@ -33,8 +33,8 @@
#include "godot_space_3d.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/local_vector.h"
-#include "core/templates/thread_work_pool.h"
class GodotStep3D {
uint64_t _step = 1;
@@ -42,8 +42,6 @@ class GodotStep3D {
int iterations = 0;
real_t delta = 0.0;
- ThreadWorkPool work_pool;
-
LocalVector<LocalVector<GodotBody3D *>> body_islands;
LocalVector<LocalVector<GodotConstraint3D *>> constraint_islands;
LocalVector<GodotConstraint3D *> all_constraints;
diff --git a/servers/physics_3d/joints/godot_cone_twist_joint_3d.h b/servers/physics_3d/joints/godot_cone_twist_joint_3d.h
index fdcc2ceea3..1651d34916 100644
--- a/servers/physics_3d/joints/godot_cone_twist_joint_3d.h
+++ b/servers/physics_3d/joints/godot_cone_twist_joint_3d.h
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GODOT_CONE_TWIST_JOINT_3D_H
+#define GODOT_CONE_TWIST_JOINT_3D_H
+
/*
Adapted to Godot from the Bullet library.
*/
@@ -49,9 +52,6 @@ subject to the following restrictions:
Written by: Marcus Hennix
*/
-#ifndef GODOT_CONE_TWIST_JOINT_3D_H
-#define GODOT_CONE_TWIST_JOINT_3D_H
-
#include "servers/physics_3d/godot_joint_3d.h"
#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
diff --git a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
index e0fa940104..dfe2bfa4d3 100644
--- a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
+++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.cpp
@@ -232,7 +232,7 @@ GodotGeneric6DOFJoint3D::GodotGeneric6DOFJoint3D(GodotBody3D *rbA, GodotBody3D *
void GodotGeneric6DOFJoint3D::calculateAngleInfo() {
Basis relative_frame = m_calculatedTransformB.basis.inverse() * m_calculatedTransformA.basis;
- m_calculatedAxisAngleDiff = relative_frame.get_euler(Basis::EULER_ORDER_XYZ);
+ m_calculatedAxisAngleDiff = relative_frame.get_euler(EulerOrder::XYZ);
// in euler angle mode we do not actually constrain the angular velocity
// along the axes axis[0] and axis[2] (although we do use axis[1]) :
diff --git a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h
index bcf2d18647..6a0ab81461 100644
--- a/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h
+++ b/servers/physics_3d/joints/godot_generic_6dof_joint_3d.h
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GODOT_GENERIC_6DOF_JOINT_3D_H
+#define GODOT_GENERIC_6DOF_JOINT_3D_H
+
/*
Adapted to Godot from the Bullet library.
*/
-#ifndef GODOT_GENERIC_6DOF_JOINT_3D_H
-#define GODOT_GENERIC_6DOF_JOINT_3D_H
-
#include "servers/physics_3d/godot_joint_3d.h"
#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
diff --git a/servers/physics_3d/joints/godot_hinge_joint_3d.h b/servers/physics_3d/joints/godot_hinge_joint_3d.h
index b934540e8d..f1187771af 100644
--- a/servers/physics_3d/joints/godot_hinge_joint_3d.h
+++ b/servers/physics_3d/joints/godot_hinge_joint_3d.h
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GODOT_HINGE_JOINT_3D_H
+#define GODOT_HINGE_JOINT_3D_H
+
/*
Adapted to Godot from the Bullet library.
*/
-#ifndef GODOT_HINGE_JOINT_3D_H
-#define GODOT_HINGE_JOINT_3D_H
-
#include "servers/physics_3d/godot_joint_3d.h"
#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
diff --git a/servers/physics_3d/joints/godot_jacobian_entry_3d.h b/servers/physics_3d/joints/godot_jacobian_entry_3d.h
index 0fe15751d5..a46ce830ec 100644
--- a/servers/physics_3d/joints/godot_jacobian_entry_3d.h
+++ b/servers/physics_3d/joints/godot_jacobian_entry_3d.h
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GODOT_JACOBIAN_ENTRY_3D_H
+#define GODOT_JACOBIAN_ENTRY_3D_H
+
/*
Adapted to Godot from the Bullet library.
*/
-#ifndef GODOT_JACOBIAN_ENTRY_3D_H
-#define GODOT_JACOBIAN_ENTRY_3D_H
-
/*
Bullet Continuous Collision Detection and Physics Library
Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
diff --git a/servers/physics_3d/joints/godot_pin_joint_3d.h b/servers/physics_3d/joints/godot_pin_joint_3d.h
index eeeaa650bd..b3e2389d5a 100644
--- a/servers/physics_3d/joints/godot_pin_joint_3d.h
+++ b/servers/physics_3d/joints/godot_pin_joint_3d.h
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GODOT_PIN_JOINT_3D_H
+#define GODOT_PIN_JOINT_3D_H
+
/*
Adapted to Godot from the Bullet library.
*/
-#ifndef GODOT_PIN_JOINT_3D_H
-#define GODOT_PIN_JOINT_3D_H
-
#include "servers/physics_3d/godot_joint_3d.h"
#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
diff --git a/servers/physics_3d/joints/godot_slider_joint_3d.h b/servers/physics_3d/joints/godot_slider_joint_3d.h
index f596c9ff75..29d19be0d7 100644
--- a/servers/physics_3d/joints/godot_slider_joint_3d.h
+++ b/servers/physics_3d/joints/godot_slider_joint_3d.h
@@ -28,13 +28,13 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef GODOT_SLIDER_JOINT_3D_H
+#define GODOT_SLIDER_JOINT_3D_H
+
/*
Adapted to Godot from the Bullet library.
*/
-#ifndef GODOT_SLIDER_JOINT_3D_H
-#define GODOT_SLIDER_JOINT_3D_H
-
#include "servers/physics_3d/godot_joint_3d.h"
#include "servers/physics_3d/joints/godot_jacobian_entry_3d.h"
diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp
index 41aae36785..21be311637 100644
--- a/servers/physics_server_2d.cpp
+++ b/servers/physics_server_2d.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/string/print_string.h"
+#include "core/variant/typed_array.h"
PhysicsServer2D *PhysicsServer2D::singleton = nullptr;
@@ -147,24 +148,36 @@ PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {}
///////////////////////////////////////////////////////
-void PhysicsRayQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
+Ref<PhysicsRayQueryParameters2D> PhysicsRayQueryParameters2D::create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const TypedArray<RID> &p_exclude) {
+ Ref<PhysicsRayQueryParameters2D> params;
+ params.instantiate();
+ params->set_from(p_from);
+ params->set_to(p_to);
+ params->set_collision_mask(p_mask);
+ params->set_exclude(p_exclude);
+ return params;
+}
+
+void PhysicsRayQueryParameters2D::set_exclude(const TypedArray<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsRayQueryParameters2D::get_exclude() const {
- Vector<RID> ret;
+TypedArray<RID> PhysicsRayQueryParameters2D::get_exclude() const {
+ TypedArray<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
for (const RID &E : parameters.exclude) {
- ret.write[idx++] = E;
+ ret[idx++] = E;
}
return ret;
}
void PhysicsRayQueryParameters2D::_bind_methods() {
+ ClassDB::bind_static_method("PhysicsRayQueryParameters2D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters2D::create, DEFVAL(UINT32_MAX), DEFVAL(TypedArray<RID>()));
+
ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters2D::set_from);
ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters2D::get_from);
@@ -197,19 +210,19 @@ void PhysicsRayQueryParameters2D::_bind_methods() {
///////////////////////////////////////////////////////
-void PhysicsPointQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
+void PhysicsPointQueryParameters2D::set_exclude(const TypedArray<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsPointQueryParameters2D::get_exclude() const {
- Vector<RID> ret;
+TypedArray<RID> PhysicsPointQueryParameters2D::get_exclude() const {
+ TypedArray<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
for (const RID &E : parameters.exclude) {
- ret.write[idx++] = E;
+ ret[idx++] = E;
}
return ret;
}
@@ -256,19 +269,19 @@ void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) {
}
}
-void PhysicsShapeQueryParameters2D::set_exclude(const Vector<RID> &p_exclude) {
+void PhysicsShapeQueryParameters2D::set_exclude(const TypedArray<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
parameters.exclude.insert(p_exclude[i]);
}
}
-Vector<RID> PhysicsShapeQueryParameters2D::get_exclude() const {
- Vector<RID> ret;
+TypedArray<RID> PhysicsShapeQueryParameters2D::get_exclude() const {
+ TypedArray<RID> ret;
ret.resize(parameters.exclude.size());
int idx = 0;
for (const RID &E : parameters.exclude) {
- ret.write[idx++] = E;
+ ret[idx++] = E;
}
return ret;
}
@@ -335,7 +348,7 @@ Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Ref<PhysicsRayQueryPa
return d;
}
-Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) {
+TypedArray<Dictionary> PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results) {
ERR_FAIL_COND_V(p_point_query.is_null(), Array());
Vector<ShapeResult> ret;
@@ -344,10 +357,10 @@ Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryPar
int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size());
if (rc == 0) {
- return Array();
+ return TypedArray<Dictionary>();
}
- Array r;
+ TypedArray<Dictionary> r;
r.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -360,13 +373,13 @@ Array PhysicsDirectSpaceState2D::_intersect_point(const Ref<PhysicsPointQueryPar
return r;
}
-Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+TypedArray<Dictionary> PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), TypedArray<Dictionary>());
Vector<ShapeResult> sr;
sr.resize(p_max_results);
int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size());
- Array ret;
+ TypedArray<Dictionary> ret;
ret.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -380,22 +393,22 @@ Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref<PhysicsShapeQueryPar
return ret;
}
-Array PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+Vector<real_t> PhysicsDirectSpaceState2D::_cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), Vector<real_t>());
real_t closest_safe, closest_unsafe;
bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe);
if (!res) {
- return Array();
+ return Vector<real_t>();
}
- Array ret;
+ Vector<real_t> ret;
ret.resize(2);
- ret[0] = closest_safe;
- ret[1] = closest_unsafe;
+ ret.write[0] = closest_safe;
+ ret.write[1] = closest_unsafe;
return ret;
}
-Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
+TypedArray<PackedVector2Array> PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
Vector<Vector2> ret;
@@ -403,9 +416,9 @@ Array PhysicsDirectSpaceState2D::_collide_shape(const Ref<PhysicsShapeQueryParam
int rc = 0;
bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc);
if (!res) {
- return Array();
+ return TypedArray<PackedVector2Array>();
}
- Array r;
+ TypedArray<PackedVector2Array> r;
r.resize(rc * 2);
for (int i = 0; i < rc * 2; i++) {
r[i] = ret[i];
@@ -448,21 +461,21 @@ void PhysicsDirectSpaceState2D::_bind_methods() {
///////////////////////////////
-Vector<RID> PhysicsTestMotionParameters2D::get_exclude_bodies() const {
- Vector<RID> exclude;
+TypedArray<RID> PhysicsTestMotionParameters2D::get_exclude_bodies() const {
+ TypedArray<RID> exclude;
exclude.resize(parameters.exclude_bodies.size());
int body_index = 0;
for (RID body : parameters.exclude_bodies) {
- exclude.write[body_index++] = body;
+ exclude[body_index++] = body;
}
return exclude;
}
-void PhysicsTestMotionParameters2D::set_exclude_bodies(const Vector<RID> &p_exclude) {
- for (RID body : p_exclude) {
- parameters.exclude_bodies.insert(body);
+void PhysicsTestMotionParameters2D::set_exclude_bodies(const TypedArray<RID> &p_exclude) {
+ for (int i = 0; i < p_exclude.size(); i++) {
+ parameters.exclude_bodies.insert(p_exclude[i]);
}
}
@@ -639,7 +652,10 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_clear_shapes", "area"), &PhysicsServer2D::area_clear_shapes);
ClassDB::bind_method(D_METHOD("area_set_collision_layer", "area", "layer"), &PhysicsServer2D::area_set_collision_layer);
+ ClassDB::bind_method(D_METHOD("area_get_collision_layer", "area"), &PhysicsServer2D::area_get_collision_layer);
+
ClassDB::bind_method(D_METHOD("area_set_collision_mask", "area", "mask"), &PhysicsServer2D::area_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("area_get_collision_mask", "area"), &PhysicsServer2D::area_get_collision_mask);
ClassDB::bind_method(D_METHOD("area_set_param", "area", "param", "value"), &PhysicsServer2D::area_set_param);
ClassDB::bind_method(D_METHOD("area_set_transform", "area", "transform"), &PhysicsServer2D::area_set_transform);
@@ -694,6 +710,9 @@ void PhysicsServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer2D::body_set_collision_mask);
ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer2D::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_priority", "body", "priority"), &PhysicsServer2D::body_set_collision_priority);
+ ClassDB::bind_method(D_METHOD("body_get_collision_priority", "body"), &PhysicsServer2D::body_get_collision_priority);
+
ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer2D::body_set_param);
ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer2D::body_get_param);
@@ -801,8 +820,8 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
@@ -834,6 +853,8 @@ void PhysicsServer2D::_bind_methods() {
BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_BIAS);
BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_FORCE);
+ BIND_ENUM_CONSTANT(PIN_JOINT_SOFTNESS);
+
BIND_ENUM_CONSTANT(DAMPED_SPRING_REST_LENGTH);
BIND_ENUM_CONSTANT(DAMPED_SPRING_STIFFNESS);
BIND_ENUM_CONSTANT(DAMPED_SPRING_DAMPING);
@@ -858,9 +879,7 @@ PhysicsServer2D::~PhysicsServer2D() {
singleton = nullptr;
}
-Vector<PhysicsServer2DManager::ClassInfo> PhysicsServer2DManager::physics_2d_servers;
-int PhysicsServer2DManager::default_server_id = -1;
-int PhysicsServer2DManager::default_server_priority = -1;
+PhysicsServer2DManager *PhysicsServer2DManager::singleton = nullptr;
const String PhysicsServer2DManager::setting_property_name(PNAME("physics/2d/physics_engine"));
void PhysicsServer2DManager::on_servers_changed() {
@@ -871,10 +890,19 @@ void PhysicsServer2DManager::on_servers_changed() {
ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers));
}
-void PhysicsServer2DManager::register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback) {
- ERR_FAIL_COND(!p_creat_callback);
+void PhysicsServer2DManager::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("register_server", "name", "create_callback"), &PhysicsServer2DManager::register_server);
+ ClassDB::bind_method(D_METHOD("set_default_server", "name", "priority"), &PhysicsServer2DManager::set_default_server);
+}
+
+PhysicsServer2DManager *PhysicsServer2DManager::get_singleton() {
+ return singleton;
+}
+
+void PhysicsServer2DManager::register_server(const String &p_name, const Callable &p_create_callback) {
+ //ERR_FAIL_COND(!p_create_callback.is_valid());
ERR_FAIL_COND(find_server_id(p_name) != -1);
- physics_2d_servers.push_back(ClassInfo(p_name, p_creat_callback));
+ physics_2d_servers.push_back(ClassInfo(p_name, p_create_callback));
on_servers_changed();
}
@@ -907,7 +935,11 @@ String PhysicsServer2DManager::get_server_name(int p_id) {
PhysicsServer2D *PhysicsServer2DManager::new_default_server() {
ERR_FAIL_COND_V(default_server_id == -1, nullptr);
- return physics_2d_servers[default_server_id].create_callback();
+ Variant ret;
+ Callable::CallError ce;
+ physics_2d_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce);
+ ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
+ return Object::cast_to<PhysicsServer2D>(ret.get_validated_object());
}
PhysicsServer2D *PhysicsServer2DManager::new_server(const String &p_name) {
@@ -915,6 +947,18 @@ PhysicsServer2D *PhysicsServer2DManager::new_server(const String &p_name) {
if (id == -1) {
return nullptr;
} else {
- return physics_2d_servers[id].create_callback();
+ Variant ret;
+ Callable::CallError ce;
+ physics_2d_servers[id].create_callback.callp(nullptr, 0, ret, ce);
+ ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
+ return Object::cast_to<PhysicsServer2D>(ret.get_validated_object());
}
}
+
+PhysicsServer2DManager::PhysicsServer2DManager() {
+ singleton = this;
+}
+
+PhysicsServer2DManager::~PhysicsServer2DManager() {
+ singleton = nullptr;
+}
diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h
index 7a821c64e6..95425e72e8 100644
--- a/servers/physics_server_2d.h
+++ b/servers/physics_server_2d.h
@@ -36,6 +36,8 @@
#include "core/object/ref_counted.h"
class PhysicsDirectSpaceState2D;
+template <typename T>
+class TypedArray;
class PhysicsDirectBodyState2D : public Object {
GDCLASS(PhysicsDirectBodyState2D, Object);
@@ -114,10 +116,10 @@ class PhysicsDirectSpaceState2D : public Object {
GDCLASS(PhysicsDirectSpaceState2D, Object);
Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters2D> &p_ray_query);
- Array _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32);
- Array _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
- Array _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query);
- Array _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_point(const Ref<PhysicsPointQueryParameters2D> &p_point_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
+ Vector<real_t> _cast_motion(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query);
+ TypedArray<PackedVector2Array> _collide_shape(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query, int p_max_results = 32);
Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters2D> &p_shape_query);
protected:
@@ -330,8 +332,11 @@ public:
virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const = 0;
virtual Transform2D area_get_transform(RID p_area) const = 0;
- virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0;
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) = 0;
+ virtual uint32_t area_get_collision_layer(RID p_area) const = 0;
+
+ virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0;
+ virtual uint32_t area_get_collision_mask(RID p_area) const = 0;
virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0;
virtual void area_set_pickable(RID p_area, bool p_pickable) = 0;
@@ -346,8 +351,8 @@ public:
enum BodyMode {
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
- BODY_MODE_DYNAMIC,
- BODY_MODE_DYNAMIC_LINEAR,
+ BODY_MODE_RIGID,
+ BODY_MODE_RIGID_LINEAR,
};
virtual RID body_create() = 0;
@@ -393,6 +398,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0;
virtual uint32_t body_get_collision_mask(RID p_body) const = 0;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) = 0;
+ virtual real_t body_get_collision_priority(RID p_body) const = 0;
+
// common body variables
enum BodyParameter {
BODY_PARAM_BOUNCE,
@@ -465,10 +473,7 @@ public:
virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
- // Callback for C++ use only.
- typedef void (*BodyStateCallback)(void *p_instance, PhysicsDirectBodyState2D *p_state);
- virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) = 0;
-
+ virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) = 0;
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0;
virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) = 0;
@@ -605,6 +610,7 @@ protected:
static void _bind_methods();
public:
+ static Ref<PhysicsRayQueryParameters2D> create(Vector2 p_from, Vector2 p_to, uint32_t p_mask, const TypedArray<RID> &p_exclude);
const PhysicsDirectSpaceState2D::RayParameters &get_parameters() const { return parameters; }
void set_from(const Vector2 &p_from) { parameters.from = p_from; }
@@ -625,8 +631,8 @@ public:
void set_hit_from_inside(bool p_enable) { parameters.hit_from_inside = p_enable; }
bool is_hit_from_inside_enabled() const { return parameters.hit_from_inside; }
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
+ void set_exclude(const TypedArray<RID> &p_exclude);
+ TypedArray<RID> get_exclude() const;
};
class PhysicsPointQueryParameters2D : public RefCounted {
@@ -655,8 +661,8 @@ public:
void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
+ void set_exclude(const TypedArray<RID> &p_exclude);
+ TypedArray<RID> get_exclude() const;
};
class PhysicsShapeQueryParameters2D : public RefCounted {
@@ -696,8 +702,8 @@ public:
void set_collide_with_areas(bool p_enable) { parameters.collide_with_areas = p_enable; }
bool is_collide_with_areas_enabled() const { return parameters.collide_with_areas; }
- void set_exclude(const Vector<RID> &p_exclude);
- Vector<RID> get_exclude() const;
+ void set_exclude(const TypedArray<RID> &p_exclude);
+ TypedArray<RID> get_exclude() const;
};
class PhysicsTestMotionParameters2D : public RefCounted {
@@ -723,8 +729,8 @@ public:
bool is_collide_separation_ray_enabled() const { return parameters.collide_separation_ray; }
void set_collide_separation_ray_enabled(bool p_enabled) { parameters.collide_separation_ray = p_enabled; }
- Vector<RID> get_exclude_bodies() const;
- void set_exclude_bodies(const Vector<RID> &p_exclude);
+ TypedArray<RID> get_exclude_bodies() const;
+ void set_exclude_bodies(const TypedArray<RID> &p_exclude);
Array get_exclude_objects() const;
void set_exclude_objects(const Array &p_exclude);
@@ -760,16 +766,18 @@ public:
real_t get_collision_unsafe_fraction() const;
};
-typedef PhysicsServer2D *(*CreatePhysicsServer2DCallback)();
+class PhysicsServer2DManager : public Object {
+ GDCLASS(PhysicsServer2DManager, Object);
+
+ static PhysicsServer2DManager *singleton;
-class PhysicsServer2DManager {
struct ClassInfo {
String name;
- CreatePhysicsServer2DCallback create_callback = nullptr;
+ Callable create_callback;
ClassInfo() {}
- ClassInfo(String p_name, CreatePhysicsServer2DCallback p_create_callback) :
+ ClassInfo(String p_name, Callable p_create_callback) :
name(p_name),
create_callback(p_create_callback) {}
@@ -783,24 +791,30 @@ class PhysicsServer2DManager {
}
};
- static Vector<ClassInfo> physics_2d_servers;
- static int default_server_id;
- static int default_server_priority;
+ Vector<ClassInfo> physics_2d_servers;
+ int default_server_id = -1;
+ int default_server_priority = -1;
+
+ void on_servers_changed();
+
+protected:
+ static void _bind_methods();
public:
static const String setting_property_name;
-private:
- static void on_servers_changed();
+ static PhysicsServer2DManager *get_singleton();
-public:
- static void register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback);
- static void set_default_server(const String &p_name, int p_priority = 0);
- static int find_server_id(const String &p_name);
- static int get_servers_count();
- static String get_server_name(int p_id);
- static PhysicsServer2D *new_default_server();
- static PhysicsServer2D *new_server(const String &p_name);
+ void register_server(const String &p_name, const Callable &p_create_callback);
+ void set_default_server(const String &p_name, int p_priority = 0);
+ int find_server_id(const String &p_name);
+ int get_servers_count();
+ String get_server_name(int p_id);
+ PhysicsServer2D *new_default_server();
+ PhysicsServer2D *new_server(const String &p_name);
+
+ PhysicsServer2DManager();
+ ~PhysicsServer2DManager();
};
VARIANT_ENUM_CAST(PhysicsServer2D::ShapeType);
@@ -814,6 +828,7 @@ VARIANT_ENUM_CAST(PhysicsServer2D::BodyState);
VARIANT_ENUM_CAST(PhysicsServer2D::CCDMode);
VARIANT_ENUM_CAST(PhysicsServer2D::JointParam);
VARIANT_ENUM_CAST(PhysicsServer2D::JointType);
+VARIANT_ENUM_CAST(PhysicsServer2D::PinJointParam);
VARIANT_ENUM_CAST(PhysicsServer2D::DampedSpringParam);
VARIANT_ENUM_CAST(PhysicsServer2D::AreaBodyStatus);
VARIANT_ENUM_CAST(PhysicsServer2D::ProcessInfo);
diff --git a/servers/physics_server_2d_wrap_mt.h b/servers/physics_server_2d_wrap_mt.h
index ddb071f603..14a6a5c2a1 100644
--- a/servers/physics_server_2d_wrap_mt.h
+++ b/servers/physics_server_2d_wrap_mt.h
@@ -156,8 +156,11 @@ public:
FUNC2RC(Variant, area_get_param, RID, AreaParameter);
FUNC1RC(Transform2D, area_get_transform, RID);
- FUNC2(area_set_collision_mask, RID, uint32_t);
FUNC2(area_set_collision_layer, RID, uint32_t);
+ FUNC1RC(uint32_t, area_get_collision_layer, RID);
+
+ FUNC2(area_set_collision_mask, RID, uint32_t);
+ FUNC1RC(uint32_t, area_get_collision_mask, RID);
FUNC2(area_set_monitorable, RID, bool);
FUNC2(area_set_pickable, RID, bool);
@@ -205,6 +208,9 @@ public:
FUNC2(body_set_collision_mask, RID, uint32_t);
FUNC1RC(uint32_t, body_get_collision_mask, RID);
+ FUNC2(body_set_collision_priority, RID, real_t);
+ FUNC1RC(real_t, body_get_collision_priority, RID);
+
FUNC3(body_set_param, RID, BodyParameter, const Variant &);
FUNC2RC(Variant, body_get_param, RID, BodyParameter);
@@ -246,7 +252,7 @@ public:
FUNC2(body_set_omit_force_integration, RID, bool);
FUNC1RC(bool, body_is_omitting_force_integration, RID);
- FUNC3(body_set_state_sync_callback, RID, void *, BodyStateCallback);
+ FUNC2(body_set_state_sync_callback, RID, const Callable &);
FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) override {
diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp
index a606d055f7..db21e1db06 100644
--- a/servers/physics_server_3d.cpp
+++ b/servers/physics_server_3d.cpp
@@ -32,6 +32,7 @@
#include "core/config/project_settings.h"
#include "core/string/print_string.h"
+#include "core/variant/typed_array.h"
void PhysicsServer3DRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) {
GDVIRTUAL_REQUIRED_CALL(_set_vertex, p_vertex_id, p_vector3);
@@ -98,6 +99,7 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState3D::get_inverse_mass);
ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState3D::get_inverse_inertia);
+ ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &PhysicsDirectBodyState3D::get_inverse_inertia_tensor);
ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &PhysicsDirectBodyState3D::set_linear_velocity);
ClassDB::bind_method(D_METHOD("get_linear_velocity"), &PhysicsDirectBodyState3D::get_linear_velocity);
@@ -152,6 +154,7 @@ void PhysicsDirectBodyState3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_angular_damp"), "", "get_total_angular_damp");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inverse_inertia"), "", "get_inverse_inertia");
+ ADD_PROPERTY(PropertyInfo(Variant::BASIS, "inverse_inertia_tensor"), "", "get_inverse_inertia_tensor");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "total_gravity"), "", "get_total_gravity");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass"), "", "get_center_of_mass");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass_local"), "", "get_center_of_mass_local");
@@ -184,6 +187,8 @@ Vector<RID> PhysicsRayQueryParameters3D::get_exclude() const {
}
void PhysicsRayQueryParameters3D::_bind_methods() {
+ ClassDB::bind_static_method("PhysicsRayQueryParameters3D", D_METHOD("create", "from", "to", "collision_mask", "exclude"), &PhysicsRayQueryParameters3D::create, DEFVAL(UINT32_MAX), DEFVAL(Vector<RID>()));
+
ClassDB::bind_method(D_METHOD("set_from", "from"), &PhysicsRayQueryParameters3D::set_from);
ClassDB::bind_method(D_METHOD("get_from"), &PhysicsRayQueryParameters3D::get_from);
@@ -220,6 +225,16 @@ void PhysicsRayQueryParameters3D::_bind_methods() {
///////////////////////////////////////////////////////
+Ref<PhysicsRayQueryParameters3D> PhysicsRayQueryParameters3D::create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude) {
+ Ref<PhysicsRayQueryParameters3D> params;
+ params.instantiate();
+ params->set_from(p_from);
+ params->set_to(p_to);
+ params->set_collision_mask(p_mask);
+ params->set_exclude(p_exclude);
+ return params;
+}
+
void PhysicsPointQueryParameters3D::set_exclude(const Vector<RID> &p_exclude) {
parameters.exclude.clear();
for (int i = 0; i < p_exclude.size(); i++) {
@@ -354,8 +369,8 @@ Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Ref<PhysicsRayQueryPa
return d;
}
-Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) {
- ERR_FAIL_COND_V(p_point_query.is_null(), Array());
+TypedArray<Dictionary> PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results) {
+ ERR_FAIL_COND_V(p_point_query.is_null(), TypedArray<Dictionary>());
Vector<ShapeResult> ret;
ret.resize(p_max_results);
@@ -363,10 +378,10 @@ Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryPar
int rc = intersect_point(p_point_query->get_parameters(), ret.ptrw(), ret.size());
if (rc == 0) {
- return Array();
+ return TypedArray<Dictionary>();
}
- Array r;
+ TypedArray<Dictionary> r;
r.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -379,13 +394,13 @@ Array PhysicsDirectSpaceState3D::_intersect_point(const Ref<PhysicsPointQueryPar
return r;
}
-Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+TypedArray<Dictionary> PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), TypedArray<Dictionary>());
Vector<ShapeResult> sr;
sr.resize(p_max_results);
int rc = intersect_shape(p_shape_query->get_parameters(), sr.ptrw(), sr.size());
- Array ret;
+ TypedArray<Dictionary> ret;
ret.resize(rc);
for (int i = 0; i < rc; i++) {
Dictionary d;
@@ -399,22 +414,22 @@ Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref<PhysicsShapeQueryPar
return ret;
}
-Array PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) {
- ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
+Vector<real_t> PhysicsDirectSpaceState3D::_cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query) {
+ ERR_FAIL_COND_V(!p_shape_query.is_valid(), Vector<real_t>());
real_t closest_safe = 1.0f, closest_unsafe = 1.0f;
bool res = cast_motion(p_shape_query->get_parameters(), closest_safe, closest_unsafe);
if (!res) {
- return Array();
+ return Vector<real_t>();
}
- Array ret;
+ Vector<real_t> ret;
ret.resize(2);
- ret[0] = closest_safe;
- ret[1] = closest_unsafe;
+ ret.write[0] = closest_safe;
+ ret.write[1] = closest_unsafe;
return ret;
}
-Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
+TypedArray<PackedVector2Array> PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results) {
ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array());
Vector<Vector3> ret;
@@ -422,9 +437,9 @@ Array PhysicsDirectSpaceState3D::_collide_shape(const Ref<PhysicsShapeQueryParam
int rc = 0;
bool res = collide_shape(p_shape_query->get_parameters(), ret.ptrw(), p_max_results, rc);
if (!res) {
- return Array();
+ return TypedArray<PackedVector2Array>();
}
- Array r;
+ TypedArray<PackedVector2Array> r;
r.resize(rc * 2);
for (int i = 0; i < rc * 2; i++) {
r[i] = ret[i];
@@ -707,7 +722,10 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("area_clear_shapes", "area"), &PhysicsServer3D::area_clear_shapes);
ClassDB::bind_method(D_METHOD("area_set_collision_layer", "area", "layer"), &PhysicsServer3D::area_set_collision_layer);
+ ClassDB::bind_method(D_METHOD("area_get_collision_layer", "area"), &PhysicsServer3D::area_get_collision_layer);
+
ClassDB::bind_method(D_METHOD("area_set_collision_mask", "area", "mask"), &PhysicsServer3D::area_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("area_get_collision_mask", "area"), &PhysicsServer3D::area_get_collision_mask);
ClassDB::bind_method(D_METHOD("area_set_param", "area", "param", "value"), &PhysicsServer3D::area_set_param);
ClassDB::bind_method(D_METHOD("area_set_transform", "area", "transform"), &PhysicsServer3D::area_set_transform);
@@ -738,6 +756,9 @@ void PhysicsServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer3D::body_set_collision_mask);
ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer3D::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_priority", "body", "priority"), &PhysicsServer3D::body_set_collision_priority);
+ ClassDB::bind_method(D_METHOD("body_get_collision_priority", "body"), &PhysicsServer3D::body_get_collision_priority);
+
ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer3D::body_add_shape, DEFVAL(Transform3D()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer3D::body_set_shape);
ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer3D::body_set_shape_transform);
@@ -972,8 +993,8 @@ void PhysicsServer3D::_bind_methods() {
BIND_ENUM_CONSTANT(BODY_MODE_STATIC);
BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC);
- BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID);
+ BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR);
BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE);
BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION);
@@ -1030,9 +1051,7 @@ PhysicsServer3D::~PhysicsServer3D() {
singleton = nullptr;
}
-Vector<PhysicsServer3DManager::ClassInfo> PhysicsServer3DManager::physics_servers;
-int PhysicsServer3DManager::default_server_id = -1;
-int PhysicsServer3DManager::default_server_priority = -1;
+PhysicsServer3DManager *PhysicsServer3DManager::singleton = nullptr;
const String PhysicsServer3DManager::setting_property_name(PNAME("physics/3d/physics_engine"));
void PhysicsServer3DManager::on_servers_changed() {
@@ -1043,10 +1062,19 @@ void PhysicsServer3DManager::on_servers_changed() {
ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2));
}
-void PhysicsServer3DManager::register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback) {
- ERR_FAIL_COND(!p_creat_callback);
+void PhysicsServer3DManager::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("register_server", "name", "create_callback"), &PhysicsServer3DManager::register_server);
+ ClassDB::bind_method(D_METHOD("set_default_server", "name", "priority"), &PhysicsServer3DManager::set_default_server);
+}
+
+PhysicsServer3DManager *PhysicsServer3DManager::get_singleton() {
+ return singleton;
+}
+
+void PhysicsServer3DManager::register_server(const String &p_name, const Callable &p_create_callback) {
+ //ERR_FAIL_COND(!p_create_callback.is_valid());
ERR_FAIL_COND(find_server_id(p_name) != -1);
- physics_servers.push_back(ClassInfo(p_name, p_creat_callback));
+ physics_servers.push_back(ClassInfo(p_name, p_create_callback));
on_servers_changed();
}
@@ -1079,7 +1107,11 @@ String PhysicsServer3DManager::get_server_name(int p_id) {
PhysicsServer3D *PhysicsServer3DManager::new_default_server() {
ERR_FAIL_COND_V(default_server_id == -1, nullptr);
- return physics_servers[default_server_id].create_callback();
+ Variant ret;
+ Callable::CallError ce;
+ physics_servers[default_server_id].create_callback.callp(nullptr, 0, ret, ce);
+ ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
+ return Object::cast_to<PhysicsServer3D>(ret.get_validated_object());
}
PhysicsServer3D *PhysicsServer3DManager::new_server(const String &p_name) {
@@ -1087,6 +1119,18 @@ PhysicsServer3D *PhysicsServer3DManager::new_server(const String &p_name) {
if (id == -1) {
return nullptr;
} else {
- return physics_servers[id].create_callback();
+ Variant ret;
+ Callable::CallError ce;
+ physics_servers[id].create_callback.callp(nullptr, 0, ret, ce);
+ ERR_FAIL_COND_V(ce.error != Callable::CallError::CALL_OK, nullptr);
+ return Object::cast_to<PhysicsServer3D>(ret.get_validated_object());
}
}
+
+PhysicsServer3DManager::PhysicsServer3DManager() {
+ singleton = this;
+}
+
+PhysicsServer3DManager::~PhysicsServer3DManager() {
+ singleton = nullptr;
+}
diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h
index 86a41d96ef..87877ad52d 100644
--- a/servers/physics_server_3d.h
+++ b/servers/physics_server_3d.h
@@ -38,6 +38,8 @@
#include "core/variant/native_ptr.h"
class PhysicsDirectSpaceState3D;
+template <typename T>
+class TypedArray;
class PhysicsDirectBodyState3D : public Object {
GDCLASS(PhysicsDirectBodyState3D, Object);
@@ -120,10 +122,10 @@ class PhysicsDirectSpaceState3D : public Object {
private:
Dictionary _intersect_ray(const Ref<PhysicsRayQueryParameters3D> &p_ray_query);
- Array _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32);
- Array _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
- Array _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
- Array _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_point(const Ref<PhysicsPointQueryParameters3D> &p_point_query, int p_max_results = 32);
+ TypedArray<Dictionary> _intersect_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
+ Vector<real_t> _cast_motion(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
+ TypedArray<PackedVector2Array> _collide_shape(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query, int p_max_results = 32);
Dictionary _get_rest_info(const Ref<PhysicsShapeQueryParameters3D> &p_shape_query);
protected:
@@ -362,8 +364,11 @@ public:
virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const = 0;
virtual Transform3D area_get_transform(RID p_area) const = 0;
- virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0;
virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) = 0;
+ virtual uint32_t area_get_collision_layer(RID p_area) const = 0;
+
+ virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0;
+ virtual uint32_t area_get_collision_mask(RID p_area) const = 0;
virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0;
@@ -379,8 +384,8 @@ public:
enum BodyMode {
BODY_MODE_STATIC,
BODY_MODE_KINEMATIC,
- BODY_MODE_DYNAMIC,
- BODY_MODE_DYNAMIC_LINEAR,
+ BODY_MODE_RIGID,
+ BODY_MODE_RIGID_LINEAR,
};
enum BodyDampMode {
@@ -421,6 +426,9 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0;
virtual uint32_t body_get_collision_mask(RID p_body) const = 0;
+ virtual void body_set_collision_priority(RID p_body, real_t p_priority) = 0;
+ virtual real_t body_get_collision_priority(RID p_body) const = 0;
+
virtual void body_set_user_flags(RID p_body, uint32_t p_flags) = 0;
virtual uint32_t body_get_user_flags(RID p_body) const = 0;
@@ -503,10 +511,7 @@ public:
virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0;
virtual bool body_is_omitting_force_integration(RID p_body) const = 0;
- // Callback for C++ use only.
- typedef void (*BodyStateCallback)(void *p_instance, PhysicsDirectBodyState3D *p_state);
- virtual void body_set_state_sync_callback(RID p_body, void *p_instance, BodyStateCallback p_callback) = 0;
-
+ virtual void body_set_state_sync_callback(RID p_body, const Callable &p_callable) = 0;
virtual void body_set_force_integration_callback(RID p_body, const Callable &p_callable, const Variant &p_udata = Variant()) = 0;
virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0;
@@ -550,6 +555,7 @@ public:
struct MotionResult {
Vector3 travel;
Vector3 remainder;
+ real_t collision_depth = 0.0;
real_t collision_safe_fraction = 0.0;
real_t collision_unsafe_fraction = 0.0;
@@ -816,6 +822,7 @@ protected:
static void _bind_methods();
public:
+ static Ref<PhysicsRayQueryParameters3D> create(Vector3 p_from, Vector3 p_to, uint32_t p_mask, const Vector<RID> &p_exclude);
const PhysicsDirectSpaceState3D::RayParameters &get_parameters() const { return parameters; }
void set_from(const Vector3 &p_from) { parameters.from = p_from; }
@@ -976,16 +983,18 @@ public:
real_t get_collision_depth(int p_collision_index = 0) const;
};
-typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)();
+class PhysicsServer3DManager : public Object {
+ GDCLASS(PhysicsServer3DManager, Object);
+
+ static PhysicsServer3DManager *singleton;
-class PhysicsServer3DManager {
struct ClassInfo {
String name;
- CreatePhysicsServer3DCallback create_callback = nullptr;
+ Callable create_callback;
ClassInfo() {}
- ClassInfo(String p_name, CreatePhysicsServer3DCallback p_create_callback) :
+ ClassInfo(String p_name, Callable p_create_callback) :
name(p_name),
create_callback(p_create_callback) {}
@@ -999,24 +1008,30 @@ class PhysicsServer3DManager {
}
};
- static Vector<ClassInfo> physics_servers;
- static int default_server_id;
- static int default_server_priority;
+ Vector<ClassInfo> physics_servers;
+ int default_server_id = -1;
+ int default_server_priority = -1;
+
+ void on_servers_changed();
+
+protected:
+ static void _bind_methods();
public:
static const String setting_property_name;
-private:
- static void on_servers_changed();
+ static PhysicsServer3DManager *get_singleton();
-public:
- static void register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback);
- static void set_default_server(const String &p_name, int p_priority = 0);
- static int find_server_id(const String &p_name);
- static int get_servers_count();
- static String get_server_name(int p_id);
- static PhysicsServer3D *new_default_server();
- static PhysicsServer3D *new_server(const String &p_name);
+ void register_server(const String &p_name, const Callable &p_create_callback);
+ void set_default_server(const String &p_name, int p_priority = 0);
+ int find_server_id(const String &p_name);
+ int get_servers_count();
+ String get_server_name(int p_id);
+ PhysicsServer3D *new_default_server();
+ PhysicsServer3D *new_server(const String &p_name);
+
+ PhysicsServer3DManager();
+ ~PhysicsServer3DManager();
};
VARIANT_ENUM_CAST(PhysicsServer3D::ShapeType);
diff --git a/servers/physics_server_3d_wrap_mt.h b/servers/physics_server_3d_wrap_mt.h
index d4a4ad3132..1d5fa95bfb 100644
--- a/servers/physics_server_3d_wrap_mt.h
+++ b/servers/physics_server_3d_wrap_mt.h
@@ -157,8 +157,11 @@ public:
FUNC2RC(Variant, area_get_param, RID, AreaParameter);
FUNC1RC(Transform3D, area_get_transform, RID);
- FUNC2(area_set_collision_mask, RID, uint32_t);
FUNC2(area_set_collision_layer, RID, uint32_t);
+ FUNC1RC(uint32_t, area_get_collision_layer, RID);
+
+ FUNC2(area_set_collision_mask, RID, uint32_t);
+ FUNC1RC(uint32_t, area_get_collision_mask, RID);
FUNC2(area_set_monitorable, RID, bool);
FUNC2(area_set_ray_pickable, RID, bool);
@@ -202,6 +205,9 @@ public:
FUNC2(body_set_collision_mask, RID, uint32_t);
FUNC1RC(uint32_t, body_get_collision_mask, RID);
+ FUNC2(body_set_collision_priority, RID, real_t);
+ FUNC1RC(real_t, body_get_collision_priority, RID);
+
FUNC2(body_set_user_flags, RID, uint32_t);
FUNC1RC(uint32_t, body_get_user_flags, RID);
@@ -249,7 +255,7 @@ public:
FUNC2(body_set_omit_force_integration, RID, bool);
FUNC1RC(bool, body_is_omitting_force_integration, RID);
- FUNC3(body_set_state_sync_callback, RID, void *, BodyStateCallback);
+ FUNC2(body_set_state_sync_callback, RID, const Callable &);
FUNC3(body_set_force_integration_callback, RID, const Callable &, const Variant &);
FUNC2(body_set_ray_pickable, RID, bool);
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 8bbe987cb7..1356fedb82 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -57,6 +57,9 @@
#include "camera_server.h"
#include "debugger/servers_debugger.h"
#include "display_server.h"
+#include "movie_writer/movie_writer.h"
+#include "movie_writer/movie_writer_mjpeg.h"
+#include "movie_writer/movie_writer_pngwav.h"
#include "navigation_server_2d.h"
#include "navigation_server_3d.h"
#include "physics_2d/godot_physics_server_2d.h"
@@ -69,6 +72,7 @@
#include "rendering/rendering_device.h"
#include "rendering/rendering_device_binds.h"
#include "rendering_server.h"
+#include "servers/extensions/physics_server_2d_extension.h"
#include "servers/extensions/physics_server_3d_extension.h"
#include "servers/rendering/shader_types.h"
#include "text/text_server_dummy.h"
@@ -81,7 +85,7 @@
ShaderTypes *shader_types = nullptr;
-PhysicsServer3D *_createGodotPhysics3DCallback() {
+static PhysicsServer3D *_createGodotPhysics3DCallback() {
bool using_threads = GLOBAL_GET("physics/3d/run_on_separate_thread");
PhysicsServer3D *physics_server_3d = memnew(GodotPhysicsServer3D(using_threads));
@@ -89,7 +93,7 @@ PhysicsServer3D *_createGodotPhysics3DCallback() {
return memnew(PhysicsServer3DWrapMT(physics_server_3d, using_threads));
}
-PhysicsServer2D *_createGodotPhysics2DCallback() {
+static PhysicsServer2D *_createGodotPhysics2DCallback() {
bool using_threads = GLOBAL_GET("physics/2d/run_on_separate_thread");
PhysicsServer2D *physics_server_2d = memnew(GodotPhysicsServer2D(using_threads));
@@ -107,6 +111,9 @@ static bool has_server_feature_callback(const String &p_feature) {
return false;
}
+static MovieWriterMJPEG *writer_mjpeg = nullptr;
+static MovieWriterPNGWAV *writer_pngwav = nullptr;
+
void register_server_types() {
shader_types = memnew(ShaderTypes);
@@ -126,7 +133,22 @@ void register_server_types() {
GDREGISTER_ABSTRACT_CLASS(RenderingServer);
GDREGISTER_CLASS(AudioServer);
+ GDREGISTER_CLASS(PhysicsServer2DManager);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2DManager", PhysicsServer2DManager::get_singleton(), "PhysicsServer2DManager"));
+
GDREGISTER_ABSTRACT_CLASS(PhysicsServer2D);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsServer2DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState2DExtension);
+ GDREGISTER_VIRTUAL_CLASS(PhysicsDirectSpaceState2DExtension);
+
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionRayResult, "Vector2 position;Vector2 normal;RID rid;ObjectID collider_id;Object *collider;int shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeResult, "RID rid;ObjectID collider_id;Object *collider;int shape");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionShapeRestInfo, "Vector2 point;Vector2 normal;RID rid;ObjectID collider_id;int shape;Vector2 linear_velocity");
+ GDREGISTER_NATIVE_STRUCT(PhysicsServer2DExtensionMotionResult, "Vector2 travel;Vector2 remainder;Vector2 collision_point;Vector2 collision_normal;Vector2 collider_velocity;real_t collision_depth;real_t collision_safe_fraction;real_t collision_unsafe_fraction;int collision_local_shape;ObjectID collider_id;RID collider;int collider_shape");
+
+ GDREGISTER_CLASS(PhysicsServer3DManager);
+ Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3DManager", PhysicsServer3DManager::get_singleton(), "PhysicsServer3DManager"));
+
GDREGISTER_ABSTRACT_CLASS(PhysicsServer3D);
GDREGISTER_VIRTUAL_CLASS(PhysicsServer3DExtension);
GDREGISTER_VIRTUAL_CLASS(PhysicsDirectBodyState3DExtension);
@@ -138,10 +160,14 @@ void register_server_types() {
GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionShapeRestInfo, "Vector3 point;Vector3 normal;RID rid;ObjectID collider_id;int shape;Vector3 linear_velocity");
GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionCollision, "Vector3 position;Vector3 normal;Vector3 collider_velocity;real_t depth;int local_shape;ObjectID collider_id;RID collider;int collider_shape");
GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionMotionResult, "Vector3 travel;Vector3 remainder;real_t collision_safe_fraction;real_t collision_unsafe_fraction;PhysicsServer3DExtensionMotionCollision collisions[32];int collision_count");
- GDREGISTER_NATIVE_STRUCT(PhysicsServer3DExtensionStateCallback, "void *instance;void (*callback)(void *p_instance, PhysicsDirectBodyState3D *p_state)");
GDREGISTER_ABSTRACT_CLASS(NavigationServer2D);
GDREGISTER_ABSTRACT_CLASS(NavigationServer3D);
+ GDREGISTER_CLASS(NavigationPathQueryParameters2D);
+ GDREGISTER_CLASS(NavigationPathQueryParameters3D);
+ GDREGISTER_CLASS(NavigationPathQueryResult2D);
+ GDREGISTER_CLASS(NavigationPathQueryResult3D);
+
GDREGISTER_CLASS(XRServer);
GDREGISTER_CLASS(CameraServer);
@@ -239,26 +265,36 @@ void register_server_types() {
GDREGISTER_CLASS(PhysicsTestMotionParameters3D);
GDREGISTER_CLASS(PhysicsTestMotionResult3D);
+ GDREGISTER_VIRTUAL_CLASS(MovieWriter);
+
ServersDebugger::initialize();
// Physics 2D
GLOBAL_DEF(PhysicsServer2DManager::setting_property_name, "DEFAULT");
ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer2DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer2DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"));
- PhysicsServer2DManager::register_server("GodotPhysics2D", &_createGodotPhysics2DCallback);
- PhysicsServer2DManager::set_default_server("GodotPhysics2D");
+ PhysicsServer2DManager::get_singleton()->register_server("GodotPhysics2D", callable_mp_static(_createGodotPhysics2DCallback));
+ PhysicsServer2DManager::get_singleton()->set_default_server("GodotPhysics2D");
// Physics 3D
GLOBAL_DEF(PhysicsServer3DManager::setting_property_name, "DEFAULT");
ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer3DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer3DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT"));
- PhysicsServer3DManager::register_server("GodotPhysics3D", &_createGodotPhysics3DCallback);
- PhysicsServer3DManager::set_default_server("GodotPhysics3D");
+ PhysicsServer3DManager::get_singleton()->register_server("GodotPhysics3D", callable_mp_static(_createGodotPhysics3DCallback));
+ PhysicsServer3DManager::get_singleton()->set_default_server("GodotPhysics3D");
+
+ writer_mjpeg = memnew(MovieWriterMJPEG);
+ MovieWriter::add_writer(writer_mjpeg);
+
+ writer_pngwav = memnew(MovieWriterPNGWAV);
+ MovieWriter::add_writer(writer_pngwav);
}
void unregister_server_types() {
ServersDebugger::deinitialize();
memdelete(shader_types);
+ memdelete(writer_mjpeg);
+ memdelete(writer_pngwav);
}
void register_server_singletons() {
diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub
index 06d1d28b08..cf26ca029d 100644
--- a/servers/rendering/SCsub
+++ b/servers/rendering/SCsub
@@ -4,5 +4,6 @@ Import("env")
env.add_source_files(env.servers_sources, "*.cpp")
+SConscript("dummy/SCsub")
SConscript("renderer_rd/SCsub")
SConscript("storage/SCsub")
diff --git a/servers/rendering/dummy/SCsub b/servers/rendering/dummy/SCsub
new file mode 100644
index 0000000000..aa688af6cd
--- /dev/null
+++ b/servers/rendering/dummy/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
+
+SConscript("storage/SCsub")
diff --git a/servers/rendering/dummy/environment/fog.h b/servers/rendering/dummy/environment/fog.h
new file mode 100644
index 0000000000..047b8e133d
--- /dev/null
+++ b/servers/rendering/dummy/environment/fog.h
@@ -0,0 +1,55 @@
+/*************************************************************************/
+/* fog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef FOG_DUMMY_H
+#define FOG_DUMMY_H
+
+#include "servers/rendering/environment/renderer_fog.h"
+
+namespace RendererDummy {
+
+class Fog : public RendererFog {
+public:
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate() override { return RID(); }
+ virtual void fog_volume_initialize(RID p_rid) override {}
+ virtual void fog_volume_free(RID p_rid) override {}
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
+};
+
+} // namespace RendererDummy
+
+#endif // FOG_DUMMY_H
diff --git a/servers/rendering/dummy/environment/gi.h b/servers/rendering/dummy/environment/gi.h
new file mode 100644
index 0000000000..fea7994cfe
--- /dev/null
+++ b/servers/rendering/dummy/environment/gi.h
@@ -0,0 +1,85 @@
+/*************************************************************************/
+/* gi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef GI_DUMMY_H
+#define GI_DUMMY_H
+
+#include "servers/rendering/environment/renderer_gi.h"
+
+namespace RendererDummy {
+
+class GI : public RendererGI {
+public:
+ /* VOXEL GI API */
+
+ virtual RID voxel_gi_allocate() override { return RID(); }
+ virtual void voxel_gi_free(RID p_rid) override {}
+ virtual void voxel_gi_initialize(RID p_rid) override {}
+ virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {}
+
+ virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); }
+ virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); }
+ virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+ virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+ virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
+
+ virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector<int>(); }
+ virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); }
+
+ virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {}
+ virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; }
+
+ virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {}
+ virtual float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; }
+
+ virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {}
+ virtual float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; }
+
+ virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) override {}
+ virtual float voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const override { return 1.0; }
+
+ virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {}
+ virtual float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; }
+
+ virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {}
+ virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; }
+
+ virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {}
+ virtual bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; }
+
+ virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {}
+ virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
+
+ virtual uint32_t voxel_gi_get_version(RID p_voxel_gi) const override { return 0; }
+};
+
+} // namespace RendererDummy
+
+#endif // GI_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_canvas_dummy.h b/servers/rendering/dummy/rasterizer_canvas_dummy.h
index 194b5b5cfe..65c64e8115 100644
--- a/servers/rendering/dummy/rasterizer_canvas_dummy.h
+++ b/servers/rendering/dummy/rasterizer_canvas_dummy.h
@@ -39,7 +39,6 @@ public:
void free_polygon(PolygonID p_polygon) override {}
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override {}
- void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) override {}
RID light_create() override { return RID(); }
void light_set_texture(RID p_rid, RID p_texture) override {}
@@ -60,4 +59,4 @@ public:
~RasterizerCanvasDummy() {}
};
-#endif // !RASTERIZER_CANVAS_DUMMY_H
+#endif // RASTERIZER_CANVAS_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_dummy.h b/servers/rendering/dummy/rasterizer_dummy.h
index 5c6fcc8386..0fde97e395 100644
--- a/servers/rendering/dummy/rasterizer_dummy.h
+++ b/servers/rendering/dummy/rasterizer_dummy.h
@@ -34,14 +34,16 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "scene/resources/mesh.h"
+#include "servers/rendering/dummy/environment/fog.h"
+#include "servers/rendering/dummy/environment/gi.h"
#include "servers/rendering/dummy/rasterizer_canvas_dummy.h"
#include "servers/rendering/dummy/rasterizer_scene_dummy.h"
-#include "servers/rendering/dummy/rasterizer_storage_dummy.h"
#include "servers/rendering/dummy/storage/light_storage.h"
#include "servers/rendering/dummy/storage/material_storage.h"
#include "servers/rendering/dummy/storage/mesh_storage.h"
#include "servers/rendering/dummy/storage/particles_storage.h"
#include "servers/rendering/dummy/storage/texture_storage.h"
+#include "servers/rendering/dummy/storage/utilities.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering_server.h"
@@ -49,24 +51,29 @@ class RasterizerDummy : public RendererCompositor {
private:
uint64_t frame = 1;
double delta = 0;
+ double time = 0.0;
protected:
RasterizerCanvasDummy canvas;
+ RendererDummy::Utilities utilities;
RendererDummy::LightStorage light_storage;
RendererDummy::MaterialStorage material_storage;
RendererDummy::MeshStorage mesh_storage;
RendererDummy::ParticlesStorage particles_storage;
RendererDummy::TextureStorage texture_storage;
- RasterizerStorageDummy storage;
+ RendererDummy::GI gi;
+ RendererDummy::Fog fog;
RasterizerSceneDummy scene;
public:
+ RendererUtilities *get_utilities() override { return &utilities; };
RendererLightStorage *get_light_storage() override { return &light_storage; };
RendererMaterialStorage *get_material_storage() override { return &material_storage; };
RendererMeshStorage *get_mesh_storage() override { return &mesh_storage; };
RendererParticlesStorage *get_particles_storage() override { return &particles_storage; };
RendererTextureStorage *get_texture_storage() override { return &texture_storage; };
- RendererStorage *get_storage() override { return &storage; }
+ RendererGI *get_gi() override { return &gi; };
+ RendererFog *get_fog() override { return &fog; };
RendererCanvasRender *get_canvas() override { return &canvas; }
RendererSceneRender *get_scene() override { return &scene; }
@@ -76,6 +83,7 @@ public:
void begin_frame(double frame_step) override {
frame++;
delta = frame_step;
+ time += frame_step;
}
void prepare_for_blitting_render_targets() override {}
@@ -100,6 +108,7 @@ public:
uint64_t get_frame_number() const override { return frame; }
double get_frame_delta_time() const override { return delta; }
+ double get_total_time() const override { return time; }
RasterizerDummy() {}
~RasterizerDummy() {}
diff --git a/servers/rendering/dummy/rasterizer_scene_dummy.h b/servers/rendering/dummy/rasterizer_scene_dummy.h
index e6d2b93f99..bc8f7c523b 100644
--- a/servers/rendering/dummy/rasterizer_scene_dummy.h
+++ b/servers/rendering/dummy/rasterizer_scene_dummy.h
@@ -31,55 +31,74 @@
#ifndef RASTERIZER_SCENE_DUMMY_H
#define RASTERIZER_SCENE_DUMMY_H
+#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_scene_render.h"
+#include "storage/utilities.h"
class RasterizerSceneDummy : public RendererSceneRender {
public:
- GeometryInstance *geometry_instance_create(RID p_base) override { return nullptr; }
- void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override {}
- void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override {}
- void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) override {}
- void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override {}
- void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override {}
- void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override {}
- void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override {}
- void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
- void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override {}
- void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override {}
- void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override {}
- void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
- void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override {}
- void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override {}
+ class GeometryInstanceDummy : public RenderGeometryInstance {
+ public:
+ GeometryInstanceDummy() {}
+
+ virtual void _mark_dirty() override {}
+
+ virtual void set_skeleton(RID p_skeleton) override {}
+ virtual void set_material_override(RID p_override) override {}
+ virtual void set_material_overlay(RID p_overlay) override {}
+ virtual void set_surface_materials(const Vector<RID> &p_materials) override {}
+ virtual void set_mesh_instance(RID p_mesh_instance) override {}
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override {}
+ virtual void set_lod_bias(float p_lod_bias) override {}
+ virtual void set_layer_mask(uint32_t p_layer_mask) override {}
+ virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override {}
+ virtual void set_parent_fade_alpha(float p_alpha) override {}
+ virtual void set_transparency(float p_transparency) override {}
+ virtual void set_use_baked_light(bool p_enable) override {}
+ virtual void set_use_dynamic_gi(bool p_enable) override {}
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override {}
+ virtual void set_lightmap_capture(const Color *p_sh9) override {}
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) override {}
+ virtual void set_cast_double_sided_shadows(bool p_enable) override {}
+
+ virtual Transform3D get_transform() override { return Transform3D(); }
+ virtual AABB get_aabb() override { return AABB(); }
+
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override {}
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
+
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override {}
+ };
+
+ PagedAllocator<GeometryInstanceDummy> geometry_instance_alloc;
- uint32_t geometry_instance_get_pair_mask() override { return 0; }
- void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override {}
- void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
- void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
- void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
- void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override {}
+public:
+ RenderGeometryInstance *geometry_instance_create(RID p_base) override {
+ RS::InstanceType type = RendererDummy::Utilities::get_singleton()->get_base_type(p_base);
+ ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
- void geometry_instance_free(GeometryInstance *p_geometry_instance) override {}
+ GeometryInstanceDummy *ginstance = geometry_instance_alloc.alloc();
- /* SHADOW ATLAS API */
+ return ginstance;
+ }
- RID shadow_atlas_create() override { return RID(); }
- void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {}
- void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
- bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
+ void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override {
+ GeometryInstanceDummy *ginstance = static_cast<GeometryInstanceDummy *>(p_geometry_instance);
+ ERR_FAIL_COND(!ginstance);
- void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {}
- int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
- void set_directional_shadow_count(int p_count) override {}
+ geometry_instance_alloc.free(ginstance);
+ }
+
+ uint32_t geometry_instance_get_pair_mask() override { return 0; }
/* SDFGI UPDATE */
- void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
- int sdfgi_get_pending_region_count(RID p_render_buffers) const override { return 0; }
- AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override { return AABB(); }
- uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override { return 0; }
+ void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override {}
+ int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override { return 0; }
+ AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return AABB(); }
+ uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override { return 0; }
/* SKY API */
@@ -92,65 +111,26 @@ public:
/* ENVIRONMENT API */
- RID environment_allocate() override { return RID(); }
- void environment_initialize(RID p_rid) override {}
- void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override {}
- void environment_set_sky(RID p_env, RID p_sky) override {}
- void environment_set_sky_custom_fov(RID p_env, float p_scale) override {}
- void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override {}
- void environment_set_bg_color(RID p_env, const Color &p_color) override {}
- void environment_set_bg_energy(RID p_env, float p_energy) override {}
- void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override {}
- void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override {}
-
- void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override {}
void environment_glow_set_use_bicubic_upscale(bool p_enable) override {}
void environment_glow_set_use_high_quality(bool p_enable) override {}
- void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override {}
void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override {}
- void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override {}
+
void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
- void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override {}
- void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
- void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override {}
+ void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override {}
void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override {}
void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override {}
void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override {}
- void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override {}
-
- void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override {}
-
- void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override {}
- void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override {}
void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override {}
void environment_set_volumetric_fog_filter_active(bool p_enable) override {}
Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override { return Ref<Image>(); }
- bool is_environment(RID p_env) const override { return false; }
- RS::EnvironmentBG environment_get_background(RID p_env) const override { return RS::ENV_BG_KEEP; }
- int environment_get_canvas_max_layer(RID p_env) const override { return 0; }
-
- RID camera_effects_allocate() override { return RID(); }
- void camera_effects_initialize(RID p_rid) override {}
- void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override {}
- void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override {}
-
- void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override {}
- void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override {}
-
- void shadows_quality_set(RS::ShadowQuality p_quality) override {}
- void directional_shadow_quality_set(RS::ShadowQuality p_quality) override {}
-
- RID light_instance_create(RID p_light) override { return RID(); }
- void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
- void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
- void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
- void light_instance_mark_visible(RID p_light_instance) override {}
+ void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {}
+ void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override {}
RID fog_volume_instance_create(RID p_fog_volume) override { return RID(); }
void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override {}
@@ -158,41 +138,22 @@ public:
RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override { return RID(); }
Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override { return Vector3(); }
- RID reflection_atlas_create() override { return RID(); }
- int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
- void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
-
- RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
- void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
- void reflection_probe_release_atlas_index(RID p_instance) override {}
- bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
- bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
- bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
- bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
-
- RID decal_instance_create(RID p_decal) override { return RID(); }
- void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
-
- RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
- void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}
-
RID voxel_gi_instance_create(RID p_voxel_gi) override { return RID(); }
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override {}
bool voxel_gi_needs_update(RID p_probe) const override { return false; }
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override {}
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override {}
void voxel_gi_set_quality(RS::VoxelGIQuality) override {}
- void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_info = nullptr) override {}
- void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
- void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override {}
+ void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RenderingMethod::RenderInfo *r_info = nullptr) override {}
+ void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override {}
+ void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override {}
void set_scene_pass(uint64_t p_pass) override {}
void set_time(double p_time, double p_step) override {}
void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) override {}
- RID render_buffers_create() override { return RID(); }
- void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override {}
+ Ref<RenderSceneBuffers> render_buffers_create() override { return Ref<RenderSceneBuffers>(); }
void gi_set_use_half_resolution(bool p_enable) override {}
void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_curve) override {}
@@ -201,9 +162,19 @@ public:
void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override {}
void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override {}
- TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
-
- bool free(RID p_rid) override { return false; }
+ TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) override { return TypedArray<Image>(); }
+
+ bool free(RID p_rid) override {
+ if (is_environment(p_rid)) {
+ environment_free(p_rid);
+ return true;
+ } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
+ RSG::camera_attributes->camera_attributes_free(p_rid);
+ return true;
+ } else {
+ return false;
+ }
+ }
void update() override {}
void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override {}
@@ -214,4 +185,4 @@ public:
~RasterizerSceneDummy() {}
};
-#endif // !RASTERIZER_SCENE_DUMMY_H
+#endif // RASTERIZER_SCENE_DUMMY_H
diff --git a/servers/rendering/dummy/rasterizer_storage_dummy.h b/servers/rendering/dummy/rasterizer_storage_dummy.h
deleted file mode 100644
index 596960786a..0000000000
--- a/servers/rendering/dummy/rasterizer_storage_dummy.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*************************************************************************/
-/* rasterizer_storage_dummy.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#ifndef RASTERIZER_STORAGE_DUMMY_H
-#define RASTERIZER_STORAGE_DUMMY_H
-
-#include "servers/rendering/renderer_storage.h"
-#include "storage/texture_storage.h"
-
-class RasterizerStorageDummy : public RendererStorage {
-public:
- void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
-
- /* VOXEL GI API */
-
- RID voxel_gi_allocate() override { return RID(); }
- void voxel_gi_initialize(RID p_rid) override {}
- void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override {}
-
- AABB voxel_gi_get_bounds(RID p_voxel_gi) const override { return AABB(); }
- Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override { return Vector3i(); }
- Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
- Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
- Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override { return Vector<uint8_t>(); }
-
- Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override { return Vector<int>(); }
- Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override { return Transform3D(); }
-
- void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override { return 0; }
-
- void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_propagation(RID p_voxel_gi) const override { return 0; }
-
- void voxel_gi_set_energy(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_energy(RID p_voxel_gi) const override { return 0.0; }
-
- void voxel_gi_set_bias(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_bias(RID p_voxel_gi) const override { return 0.0; }
-
- void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override {}
- float voxel_gi_get_normal_bias(RID p_voxel_gi) const override { return 0.0; }
-
- void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override {}
- bool voxel_gi_is_interior(RID p_voxel_gi) const override { return false; }
-
- void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override {}
- bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override { return false; }
-
- void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) override {}
- float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const override { return 0; }
-
- uint32_t voxel_gi_get_version(RID p_voxel_gi) override { return 0; }
-
- /* OCCLUDER */
-
- void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
-
- /* FOG VOLUMES */
-
- RID fog_volume_allocate() override { return RID(); }
- void fog_volume_initialize(RID p_rid) override {}
-
- void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override {}
- void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override {}
- void fog_volume_set_material(RID p_fog_volume, RID p_material) override {}
- AABB fog_volume_get_aabb(RID p_fog_volume) const override { return AABB(); }
- RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override { return RS::FOG_VOLUME_SHAPE_BOX; }
-
- /* VISIBILITY NOTIFIER */
- virtual RID visibility_notifier_allocate() override { return RID(); }
- virtual void visibility_notifier_initialize(RID p_notifier) override {}
- virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
- virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
-
- virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
- virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
-
- /* STORAGE */
-
- RS::InstanceType get_base_type(RID p_rid) const override { return RS::INSTANCE_NONE; }
- bool free(RID p_rid) override {
- if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) {
- RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid);
- return true;
- }
- return false;
- }
-
- virtual void update_memory_info() override {}
- virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
-
- bool has_os_feature(const String &p_feature) const override {
- return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2";
- }
-
- void update_dirty_resources() override {}
-
- void set_debug_generate_wireframes(bool p_generate) override {}
-
- String get_video_adapter_name() const override { return String(); }
- String get_video_adapter_vendor() const override { return String(); }
- RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
- String get_video_adapter_api_version() const override { return String(); }
-
- static RendererStorage *base_singleton;
-
- void capture_timestamps_begin() override {}
- void capture_timestamp(const String &p_name) override {}
- uint32_t get_captured_timestamps_count() const override { return 0; }
- uint64_t get_captured_timestamps_frame() const override { return 0; }
- uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
- uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
- String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
-
- RasterizerStorageDummy() {}
- ~RasterizerStorageDummy() {}
-};
-
-#endif // !RASTERIZER_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/SCsub b/servers/rendering/dummy/storage/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/rendering/dummy/storage/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/rendering/dummy/storage/light_storage.h b/servers/rendering/dummy/storage/light_storage.h
index b0100a5fe7..13c342d823 100644
--- a/servers/rendering/dummy/storage/light_storage.h
+++ b/servers/rendering/dummy/storage/light_storage.h
@@ -81,6 +81,15 @@ public:
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override { return 0; }
virtual uint64_t light_get_version(RID p_light) const override { return 0; }
+ /* LIGHT INSTANCE API */
+
+ RID light_instance_create(RID p_light) override { return RID(); }
+ void light_instance_free(RID p_light) override {}
+ void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override {}
+ void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override {}
+ void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override {}
+ void light_instance_mark_visible(RID p_light_instance) override {}
+
/* PROBE API */
virtual RID reflection_probe_allocate() override { return RID(); }
virtual void reflection_probe_initialize(RID p_rid) override {}
@@ -110,7 +119,26 @@ public:
virtual float reflection_probe_get_origin_max_distance(RID p_probe) const override { return 0.0; }
virtual bool reflection_probe_renders_shadows(RID p_probe) const override { return false; }
+ /* REFLECTION ATLAS */
+
+ virtual RID reflection_atlas_create() override { return RID(); }
+ virtual void reflection_atlas_free(RID p_ref_atlas) override {}
+ virtual int reflection_atlas_get_size(RID p_ref_atlas) const override { return 0; }
+ virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override {}
+
+ /* REFLECTION PROBE INSTANCE */
+
+ virtual RID reflection_probe_instance_create(RID p_probe) override { return RID(); }
+ virtual void reflection_probe_instance_free(RID p_instance) override {}
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override {}
+ virtual void reflection_probe_release_atlas_index(RID p_instance) override {}
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override { return false; }
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance) override { return false; }
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override { return false; }
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override { return true; }
+
/* LIGHTMAP CAPTURE */
+
virtual RID lightmap_allocate() override { return RID(); }
virtual void lightmap_initialize(RID p_rid) override {}
virtual void lightmap_free(RID p_rid) override {}
@@ -119,6 +147,7 @@ public:
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override {}
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override {}
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override {}
+ virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) override {}
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override { return PackedVector3Array(); }
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override { return PackedColorArray(); }
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override { return PackedInt32Array(); }
@@ -128,8 +157,27 @@ public:
virtual bool lightmap_is_interior(RID p_lightmap) const override { return false; }
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override {}
virtual float lightmap_get_probe_capture_update_speed() const override { return 0; }
+
+ /* LIGHTMAP INSTANCE */
+
+ RID lightmap_instance_create(RID p_lightmap) override { return RID(); }
+ void lightmap_instance_free(RID p_lightmap) override {}
+ void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override {}
+
+ /* SHADOW ATLAS API */
+ virtual RID shadow_atlas_create() override { return RID(); }
+ virtual void shadow_atlas_free(RID p_atlas) override {}
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override {}
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override {}
+ virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) override { return false; }
+
+ virtual void shadow_atlas_update(RID p_atlas) override {}
+
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override {}
+ virtual int get_directional_light_shadow_size(RID p_light_intance) override { return 0; }
+ virtual void set_directional_shadow_count(int p_count) override {}
};
} // namespace RendererDummy
-#endif // !LIGHT_STORAGE_DUMMY_H
+#endif // LIGHT_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/material_storage.h b/servers/rendering/dummy/storage/material_storage.h
index 8890be8ea9..b4e0a21ee1 100644
--- a/servers/rendering/dummy/storage/material_storage.h
+++ b/servers/rendering/dummy/storage/material_storage.h
@@ -32,28 +32,29 @@
#define MATERIAL_STORAGE_DUMMY_H
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererDummy {
class MaterialStorage : public RendererMaterialStorage {
public:
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override {}
- virtual void global_variable_remove(const StringName &p_name) override {}
- virtual Vector<StringName> global_variable_get_list() const override { return Vector<StringName>(); }
+ virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) override {}
+ virtual void global_shader_parameter_remove(const StringName &p_name) override {}
+ virtual Vector<StringName> global_shader_parameter_get_list() const override { return Vector<StringName>(); }
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override {}
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override {}
- virtual Variant global_variable_get(const StringName &p_name) const override { return Variant(); }
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
+ virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) override {}
+ virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) override {}
+ virtual Variant global_shader_parameter_get(const StringName &p_name) const override { return Variant(); }
+ virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const override { return RS::GLOBAL_VAR_TYPE_MAX; }
- virtual void global_variables_load_settings(bool p_load_textures = true) override {}
- virtual void global_variables_clear() override {}
+ virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override {}
+ virtual void global_shader_parameters_clear() override {}
- virtual int32_t global_variables_instance_allocate(RID p_instance) override { return 0; }
- virtual void global_variables_instance_free(RID p_instance) override {}
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override {}
+ virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override { return 0; }
+ virtual void global_shader_parameters_instance_free(RID p_instance) override {}
+ virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) override {}
/* SHADER API */
@@ -62,12 +63,14 @@ public:
virtual void shader_free(RID p_rid) override{};
virtual void shader_set_code(RID p_shader, const String &p_code) override {}
+ virtual void shader_set_path_hint(RID p_shader, const String &p_code) override {}
+
virtual String shader_get_code(RID p_shader) const override { return ""; }
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
+ virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const override {}
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
- virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const override { return Variant(); }
+ virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override {}
+ virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override { return RID(); }
+ virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const override { return Variant(); }
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override { return RS::ShaderNativeSourceCode(); };
@@ -87,9 +90,9 @@ public:
virtual bool material_is_animated(RID p_material) override { return false; }
virtual bool material_casts_shadows(RID p_material) override { return false; }
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override {}
- virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override {}
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override {}
};
} // namespace RendererDummy
-#endif // !MATERIAL_STORAGE_DUMMY_H
+#endif // MATERIAL_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/mesh_storage.cpp b/servers/rendering/dummy/storage/mesh_storage.cpp
new file mode 100644
index 0000000000..adf736eee3
--- /dev/null
+++ b/servers/rendering/dummy/storage/mesh_storage.cpp
@@ -0,0 +1,58 @@
+/*************************************************************************/
+/* mesh_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "mesh_storage.h"
+
+using namespace RendererDummy;
+
+MeshStorage *MeshStorage::singleton = nullptr;
+
+MeshStorage::MeshStorage() {
+ singleton = this;
+}
+
+MeshStorage::~MeshStorage() {
+ singleton = nullptr;
+}
+
+RID MeshStorage::mesh_allocate() {
+ return mesh_owner.allocate_rid();
+}
+
+void MeshStorage::mesh_initialize(RID p_rid) {
+ mesh_owner.initialize_rid(p_rid, DummyMesh());
+}
+
+void MeshStorage::mesh_free(RID p_rid) {
+ DummyMesh *mesh = mesh_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!mesh);
+
+ mesh_owner.free(p_rid);
+}
diff --git a/servers/rendering/dummy/storage/mesh_storage.h b/servers/rendering/dummy/storage/mesh_storage.h
index dfbd265bba..4399f4ab66 100644
--- a/servers/rendering/dummy/storage/mesh_storage.h
+++ b/servers/rendering/dummy/storage/mesh_storage.h
@@ -31,22 +31,59 @@
#ifndef MESH_STORAGE_DUMMY_H
#define MESH_STORAGE_DUMMY_H
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
#include "servers/rendering/storage/mesh_storage.h"
namespace RendererDummy {
class MeshStorage : public RendererMeshStorage {
+private:
+ static MeshStorage *singleton;
+
+ struct DummyMesh {
+ Vector<RS::SurfaceData> surfaces;
+ int blend_shape_count;
+ RS::BlendShapeMode blend_shape_mode;
+ PackedFloat32Array blend_shape_values;
+ };
+
+ mutable RID_Owner<DummyMesh> mesh_owner;
+
public:
+ static MeshStorage *get_singleton() {
+ return singleton;
+ };
+
+ MeshStorage();
+ ~MeshStorage();
+
/* MESH API */
- virtual RID mesh_allocate() override { return RID(); }
- virtual void mesh_initialize(RID p_rid) override {}
- virtual void mesh_free(RID p_rid) override {}
+ bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
+
+ virtual RID mesh_allocate() override;
+ virtual void mesh_initialize(RID p_rid) override;
+ virtual void mesh_free(RID p_rid) override;
virtual void mesh_set_blend_shape_count(RID p_mesh, int p_blend_shape_count) override {}
virtual bool mesh_needs_instance(RID p_mesh, bool p_has_skeleton) override { return false; }
- virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {}
+ virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND(!m);
+ m->surfaces.push_back(RS::SurfaceData());
+ RS::SurfaceData *s = &m->surfaces.write[m->surfaces.size() - 1];
+ s->format = p_surface.format;
+ s->primitive = p_surface.primitive;
+ s->vertex_data = p_surface.vertex_data;
+ s->attribute_data = p_surface.attribute_data;
+ s->vertex_count = p_surface.vertex_count;
+ s->index_data = p_surface.index_data;
+ s->index_count = p_surface.index_count;
+ s->aabb = p_surface.aabb;
+ s->skin_data = p_surface.skin_data;
+ }
virtual int mesh_get_blend_shape_count(RID p_mesh) const override { return 0; }
@@ -60,8 +97,19 @@ public:
virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) override {}
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const override { return RID(); }
- virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override { return RS::SurfaceData(); }
- virtual int mesh_get_surface_count(RID p_mesh) const override { return 0; }
+ virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!m, RS::SurfaceData());
+ ERR_FAIL_INDEX_V(p_surface, m->surfaces.size(), RS::SurfaceData());
+ RS::SurfaceData s = m->surfaces[p_surface];
+ return s;
+ }
+
+ virtual int mesh_get_surface_count(RID p_mesh) const override {
+ DummyMesh *m = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!m, 0);
+ return m->surfaces.size();
+ }
virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) override {}
virtual AABB mesh_get_custom_aabb(RID p_mesh) const override { return AABB(); }
@@ -121,9 +169,13 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override {}
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override { return Transform2D(); }
- virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) override {}
+ virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
+
+ /* OCCLUDER */
+
+ void occluder_set_mesh(RID p_occluder, const PackedVector3Array &p_vertices, const PackedInt32Array &p_indices) {}
};
} // namespace RendererDummy
-#endif // !MESH_STORAGE_DUMMY_H
+#endif // MESH_STORAGE_DUMMY_H
diff --git a/servers/rendering/dummy/storage/particles_storage.h b/servers/rendering/dummy/storage/particles_storage.h
index f614b41c4c..7cee55922d 100644
--- a/servers/rendering/dummy/storage/particles_storage.h
+++ b/servers/rendering/dummy/storage/particles_storage.h
@@ -123,4 +123,4 @@ public:
} // namespace RendererDummy
-#endif // !PARTICLES_STORAGE_DUMMY_H
+#endif // PARTICLES_STORAGE_DUMMY_H
diff --git a/servers/rendering/renderer_thread_pool.cpp b/servers/rendering/dummy/storage/texture_storage.cpp
index ddf1d1bd00..62e2a306a2 100644
--- a/servers/rendering/renderer_thread_pool.cpp
+++ b/servers/rendering/dummy/storage/texture_storage.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_thread_pool.cpp */
+/* texture_storage.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,15 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_thread_pool.h"
+#include "texture_storage.h"
-RendererThreadPool *RendererThreadPool::singleton = nullptr;
+using namespace RendererDummy;
-RendererThreadPool::RendererThreadPool() {
+TextureStorage *TextureStorage::singleton = nullptr;
+
+TextureStorage::TextureStorage() {
singleton = this;
- thread_work_pool.init();
}
-RendererThreadPool::~RendererThreadPool() {
- thread_work_pool.finish();
+TextureStorage::~TextureStorage() {
+ singleton = nullptr;
}
diff --git a/servers/rendering/dummy/storage/texture_storage.h b/servers/rendering/dummy/storage/texture_storage.h
index 11d827a6e3..a17d734e10 100644
--- a/servers/rendering/dummy/storage/texture_storage.h
+++ b/servers/rendering/dummy/storage/texture_storage.h
@@ -38,6 +38,8 @@ namespace RendererDummy {
class TextureStorage : public RendererTextureStorage {
private:
+ static TextureStorage *singleton;
+
struct DummyTexture {
Ref<Image> image;
};
@@ -45,11 +47,12 @@ private:
public:
static TextureStorage *get_singleton() {
- // Here we cheat until we can retire RasterizerStorageDummy::free()
-
- return (TextureStorage *)RSG::texture_storage;
+ return singleton;
};
+ TextureStorage();
+ ~TextureStorage();
+
virtual bool can_create_resources_async() const override { return false; }
/* Canvas Texture API */
@@ -66,7 +69,6 @@ public:
/* Texture API */
- DummyTexture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
virtual RID texture_allocate() override {
@@ -124,6 +126,8 @@ public:
virtual Size2 texture_size_with_proxy(RID p_proxy) override { return Size2(); };
+ virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const override { return RID(); };
+
/* DECAL API */
virtual RID decal_allocate() override { return RID(); }
virtual void decal_initialize(RID p_rid) override {}
@@ -144,18 +148,28 @@ public:
virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) override {}
+ /* DECAL INSTANCE */
+
+ virtual RID decal_instance_create(RID p_decal) override { return RID(); }
+ virtual void decal_instance_free(RID p_decal_instance) override {}
+ virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override {}
+
/* RENDER TARGET */
virtual RID render_target_create() override { return RID(); }
virtual void render_target_free(RID p_rid) override {}
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override {}
+ virtual Point2i render_target_get_position(RID p_render_target) const override { return Point2i(); }
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override {}
- virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override {}
+ virtual Size2i render_target_get_size(RID p_render_target) const override { return Size2i(); }
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override {}
+ virtual bool render_target_get_transparent(RID p_render_target) const override { return false; }
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override {}
- virtual bool render_target_was_used(RID p_render_target) override { return false; }
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const override { return false; }
+ virtual bool render_target_was_used(RID p_render_target) const override { return false; }
virtual void render_target_set_as_unused(RID p_render_target) override {}
+ virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override {}
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override { return RS::VIEWPORT_MSAA_DISABLED; }
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) override {}
virtual bool render_target_is_clear_requested(RID p_render_target) override { return false; }
@@ -166,8 +180,20 @@ public:
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) override {}
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const override { return Rect2i(); }
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override {}
+
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override {}
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override { return RS::VIEWPORT_VRS_DISABLED; }
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override {}
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const override { return RID(); }
+
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override {}
+ virtual RID render_target_get_override_color(RID p_render_target) const override { return RID(); }
+ virtual RID render_target_get_override_depth(RID p_render_target) const override { return RID(); }
+ virtual RID render_target_get_override_velocity(RID p_render_target) const override { return RID(); }
+
+ virtual RID render_target_get_texture(RID p_render_target) override { return RID(); }
};
} // namespace RendererDummy
-#endif // !TEXTURE_STORAGE_DUMMY_H
+#endif // TEXTURE_STORAGE_DUMMY_H
diff --git a/servers/rendering/renderer_thread_pool.h b/servers/rendering/dummy/storage/utilities.cpp
index 4626490d32..125ed81917 100644
--- a/servers/rendering/renderer_thread_pool.h
+++ b/servers/rendering/dummy/storage/utilities.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_thread_pool.h */
+/* utilities.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,18 +28,16 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERERTHREADPOOL_H
-#define RENDERERTHREADPOOL_H
+#include "utilities.h"
-#include "core/templates/thread_work_pool.h"
+using namespace RendererDummy;
-class RendererThreadPool {
-public:
- ThreadWorkPool thread_work_pool;
+Utilities *Utilities::singleton = nullptr;
- static RendererThreadPool *singleton;
- RendererThreadPool();
- ~RendererThreadPool();
-};
+Utilities::Utilities() {
+ singleton = this;
+}
-#endif // RENDERERTHREADPOOL_H
+Utilities::~Utilities() {
+ singleton = nullptr;
+}
diff --git a/servers/rendering/dummy/storage/utilities.h b/servers/rendering/dummy/storage/utilities.h
new file mode 100644
index 0000000000..a42ab0d814
--- /dev/null
+++ b/servers/rendering/dummy/storage/utilities.h
@@ -0,0 +1,118 @@
+/*************************************************************************/
+/* utilities.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef UTILITIES_DUMMY_H
+#define UTILITIES_DUMMY_H
+
+#include "mesh_storage.h"
+#include "servers/rendering/storage/utilities.h"
+#include "texture_storage.h"
+
+namespace RendererDummy {
+
+class Utilities : public RendererUtilities {
+private:
+ static Utilities *singleton;
+
+public:
+ static Utilities *get_singleton() { return singleton; }
+
+ Utilities();
+ ~Utilities();
+
+ /* INSTANCES */
+
+ virtual RS::InstanceType get_base_type(RID p_rid) const override {
+ if (RendererDummy::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ return RS::INSTANCE_MESH;
+ }
+ return RS::INSTANCE_NONE;
+ }
+
+ virtual bool free(RID p_rid) override {
+ if (RendererDummy::TextureStorage::get_singleton()->owns_texture(p_rid)) {
+ RendererDummy::TextureStorage::get_singleton()->texture_free(p_rid);
+ return true;
+ } else if (RendererDummy::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ RendererDummy::MeshStorage::get_singleton()->mesh_free(p_rid);
+ return true;
+ }
+ return false;
+ }
+
+ /* DEPENDENCIES */
+
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override {}
+
+ /* VISIBILITY NOTIFIER */
+
+ virtual RID visibility_notifier_allocate() override { return RID(); }
+ virtual void visibility_notifier_initialize(RID p_notifier) override {}
+ virtual void visibility_notifier_free(RID p_notifier) override {}
+
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override {}
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override {}
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override { return AABB(); }
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override {}
+
+ /* TIMING */
+
+ virtual void capture_timestamps_begin() override {}
+ virtual void capture_timestamp(const String &p_name) override {}
+ virtual uint32_t get_captured_timestamps_count() const override { return 0; }
+ virtual uint64_t get_captured_timestamps_frame() const override { return 0; }
+ virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override { return 0; }
+ virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override { return 0; }
+ virtual String get_captured_timestamp_name(uint32_t p_index) const override { return String(); }
+
+ /* MISC */
+
+ virtual void update_dirty_resources() override {}
+ virtual void set_debug_generate_wireframes(bool p_generate) override {}
+
+ virtual bool has_os_feature(const String &p_feature) const override {
+ return p_feature == "rgtc" || p_feature == "bptc" || p_feature == "s3tc" || p_feature == "etc" || p_feature == "etc2";
+ }
+
+ virtual void update_memory_info() override {}
+
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override { return 0; }
+ virtual String get_video_adapter_name() const override { return String(); }
+ virtual String get_video_adapter_vendor() const override { return String(); }
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const override { return RenderingDevice::DeviceType::DEVICE_TYPE_OTHER; }
+ virtual String get_video_adapter_api_version() const override { return String(); }
+
+ virtual Size2i get_maximum_viewport_size() const override { return Size2i(); };
+};
+
+} // namespace RendererDummy
+
+#endif // UTILITIES_DUMMY_H
diff --git a/servers/rendering/environment/renderer_fog.h b/servers/rendering/environment/renderer_fog.h
new file mode 100644
index 0000000000..8f38d5745e
--- /dev/null
+++ b/servers/rendering/environment/renderer_fog.h
@@ -0,0 +1,53 @@
+/*************************************************************************/
+/* renderer_fog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDERER_FOG_H
+#define RENDERER_FOG_H
+
+#include "servers/rendering_server.h"
+
+class RendererFog {
+public:
+ virtual ~RendererFog() {}
+
+ /* FOG VOLUMES */
+
+ virtual RID fog_volume_allocate() = 0;
+ virtual void fog_volume_initialize(RID p_rid) = 0;
+ virtual void fog_volume_free(RID p_rid) = 0;
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0;
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0;
+};
+
+#endif // RENDERER_FOG_H
diff --git a/servers/rendering/environment/renderer_gi.h b/servers/rendering/environment/renderer_gi.h
new file mode 100644
index 0000000000..0faf683015
--- /dev/null
+++ b/servers/rendering/environment/renderer_gi.h
@@ -0,0 +1,84 @@
+/*************************************************************************/
+/* renderer_gi.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDERER_GI_H
+#define RENDERER_GI_H
+
+#include "servers/rendering_server.h"
+
+class RendererGI {
+public:
+ virtual ~RendererGI() {}
+
+ /* VOXEL GI API */
+
+ virtual RID voxel_gi_allocate() = 0;
+ virtual void voxel_gi_free(RID p_rid) = 0;
+ virtual void voxel_gi_initialize(RID p_rid) = 0;
+
+ virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
+
+ virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const = 0;
+ virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const = 0;
+ virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const = 0;
+
+ virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const = 0;
+ virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_propagation(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
+ virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) = 0;
+ virtual float voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
+ virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0;
+ virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0;
+ virtual bool voxel_gi_is_interior(RID p_voxel_gi) const = 0;
+
+ virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0;
+ virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
+
+ virtual uint32_t voxel_gi_get_version(RID p_probe) const = 0;
+};
+
+#endif // RENDERER_GI_H
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp
index bc1e8eb348..16d382a5f3 100644
--- a/servers/rendering/renderer_canvas_cull.cpp
+++ b/servers/rendering/renderer_canvas_cull.cpp
@@ -38,17 +38,17 @@
static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1;
-void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) {
+void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask) {
RENDER_TIMESTAMP("Cull CanvasItem Tree");
memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *));
for (int i = 0; i < p_child_item_count; i++) {
- _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true);
+ _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask);
}
if (p_canvas_item) {
- _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true);
+ _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask);
}
RendererCanvasRender::Item *list = nullptr;
@@ -76,10 +76,11 @@ void RendererCanvasCull::_render_canvas_item_tree(RID p_to_render_target, Canvas
}
}
-void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index) {
+void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2D p_transform, RendererCanvasCull::Item *p_material_owner, RendererCanvasCull::Item **r_items, int &r_index, int p_z) {
int child_item_count = p_canvas_item->child_items.size();
RendererCanvasCull::Item **child_items = p_canvas_item->child_items.ptrw();
for (int i = 0; i < child_item_count; i++) {
+ int abs_z = 0;
if (child_items[i]->visible) {
if (r_items) {
r_items[r_index] = child_items[i];
@@ -87,12 +88,20 @@ void _collect_ysort_children(RendererCanvasCull::Item *p_canvas_item, Transform2
child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.columns[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : nullptr;
child_items[i]->ysort_index = r_index;
+ child_items[i]->ysort_parent_abs_z_index = p_z;
+
+ // Y sorted canvas items are flattened into r_items. Calculate their absolute z index to use when rendering r_items.
+ if (child_items[i]->z_relative) {
+ abs_z = CLAMP(p_z + child_items[i]->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
+ } else {
+ abs_z = child_items[i]->z_index;
+ }
}
r_index++;
if (child_items[i]->sort_y) {
- _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index);
+ _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index, abs_z);
}
}
}
@@ -105,16 +114,16 @@ void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_Owner<Renderer
} while (ysort_owner && ysort_owner->sort_y);
}
-void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform) {
+void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform) {
if (ci->copy_back_buffer) {
ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect);
}
- if (use_canvas_group) {
+ if (p_use_canvas_group) {
int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
if (canvas_group_from == nullptr) {
// no list before processing this item, means must put stuff in group from the beginning of list.
- canvas_group_from = z_list[zidx];
+ canvas_group_from = r_z_list[zidx];
} else {
// there was a list before processing, so begin group from this one.
canvas_group_from = canvas_group_from->next;
@@ -180,7 +189,7 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
RenderingServerDefault::redraw_request();
}
- if (ci->commands != nullptr) {
+ if (ci->commands != nullptr || ci->copy_back_buffer) {
ci->final_transform = xform;
ci->final_modulate = modulate * ci->self_modulate;
ci->global_rect_cache = global_rect;
@@ -189,13 +198,13 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
- if (z_last_list[zidx]) {
- z_last_list[zidx]->next = ci;
- z_last_list[zidx] = ci;
+ if (r_z_last_list[zidx]) {
+ r_z_last_list[zidx]->next = ci;
+ r_z_last_list[zidx] = ci;
} else {
- z_list[zidx] = ci;
- z_last_list[zidx] = ci;
+ r_z_list[zidx] = ci;
+ r_z_last_list[zidx] = ci;
}
ci->z_final = p_z;
@@ -214,13 +223,17 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *
}
}
-void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort) {
+void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask) {
Item *ci = p_canvas_item;
if (!ci->visible) {
return;
}
+ if (!(ci->visibility_layer & canvas_cull_mask)) {
+ return;
+ }
+
if (ci->children_order_dirty) {
ci->child_items.sort_custom<ItemIndexSort>();
ci->children_order_dirty = false;
@@ -277,6 +290,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
ci->final_clip_owner = p_canvas_clip;
}
+ int parent_z = p_z;
if (ci->z_relative) {
p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX);
} else {
@@ -287,58 +301,59 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2
if (allow_y_sort) {
if (ci->ysort_children_count == -1) {
ci->ysort_children_count = 0;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count);
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, nullptr, ci->ysort_children_count, p_z);
}
child_item_count = ci->ysort_children_count + 1;
child_items = (Item **)alloca(child_item_count * sizeof(Item *));
+ ci->ysort_parent_abs_z_index = parent_z;
child_items[0] = ci;
int i = 1;
- _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i);
+ _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i, p_z);
ci->ysort_xform = ci->xform.affine_inverse();
SortArray<Item *, ItemPtrSort> sorter;
sorter.sort(child_items, child_item_count);
for (i = 0; i < child_item_count; i++) {
- _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false);
+ _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, canvas_cull_mask);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
if (use_canvas_group) {
int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
- canvas_group_from = z_last_list[zidx];
+ canvas_group_from = r_z_last_list[zidx];
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
}
} else {
RendererCanvasRender::Item *canvas_group_from = nullptr;
bool use_canvas_group = ci->canvas_group != nullptr && (ci->canvas_group->fit_empty || ci->commands != nullptr);
if (use_canvas_group) {
int zidx = p_z - RS::CANVAS_ITEM_Z_MIN;
- canvas_group_from = z_last_list[zidx];
+ canvas_group_from = r_z_last_list[zidx];
}
for (int i = 0; i < child_item_count; i++) {
if (!child_items[i]->behind && !use_canvas_group) {
continue;
}
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
+ _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask);
}
- _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
+ _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform);
for (int i = 0; i < child_item_count; i++) {
if (child_items[i]->behind || use_canvas_group) {
continue;
}
- _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true);
+ _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask);
}
}
}
-void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel) {
+void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask) {
RENDER_TIMESTAMP("> Render Canvas");
sdf_used = false;
@@ -361,26 +376,26 @@ void RendererCanvasCull::render_canvas(RID p_render_target, Canvas *p_canvas, co
}
if (!has_mirror) {
- _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
+ _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
} else {
//used for parallaxlayer mirroring
for (int i = 0; i < l; i++) {
const Canvas::ChildItem &ci2 = p_canvas->child_items[i];
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
//mirroring (useful for scrolling backgrounds)
if (ci2.mirror.x != 0) {
Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0));
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
}
if (ci2.mirror.y != 0) {
Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y));
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
}
if (ci2.mirror.y != 0 && ci2.mirror.x != 0) {
Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror);
- _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel);
+ _render_canvas_item_tree(p_render_target, nullptr, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights, p_directional_lights, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel, canvas_cull_mask);
}
}
}
@@ -502,6 +517,20 @@ void RendererCanvasCull::canvas_item_set_transform(RID p_item, const Transform2D
canvas_item->xform = p_transform;
}
+void RendererCanvasCull::canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->visibility_layer = p_visibility_layer;
+}
+
+uint32_t RendererCanvasCull::canvas_item_get_visibility_layer(RID p_item) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ if (!canvas_item)
+ return 0;
+ return canvas_item->visibility_layer;
+}
+
void RendererCanvasCull::canvas_item_set_clip(RID p_item, bool p_clip) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -594,9 +623,13 @@ void RendererCanvasCull::canvas_item_add_line(RID p_item, const Point2 &p_from,
}
if (p_antialiased) {
- float border_size = 2.0;
- if (p_width < border_size) {
- border_size = p_width;
+ // Use the same antialiasing feather size as StyleBoxFlat's default
+ // (but doubled, as it's specified for both sides here).
+ // This value is empirically determined to provide good antialiasing quality
+ // while not making lines appear too soft.
+ float border_size = 1.25f;
+ if (p_width < 1.0f) {
+ border_size *= p_width;
}
Vector2 dir2 = diff.normalized();
@@ -763,9 +796,13 @@ void RendererCanvasCull::canvas_item_add_polyline(RID p_item, const Vector<Point
Color *colors_ptr = colors.ptrw();
if (p_antialiased) {
- float border_size = 2.0;
- if (p_width < border_size) {
- border_size = p_width;
+ // Use the same antialiasing feather size as StyleBoxFlat's default
+ // (but doubled, as it's specified for both sides here).
+ // This value is empirically determined to provide good antialiasing quality
+ // while not making lines appear too soft.
+ float border_size = 1.25f;
+ if (p_width < 1.0f) {
+ border_size *= p_width;
}
Color color2 = Color(1, 1, 1, 0);
@@ -1164,6 +1201,38 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co
rect->px_range = p_px_range;
}
+void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) {
+ Item *canvas_item = canvas_item_owner.get_or_null(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>();
+ ERR_FAIL_COND(!rect);
+ rect->modulate = p_modulate;
+ rect->rect = p_rect;
+
+ rect->texture = p_texture;
+
+ rect->source = p_src_rect;
+ rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_LCD;
+
+ if (p_rect.size.x < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->rect.size.x = -rect->rect.size.x;
+ }
+ if (p_src_rect.size.x < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H;
+ rect->source.size.x = -rect->source.size.x;
+ }
+ if (p_rect.size.y < 0) {
+ rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->rect.size.y = -rect->rect.size.y;
+ }
+ if (p_src_rect.size.y < 0) {
+ rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V;
+ rect->source.size.y = -rect->source.size.y;
+ }
+}
+
void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) {
Item *canvas_item = canvas_item_owner.get_or_null(p_item);
ERR_FAIL_COND(!canvas_item);
@@ -1895,11 +1964,11 @@ void RendererCanvasCull::update_visibility_notifiers() {
if (!visibility_notifier->enter_callable.is_null()) {
if (RSG::threaded) {
- visibility_notifier->enter_callable.call_deferred(nullptr, 0);
+ visibility_notifier->enter_callable.call_deferred();
} else {
Callable::CallError ce;
Variant ret;
- visibility_notifier->enter_callable.call(nullptr, 0, ret, ce);
+ visibility_notifier->enter_callable.callp(nullptr, 0, ret, ce);
}
}
} else {
@@ -1908,11 +1977,11 @@ void RendererCanvasCull::update_visibility_notifiers() {
if (!visibility_notifier->exit_callable.is_null()) {
if (RSG::threaded) {
- visibility_notifier->exit_callable.call_deferred(nullptr, 0);
+ visibility_notifier->exit_callable.call_deferred();
} else {
Callable::CallError ce;
Variant ret;
- visibility_notifier->exit_callable.call(nullptr, 0, ret, ce);
+ visibility_notifier->exit_callable.callp(nullptr, 0, ret, ce);
}
}
}
diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h
index 963cca7630..198e1020f0 100644
--- a/servers/rendering/renderer_canvas_cull.h
+++ b/servers/rendering/renderer_canvas_cull.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_CANVAS_CULL_H
-#define RENDERING_SERVER_CANVAS_CULL_H
+#ifndef RENDERER_CANVAS_CULL_H
+#define RENDERER_CANVAS_CULL_H
#include "core/templates/paged_allocator.h"
#include "renderer_compositor.h"
@@ -53,6 +53,8 @@ public:
Transform2D ysort_xform;
Vector2 ysort_pos;
int ysort_index;
+ int ysort_parent_abs_z_index; // Absolute Z index of parent. Only populated and used when y-sorting.
+ uint32_t visibility_layer = 0xffffffff;
Vector<Item *> child_items;
@@ -84,6 +86,7 @@ public:
ysort_xform = Transform2D();
ysort_pos = Vector2();
ysort_index = 0;
+ ysort_parent_abs_z_index = 0;
}
};
@@ -174,17 +177,17 @@ public:
PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator;
SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list;
- _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform);
+ _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform);
private:
- void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel);
- void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort);
+ void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask);
+ void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask);
RendererCanvasRender::Item **z_list;
RendererCanvasRender::Item **z_last_list;
public:
- void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel);
+ void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, const Rect2 &p_clip_rect, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_transforms_to_pixel, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask);
bool was_sdf_used();
@@ -204,6 +207,9 @@ public:
void canvas_item_set_visible(RID p_item, bool p_visible);
void canvas_item_set_light_mask(RID p_item, int p_mask);
+ void canvas_item_set_visibility_layer(RID p_item, uint32_t p_layer);
+ uint32_t canvas_item_get_visibility_layer(RID p_item);
+
void canvas_item_set_transform(RID p_item, const Transform2D &p_transform);
void canvas_item_set_clip(RID p_item, bool p_clip);
void canvas_item_set_distance_field_mode(RID p_item, bool p_enable);
@@ -223,6 +229,7 @@ public:
void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false);
void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0);
+ void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1));
void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0);
void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID());
@@ -315,4 +322,4 @@ public:
~RendererCanvasCull();
};
-#endif // RENDERING_SERVER_CANVAS_CULL_H
+#endif // RENDERER_CANVAS_CULL_H
diff --git a/servers/rendering/renderer_canvas_render.cpp b/servers/rendering/renderer_canvas_render.cpp
index 163a24247e..623f0c647b 100644
--- a/servers/rendering/renderer_canvas_render.cpp
+++ b/servers/rendering/renderer_canvas_render.cpp
@@ -128,3 +128,9 @@ const Rect2 &RendererCanvasRender::Item::get_rect() const {
rect_dirty = false;
return rect;
}
+
+RendererCanvasRender::Item::CommandMesh::~CommandMesh() {
+ if (mesh_instance.is_valid()) {
+ RSG::mesh_storage->mesh_instance_free(mesh_instance);
+ }
+}
diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h
index 1724a99b20..375358a5e8 100644
--- a/servers/rendering/renderer_canvas_render.h
+++ b/servers/rendering/renderer_canvas_render.h
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERCANVASRENDER_H
-#define RENDERINGSERVERCANVASRENDER_H
+#ifndef RENDERER_CANVAS_RENDER_H
+#define RENDERER_CANVAS_RENDER_H
-#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering_server.h"
class RendererCanvasRender {
public:
@@ -46,6 +46,7 @@ public:
CANVAS_RECT_CLIP_UV = 32,
CANVAS_RECT_IS_GROUP = 64,
CANVAS_RECT_MSDF = 128,
+ CANVAS_RECT_LCD = 256,
};
struct Light {
@@ -77,7 +78,7 @@ public:
Rect2 rect_cache;
Transform2D xform_cache;
float radius_cache; //used for shadow far plane
- //CameraMatrix shadow_matrix_cache;
+ //Projection shadow_matrix_cache;
Transform2D light_shader_xform;
//Vector2 light_shader_pos;
@@ -193,7 +194,7 @@ public:
Rect2 rect;
Color modulate;
Rect2 source;
- uint8_t flags;
+ uint16_t flags;
float outline;
float px_range;
@@ -257,11 +258,7 @@ public:
RID texture;
CommandMesh() { type = TYPE_MESH; }
- ~CommandMesh() {
- if (mesh_instance.is_valid()) {
- RendererStorage::base_singleton->free(mesh_instance);
- }
- }
+ ~CommandMesh();
};
struct CommandMultiMesh : public Command {
@@ -479,7 +476,6 @@ public:
};
virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) = 0;
- virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0;
struct LightOccluderInstance {
bool enabled;
@@ -524,4 +520,4 @@ public:
virtual ~RendererCanvasRender() {}
};
-#endif // RENDERINGSERVERCANVASRENDER_H
+#endif // RENDERER_CANVAS_RENDER_H
diff --git a/servers/rendering/renderer_compositor.cpp b/servers/rendering/renderer_compositor.cpp
index b331ec2c1d..80e71a0df3 100644
--- a/servers/rendering/renderer_compositor.cpp
+++ b/servers/rendering/renderer_compositor.cpp
@@ -33,6 +33,7 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include "servers/xr_server.h"
RendererCompositor *(*RendererCompositor::_create_func)() = nullptr;
bool RendererCompositor::low_end = false;
@@ -46,7 +47,11 @@ bool RendererCompositor::is_xr_enabled() const {
}
RendererCompositor::RendererCompositor() {
- xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ if (XRServer::get_xr_mode() == XRServer::XRMODE_DEFAULT) {
+ xr_enabled = GLOBAL_GET("xr/shaders/enabled");
+ } else {
+ xr_enabled = XRServer::get_xr_mode() == XRServer::XRMODE_ON;
+ }
}
RendererCanvasRender *RendererCanvasRender::singleton = nullptr;
diff --git a/servers/rendering/renderer_compositor.h b/servers/rendering/renderer_compositor.h
index df3df1077a..169988f72c 100644
--- a/servers/rendering/renderer_compositor.h
+++ b/servers/rendering/renderer_compositor.h
@@ -28,17 +28,20 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_COMPOSITOR_H
-#define RENDERING_SERVER_COMPOSITOR_H
+#ifndef RENDERER_COMPOSITOR_H
+#define RENDERER_COMPOSITOR_H
+#include "servers/rendering/environment/renderer_fog.h"
+#include "servers/rendering/environment/renderer_gi.h"
#include "servers/rendering/renderer_canvas_render.h"
-#include "servers/rendering/renderer_scene.h"
-#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/rendering_method.h"
+#include "servers/rendering/storage/camera_attributes_storage.h"
#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/material_storage.h"
#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/particles_storage.h"
#include "servers/rendering/storage/texture_storage.h"
+#include "servers/rendering/storage/utilities.h"
#include "servers/rendering_server.h"
class RendererSceneRender;
@@ -76,12 +79,14 @@ protected:
public:
static RendererCompositor *create();
+ virtual RendererUtilities *get_utilities() = 0;
virtual RendererLightStorage *get_light_storage() = 0;
virtual RendererMaterialStorage *get_material_storage() = 0;
virtual RendererMeshStorage *get_mesh_storage() = 0;
virtual RendererParticlesStorage *get_particles_storage() = 0;
virtual RendererTextureStorage *get_texture_storage() = 0;
- virtual RendererStorage *get_storage() = 0;
+ virtual RendererGI *get_gi() = 0;
+ virtual RendererFog *get_fog() = 0;
virtual RendererCanvasRender *get_canvas() = 0;
virtual RendererSceneRender *get_scene() = 0;
@@ -97,6 +102,7 @@ public:
virtual void finalize() = 0;
virtual uint64_t get_frame_number() const = 0;
virtual double get_frame_delta_time() const = 0;
+ virtual double get_total_time() const = 0;
static bool is_low_end() { return low_end; };
virtual bool is_xr_enabled() const;
@@ -105,4 +111,4 @@ public:
virtual ~RendererCompositor() {}
};
-#endif // RASTERIZER_H
+#endif // RENDERER_COMPOSITOR_H
diff --git a/servers/rendering/renderer_geometry_instance.cpp b/servers/rendering/renderer_geometry_instance.cpp
new file mode 100644
index 0000000000..675659f4c8
--- /dev/null
+++ b/servers/rendering/renderer_geometry_instance.cpp
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* renderer_geometry_instance.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "servers/rendering/renderer_geometry_instance.h"
+
+void RenderGeometryInstanceBase::set_skeleton(RID p_skeleton) {
+ data->skeleton = p_skeleton;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_material_override(RID p_override) {
+ data->material_override = p_override;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_material_overlay(RID p_overlay) {
+ data->material_overlay = p_overlay;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_surface_materials(const Vector<RID> &p_materials) {
+ data->surface_materials = p_materials;
+
+ _mark_dirty();
+ data->dirty_dependencies = true;
+}
+
+void RenderGeometryInstanceBase::set_mesh_instance(RID p_mesh_instance) {
+ mesh_instance = p_mesh_instance;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
+ transform = p_transform;
+ mirror = p_transform.basis.determinant() < 0;
+ data->aabb = p_aabb;
+ transformed_aabb = p_transformed_aabb;
+
+ Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
+ // handle non uniform scale here
+
+ float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
+ float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
+ non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
+
+ lod_model_scale = max_scale;
+}
+
+void RenderGeometryInstanceBase::set_lod_bias(float p_lod_bias) {
+ lod_bias = p_lod_bias;
+}
+
+void RenderGeometryInstanceBase::set_layer_mask(uint32_t p_layer_mask) {
+ layer_mask = p_layer_mask;
+}
+
+void RenderGeometryInstanceBase::set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
+ fade_near = p_enable_near;
+ fade_near_begin = p_near_begin;
+ fade_near_end = p_near_end;
+ fade_far = p_enable_far;
+ fade_far_begin = p_far_begin;
+ fade_far_end = p_far_end;
+}
+
+void RenderGeometryInstanceBase::set_parent_fade_alpha(float p_alpha) {
+ parent_fade_alpha = p_alpha;
+}
+
+void RenderGeometryInstanceBase::set_transparency(float p_transparency) {
+ force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+}
+
+void RenderGeometryInstanceBase::set_use_baked_light(bool p_enable) {
+ data->use_baked_light = p_enable;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_use_dynamic_gi(bool p_enable) {
+ data->use_dynamic_gi = p_enable;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_instance_shader_uniforms_offset(int32_t p_offset) {
+ shader_uniforms_offset = p_offset;
+
+ _mark_dirty();
+}
+
+void RenderGeometryInstanceBase::set_cast_double_sided_shadows(bool p_enable) {
+ data->cast_double_sided_shadows = p_enable;
+
+ _mark_dirty();
+}
+
+Transform3D RenderGeometryInstanceBase::get_transform() {
+ return transform;
+}
+
+AABB RenderGeometryInstanceBase::get_aabb() {
+ return data->aabb;
+}
diff --git a/servers/rendering/renderer_geometry_instance.h b/servers/rendering/renderer_geometry_instance.h
new file mode 100644
index 0000000000..fecb9878c2
--- /dev/null
+++ b/servers/rendering/renderer_geometry_instance.h
@@ -0,0 +1,150 @@
+/*************************************************************************/
+/* renderer_geometry_instance.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDERER_GEOMETRY_INSTANCE_H
+#define RENDERER_GEOMETRY_INSTANCE_H
+
+#include "core/math/rect2.h"
+#include "core/math/transform_3d.h"
+#include "core/math/vector3.h"
+#include "core/templates/rid.h"
+#include "storage/utilities.h"
+
+// API definition for our RenderGeometryInstance class so we can expose this through GDExternal in the near future
+class RenderGeometryInstance {
+public:
+ virtual ~RenderGeometryInstance() {}
+
+ virtual void _mark_dirty() = 0;
+
+ virtual void set_skeleton(RID p_skeleton) = 0;
+ virtual void set_material_override(RID p_override) = 0;
+ virtual void set_material_overlay(RID p_overlay) = 0;
+ virtual void set_surface_materials(const Vector<RID> &p_materials) = 0;
+ virtual void set_mesh_instance(RID p_mesh_instance) = 0;
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) = 0;
+ virtual void set_lod_bias(float p_lod_bias) = 0;
+ virtual void set_layer_mask(uint32_t p_layer_mask) = 0;
+ virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0;
+ virtual void set_parent_fade_alpha(float p_alpha) = 0;
+ virtual void set_transparency(float p_transparency) = 0;
+ virtual void set_use_baked_light(bool p_enable) = 0;
+ virtual void set_use_dynamic_gi(bool p_enable) = 0;
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
+ virtual void set_lightmap_capture(const Color *p_sh9) = 0;
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) = 0;
+ virtual void set_cast_double_sided_shadows(bool p_enable) = 0;
+
+ virtual Transform3D get_transform() = 0;
+ virtual AABB get_aabb() = 0;
+
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
+
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) = 0;
+};
+
+// Base implementation of RenderGeometryInstance shared by internal renderers.
+class RenderGeometryInstanceBase : public RenderGeometryInstance {
+public:
+ // setup
+ uint32_t base_flags = 0;
+ uint32_t flags_cache = 0;
+
+ // used during rendering
+ float depth = 0;
+
+ RID mesh_instance;
+
+ Transform3D transform;
+ bool mirror = false; // move into data?
+ AABB transformed_aabb; //needed for LOD
+ bool non_uniform_scale = false;
+ float lod_model_scale = 1.0;
+ float lod_bias = 0.0;
+
+ uint32_t layer_mask = 1;
+
+ bool fade_near = false;
+ float fade_near_begin = 0;
+ float fade_near_end = 0;
+ bool fade_far = false;
+ float fade_far_begin = 0;
+ float fade_far_end = 0;
+
+ float parent_fade_alpha = 1.0;
+ float force_alpha = 1.0;
+
+ int32_t shader_uniforms_offset = -1;
+
+ struct Data {
+ //data used less often goes into regular heap
+ RID base;
+ RS::InstanceType base_type;
+
+ RID skeleton;
+ Vector<RID> surface_materials;
+ RID material_override;
+ RID material_overlay;
+ AABB aabb;
+
+ bool use_baked_light = false;
+ bool use_dynamic_gi = false;
+ bool cast_double_sided_shadows = false;
+ bool dirty_dependencies = false;
+
+ DependencyTracker dependency_tracker;
+ };
+
+ Data *data = nullptr;
+
+ virtual void set_skeleton(RID p_skeleton) override;
+ virtual void set_material_override(RID p_override) override;
+ virtual void set_material_overlay(RID p_overlay) override;
+ virtual void set_surface_materials(const Vector<RID> &p_materials) override;
+ virtual void set_mesh_instance(RID p_mesh_instance) override;
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
+ virtual void set_lod_bias(float p_lod_bias) override;
+ virtual void set_layer_mask(uint32_t p_layer_mask) override;
+ virtual void set_fade_range(bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
+ virtual void set_parent_fade_alpha(float p_alpha) override;
+ virtual void set_transparency(float p_transparency) override;
+ virtual void set_use_baked_light(bool p_enable) override;
+ virtual void set_use_dynamic_gi(bool p_enable) override;
+ virtual void set_instance_shader_uniforms_offset(int32_t p_offset) override;
+ virtual void set_cast_double_sided_shadows(bool p_enable) override;
+
+ virtual Transform3D get_transform() override;
+ virtual AABB get_aabb() override;
+};
+
+#endif // RENDERER_GEOMETRY_INSTANCE_H
diff --git a/servers/rendering/renderer_rd/SCsub b/servers/rendering/renderer_rd/SCsub
index 774a6b7951..10b83dca11 100644
--- a/servers/rendering/renderer_rd/SCsub
+++ b/servers/rendering/renderer_rd/SCsub
@@ -5,6 +5,7 @@ Import("env")
env.add_source_files(env.servers_sources, "*.cpp")
SConscript("effects/SCsub")
+SConscript("environment/SCsub")
SConscript("forward_clustered/SCsub")
SConscript("forward_mobile/SCsub")
SConscript("shaders/SCsub")
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.cpp b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
index 0b36fe3964..1bb45cbcc1 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.cpp
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.cpp
@@ -374,7 +374,7 @@ void ClusterBuilderRD::setup(Size2i p_screen_size, uint32_t p_max_elements, RID
}
}
-void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y) {
+void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y) {
view_xform = p_view_transform.affine_inverse();
projection = p_cam_projection;
z_near = projection.get_z_near();
@@ -385,7 +385,7 @@ void ClusterBuilderRD::begin(const Transform3D &p_view_transform, const CameraMa
adjusted_projection.adjust_perspective_znear(0.0001);
}
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(p_flip_y);
projection = correction * projection;
adjusted_projection = correction * adjusted_projection;
@@ -413,7 +413,7 @@ void ClusterBuilderRD::bake_cluster() {
StateUniform state;
- RendererStorageRD::store_camera(adjusted_projection, state.projection);
+ RendererRD::MaterialStorage::store_camera(adjusted_projection, state.projection);
state.inv_z_far = 1.0 / z_far;
state.screen_to_clusters_shift = get_shift_from_power_of_2(cluster_size);
state.screen_to_clusters_shift -= divisor; //screen is smaller, shift one less
diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h
index e82193ea6a..ef17ceb98c 100644
--- a/servers/rendering/renderer_rd/cluster_builder_rd.h
+++ b/servers/rendering/renderer_rd/cluster_builder_rd.h
@@ -31,10 +31,10 @@
#ifndef CLUSTER_BUILDER_RD_H
#define CLUSTER_BUILDER_RD_H
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/cluster_debug.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cluster_render.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/cluster_store.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
class ClusterBuilderSharedDataRD {
friend class ClusterBuilderRD;
@@ -168,8 +168,8 @@ private:
uint32_t render_element_max = 0;
Transform3D view_xform;
- CameraMatrix adjusted_projection;
- CameraMatrix projection;
+ Projection adjusted_projection;
+ Projection projection;
float z_far = 0;
float z_near = 0;
bool orthogonal = false;
@@ -220,7 +220,7 @@ private:
public:
void setup(Size2i p_screen_size, uint32_t p_max_elements, RID p_depth_buffer, RID p_depth_buffer_sampler, RID p_color_buffer);
- void begin(const Transform3D &p_view_transform, const CameraMatrix &p_cam_projection, bool p_flip_y);
+ void begin(const Transform3D &p_view_transform, const Projection &p_cam_projection, bool p_flip_y);
_FORCE_INLINE_ void add_light(LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {
if (p_type == LIGHT_TYPE_OMNI && cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT] == max_elements_by_type) {
@@ -261,7 +261,7 @@ public:
e.type = ELEMENT_TYPE_OMNI_LIGHT;
e.original_index = cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT];
- RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+ RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
cluster_count_by_type[ELEMENT_TYPE_OMNI_LIGHT]++;
@@ -269,7 +269,7 @@ public:
//spot
radius *= shared->cone_overfit; // overfit icosphere
- real_t len = Math::tan(Math::deg2rad(p_spot_aperture)) * radius;
+ real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius;
//approximate, probably better to use a cone support function
float max_d = -1e20;
float min_d = 1e20;
@@ -293,7 +293,7 @@ public:
float dist = base_plane.distance_to(Vector3());
if (dist >= 0 && dist < radius) {
//inside, check angle
- float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z))));
+ float angle = Math::rad_to_deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z))));
e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit
} else {
e.touches_near = false;
@@ -309,7 +309,7 @@ public:
e.type = ELEMENT_TYPE_SPOT_LIGHT;
e.original_index = cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]; //use omni since they share index
- RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+ RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
cluster_count_by_type[ELEMENT_TYPE_SPOT_LIGHT]++;
}
@@ -356,7 +356,7 @@ public:
e.type = (p_box_type == BOX_TYPE_DECAL) ? ELEMENT_TYPE_DECAL : ELEMENT_TYPE_REFLECTION_PROBE;
e.original_index = cluster_count_by_type[e.type];
- RendererStorageRD::store_transform_transposed_3x4(xform, e.transform_inv);
+ RendererRD::MaterialStorage::store_transform_transposed_3x4(xform, e.transform_inv);
cluster_count_by_type[e.type]++;
render_element_count++;
@@ -375,4 +375,4 @@ public:
~ClusterBuilderRD();
};
-#endif // CLUSTER_BUILDER_H
+#endif // CLUSTER_BUILDER_RD_H
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
index cc7441776d..27850695b0 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.cpp
@@ -33,6 +33,8 @@
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/storage/camera_attributes_storage.h"
using namespace RendererRD;
@@ -84,7 +86,7 @@ BokehDOF::~BokehDOF() {
}
}
-void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of bokeh depth of field with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -92,22 +94,39 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
+ float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
+ float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
+ bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
+ float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
+ float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
+ float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
+
+ bool use_jitter = RSG::camera_attributes->camera_attributes_get_dof_blur_use_jitter();
+ RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
+ RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
+
// setup our push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
- bokeh.push_constant.blur_far_active = p_dof_far;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
-
- bokeh.push_constant.blur_near_active = p_dof_near;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size);
- bokeh.push_constant.use_jitter = p_use_jitter;
+ bokeh.push_constant.blur_far_active = dof_far;
+ bokeh.push_constant.blur_far_begin = dof_far_begin;
+ bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size; // Only used with non-physically-based.
+ bokeh.push_constant.use_physical_far = dof_far_size < 0.0;
+ bokeh.push_constant.blur_size_far = bokeh_size; // Only used with physically-based.
+
+ bokeh.push_constant.blur_near_active = dof_near;
+ bokeh.push_constant.blur_near_begin = dof_near_begin;
+ bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size; // Only used with non-physically-based.
+ bokeh.push_constant.use_physical_near = dof_near_size < 0.0;
+ bokeh.push_constant.blur_size_near = bokeh_size; // Only used with physically-based.
+
+ bokeh.push_constant.use_jitter = use_jitter;
bokeh.push_constant.jitter_seed = Math::randf() * 1000.0;
bokeh.push_constant.z_near = p_cam_znear;
bokeh.push_constant.z_far = p_cam_zfar;
bokeh.push_constant.orthogonal = p_cam_orthogonal;
- bokeh.push_constant.blur_size = p_bokeh_size;
+ bokeh.push_constant.blur_size = (dof_near_size < 0.0 && dof_far_size < 0.0) ? 32 : bokeh_size; // Cap with physically-based to keep performance reasonable.
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
@@ -150,9 +169,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_buffers.base_texture_size.x, p_buffers.base_texture_size.y, 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
//second pass
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -160,9 +179,9 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const int quality_samples[4] = { 6, 12, 12, 24 };
- bokeh.push_constant.steps = quality_samples[p_quality];
+ bokeh.push_constant.steps = quality_samples[blur_quality];
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image0), 0);
@@ -187,7 +206,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
//third pass
bokeh.push_constant.second_pass = true;
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_half_image1), 0);
RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_half_texture0), 1);
} else {
@@ -200,7 +219,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_dispatch_threads(compute_list, bokeh.push_constant.size[0], bokeh.push_constant.size[1], 1);
RD::get_singleton()->compute_list_add_barrier(compute_list);
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//forth pass, upscale for low quality
shader = bokeh.compute_shader.version_get_shader(bokeh.shader_version, BOKEH_COMPOSITE);
@@ -232,7 +251,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
bokeh.push_constant.steps = 0;
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.blur_scale = quality_scale[blur_quality];
//circle always runs in half size, otherwise too expensive
@@ -273,7 +292,7 @@ void BokehDOF::bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far,
RD::get_singleton()->compute_list_end();
}
-void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
+void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't blur-based depth of field with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -281,6 +300,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ bool dof_far = RSG::camera_attributes->camera_attributes_get_dof_far_enabled(p_camera_attributes);
+ float dof_far_begin = RSG::camera_attributes->camera_attributes_get_dof_far_distance(p_camera_attributes);
+ float dof_far_size = RSG::camera_attributes->camera_attributes_get_dof_far_transition(p_camera_attributes);
+ bool dof_near = RSG::camera_attributes->camera_attributes_get_dof_near_enabled(p_camera_attributes);
+ float dof_near_begin = RSG::camera_attributes->camera_attributes_get_dof_near_distance(p_camera_attributes);
+ float dof_near_size = RSG::camera_attributes->camera_attributes_get_dof_near_transition(p_camera_attributes);
+ float bokeh_size = RSG::camera_attributes->camera_attributes_get_dof_blur_amount(p_camera_attributes) * 64; // Base 64 pixel radius.
+
+ RS::DOFBokehShape bokeh_shape = RSG::camera_attributes->camera_attributes_get_dof_blur_bokeh_shape();
+ RS::DOFBlurQuality blur_quality = RSG::camera_attributes->camera_attributes_get_dof_blur_quality();
+
// setup our base push constant
memset(&bokeh.push_constant, 0, sizeof(BokehPushConstant));
@@ -292,7 +322,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
bokeh.push_constant.second_pass = false;
bokeh.push_constant.half_size = false;
- bokeh.push_constant.blur_size = p_dof_blur_amount;
+ bokeh.push_constant.blur_size = bokeh_size;
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -307,17 +337,17 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::Uniform u_weight_texture2(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[2] }));
RD::Uniform u_weight_texture3(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_buffers.weight_texture[3] }));
- if (p_dof_far || p_dof_near) {
- if (p_dof_far) {
+ if (dof_far || dof_near) {
+ if (dof_far) {
bokeh.push_constant.blur_far_active = true;
- bokeh.push_constant.blur_far_begin = p_dof_far_begin;
- bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size;
+ bokeh.push_constant.blur_far_begin = dof_far_begin;
+ bokeh.push_constant.blur_far_end = dof_far_begin + dof_far_size;
}
- if (p_dof_near) {
+ if (dof_near) {
bokeh.push_constant.blur_near_active = true;
- bokeh.push_constant.blur_near_begin = p_dof_near_begin;
- bokeh.push_constant.blur_near_end = p_dof_near_begin - p_dof_near_size;
+ bokeh.push_constant.blur_near_begin = dof_near_begin;
+ bokeh.push_constant.blur_near_end = dof_near_begin - dof_near_size;
}
{
@@ -337,14 +367,14 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
RD::get_singleton()->draw_list_end();
}
- if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
+ if (bokeh_shape == RS::DOF_BOKEH_BOX || bokeh_shape == RS::DOF_BOKEH_HEXAGON) {
// double pass approach
- BokehMode mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
+ BokehMode mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL;
RID shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) {
+ if (blur_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || blur_quality == RS::DOF_BLUR_QUALITY_LOW) {
//box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes)
bokeh.push_constant.size[0] = p_buffers.base_texture_size.x >> 1;
bokeh.push_constant.size[1] = p_buffers.base_texture_size.y >> 1;
@@ -354,7 +384,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
static const int quality_samples[4] = { 6, 12, 12, 24 };
bokeh.push_constant.blur_scale = 0.5;
- bokeh.push_constant.steps = quality_samples[p_quality];
+ bokeh.push_constant.steps = quality_samples[blur_quality];
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
@@ -373,7 +403,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
// Pass 2
if (!bokeh.push_constant.half_size) {
// do not output weight, we're writing back into our base buffer
- mode = p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
+ mode = bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX_NOWEIGHT : BOKEH_GEN_BOKEH_HEXAGONAL_NOWEIGHT;
shader = bokeh.raster_shader.version_get_shader(bokeh.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
@@ -432,7 +462,7 @@ void BokehDOF::bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, f
}
static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 };
- bokeh.push_constant.blur_scale = quality_scale[p_quality];
+ bokeh.push_constant.blur_scale = quality_scale[blur_quality];
bokeh.push_constant.steps = 0.0;
RID framebuffer = bokeh.push_constant.half_size ? p_buffers.half_fb[0] : p_buffers.secondary_fb;
diff --git a/servers/rendering/renderer_rd/effects/bokeh_dof.h b/servers/rendering/renderer_rd/effects/bokeh_dof.h
index d7b736119c..33dbdfcdc1 100644
--- a/servers/rendering/renderer_rd/effects/bokeh_dof.h
+++ b/servers/rendering/renderer_rd/effects/bokeh_dof.h
@@ -66,6 +66,11 @@ private:
uint32_t use_jitter;
float jitter_seed;
+ uint32_t use_physical_near;
+ uint32_t use_physical_far;
+
+ float blur_size_near;
+ float blur_size_far;
uint32_t pad[2];
};
@@ -111,10 +116,10 @@ public:
BokehDOF(bool p_prefer_raster_effects);
~BokehDOF();
- void bokeh_dof_compute(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
- void bokeh_dof_raster(const BokehBuffers &p_buffers, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_dof_blur_amount, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_compute(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
+ void bokeh_dof_raster(const BokehBuffers &p_buffers, RID p_camera_attributes, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal);
};
} // namespace RendererRD
-#endif // !BOKEH_DOF_RD_H
+#endif // BOKEH_DOF_RD_H
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.cpp b/servers/rendering/renderer_rd/effects/copy_effects.cpp
index 6b786fdf16..27f977a80b 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.cpp
+++ b/servers/rendering/renderer_rd/effects/copy_effects.cpp
@@ -29,9 +29,11 @@
/*************************************************************************/
#include "copy_effects.h"
+#include "core/config/project_settings.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+#include "thirdparty/misc/cubemap_coeffs.h"
using namespace RendererRD;
@@ -98,11 +100,11 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
{
Vector<String> copy_modes;
- copy_modes.push_back("\n");
- copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n");
- copy_modes.push_back("\n#define MODE_TWO_SOURCES\n");
- copy_modes.push_back("\n#define MULTIVIEW\n");
- copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n");
+ copy_modes.push_back("\n"); // COPY_TO_FB_COPY
+ copy_modes.push_back("\n#define MODE_PANORAMA_TO_DP\n"); // COPY_TO_FB_COPY_PANORAMA_TO_DP
+ copy_modes.push_back("\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_COPY2
+ copy_modes.push_back("\n#define MULTIVIEW\n"); // COPY_TO_FB_MULTIVIEW
+ copy_modes.push_back("\n#define MULTIVIEW\n#define MODE_TWO_SOURCES\n"); // COPY_TO_FB_MULTIVIEW_WITH_DEPTH
copy_to_fb.shader.initialize(copy_modes);
@@ -123,16 +125,209 @@ CopyEffects::CopyEffects(bool p_prefer_raster_effects) {
}
}
}
+
+ {
+ // Initialize copier
+ Vector<String> copy_modes;
+ copy_modes.push_back("\n");
+
+ cube_to_dp.shader.initialize(copy_modes);
+
+ cube_to_dp.shader_version = cube_to_dp.shader.version_create();
+ RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
+ RD::PipelineDepthStencilState dss;
+ dss.enable_depth_test = true;
+ dss.depth_compare_operator = RD::COMPARE_OP_ALWAYS;
+ dss.enable_depth_write = true;
+ cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
+ }
+
+ {
+ //Initialize cubemap downsampler
+ Vector<String> cubemap_downsampler_modes;
+ cubemap_downsampler_modes.push_back("");
+
+ if (prefer_raster_effects) {
+ cubemap_downsampler.raster_shader.initialize(cubemap_downsampler_modes);
+
+ cubemap_downsampler.shader_version = cubemap_downsampler.raster_shader.version_create();
+
+ cubemap_downsampler.raster_pipeline.setup(cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ cubemap_downsampler.compute_shader.initialize(cubemap_downsampler_modes);
+
+ cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create();
+
+ cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0));
+ cubemap_downsampler.raster_pipeline.clear();
+ }
+ }
+
+ {
+ // Initialize cubemap filter
+ filter.use_high_quality = GLOBAL_GET("rendering/reflections/sky_reflections/fast_filter_high_quality");
+
+ Vector<String> cubemap_filter_modes;
+ cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n");
+ cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n");
+ cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n");
+ cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n");
+
+ if (filter.use_high_quality) {
+ filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs));
+ RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(high_quality_coeffs), &high_quality_coeffs[0]);
+ } else {
+ filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(low_quality_coeffs));
+ RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0]);
+ }
+
+ if (prefer_raster_effects) {
+ filter.raster_shader.initialize(cubemap_filter_modes);
+
+ // array variants are not supported in raster
+ filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false);
+ filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false);
+
+ filter.shader_version = filter.raster_shader.version_create();
+
+ for (int i = 0; i < FILTER_MODE_MAX; i++) {
+ if (filter.raster_shader.is_variant_enabled(i)) {
+ filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ filter.raster_pipelines[i].clear();
+ }
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(filter.coefficient_buffer);
+ uniforms.push_back(u);
+ }
+ filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
+ } else {
+ filter.compute_shader.initialize(cubemap_filter_modes);
+ filter.shader_version = filter.compute_shader.version_create();
+
+ for (int i = 0; i < FILTER_MODE_MAX; i++) {
+ filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i));
+ filter.raster_pipelines[i].clear();
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(filter.coefficient_buffer);
+ uniforms.push_back(u);
+ }
+ filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
+ }
+ }
+
+ {
+ // Initialize roughness
+ Vector<String> cubemap_roughness_modes;
+ cubemap_roughness_modes.push_back("");
+
+ if (prefer_raster_effects) {
+ roughness.raster_shader.initialize(cubemap_roughness_modes);
+
+ roughness.shader_version = roughness.raster_shader.version_create();
+
+ roughness.raster_pipeline.setup(roughness.raster_shader.version_get_shader(roughness.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+
+ } else {
+ roughness.compute_shader.initialize(cubemap_roughness_modes);
+
+ roughness.shader_version = roughness.compute_shader.version_create();
+
+ roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0));
+ roughness.raster_pipeline.clear();
+ }
+ }
+
+ {
+ Vector<String> specular_modes;
+ specular_modes.push_back("\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD
+ specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR
+ specular_modes.push_back("\n"); // SPECULAR_MERGE_ADDITIVE_ADD
+ specular_modes.push_back("\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR
+
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n"); // SPECULAR_MERGE_ADD_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_MERGE\n#define MODE_SSR\n"); // SPECULAR_MERGE_SSR_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n"); // SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW
+ specular_modes.push_back("\n#define USE_MULTIVIEW\n#define MODE_SSR\n"); // SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW
+
+ specular_merge.shader.initialize(specular_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADD_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_SSR_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW, false);
+ specular_merge.shader.set_variant_enabled(SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW, false);
+ }
+
+ specular_merge.shader_version = specular_merge.shader.version_create();
+
+ //use additive
+
+ RD::PipelineColorBlendState::Attachment ba;
+ ba.enable_blend = true;
+ ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ ba.color_blend_op = RD::BLEND_OP_ADD;
+ ba.alpha_blend_op = RD::BLEND_OP_ADD;
+
+ RD::PipelineColorBlendState blend_additive;
+ blend_additive.attachments.push_back(ba);
+
+ for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
+ if (specular_merge.shader.is_variant_enabled(i)) {
+ RD::PipelineColorBlendState blend_state;
+ if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR || i == SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW || i == SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW) {
+ blend_state = blend_additive;
+ } else {
+ blend_state = RD::PipelineColorBlendState::create_disabled();
+ }
+ specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
+ }
+ }
}
CopyEffects::~CopyEffects() {
if (prefer_raster_effects) {
blur_raster.shader.version_free(blur_raster.shader_version);
+ cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
+ filter.raster_shader.version_free(filter.shader_version);
+ roughness.raster_shader.version_free(roughness.shader_version);
} else {
copy.shader.version_free(copy.shader_version);
+ cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
+ filter.compute_shader.version_free(filter.shader_version);
+ roughness.compute_shader.version_free(roughness.shader_version);
+ }
+
+ specular_merge.shader.version_free(specular_merge.shader_version);
+
+ RD::get_singleton()->free(filter.coefficient_buffer);
+
+ if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
+ RD::get_singleton()->free(filter.image_uniform_set);
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(filter.uniform_set)) {
+ RD::get_singleton()->free(filter.uniform_set);
}
copy_to_fb.shader.version_free(copy_to_fb.shader_version);
+ cube_to_dp.shader.version_free(cube_to_dp.shader_version);
singleton = nullptr;
}
@@ -162,8 +357,8 @@ void CopyEffects::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, cons
copy.push_constant.flags |= COPY_FLAG_ALPHA_TO_ONE;
}
- copy.push_constant.section[0] = 0;
- copy.push_constant.section[1] = 0;
+ copy.push_constant.section[0] = p_rect.position.x;
+ copy.push_constant.section[1] = p_rect.position.y;
copy.push_constant.section[2] = p_rect.size.width;
copy.push_constant.section[3] = p_rect.size.height;
copy.push_constant.target[0] = p_rect.position.x;
@@ -459,7 +654,7 @@ void CopyEffects::gaussian_blur(RID p_source_rd_texture, RID p_texture, const Re
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute version of the gaussian glow with the mobile renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -483,7 +678,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
copy.push_constant.glow_white = 0; //actually unused
copy.push_constant.glow_luminance_cap = p_luminance_cap;
- copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+ copy.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
// setup our uniforms
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
@@ -510,7 +705,7 @@ void CopyEffects::gaussian_glow(RID p_source_rd_texture, RID p_back_texture, con
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) {
+void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength, bool p_high_quality, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_scale) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of the gaussian glow with the clustered renderer.");
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
@@ -518,6 +713,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
MaterialStorage *material_storage = MaterialStorage::get_singleton();
ERR_FAIL_NULL(material_storage);
+ RID half_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_half_texture);
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
memset(&blur_raster.push_constant, 0, sizeof(BlurRasterPushConstant));
BlurRasterMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW;
@@ -534,7 +732,7 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
blur_raster.push_constant.glow_white = 0; //actually unused
blur_raster.push_constant.glow_luminance_cap = p_luminance_cap;
- blur_raster.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also
+ blur_raster.push_constant.glow_auto_exposure_scale = p_auto_exposure_scale; //unused also
blur_raster.push_constant.luminance_multiplier = p_luminance_multiplier;
@@ -542,14 +740,14 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
- RD::Uniform u_rd_texture_half(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_rd_texture_half }));
+ RD::Uniform u_half_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_half_texture }));
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, blur_mode);
ERR_FAIL_COND(shader.is_null());
//HORIZONTAL
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half)));
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(half_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(half_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
if (p_auto_exposure.is_valid() && p_first_pass) {
RD::Uniform u_auto_exposure(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_auto_exposure }));
@@ -569,9 +767,9 @@ void CopyEffects::gaussian_glow_raster(RID p_source_rd_texture, float p_luminanc
ERR_FAIL_COND(shader.is_null());
//VERTICAL
- draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_rd_texture_half), 0);
+ draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_half_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
blur_raster.push_constant.flags = base_flags;
@@ -615,9 +813,11 @@ void CopyEffects::make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const
RD::get_singleton()->compute_list_end();
}
-void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size) {
+void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size) {
ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use the raster version of mipmap with the clustered renderer.");
+ RID dest_framebuffer = FramebufferCacheRD::get_singleton()->get_cache(p_dest_texture);
+
UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
ERR_FAIL_NULL(uniform_set_cache);
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -638,8 +838,8 @@ void CopyEffects::make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebu
RID shader = blur_raster.shader.version_get_shader(blur_raster.shader_version, mode);
ERR_FAIL_COND(shader.is_null());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur_raster.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(dest_framebuffer)));
RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur_raster.push_constant, sizeof(BlurRasterPushConstant));
@@ -681,3 +881,316 @@ void CopyEffects::set_color(RID p_dest_texture, const Color &p_color, const Rect
RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_region.size.width, p_region.size.height, 1);
RD::get_singleton()->compute_list_end();
}
+
+void CopyEffects::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ CopyToDPPushConstant push_constant;
+ push_constant.screen_rect[0] = p_rect.position.x;
+ push_constant.screen_rect[1] = p_rect.position.y;
+ push_constant.screen_rect[2] = p_rect.size.width;
+ push_constant.screen_rect[3] = p_rect.size.height;
+ push_constant.z_far = p_z_far;
+ push_constant.z_near = p_z_near;
+ push_constant.texel_size[0] = 1.0f / p_dst_size.x;
+ push_constant.texel_size[1] = 1.0f / p_dst_size.y;
+ push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
+}
+
+void CopyEffects::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap downsample with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ cubemap_downsampler.push_constant.face_size = p_size.x;
+ cubemap_downsampler.push_constant.face_id = 0; // we render all 6 sides to each layer in one call
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cubemap }));
+ RD::Uniform u_dest_cubemap(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_cubemap }));
+
+ RID shader = cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_cubemap), 1);
+
+ int x_groups = (p_size.x - 1) / 8 + 1;
+ int y_groups = (p_size.y - 1) / 8 + 1;
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 6); // one z_group for each face
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap downsample with the clustered renderer.");
+ ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap downsample must process one side at a time.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ cubemap_downsampler.push_constant.face_size = p_size.x;
+ cubemap_downsampler.push_constant.face_id = p_face_id;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_cubemap }));
+
+ RID shader = cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap filter with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ Vector<RD::Uniform> uniforms;
+ for (int i = 0; i < p_dest_cubemap.size(); i++) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = i;
+ u.append_id(p_dest_cubemap[i]);
+ uniforms.push_back(u);
+ }
+ if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
+ RD::get_singleton()->free(filter.image_uniform_set);
+ }
+ filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, 0), 2);
+
+ // setup our uniforms
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_cubemap }));
+
+ int mode = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY;
+ mode = filter.use_high_quality ? mode : mode + 1;
+
+ RID shader = filter.compute_shader.version_get_shader(filter.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2);
+
+ int x_groups = p_use_array ? 1792 : 342; // (128 * 128 * 7) / 64 : (128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) / 64
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, 6, 1); // one y_group for each face
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap filter with the clustered renderer.");
+ ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap filter must process one side at a time.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // TODO implement!
+ CubemapFilterRasterPushConstant push_constant;
+ push_constant.mip_level = p_mip_level;
+ push_constant.face_id = p_face_id;
+
+ // setup our uniforms
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_cubemap(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_cubemap }));
+
+ CubemapFilterMode mode = filter.use_high_quality ? FILTER_MODE_HIGH_QUALITY : FILTER_MODE_LOW_QUALITY;
+
+ RID shader = filter.raster_shader.version_get_shader(filter.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_cubemap), 0);
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CubemapFilterRasterPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
+ ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap roughness with the mobile renderer.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
+
+ roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
+ roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in.
+ roughness.push_constant.sample_count = p_sample_count;
+ roughness.push_constant.use_direct_write = p_roughness == 0.0;
+ roughness.push_constant.face_size = p_size;
+
+ // setup our uniforms
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_mipmap_sampler, p_source_rd_texture }));
+ RD::Uniform u_dest_texture(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_texture }));
+
+ RID shader = roughness.compute_shader.version_get_shader(roughness.shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
+
+ int x_groups = (p_size - 1) / 8 + 1;
+ int y_groups = (p_size - 1) / 8 + 1;
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void CopyEffects::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
+ ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap roughness with the clustered renderer.");
+ ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap roughness must process one side at a time.");
+
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
+
+ roughness.push_constant.face_id = p_face_id;
+ roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in.
+ roughness.push_constant.sample_count = p_sample_count;
+ roughness.push_constant.use_direct_write = p_roughness == 0.0;
+ roughness.push_constant.face_size = p_size;
+
+ // Setup our uniforms.
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ RID shader = roughness.raster_shader.version_get_shader(roughness.shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
+
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+void CopyEffects::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::get_singleton()->draw_command_begin_label("Merge specular");
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>());
+
+ int mode;
+ if (p_reflection.is_valid()) {
+ if (p_base.is_valid()) {
+ mode = SPECULAR_MERGE_SSR;
+ } else {
+ mode = SPECULAR_MERGE_ADDITIVE_SSR;
+ }
+ } else {
+ if (p_base.is_valid()) {
+ mode = SPECULAR_MERGE_ADD;
+ } else {
+ mode = SPECULAR_MERGE_ADDITIVE_ADD;
+ }
+ }
+
+ if (p_view_count > 1) {
+ mode += SPECULAR_MERGE_ADD_MULTIVIEW;
+ }
+
+ RID shader = specular_merge.shader.version_get_shader(specular_merge.shader_version, mode);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+
+ if (p_base.is_valid()) {
+ RD::Uniform u_base(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_base }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 2, u_base), 2);
+ }
+
+ RD::Uniform u_specular(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_specular }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_specular), 0);
+
+ if (p_reflection.is_valid()) {
+ RD::Uniform u_reflection(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_reflection }));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 1, u_reflection), 1);
+ }
+
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/effects/copy_effects.h b/servers/rendering/renderer_rd/effects/copy_effects.h
index e522408d20..0ddb60ebef 100644
--- a/servers/rendering/renderer_rd/effects/copy_effects.h
+++ b/servers/rendering/renderer_rd/effects/copy_effects.h
@@ -28,13 +28,21 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef COPY_RD_H
-#define COPY_RD_H
+#ifndef COPY_EFFECTS_RD_H
+#define COPY_EFFECTS_RD_H
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/copy.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@@ -78,7 +86,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
float luminance_multiplier;
float res1;
@@ -140,7 +148,7 @@ private:
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
// DOF.
float camera_z_far;
float camera_z_near;
@@ -189,6 +197,111 @@ private:
} copy_to_fb;
+ // Copy to DP
+
+ struct CopyToDPPushConstant {
+ float z_far;
+ float z_near;
+ float texel_size[2];
+ float screen_rect[4];
+ };
+
+ struct CopyToDP {
+ CubeToDpShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipeline;
+ } cube_to_dp;
+
+ // Cubemap effects
+
+ struct CubemapDownsamplerPushConstant {
+ uint32_t face_size;
+ uint32_t face_id;
+ float pad[2];
+ };
+
+ struct CubemapDownsampler {
+ CubemapDownsamplerPushConstant push_constant;
+ CubemapDownsamplerShaderRD compute_shader;
+ CubemapDownsamplerRasterShaderRD raster_shader;
+ RID shader_version;
+ RID compute_pipeline;
+ PipelineCacheRD raster_pipeline;
+ } cubemap_downsampler;
+
+ enum CubemapFilterMode {
+ FILTER_MODE_HIGH_QUALITY,
+ FILTER_MODE_LOW_QUALITY,
+ FILTER_MODE_HIGH_QUALITY_ARRAY,
+ FILTER_MODE_LOW_QUALITY_ARRAY,
+ FILTER_MODE_MAX,
+ };
+
+ struct CubemapFilterRasterPushConstant {
+ uint32_t mip_level;
+ uint32_t face_id;
+ float pad[2];
+ };
+
+ struct CubemapFilter {
+ CubemapFilterShaderRD compute_shader;
+ CubemapFilterRasterShaderRD raster_shader;
+ RID shader_version;
+ RID compute_pipelines[FILTER_MODE_MAX];
+ PipelineCacheRD raster_pipelines[FILTER_MODE_MAX];
+
+ RID uniform_set;
+ RID image_uniform_set;
+ RID coefficient_buffer;
+ bool use_high_quality;
+
+ } filter;
+
+ struct CubemapRoughnessPushConstant {
+ uint32_t face_id;
+ uint32_t sample_count;
+ float roughness;
+ uint32_t use_direct_write;
+ float face_size;
+ float pad[3];
+ };
+
+ struct CubemapRoughness {
+ CubemapRoughnessPushConstant push_constant;
+ CubemapRoughnessShaderRD compute_shader;
+ CubemapRoughnessRasterShaderRD raster_shader;
+ RID shader_version;
+ RID compute_pipeline;
+ PipelineCacheRD raster_pipeline;
+ } roughness;
+
+ // Merge specular
+
+ enum SpecularMergeMode {
+ SPECULAR_MERGE_ADD,
+ SPECULAR_MERGE_SSR,
+ SPECULAR_MERGE_ADDITIVE_ADD,
+ SPECULAR_MERGE_ADDITIVE_SSR,
+
+ SPECULAR_MERGE_ADD_MULTIVIEW,
+ SPECULAR_MERGE_SSR_MULTIVIEW,
+ SPECULAR_MERGE_ADDITIVE_ADD_MULTIVIEW,
+ SPECULAR_MERGE_ADDITIVE_SSR_MULTIVIEW,
+
+ SPECULAR_MERGE_MAX
+ };
+
+ /* Specular merge must be done using raster, rather than compute
+ * because it must continue the existing color buffer
+ */
+
+ struct SpecularMerge {
+ SpecularMergeShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[SPECULAR_MERGE_MAX];
+
+ } specular_merge;
+
static CopyEffects *singleton;
public:
@@ -197,6 +310,8 @@ public:
CopyEffects(bool p_prefer_raster_effects);
~CopyEffects();
+ bool get_prefer_raster_effects() { return prefer_raster_effects; }
+
void copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_all_source = false, bool p_8_bit_dst = false, bool p_alpha_to_one = false);
void copy_cubemap_to_panorama(RID p_source_cube, RID p_dest_panorama, const Size2i &p_panorama_size, float p_lod, bool p_is_array);
void copy_depth_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false);
@@ -206,15 +321,26 @@ public:
void copy_raster(RID p_source_texture, RID p_dest_framebuffer);
void gaussian_blur(RID p_source_rd_texture, RID p_texture, const Rect2i &p_region, bool p_8bit_dst = false);
- void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
- void gaussian_glow_raster(RID p_source_rd_texture, float p_luminance_multiplier, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0);
+ void gaussian_glow(RID p_source_rd_texture, RID p_back_texture, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
+ void gaussian_glow_raster(RID p_source_rd_texture, RID p_half_texture, RID p_dest_texture, float p_luminance_multiplier, const Size2i &p_size, float p_strength = 1.0, bool p_high_quality = false, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_threshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_scale = 1.0);
void make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
- void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_framebuffer, const Size2i &p_size);
+ void make_mipmap_raster(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size);
void set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst = false);
+
+ void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
+ void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
+ void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size);
+ void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
+ void cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level);
+
+ void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
+ void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
+
+ void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection, uint32_t p_view_count);
};
} // namespace RendererRD
-#endif // !COPY_RD_H
+#endif // COPY_EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/effects/fsr.cpp b/servers/rendering/renderer_rd/effects/fsr.cpp
new file mode 100644
index 0000000000..92b34ede0e
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/fsr.cpp
@@ -0,0 +1,128 @@
+/*************************************************************************/
+/* fsr.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "fsr.h"
+#include "../storage_rd/material_storage.h"
+#include "../uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+FSR::FSR() {
+ Vector<String> FSR_upscale_modes;
+
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+#else
+ // Everyone else can use normal mode when available.
+ if (RD::get_singleton()->has_feature(RD::SUPPORTS_FSR_HALF_FLOAT)) {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
+ } else {
+ FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
+ }
+#endif
+
+ fsr_shader.initialize(FSR_upscale_modes);
+
+ shader_version = fsr_shader.version_create();
+ pipeline = RD::get_singleton()->compute_pipeline_create(fsr_shader.version_get_shader(shader_version, 0));
+}
+
+FSR::~FSR() {
+ fsr_shader.version_free(shader_version);
+}
+
+void FSR::fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ Size2i target_size = p_render_buffers->get_target_size();
+ float fsr_upscale_sharpness = p_render_buffers->get_fsr_sharpness();
+
+ if (!p_render_buffers->has_texture(SNAME("FSR"), SNAME("upscale_texture"))) {
+ RD::DataFormat format = p_render_buffers->get_base_data_format();
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ uint32_t layers = 1; // we only need one layer, in multiview we're processing one layer at a time.
+
+ p_render_buffers->create_texture(SNAME("FSR"), SNAME("upscale_texture"), format, usage_bits, RD::TEXTURE_SAMPLES_1, target_size, layers);
+ }
+
+ RID upscale_texture = p_render_buffers->get_texture(SNAME("FSR"), SNAME("upscale_texture"));
+
+ FSRUpscalePushConstant push_constant;
+ memset(&push_constant, 0, sizeof(FSRUpscalePushConstant));
+
+ int dispatch_x = (target_size.x + 15) / 16;
+ int dispatch_y = (target_size.y + 15) / 16;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
+
+ push_constant.resolution_width = internal_size.width;
+ push_constant.resolution_height = internal_size.height;
+ push_constant.upscaled_width = target_size.width;
+ push_constant.upscaled_height = target_size.height;
+ push_constant.sharpness = fsr_upscale_sharpness;
+
+ RID shader = fsr_shader.version_get_shader(shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ //FSR Easc
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, p_source_rd_texture });
+ RD::Uniform u_upscale_texture(RD::UNIFORM_TYPE_IMAGE, 0, { upscale_texture });
+
+ push_constant.pass = FSR_UPSCALE_PASS_EASU;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_upscale_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //FSR Rcas
+ RD::Uniform u_upscale_texture_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, { default_sampler, upscale_texture });
+ RD::Uniform u_destination_texture(RD::UNIFORM_TYPE_IMAGE, 0, { p_destination_texture });
+
+ push_constant.pass = FSR_UPSCALE_PASS_RCAS;
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_texture_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_destination_texture), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(FSRUpscalePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
+
+ RD::get_singleton()->compute_list_end(compute_list);
+}
diff --git a/servers/rendering/renderer_rd/effects/fsr.h b/servers/rendering/renderer_rd/effects/fsr.h
new file mode 100644
index 0000000000..69088e526a
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/fsr.h
@@ -0,0 +1,72 @@
+/*************************************************************************/
+/* fsr.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef FSR_RD_H
+#define FSR_RD_H
+
+#include "../pipeline_cache_rd.h"
+#include "../shaders/effects/fsr_upscale.glsl.gen.h"
+#include "../storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class FSR {
+public:
+ FSR();
+ ~FSR();
+
+ void fsr_upscale(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_source_rd_texture, RID p_destination_texture);
+
+private:
+ enum FSRUpscalePass {
+ FSR_UPSCALE_PASS_EASU = 0,
+ FSR_UPSCALE_PASS_RCAS = 1
+ };
+
+ struct FSRUpscalePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float upscaled_width;
+ float upscaled_height;
+ float sharpness;
+ int pass;
+ int _unused0, _unused1;
+ };
+
+ FsrUpscaleShaderRD fsr_shader;
+ RID shader_version;
+ RID pipeline;
+};
+
+} // namespace RendererRD
+
+#endif // FSR_RD_H
diff --git a/servers/rendering/renderer_rd/effects/resolve.cpp b/servers/rendering/renderer_rd/effects/resolve.cpp
new file mode 100644
index 0000000000..6c49a2ebce
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/resolve.cpp
@@ -0,0 +1,130 @@
+/*************************************************************************/
+/* resolve.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "resolve.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+Resolve::Resolve() {
+ Vector<String> resolve_modes;
+ resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n");
+ resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n");
+ resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n");
+
+ resolve.shader.initialize(resolve_modes);
+
+ resolve.shader_version = resolve.shader.version_create();
+
+ for (int i = 0; i < RESOLVE_MODE_MAX; i++) {
+ resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i));
+ }
+}
+
+Resolve::~Resolve() {
+ resolve.shader.version_free(resolve.shader_version);
+}
+
+void Resolve::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ ResolvePushConstant push_constant;
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.samples = p_samples;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_depth }));
+ RD::Uniform u_source_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_source_normal_roughness }));
+ RD::Uniform u_dest_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_dest_depth }));
+ RD::Uniform u_dest_normal_roughness(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_dest_normal_roughness }));
+
+ ResolveMode mode = p_source_voxel_gi.is_valid() ? RESOLVE_MODE_GI_VOXEL_GI : RESOLVE_MODE_GI;
+ RID shader = resolve.shader.version_get_shader(resolve.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_depth, u_source_normal_roughness), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_depth, u_dest_normal_roughness), 1);
+ if (p_source_voxel_gi.is_valid()) {
+ RD::Uniform u_source_voxel_gi(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_voxel_gi }));
+ RD::Uniform u_dest_voxel_gi(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_voxel_gi);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_source_voxel_gi), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_dest_voxel_gi), 3);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1);
+
+ RD::get_singleton()->compute_list_end(p_barrier);
+}
+
+void Resolve::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ ResolvePushConstant push_constant;
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.samples = p_samples;
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_depth }));
+ RD::Uniform u_dest_depth(RD::UNIFORM_TYPE_IMAGE, 0, p_dest_depth);
+
+ ResolveMode mode = RESOLVE_MODE_DEPTH;
+ RID shader = resolve.shader.version_get_shader(resolve.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_source_depth), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_dest_depth), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1);
+
+ RD::get_singleton()->compute_list_end(p_barrier);
+}
diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h
new file mode 100644
index 0000000000..2a4cd06827
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/resolve.h
@@ -0,0 +1,74 @@
+/*************************************************************************/
+/* resolve.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RESOLVE_RD_H
+#define RESOLVE_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/resolve.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class Resolve {
+private:
+ struct ResolvePushConstant {
+ int32_t screen_size[2];
+ int32_t samples;
+ uint32_t pad;
+ };
+
+ enum ResolveMode {
+ RESOLVE_MODE_GI,
+ RESOLVE_MODE_GI_VOXEL_GI,
+ RESOLVE_MODE_DEPTH,
+ RESOLVE_MODE_MAX
+ };
+
+ struct ResolveShader {
+ ResolvePushConstant push_constant;
+ ResolveShaderRD shader;
+ RID shader_version;
+ RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels
+ } resolve;
+
+public:
+ Resolve();
+ ~Resolve();
+
+ void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+};
+
+} // namespace RendererRD
+
+#endif // RESOLVE_RD_H
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp
new file mode 100644
index 0000000000..9653382e96
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp
@@ -0,0 +1,1876 @@
+/*************************************************************************/
+/* ss_effects.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "ss_effects.h"
+
+#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+SSEffects *SSEffects::singleton = nullptr;
+
+static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ p_array[i * 4 + j] = p_mtx.columns[i][j];
+ }
+ }
+}
+
+SSEffects::SSEffects() {
+ singleton = this;
+
+ // Initialize depth buffer for screen space effects
+ {
+ Vector<String> downsampler_modes;
+ downsampler_modes.push_back("\n");
+ downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
+ downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
+ downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
+
+ ss_effects.downsample_shader.initialize(downsampler_modes);
+
+ ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
+
+ for (int i = 0; i < SS_EFFECTS_MAX; i++) {
+ ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
+ }
+
+ ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
+ SSEffectsGatherConstants gather_constants;
+
+ const int sub_pass_count = 5;
+ for (int pass = 0; pass < 4; pass++) {
+ for (int subPass = 0; subPass < sub_pass_count; subPass++) {
+ int a = pass;
+ int b = subPass;
+
+ int spmap[5]{ 0, 1, 4, 3, 2 };
+ b = spmap[subPass];
+
+ float ca, sa;
+ float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
+
+ ca = Math::cos(angle0);
+ sa = Math::sin(angle0);
+
+ float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;
+
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;
+ gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;
+ }
+ }
+
+ RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
+ }
+
+ // Initialize Screen Space Indirect Lighting (SSIL)
+ ssil_set_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to"));
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n");
+ ssil_modes.push_back("\n#define SSIL_BASE\n");
+ ssil_modes.push_back("\n#define ADAPTIVE\n");
+
+ ssil.gather_shader.initialize(ssil_modes);
+
+ ssil.gather_shader_version = ssil.gather_shader.version_create();
+
+ for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
+ }
+ ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define GENERATE_MAP\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssil_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssil.importance_map_shader.initialize(ssil_modes);
+
+ ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
+
+ for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
+ }
+ ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_WIDE\n");
+
+ ssil.blur_shader.initialize(ssil_modes);
+
+ ssil.blur_shader_version = ssil.blur_shader.version_create();
+ for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
+ }
+ }
+
+ {
+ Vector<String> ssil_modes;
+ ssil_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssil_modes.push_back("\n#define MODE_SMART\n");
+ ssil_modes.push_back("\n#define MODE_HALF\n");
+
+ ssil.interleave_shader.initialize(ssil_modes);
+
+ ssil.interleave_shader_version = ssil.interleave_shader.version_create();
+ for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
+ ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
+ }
+ }
+
+ // Initialize Screen Space Ambient Occlusion (SSAO)
+ ssao_set_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
+
+ {
+ RD::SamplerState sampler;
+ sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
+ sampler.max_lod = 4;
+
+ uint32_t pipeline = 0;
+ {
+ Vector<String> ssao_modes;
+
+ ssao_modes.push_back("\n");
+ ssao_modes.push_back("\n#define SSAO_BASE\n");
+ ssao_modes.push_back("\n#define ADAPTIVE\n");
+
+ ssao.gather_shader.initialize(ssao_modes);
+
+ ssao.gather_shader_version = ssao.gather_shader.version_create();
+
+ for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
+ pipeline++;
+ }
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define GENERATE_MAP\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPA\n");
+ ssao_modes.push_back("\n#define PROCESS_MAPB\n");
+
+ ssao.importance_map_shader.initialize(ssao_modes);
+
+ ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
+
+ for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
+
+ pipeline++;
+ }
+
+ ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
+ RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 0;
+ u.append_id(ssao.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
+ RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_WIDE\n");
+
+ ssao.blur_shader.initialize(ssao_modes);
+
+ ssao.blur_shader_version = ssao.blur_shader.version_create();
+
+ for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
+
+ pipeline++;
+ }
+ }
+
+ {
+ Vector<String> ssao_modes;
+ ssao_modes.push_back("\n#define MODE_NON_SMART\n");
+ ssao_modes.push_back("\n#define MODE_SMART\n");
+ ssao_modes.push_back("\n#define MODE_HALF\n");
+
+ ssao.interleave_shader.initialize(ssao_modes);
+
+ ssao.interleave_shader_version = ssao.interleave_shader.version_create();
+ for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
+ ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
+ RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
+ pipeline++;
+ }
+ }
+
+ ERR_FAIL_COND(pipeline != SSAO_MAX);
+
+ ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
+ }
+
+ // Screen Space Reflections
+ ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality")));
+
+ {
+ Vector<RD::PipelineSpecializationConstant> specialization_constants;
+
+ {
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 0; // SSR_USE_FULL_PROJECTION_MATRIX
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+ }
+
+ {
+ Vector<String> ssr_scale_modes;
+ ssr_scale_modes.push_back("\n");
+
+ ssr_scale.shader.initialize(ssr_scale_modes);
+ ssr_scale.shader_version = ssr_scale.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ ssr_scale.pipelines[v] = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), specialization_constants);
+ }
+ }
+
+ {
+ Vector<String> ssr_modes;
+ ssr_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_NORMAL
+ ssr_modes.push_back("\n#define MODE_ROUGH\n"); // SCREEN_SPACE_REFLECTION_ROUGH
+
+ ssr.shader.initialize(ssr_modes);
+ ssr.shader_version = ssr.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
+ ssr.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i), specialization_constants);
+ }
+ }
+ }
+
+ {
+ Vector<String> ssr_filter_modes;
+ ssr_filter_modes.push_back("\n"); // SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL
+ ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n"); // SCREEN_SPACE_REFLECTION_FILTER_VERTICAL
+
+ ssr_filter.shader.initialize(ssr_filter_modes);
+ ssr_filter.shader_version = ssr_filter.shader.version_create();
+
+ for (int v = 0; v < SSR_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SSR_MULTIVIEW) ? true : false;
+ for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
+ ssr_filter.pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i), specialization_constants);
+ }
+ }
+ }
+ }
+
+ // Subsurface scattering
+ sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
+ sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
+ sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
+
+ {
+ Vector<String> sss_modes;
+ sss_modes.push_back("\n#define USE_11_SAMPLES\n");
+ sss_modes.push_back("\n#define USE_17_SAMPLES\n");
+ sss_modes.push_back("\n#define USE_25_SAMPLES\n");
+
+ sss.shader.initialize(sss_modes);
+
+ sss.shader_version = sss.shader.version_create();
+
+ for (int i = 0; i < sss_modes.size(); i++) {
+ sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
+ }
+ }
+}
+
+SSEffects::~SSEffects() {
+ {
+ // Cleanup SS Reflections
+ ssr.shader.version_free(ssr.shader_version);
+ ssr_filter.shader.version_free(ssr_filter.shader_version);
+ ssr_scale.shader.version_free(ssr_scale.shader_version);
+
+ if (ssr.ubo.is_valid()) {
+ RD::get_singleton()->free(ssr.ubo);
+ }
+ }
+
+ {
+ // Cleanup SS downsampler
+ ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
+
+ RD::get_singleton()->free(ss_effects.mirror_sampler);
+ RD::get_singleton()->free(ss_effects.gather_constants_buffer);
+ }
+
+ {
+ // Cleanup SSIL
+ ssil.blur_shader.version_free(ssil.blur_shader_version);
+ ssil.gather_shader.version_free(ssil.gather_shader_version);
+ ssil.interleave_shader.version_free(ssil.interleave_shader_version);
+ ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
+
+ RD::get_singleton()->free(ssil.importance_map_load_counter);
+ RD::get_singleton()->free(ssil.projection_uniform_buffer);
+ }
+
+ {
+ // Cleanup SSAO
+ ssao.blur_shader.version_free(ssao.blur_shader_version);
+ ssao.gather_shader.version_free(ssao.gather_shader_version);
+ ssao.interleave_shader.version_free(ssao.interleave_shader_version);
+ ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
+
+ RD::get_singleton()->free(ssao.importance_map_load_counter);
+ }
+
+ {
+ // Cleanup Subsurface scattering
+ sss.shader.version_free(sss.shader_version);
+ }
+
+ singleton = nullptr;
+}
+
+/* SS Downsampler */
+
+void SSEffects::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // Downsample and deinterleave the depth buffer for SSAO and SSIL
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ int downsample_mode = SS_EFFECTS_DOWNSAMPLE;
+ bool use_mips = ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
+
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_HALF;
+ } else if (use_mips) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ }
+
+ bool use_half_size = false;
+ bool use_full_mips = false;
+
+ if (ssao_half_size && ssil_half_size) {
+ downsample_mode++;
+ use_half_size = true;
+ } else if (ssao_half_size != ssil_half_size) {
+ if (use_mips) {
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
+ use_full_mips = true;
+ } else {
+ // Only need the first two mipmaps, but the cost to generate the next two is trivial
+ // TODO investigate the benefit of a shader version to generate only 2 mips
+ downsample_mode = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
+ use_mips = true;
+ }
+ }
+
+ int depth_index = use_half_size ? 1 : 0;
+
+ RD::get_singleton()->draw_command_begin_label("Downsample Depth");
+ if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
+ if (ss_effects.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects.downsample_uniform_set)) {
+ RD::get_singleton()->free(ss_effects.downsample_uniform_set);
+ ss_effects.downsample_uniform_set = RID();
+ }
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_depth_mipmaps[depth_index + 1]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_depth_mipmaps[depth_index + 2]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 2;
+ u.append_id(p_depth_mipmaps[depth_index + 3]);
+ uniforms.push_back(u);
+ }
+ if (use_full_mips) {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.append_id(p_depth_mipmaps[4]);
+ uniforms.push_back(u);
+ }
+ ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
+ }
+
+ float depth_linearize_mul = -p_projection.columns[3][2];
+ float depth_linearize_add = p_projection.columns[2][2];
+ if (depth_linearize_mul * depth_linearize_add < 0) {
+ depth_linearize_add = -depth_linearize_add;
+ }
+
+ ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
+ ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
+ ss_effects.downsample_push_constant.z_far = depth_linearize_add;
+ if (ss_effects.downsample_push_constant.orthogonal) {
+ ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
+ ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
+ }
+ ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
+ ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
+ ss_effects.downsample_push_constant.radius_sq = 1.0;
+
+ RID shader = ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, downsample_mode);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_depth_buffer(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_buffer }));
+ RD::Uniform u_depth_mipmaps(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_depth_mipmaps[depth_index + 0] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_depth_buffer), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth_mipmaps), 1);
+ if (use_mips) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
+ }
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
+
+ Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
+
+ ss_effects.used_full_mips_last_frame = use_full_mips;
+ ss_effects.used_half_size_last_frame = use_half_size;
+ ss_effects.used_mips_last_frame = use_mips;
+}
+
+/* SSIL */
+
+void SSEffects::ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
+ ssil_quality = p_quality;
+ ssil_half_size = p_half_size;
+ ssil_adaptive_target = p_adaptive_target;
+ ssil_blur_passes = p_blur_passes;
+ ssil_fadeout_from = p_fadeout_from;
+ ssil_fadeout_to = p_fadeout_to;
+}
+
+void SSEffects::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
+ if ((ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
+
+ RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
+
+ for (int i = 0; i < 4; i++) {
+ if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_slices[i] }));
+ RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_edges_slices[i] }));
+
+ ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
+ ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
+ ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
+ ssil.gather_push_constant.pass = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ssil_slice, u_edges_slice), 2);
+ RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
+
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (ssil_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssil_half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
+ }
+ RD::get_singleton()->compute_list_add_barrier(p_compute_list);
+}
+
+void SSEffects::ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth) {
+ if (p_ssil_buffers.half_size != ssil_half_size) {
+ ssil_free(p_ssil_buffers);
+ }
+
+ if (ssil_half_size) {
+ p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
+ p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
+ } else {
+ p_ssil_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
+ p_ssil_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
+ p_ssil_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssil_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ }
+
+ if (p_ssil_buffers.ssil_final.is_null()) {
+ {
+ p_ssil_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = p_settings.full_screen_size.x;
+ tf.height = p_settings.full_screen_size.y;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ p_ssil_buffers.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.ssil_final, "SSIL texture");
+ RD::get_singleton()->texture_clear(p_ssil_buffers.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ if (p_ssil_buffers.last_frame.is_null()) {
+ tf.mipmaps = 6;
+ p_ssil_buffers.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.last_frame, "Last Frame Radiance");
+ RD::get_singleton()->texture_clear(p_ssil_buffers.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
+ for (uint32_t i = 0; i < 6; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.last_frame, 0, i);
+ p_ssil_buffers.last_frame_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
+ }
+ }
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.deinterleaved, "SSIL deinterleaved buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.deinterleaved, i, 0);
+ p_ssil_buffers.deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.pong, "SSIL deinterleaved pong buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.pong, i, 0);
+ p_ssil_buffers.pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssil_buffers.buffer_width;
+ tf.height = p_ssil_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.edges, "SSIL edges buffer");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssil_buffers.edges, i, 0);
+ p_ssil_buffers.edges_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_ssil_buffers.half_buffer_width;
+ tf.height = p_ssil_buffers.half_buffer_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssil_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[0], "SSIL Importance Map");
+ p_ssil_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssil_buffers.importance_map[1], "SSIL Importance Map Pong");
+ }
+ p_ssil_buffers.half_size = ssil_half_size;
+ }
+}
+
+void SSEffects::screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
+ //Store projection info before starting the compute list
+ SSILProjectionUniforms projection_uniforms;
+ store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
+
+ RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
+
+ memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
+
+ RID shader = ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ RID default_mipmap_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ {
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
+
+ ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
+ ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
+ ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
+ ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
+ ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
+ ssil.gather_push_constant.z_near = p_projection.get_z_near();
+ ssil.gather_push_constant.z_far = p_projection.get_z_far();
+ ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
+
+ ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
+ ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+
+ ssil.gather_push_constant.radius = p_settings.radius;
+ float radius_near_limit = (p_settings.radius * 1.2f);
+ if (ssil_quality <= RS::ENV_SSIL_QUALITY_LOW) {
+ radius_near_limit *= 1.50f;
+
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ ssil.gather_push_constant.radius *= 0.8f;
+ }
+ }
+ radius_near_limit /= tan_half_fov_y;
+ ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
+ ssil.gather_push_constant.fade_out_mul = -1.0 / (ssil_fadeout_to - ssil_fadeout_from);
+ ssil.gather_push_constant.fade_out_add = ssil_fadeout_from / (ssil_fadeout_to - ssil_fadeout_from) + 1.0;
+ ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
+ ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
+ ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
+
+ ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssil_buffers.half_buffer_width) * (p_ssil_buffers.half_buffer_height) * 255);
+ ssil.gather_push_constant.adaptive_sample_limit = ssil_adaptive_target;
+
+ ssil.gather_push_constant.quality = MAX(0, ssil_quality - 1);
+ ssil.gather_push_constant.size_multiplier = ssil_half_size ? 2 : 1;
+
+ if (p_ssil_buffers.projection_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_mipmap_sampler);
+ u.append_id(p_ssil_buffers.last_frame);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 1;
+ u.append_id(ssil.projection_uniform_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
+ }
+
+ if (p_ssil_buffers.gather_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_sampler);
+ u.append_id(p_ssil_buffers.depth_texture_view);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_normal_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(ss_effects.gather_constants_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
+ }
+
+ if (p_ssil_buffers.importance_map_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_ssil_buffers.pong);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.append_id(default_sampler);
+ u.append_id(p_ssil_buffers.importance_map[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(ssil.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ p_ssil_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
+ }
+
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
+ ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+ ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
+ //base pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
+ gather_ssil(compute_list, p_ssil_buffers.pong_slices, p_ssil_buffers.edges_slices, p_settings, true, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+
+ //generate importance map
+ RD::Uniform u_ssil_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[0] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // process Importance Map A
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[0] }));
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.importance_map[1] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // process Importance Map B
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.importance_map[1] }));
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssil_buffers.half_buffer_width, p_ssil_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
+ }
+
+ gather_ssil(compute_list, p_ssil_buffers.deinterleaved_slices, p_ssil_buffers.edges_slices, p_settings, false, p_ssil_buffers.gather_uniform_set, p_ssil_buffers.importance_map_uniform_set, p_ssil_buffers.projection_uniform_set);
+ RD::get_singleton()->draw_command_end_label(); //Gather
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
+ ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
+ ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssil_buffers.buffer_width;
+ ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssil_buffers.buffer_height;
+
+ int blur_passes = ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? ssil_blur_passes : 1;
+
+ shader = ssil.blur_shader.version_get_shader(ssil.blur_shader_version, 0);
+
+ for (int pass = 0; pass < blur_passes; pass++) {
+ int blur_pipeline = SSIL_BLUR_PASS;
+ if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ blur_pipeline = SSIL_BLUR_PASS_SMART;
+ if (pass < blur_passes - 2) {
+ blur_pipeline = SSIL_BLUR_PASS_WIDE;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if ((ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
+ if (pass % 2 == 0) {
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ } else {
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_slice), 0);
+ }
+
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong_slice), 1);
+ } else {
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ } else {
+ RD::Uniform u_ssil_pong_slice(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssil_buffers.pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ssil_pong_slice), 0);
+ }
+
+ RD::Uniform u_ssil_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_slice), 1);
+ }
+
+ RD::Uniform u_edges_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges_slice), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
+
+ int x_groups = (p_settings.full_screen_size.x >> (ssil_half_size ? 2 : 1));
+ int y_groups = (p_settings.full_screen_size.y >> (ssil_half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
+ if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ }
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // Blur
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
+ ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
+ ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
+ ssil.interleave_push_constant.size_modifier = uint32_t(ssil_half_size ? 4 : 2);
+
+ int interleave_pipeline = SSIL_INTERLEAVE_HALF;
+ if (ssil_quality == RS::ENV_SSIL_QUALITY_LOW) {
+ interleave_pipeline = SSIL_INTERLEAVE;
+ } else if (ssil_quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
+ interleave_pipeline = SSIL_INTERLEAVE_SMART;
+ }
+
+ shader = ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, 0);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
+
+ RD::Uniform u_destination(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.ssil_final }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_destination), 0);
+
+ if (ssil_quality > RS::ENV_SSIL_QUALITY_VERY_LOW && ssil_blur_passes % 2 == 0) {
+ RD::Uniform u_ssil(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.deinterleaved }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil), 1);
+ } else {
+ RD::Uniform u_ssil_pong(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssil_buffers.pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ssil_pong), 1);
+ }
+
+ RD::Uniform u_edges(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssil_buffers.edges }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_edges), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
+ }
+
+ RD::get_singleton()->draw_command_end_label(); // SSIL
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
+
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
+}
+
+void SSEffects::ssil_free(SSILRenderBuffers &p_ssil_buffers) {
+ if (p_ssil_buffers.ssil_final.is_valid()) {
+ RD::get_singleton()->free(p_ssil_buffers.ssil_final);
+ RD::get_singleton()->free(p_ssil_buffers.deinterleaved);
+ RD::get_singleton()->free(p_ssil_buffers.pong);
+ RD::get_singleton()->free(p_ssil_buffers.edges);
+ RD::get_singleton()->free(p_ssil_buffers.importance_map[0]);
+ RD::get_singleton()->free(p_ssil_buffers.importance_map[1]);
+ RD::get_singleton()->free(p_ssil_buffers.last_frame);
+
+ p_ssil_buffers.ssil_final = RID();
+ p_ssil_buffers.deinterleaved = RID();
+ p_ssil_buffers.pong = RID();
+ p_ssil_buffers.edges = RID();
+ p_ssil_buffers.deinterleaved_slices.clear();
+ p_ssil_buffers.pong_slices.clear();
+ p_ssil_buffers.edges_slices.clear();
+ p_ssil_buffers.importance_map[0] = RID();
+ p_ssil_buffers.importance_map[1] = RID();
+ p_ssil_buffers.last_frame = RID();
+ p_ssil_buffers.last_frame_slices.clear();
+
+ p_ssil_buffers.gather_uniform_set = RID();
+ p_ssil_buffers.importance_map_uniform_set = RID();
+ p_ssil_buffers.projection_uniform_set = RID();
+ }
+}
+
+/* SSAO */
+
+void SSEffects::ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
+ ssao_quality = p_quality;
+ ssao_half_size = p_half_size;
+ ssao_adaptive_target = p_adaptive_target;
+ ssao_blur_passes = p_blur_passes;
+ ssao_fadeout_from = p_fadeout_from;
+ ssao_fadeout_to = p_fadeout_to;
+}
+
+void SSEffects::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
+ if ((ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 0);
+ }
+
+ RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 1); //
+
+ for (int i = 0; i < 4; i++) {
+ if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::Uniform u_ao_slice(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ao_slices[i] }));
+
+ ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
+ ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
+ ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
+ ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
+ ssao.gather_push_constant.pass = i;
+ RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, uniform_set_cache->get_cache(shader, 2, u_ao_slice), 2);
+ RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
+
+ Size2i size = Size2i(p_settings.full_screen_size.x >> (ssao_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssao_half_size ? 2 : 1));
+
+ RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
+ }
+ RD::get_singleton()->compute_list_add_barrier(p_compute_list);
+}
+
+void SSEffects::ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth) {
+ if (p_ssao_buffers.half_size != ssao_half_size) {
+ ssao_free(p_ssao_buffers);
+ }
+
+ if (ssao_half_size) {
+ p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 7) / 8;
+ p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 7) / 8;
+ } else {
+ p_ssao_buffers.buffer_width = (p_settings.full_screen_size.x + 1) / 2;
+ p_ssao_buffers.buffer_height = (p_settings.full_screen_size.y + 1) / 2;
+ p_ssao_buffers.half_buffer_width = (p_settings.full_screen_size.x + 3) / 4;
+ p_ssao_buffers.half_buffer_height = (p_settings.full_screen_size.y + 3) / 4;
+ }
+
+ if (p_ssao_buffers.ao_deinterleaved.is_null()) {
+ {
+ p_ssao_buffers.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_deinterleaved, "SSAO De-interleaved Array");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_deinterleaved, i, 0);
+ p_ssao_buffers.ao_deinterleaved_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8G8_UNORM;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_pong, "SSAO De-interleaved Array Pong");
+ for (uint32_t i = 0; i < 4; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssao_buffers.ao_pong, i, 0);
+ p_ssao_buffers.ao_pong_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
+ }
+ }
+
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_ssao_buffers.buffer_width;
+ tf.height = p_ssao_buffers.buffer_height;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[0], "SSAO Importance Map");
+ p_ssao_buffers.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map[1], "SSAO Importance Map Pong");
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_settings.full_screen_size.x;
+ tf.height = p_settings.full_screen_size.y;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ p_ssao_buffers.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.ao_final, "SSAO Final");
+ }
+ p_ssao_buffers.half_size = ssao_half_size;
+ }
+}
+
+void SSEffects::generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
+ /* FIRST PASS */
+
+ RID shader = ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0);
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
+ /* SECOND PASS */
+ // Sample SSAO
+ {
+ RD::get_singleton()->draw_command_begin_label("Gather Samples");
+ ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
+ ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
+
+ ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ float tan_half_fov_x = 1.0 / p_projection.columns[0][0];
+ float tan_half_fov_y = 1.0 / p_projection.columns[1][1];
+ ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
+ ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
+ ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
+ ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
+ ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
+
+ ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
+ ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
+
+ ssao.gather_push_constant.radius = p_settings.radius;
+ float radius_near_limit = (p_settings.radius * 1.2f);
+ if (ssao_quality <= RS::ENV_SSAO_QUALITY_LOW) {
+ radius_near_limit *= 1.50f;
+
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ ssao.gather_push_constant.radius *= 0.8f;
+ }
+ }
+ radius_near_limit /= tan_half_fov_y;
+ ssao.gather_push_constant.intensity = p_settings.intensity;
+ ssao.gather_push_constant.shadow_power = p_settings.power;
+ ssao.gather_push_constant.shadow_clamp = 0.98;
+ ssao.gather_push_constant.fade_out_mul = -1.0 / (ssao_fadeout_to - ssao_fadeout_from);
+ ssao.gather_push_constant.fade_out_add = ssao_fadeout_from / (ssao_fadeout_to - ssao_fadeout_from) + 1.0;
+ ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
+ ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
+ ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
+
+ ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_ssao_buffers.half_buffer_width) * (p_ssao_buffers.half_buffer_height) * 255);
+ ssao.gather_push_constant.adaptive_sample_limit = ssao_adaptive_target;
+
+ ssao.gather_push_constant.detail_intensity = p_settings.detail;
+ ssao.gather_push_constant.quality = MAX(0, ssao_quality - 1);
+ ssao.gather_push_constant.size_multiplier = ssao_half_size ? 2 : 1;
+
+ if (p_ssao_buffers.gather_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 0;
+ u.append_id(default_sampler);
+ u.append_id(p_ssao_buffers.depth_texture_view);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 1;
+ u.append_id(p_normal_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(ss_effects.gather_constants_buffer);
+ uniforms.push_back(u);
+ }
+ p_ssao_buffers.gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader, 0);
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.gather_uniform_set, "SSAO Gather Uniform Set");
+ }
+
+ if (p_ssao_buffers.importance_map_uniform_set.is_null()) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 0;
+ u.append_id(p_ssao_buffers.ao_pong);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
+ u.binding = 1;
+ u.append_id(default_sampler);
+ u.append_id(p_ssao_buffers.importance_map[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(ssao.importance_map_load_counter);
+ uniforms.push_back(u);
+ }
+ p_ssao_buffers.importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
+ RD::get_singleton()->set_resource_name(p_ssao_buffers.importance_map_uniform_set, "SSAO Importance Map Uniform Set");
+ }
+
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_ULTRA) {
+ RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
+ ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+ ssao.importance_map_push_constant.intensity = p_settings.intensity;
+ ssao.importance_map_push_constant.power = p_settings.power;
+
+ //base pass
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
+ gather_ssao(compute_list, p_ssao_buffers.ao_pong_slices, p_settings, true, p_ssao_buffers.gather_uniform_set, RID());
+
+ //generate importance map
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
+
+ RD::Uniform u_ao_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_with_sampler), 0);
+
+ RD::Uniform u_importance_map(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //process importance map A
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
+
+ RD::Uniform u_importance_map_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_with_sampler), 0);
+
+ RD::Uniform u_importance_map_pong(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.importance_map[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map_pong), 1);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ //process Importance Map B
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
+
+ RD::Uniform u_importance_map_pong_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.importance_map[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_importance_map_pong_with_sampler), 0);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_importance_map), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_ssao_buffers.half_buffer_width, p_ssao_buffers.half_buffer_height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
+ RD::get_singleton()->draw_command_end_label(); // Importance Map
+ } else {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
+ }
+
+ gather_ssao(compute_list, p_ssao_buffers.ao_deinterleaved_slices, p_settings, false, p_ssao_buffers.gather_uniform_set, p_ssao_buffers.importance_map_uniform_set);
+ RD::get_singleton()->draw_command_end_label(); // Gather SSAO
+ }
+
+ // /* THIRD PASS */
+ // // Blur
+ //
+ {
+ RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
+ ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
+ ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_ssao_buffers.buffer_width;
+ ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_ssao_buffers.buffer_height;
+
+ int blur_passes = ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? ssao_blur_passes : 1;
+
+ shader = ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0);
+
+ for (int pass = 0; pass < blur_passes; pass++) {
+ int blur_pipeline = SSAO_BLUR_PASS;
+ if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
+ if (pass < blur_passes - 2) {
+ blur_pipeline = SSAO_BLUR_PASS_WIDE;
+ } else {
+ blur_pipeline = SSAO_BLUR_PASS_SMART;
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if ((ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
+ continue;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
+ if (pass % 2 == 0) {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ } else {
+ RD::Uniform u_ao_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_slices_with_sampler), 0);
+ }
+
+ RD::Uniform u_ao_pong_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_pong_slices), 1);
+ } else {
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ } else {
+ RD::Uniform u_ao_pong_slices_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ ss_effects.mirror_sampler, p_ssao_buffers.ao_pong_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_ao_pong_slices_with_sampler), 0);
+ }
+
+ RD::Uniform u_ao_slices(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_deinterleaved_slices[i] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao_slices), 1);
+ }
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
+
+ Size2i size(p_settings.full_screen_size.x >> (ssao_half_size ? 2 : 1), p_settings.full_screen_size.y >> (ssao_half_size ? 2 : 1));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
+ }
+
+ if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ }
+ RD::get_singleton()->draw_command_end_label(); // Blur
+ }
+
+ /* FOURTH PASS */
+ // Interleave buffers
+ // back to full size
+ {
+ RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
+ ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
+ ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
+ ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
+ ssao.interleave_push_constant.size_modifier = uint32_t(ssao_half_size ? 4 : 2);
+
+ shader = ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, 0);
+
+ int interleave_pipeline = SSAO_INTERLEAVE_HALF;
+ if (ssao_quality == RS::ENV_SSAO_QUALITY_LOW) {
+ interleave_pipeline = SSAO_INTERLEAVE;
+ } else if (ssao_quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
+ interleave_pipeline = SSAO_INTERLEAVE_SMART;
+ }
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
+
+ RD::Uniform u_upscale_buffer(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssao_buffers.ao_final }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_upscale_buffer), 0);
+
+ if (ssao_quality > RS::ENV_SSAO_QUALITY_VERY_LOW && ssao_blur_passes % 2 == 0) {
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_deinterleaved }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ } else {
+ RD::Uniform u_ao(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_ssao_buffers.ao_pong }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_ao), 1);
+ }
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label(); // Interleave
+ }
+ RD::get_singleton()->draw_command_end_label(); //SSAO
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
+
+ int zero[1] = { 0 };
+ RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
+}
+
+void SSEffects::ssao_free(SSAORenderBuffers &p_ssao_buffers) {
+ if (p_ssao_buffers.ao_final.is_valid()) {
+ RD::get_singleton()->free(p_ssao_buffers.ao_deinterleaved);
+ RD::get_singleton()->free(p_ssao_buffers.ao_pong);
+ RD::get_singleton()->free(p_ssao_buffers.ao_final);
+
+ RD::get_singleton()->free(p_ssao_buffers.importance_map[0]);
+ RD::get_singleton()->free(p_ssao_buffers.importance_map[1]);
+
+ p_ssao_buffers.ao_deinterleaved = RID();
+ p_ssao_buffers.ao_pong = RID();
+ p_ssao_buffers.ao_final = RID();
+ p_ssao_buffers.importance_map[0] = RID();
+ p_ssao_buffers.importance_map[1] = RID();
+ p_ssao_buffers.ao_deinterleaved_slices.clear();
+ p_ssao_buffers.ao_pong_slices.clear();
+
+ p_ssao_buffers.gather_uniform_set = RID();
+ p_ssao_buffers.importance_map_uniform_set = RID();
+ }
+}
+
+/* Screen Space Reflection */
+
+void SSEffects::ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
+ ssr_roughness_quality = p_quality;
+}
+
+void SSEffects::ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count) {
+ // As we are processing one view at a time, we can reuse buffers, only our output needs to have layers for each view.
+ if (p_ssr_buffers.size != p_screen_size || p_ssr_buffers.roughness_quality != ssr_roughness_quality) {
+ ssr_free(p_ssr_buffers);
+ }
+
+ if (p_ssr_buffers.output.is_valid()) {
+ // already allocated
+ return;
+ }
+
+ p_ssr_buffers.size = p_screen_size;
+ p_ssr_buffers.roughness_quality = ssr_roughness_quality;
+
+ if (p_ssr_buffers.depth_scaled.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R32_SFLOAT;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_ssr_buffers.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.depth_scaled, "SSR Depth Scaled");
+
+ tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+
+ p_ssr_buffers.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.normal_scaled, "SSR Normal Scaled");
+ }
+
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !p_ssr_buffers.blur_radius[0].is_valid()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ p_ssr_buffers.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[0], "SSR Blur Radius 0");
+ p_ssr_buffers.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.blur_radius[1], "SSR Blur Radius 1");
+ }
+
+ if (p_ssr_buffers.intermediate.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = p_color_format;
+ tf.width = p_screen_size.x;
+ tf.height = p_screen_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_ssr_buffers.intermediate = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.intermediate, "SSR Intermediate");
+
+ if (p_view_count > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.array_layers = p_view_count;
+ } else {
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1;
+ }
+
+ p_ssr_buffers.output = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(p_ssr_buffers.output, "SSR Output");
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ p_ssr_buffers.output_slices[v] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_ssr_buffers.output, v, 0);
+ }
+ }
+}
+
+void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ {
+ // Store some scene data in a UBO, in the near future we will use a UBO shared with other shaders
+ ScreenSpaceReflectionSceneData scene_data;
+
+ if (ssr.ubo.is_null()) {
+ ssr.ubo = RD::get_singleton()->uniform_buffer_create(sizeof(ScreenSpaceReflectionSceneData));
+ }
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ store_camera(p_projections[v], scene_data.projection[v]);
+ store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
+ scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
+ scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
+ scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
+ scene_data.eye_offset[v][3] = 0.0;
+ }
+
+ RD::get_singleton()->buffer_update(ssr.ubo, 0, sizeof(ScreenSpaceReflectionSceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
+ }
+
+ uint32_t pipeline_specialization = 0;
+ if (p_view_count > 1) {
+ pipeline_specialization |= SSR_MULTIVIEW;
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ RD::get_singleton()->draw_command_begin_label(String("SSR View ") + itos(v));
+
+ { //scale color and depth to half
+ RD::get_singleton()->draw_command_begin_label("SSR Scale");
+
+ ScreenSpaceReflectionScalePushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.camera_z_far = p_projections[v].get_z_far();
+ push_constant.camera_z_near = p_projections[v].get_z_near();
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.filter = false; //enabling causes arctifacts
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+
+ RID shader = ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipelines[pipeline_specialization]);
+
+ RD::Uniform u_diffuse(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse), 0);
+
+ RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth_slices[v] }));
+ RD::Uniform u_normal_roughness(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, Vector<RID>({ default_sampler, p_normal_roughness_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_depth, u_normal_roughness), 1);
+
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output), 2);
+ } else {
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
+ }
+
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth, u_scale_normal), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ {
+ RD::get_singleton()->draw_command_begin_label("SSR main");
+
+ ScreenSpaceReflectionPushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.camera_z_far = p_projections[v].get_z_far();
+ push_constant.camera_z_near = p_projections[v].get_z_near();
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.screen_size[0] = p_screen_size.x;
+ push_constant.screen_size[1] = p_screen_size.y;
+ push_constant.curve_fade_in = p_fade_in;
+ push_constant.distance_fade = p_fade_out;
+ push_constant.num_steps = p_max_steps;
+ push_constant.depth_tolerance = p_tolerance;
+ push_constant.use_half_res = true;
+ push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
+
+ ScreenSpaceReflectionMode mode = (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL;
+ RID shader = ssr.shader.version_get_shader(ssr.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[pipeline_specialization][mode]);
+
+ RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ // read from output slices (our scale wrote into these)
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output, u_scale_depth), 0);
+
+ // write to intermediate (our roughness pass will output into output slices)
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate, u_blur_radius), 1);
+ } else {
+ // read from intermediate (our scale wrote into these)
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_scale_depth), 0);
+
+ // We are not performing our blur so go directly to output.
+ RD::Uniform u_output(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_output), 1);
+ }
+
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_scale_normal), 2);
+
+ RD::Uniform u_metallic(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_metallic_slices[v] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_metallic), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
+ RD::get_singleton()->draw_command_begin_label("SSR filter");
+ //blur
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ ScreenSpaceReflectionFilterPushConstant push_constant;
+ push_constant.view_index = v;
+ push_constant.orthogonal = p_projections[v].is_orthogonal();
+ push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0));
+ push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].columns[0][0]);
+ push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].columns[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[v].columns[0][2]) / p_projections[v].columns[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[v].columns[1][2]) / p_projections[v].columns[1][1];
+ push_constant.vertical = 0;
+ if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
+ push_constant.steps = p_max_steps / 3;
+ push_constant.increment = 3;
+ } else if (ssr_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
+ push_constant.steps = p_max_steps / 2;
+ push_constant.increment = 2;
+ } else {
+ push_constant.steps = p_max_steps;
+ push_constant.increment = 1;
+ }
+
+ push_constant.screen_size[0] = p_screen_size.width;
+ push_constant.screen_size[1] = p_screen_size.height;
+
+ // Horizontal pass
+
+ SSRReflectionMode mode = SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL;
+
+ RID shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
+
+ RD::Uniform u_scene_data(RD::UNIFORM_TYPE_UNIFORM_BUFFER, 0, ssr.ubo);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.intermediate }));
+ RD::Uniform u_blur_radius(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[0] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate, u_blur_radius), 0);
+
+ RD::Uniform u_scale_normal(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.normal_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
+
+ RD::Uniform u_output_blur(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.output_slices[v] }));
+ RD::Uniform u_blur_radius2(RD::UNIFORM_TYPE_IMAGE, 1, Vector<RID>({ p_ssr_buffers.blur_radius[1] }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_output_blur, u_blur_radius2), 2);
+
+ RD::Uniform u_scale_depth(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_ssr_buffers.depth_scaled }));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // Vertical pass
+
+ mode = SCREEN_SPACE_REFLECTION_FILTER_VERTICAL;
+ shader = ssr_filter.shader.version_get_shader(ssr_filter.shader_version, mode);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[pipeline_specialization][mode]);
+
+ push_constant.vertical = 1;
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_output_blur, u_blur_radius2), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_scale_normal), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_intermediate), 2);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 3, u_scale_depth), 3);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 4, u_scene_data), 4);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ if (v != p_view_count - 1) {
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RD::get_singleton()->compute_list_end();
+}
+
+void SSEffects::ssr_free(SSRRenderBuffers &p_ssr_buffers) {
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ p_ssr_buffers.output_slices[v] = RID();
+ }
+
+ if (p_ssr_buffers.output.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.output);
+ p_ssr_buffers.output = RID();
+ }
+
+ if (p_ssr_buffers.intermediate.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.intermediate);
+ p_ssr_buffers.intermediate = RID();
+ }
+
+ if (p_ssr_buffers.blur_radius[0].is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.blur_radius[0]);
+ RD::get_singleton()->free(p_ssr_buffers.blur_radius[1]);
+ p_ssr_buffers.blur_radius[0] = RID();
+ p_ssr_buffers.blur_radius[1] = RID();
+ }
+
+ if (p_ssr_buffers.depth_scaled.is_valid()) {
+ RD::get_singleton()->free(p_ssr_buffers.depth_scaled);
+ p_ssr_buffers.depth_scaled = RID();
+ RD::get_singleton()->free(p_ssr_buffers.normal_scaled);
+ p_ssr_buffers.normal_scaled = RID();
+ }
+}
+
+/* Subsurface scattering */
+
+void SSEffects::sss_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
+ sss_quality = p_quality;
+}
+
+RS::SubSurfaceScatteringQuality SSEffects::sss_get_quality() const {
+ return sss_quality;
+}
+
+void SSEffects::sss_set_scale(float p_scale, float p_depth_scale) {
+ sss_scale = p_scale;
+ sss_depth_scale = p_depth_scale;
+}
+
+void SSEffects::sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ // Our intermediate buffer is only created if we haven't created it already.
+ RD::DataFormat format = p_render_buffers->get_base_data_format();
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ uint32_t layers = 1; // We only need one layer, we're handling one view at a time
+ uint32_t mipmaps = 1; // Image::get_image_required_mipmaps(p_screen_size.x, p_screen_size.y, Image::FORMAT_RGBAH);
+ RID intermediate = p_render_buffers->create_texture(SNAME("SSR"), SNAME("intermediate"), format, usage_bits, RD::TEXTURE_SAMPLES_1, p_screen_size, layers, mipmaps);
+
+ Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
+ p.normal /= p.d;
+ float unit_size = p.normal.x;
+
+ { //scale color and depth to half
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ sss.push_constant.camera_z_far = p_camera.get_z_far();
+ sss.push_constant.camera_z_near = p_camera.get_z_near();
+ sss.push_constant.orthogonal = p_camera.is_orthogonal();
+ sss.push_constant.unit_size = unit_size;
+ sss.push_constant.screen_size[0] = p_screen_size.x;
+ sss.push_constant.screen_size[1] = p_screen_size.y;
+ sss.push_constant.vertical = false;
+ sss.push_constant.scale = sss_scale;
+ sss.push_constant.depth_scale = sss_depth_scale;
+
+ RID shader = sss.shader.version_get_shader(sss.shader_version, sss_quality - 1);
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[sss_quality - 1]);
+
+ RD::Uniform u_diffuse_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_diffuse }));
+ RD::Uniform u_diffuse(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ p_diffuse }));
+ RD::Uniform u_intermediate_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, intermediate }));
+ RD::Uniform u_intermediate(RD::UNIFORM_TYPE_IMAGE, 0, Vector<RID>({ intermediate }));
+ RD::Uniform u_depth_with_sampler(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_depth }));
+
+ // horizontal
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_diffuse_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_intermediate), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
+
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // vertical
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_intermediate_with_sampler), 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 1, u_diffuse), 1);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 2, u_depth_with_sampler), 2);
+
+ sss.push_constant.vertical = true;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
+
+ RD::get_singleton()->compute_list_end();
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/ss_effects.h b/servers/rendering/renderer_rd/effects/ss_effects.h
new file mode 100644
index 0000000000..dfaf3881bb
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/ss_effects.h
@@ -0,0 +1,552 @@
+/*************************************************************************/
+/* ss_effects.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef SS_EFFECTS_RD_H
+#define SS_EFFECTS_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering_server.h"
+
+class RenderSceneBuffersRD;
+
+namespace RendererRD {
+
+class SSEffects {
+private:
+ static SSEffects *singleton;
+
+public:
+ static SSEffects *get_singleton() { return singleton; }
+
+ SSEffects();
+ ~SSEffects();
+
+ /* SS Downsampler */
+
+ void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, bool p_invalidate_uniform_set, Size2i p_full_screen_size, const Projection &p_projection);
+
+ /* SSIL */
+ void ssil_set_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
+
+ struct SSILRenderBuffers {
+ bool half_size = false;
+ int buffer_width;
+ int buffer_height;
+ int half_buffer_width;
+ int half_buffer_height;
+
+ RID ssil_final;
+ RID deinterleaved;
+ Vector<RID> deinterleaved_slices;
+ RID pong;
+ Vector<RID> pong_slices;
+ RID edges;
+ Vector<RID> edges_slices;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID last_frame;
+ Vector<RID> last_frame_slices;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ RID projection_uniform_set;
+ };
+
+ struct SSILSettings {
+ float radius = 1.0;
+ float intensity = 2.0;
+ float sharpness = 0.98;
+ float normal_rejection = 1.0;
+
+ Size2i full_screen_size = Size2i();
+ };
+
+ void ssil_allocate_buffers(SSILRenderBuffers &p_ssil_buffers, const SSILSettings &p_settings, RID p_linear_depth);
+ void screen_space_indirect_lighting(SSILRenderBuffers &p_ssil_buffers, RID p_normal_buffer, const Projection &p_projection, const Projection &p_last_projection, const SSILSettings &p_settings);
+ void ssil_free(SSILRenderBuffers &p_ssil_buffers);
+
+ /* SSAO */
+ void ssao_set_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to);
+
+ struct SSAORenderBuffers {
+ bool half_size = false;
+ int buffer_width;
+ int buffer_height;
+ int half_buffer_width;
+ int half_buffer_height;
+
+ RID ao_deinterleaved;
+ Vector<RID> ao_deinterleaved_slices;
+ RID ao_pong;
+ Vector<RID> ao_pong_slices;
+ RID ao_final;
+ RID importance_map[2];
+ RID depth_texture_view;
+
+ RID gather_uniform_set;
+ RID importance_map_uniform_set;
+ };
+
+ struct SSAOSettings {
+ float radius = 1.0;
+ float intensity = 2.0;
+ float power = 1.5;
+ float detail = 0.5;
+ float horizon = 0.06;
+ float sharpness = 0.98;
+
+ Size2i full_screen_size = Size2i();
+ };
+
+ void ssao_allocate_buffers(SSAORenderBuffers &p_ssao_buffers, const SSAOSettings &p_settings, RID p_linear_depth);
+ void generate_ssao(SSAORenderBuffers &p_ssao_buffers, RID p_normal_buffer, const Projection &p_projection, const SSAOSettings &p_settings);
+ void ssao_free(SSAORenderBuffers &p_ssao_buffers);
+
+ /* Screen Space Reflection */
+ void ssr_set_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality);
+
+ struct SSRRenderBuffers {
+ Size2i size;
+ RenderingServer::EnvironmentSSRRoughnessQuality roughness_quality = RenderingServer::ENV_SSR_ROUGHNESS_QUALITY_DISABLED;
+
+ RID normal_scaled;
+ RID depth_scaled;
+ RID blur_radius[2];
+ RID intermediate;
+ RID output;
+ RID output_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ };
+
+ void ssr_allocate_buffers(SSRRenderBuffers &p_ssr_buffers, const RenderingDevice::DataFormat p_color_format, const Size2i &p_screen_size, const uint32_t p_view_count);
+ void screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const RID *p_diffuse_slices, const RID *p_normal_roughness_slices, const RID *p_metallic_slices, const RID *p_depth_slices, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets);
+ void ssr_free(SSRRenderBuffers &p_ssr_buffers);
+
+ /* subsurface scattering */
+ void sss_set_quality(RS::SubSurfaceScatteringQuality p_quality);
+ RS::SubSurfaceScatteringQuality sss_get_quality() const;
+ void sss_set_scale(float p_scale, float p_depth_scale);
+
+ void sub_surface_scattering(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_diffuse, RID p_depth, const Projection &p_camera, const Size2i &p_screen_size);
+
+private:
+ /* Settings */
+
+ RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
+ bool ssao_half_size = false;
+ float ssao_adaptive_target = 0.5;
+ int ssao_blur_passes = 2;
+ float ssao_fadeout_from = 50.0;
+ float ssao_fadeout_to = 300.0;
+
+ RS::EnvironmentSSILQuality ssil_quality = RS::ENV_SSIL_QUALITY_MEDIUM;
+ bool ssil_half_size = false;
+ float ssil_adaptive_target = 0.5;
+ int ssil_blur_passes = 4;
+ float ssil_fadeout_from = 50.0;
+ float ssil_fadeout_to = 300.0;
+
+ RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
+
+ RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM;
+ float sss_scale = 0.05;
+ float sss_depth_scale = 0.01;
+
+ /* SS Downsampler */
+
+ struct SSEffectsDownsamplePushConstant {
+ float pixel_size[2];
+ float z_far;
+ float z_near;
+ uint32_t orthogonal;
+ float radius_sq;
+ uint32_t pad[2];
+ };
+
+ enum SSEffectsMode {
+ SS_EFFECTS_DOWNSAMPLE,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP,
+ SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES,
+ SS_EFFECTS_DOWNSAMPLE_HALF,
+ SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF,
+ SS_EFFECTS_DOWNSAMPLE_FULL_MIPS,
+ SS_EFFECTS_MAX
+ };
+
+ struct SSEffectsGatherConstants {
+ float rotation_matrices[80]; //5 vec4s * 4
+ };
+
+ struct SSEffectsShader {
+ SSEffectsDownsamplePushConstant downsample_push_constant;
+ SsEffectsDownsampleShaderRD downsample_shader;
+ RID downsample_shader_version;
+ RID downsample_uniform_set;
+ bool used_half_size_last_frame = false;
+ bool used_mips_last_frame = false;
+ bool used_full_mips_last_frame = false;
+
+ RID gather_constants_buffer;
+
+ RID mirror_sampler;
+
+ RID pipelines[SS_EFFECTS_MAX];
+ } ss_effects;
+
+ /* SSIL */
+
+ enum SSILMode {
+ SSIL_GATHER,
+ SSIL_GATHER_BASE,
+ SSIL_GATHER_ADAPTIVE,
+ SSIL_GENERATE_IMPORTANCE_MAP,
+ SSIL_PROCESS_IMPORTANCE_MAPA,
+ SSIL_PROCESS_IMPORTANCE_MAPB,
+ SSIL_BLUR_PASS,
+ SSIL_BLUR_PASS_SMART,
+ SSIL_BLUR_PASS_WIDE,
+ SSIL_INTERLEAVE,
+ SSIL_INTERLEAVE_SMART,
+ SSIL_INTERLEAVE_HALF,
+ SSIL_MAX
+ };
+
+ struct SSILGatherPushConstant {
+ int32_t screen_size[2];
+ int pass;
+ int quality;
+
+ float half_screen_pixel_size[2];
+ float half_screen_pixel_size_x025[2];
+
+ float NDC_to_view_mul[2];
+ float NDC_to_view_add[2];
+
+ float pad2[2];
+ float z_near;
+ float z_far;
+
+ float radius;
+ float intensity;
+ int size_multiplier;
+ int pad;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float normal_rejection_amount;
+ float inv_radius_near_limit;
+
+ uint32_t is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ int32_t pass_coord_offset[2];
+ float pass_uv_offset[2];
+ };
+
+ struct SSILImportanceMapPushConstant {
+ float half_screen_pixel_size[2];
+ float intensity;
+ float pad;
+ };
+
+ struct SSILBlurPushConstant {
+ float edge_sharpness;
+ float pad;
+ float half_screen_pixel_size[2];
+ };
+
+ struct SSILInterleavePushConstant {
+ float inv_sharpness;
+ uint32_t size_modifier;
+ float pixel_size[2];
+ };
+
+ struct SSILProjectionUniforms {
+ float inv_last_frame_projection_matrix[16];
+ };
+
+ struct SSIL {
+ SSILGatherPushConstant gather_push_constant;
+ SsilShaderRD gather_shader;
+ RID gather_shader_version;
+ RID projection_uniform_buffer;
+
+ SSILImportanceMapPushConstant importance_map_push_constant;
+ SsilImportanceMapShaderRD importance_map_shader;
+ RID importance_map_shader_version;
+ RID importance_map_load_counter;
+ RID counter_uniform_set;
+
+ SSILBlurPushConstant blur_push_constant;
+ SsilBlurShaderRD blur_shader;
+ RID blur_shader_version;
+
+ SSILInterleavePushConstant interleave_push_constant;
+ SsilInterleaveShaderRD interleave_shader;
+ RID interleave_shader_version;
+
+ RID pipelines[SSIL_MAX];
+ } ssil;
+
+ void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
+
+ /* SSAO */
+
+ enum SSAOMode {
+ SSAO_GATHER,
+ SSAO_GATHER_BASE,
+ SSAO_GATHER_ADAPTIVE,
+ SSAO_GENERATE_IMPORTANCE_MAP,
+ SSAO_PROCESS_IMPORTANCE_MAPA,
+ SSAO_PROCESS_IMPORTANCE_MAPB,
+ SSAO_BLUR_PASS,
+ SSAO_BLUR_PASS_SMART,
+ SSAO_BLUR_PASS_WIDE,
+ SSAO_INTERLEAVE,
+ SSAO_INTERLEAVE_SMART,
+ SSAO_INTERLEAVE_HALF,
+ SSAO_MAX
+ };
+
+ struct SSAOGatherPushConstant {
+ int32_t screen_size[2];
+ int pass;
+ int quality;
+
+ float half_screen_pixel_size[2];
+ int size_multiplier;
+ float detail_intensity;
+
+ float NDC_to_view_mul[2];
+ float NDC_to_view_add[2];
+
+ float pad[2];
+ float half_screen_pixel_size_x025[2];
+
+ float radius;
+ float intensity;
+ float shadow_power;
+ float shadow_clamp;
+
+ float fade_out_mul;
+ float fade_out_add;
+ float horizon_angle_threshold;
+ float inv_radius_near_limit;
+
+ uint32_t is_orthogonal;
+ float neg_inv_radius;
+ float load_counter_avg_div;
+ float adaptive_sample_limit;
+
+ int32_t pass_coord_offset[2];
+ float pass_uv_offset[2];
+ };
+
+ struct SSAOImportanceMapPushConstant {
+ float half_screen_pixel_size[2];
+ float intensity;
+ float power;
+ };
+
+ struct SSAOBlurPushConstant {
+ float edge_sharpness;
+ float pad;
+ float half_screen_pixel_size[2];
+ };
+
+ struct SSAOInterleavePushConstant {
+ float inv_sharpness;
+ uint32_t size_modifier;
+ float pixel_size[2];
+ };
+
+ struct SSAO {
+ SSAOGatherPushConstant gather_push_constant;
+ SsaoShaderRD gather_shader;
+ RID gather_shader_version;
+
+ SSAOImportanceMapPushConstant importance_map_push_constant;
+ SsaoImportanceMapShaderRD importance_map_shader;
+ RID importance_map_shader_version;
+ RID importance_map_load_counter;
+ RID counter_uniform_set;
+
+ SSAOBlurPushConstant blur_push_constant;
+ SsaoBlurShaderRD blur_shader;
+ RID blur_shader_version;
+
+ SSAOInterleavePushConstant interleave_push_constant;
+ SsaoInterleaveShaderRD interleave_shader;
+ RID interleave_shader_version;
+
+ RID pipelines[SSAO_MAX];
+ } ssao;
+
+ void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
+
+ /* Screen Space Reflection */
+
+ enum SSRShaderSpecializations {
+ SSR_MULTIVIEW = 1 << 0,
+ SSR_VARIATIONS = 2,
+ };
+
+ struct ScreenSpaceReflectionSceneData {
+ float projection[2][16];
+ float inv_projection[2][16];
+ float eye_offset[2][4];
+ };
+
+ // SSR Scale
+
+ struct ScreenSpaceReflectionScalePushConstant {
+ int32_t screen_size[2];
+ float camera_z_near;
+ float camera_z_far;
+
+ uint32_t orthogonal;
+ uint32_t filter;
+ uint32_t view_index;
+ uint32_t pad1;
+ };
+
+ struct ScreenSpaceReflectionScale {
+ ScreenSpaceReflectionScaleShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS];
+ } ssr_scale;
+
+ // SSR main
+
+ enum ScreenSpaceReflectionMode {
+ SCREEN_SPACE_REFLECTION_NORMAL,
+ SCREEN_SPACE_REFLECTION_ROUGH,
+ SCREEN_SPACE_REFLECTION_MAX,
+ };
+
+ struct ScreenSpaceReflectionPushConstant {
+ float proj_info[4]; // 16 - 16
+
+ int32_t screen_size[2]; // 8 - 24
+ float camera_z_near; // 4 - 28
+ float camera_z_far; // 4 - 32
+
+ int32_t num_steps; // 4 - 36
+ float depth_tolerance; // 4 - 40
+ float distance_fade; // 4 - 44
+ float curve_fade_in; // 4 - 48
+
+ uint32_t orthogonal; // 4 - 52
+ float filter_mipmap_levels; // 4 - 56
+ uint32_t use_half_res; // 4 - 60
+ uint32_t view_index; // 4 - 64
+
+ // float projection[16]; // this is in our ScreenSpaceReflectionSceneData now
+ };
+
+ struct ScreenSpaceReflection {
+ ScreenSpaceReflectionShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_MAX];
+
+ RID ubo;
+ } ssr;
+
+ // SSR Filter
+
+ struct ScreenSpaceReflectionFilterPushConstant {
+ float proj_info[4]; // 16 - 16
+
+ uint32_t orthogonal; // 4 - 20
+ float edge_tolerance; // 4 - 24
+ int32_t increment; // 4 - 28
+ uint32_t view_index; // 4 - 32
+
+ int32_t screen_size[2]; // 8 - 40
+ uint32_t vertical; // 4 - 44
+ uint32_t steps; // 4 - 48
+ };
+
+ enum SSRReflectionMode {
+ SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL,
+ SCREEN_SPACE_REFLECTION_FILTER_VERTICAL,
+ SCREEN_SPACE_REFLECTION_FILTER_MAX,
+ };
+
+ struct ScreenSpaceReflectionFilter {
+ ScreenSpaceReflectionFilterShaderRD shader;
+ RID shader_version;
+ RID pipelines[SSR_VARIATIONS][SCREEN_SPACE_REFLECTION_FILTER_MAX];
+ } ssr_filter;
+
+ /* Subsurface scattering */
+
+ struct SubSurfaceScatteringPushConstant {
+ int32_t screen_size[2];
+ float camera_z_far;
+ float camera_z_near;
+
+ uint32_t vertical;
+ uint32_t orthogonal;
+ float unit_size;
+ float scale;
+
+ float depth_scale;
+ uint32_t pad[3];
+ };
+
+ struct SubSurfaceScattering {
+ SubSurfaceScatteringPushConstant push_constant;
+ SubsurfaceScatteringShaderRD shader;
+ RID shader_version;
+ RID pipelines[3]; //3 quality levels
+ } sss;
+};
+
+} // namespace RendererRD
+
+#endif // SS_EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/effects/taa.cpp b/servers/rendering/renderer_rd/effects/taa.cpp
new file mode 100644
index 0000000000..657385a509
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/taa.cpp
@@ -0,0 +1,138 @@
+/*************************************************************************/
+/* taa.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "taa.h"
+#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
+
+using namespace RendererRD;
+
+TAA::TAA() {
+ Vector<String> taa_modes;
+ taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
+ taa_shader.initialize(taa_modes);
+ shader_version = taa_shader.version_create();
+ pipeline = RD::get_singleton()->compute_pipeline_create(taa_shader.version_get_shader(shader_version, 0));
+}
+
+TAA::~TAA() {
+ taa_shader.version_free(shader_version);
+}
+
+void TAA::msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ if (!p_render_buffers->has_velocity_buffer(true)) {
+ // nothing to resolve
+ return;
+ }
+
+ for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
+ RID velocity_buffer_msaa = p_render_buffers->get_velocity_buffer(true, v);
+ RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
+
+ RD::get_singleton()->texture_resolve_multisample(velocity_buffer_msaa, velocity_buffer);
+ }
+}
+
+void TAA::resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ RID shader = taa_shader.version_get_shader(shader_version, 0);
+ ERR_FAIL_COND(shader.is_null());
+
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ TAAResolvePushConstant push_constant;
+ memset(&push_constant, 0, sizeof(TAAResolvePushConstant));
+ push_constant.resolution_width = p_resolution.width;
+ push_constant.resolution_height = p_resolution.height;
+ push_constant.disocclusion_threshold = 0.025f;
+ push_constant.disocclusion_scale = 10.0f;
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipeline);
+
+ RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
+ RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
+ RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
+ RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
+ RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
+ RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(TAAResolvePushConstant));
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
+ RD::get_singleton()->compute_list_end();
+}
+
+void TAA::process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far) {
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
+
+ uint32_t view_count = p_render_buffers->get_view_count();
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ Size2i target_size = p_render_buffers->get_target_size();
+
+ bool just_allocated = false;
+ if (!p_render_buffers->has_texture(SNAME("taa"), SNAME("history"))) {
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ p_render_buffers->create_texture(SNAME("taa"), SNAME("history"), p_format, usage_bits);
+ p_render_buffers->create_texture(SNAME("taa"), SNAME("temp"), p_format, usage_bits);
+
+ p_render_buffers->create_texture(SNAME("taa"), SNAME("prev_velocity"), RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
+
+ just_allocated = true;
+ }
+
+ RD::get_singleton()->draw_command_begin_label("TAA");
+
+ for (uint32_t v = 0; v < view_count; v++) {
+ // Get our (cached) slices
+ RID internal_texture = p_render_buffers->get_internal_texture(v);
+ RID velocity_buffer = p_render_buffers->get_velocity_buffer(false, v);
+ RID taa_history = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("history"), v, 0);
+ RID taa_prev_velocity = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("prev_velocity"), v, 0);
+
+ if (!just_allocated) {
+ RID depth_texture = p_render_buffers->get_depth_texture(v);
+ RID taa_temp = p_render_buffers->get_texture_slice(SNAME("taa"), SNAME("temp"), v, 0);
+ resolve(internal_texture, taa_temp, depth_texture, velocity_buffer, taa_prev_velocity, taa_history, Size2(internal_size.x, internal_size.y), p_z_near, p_z_far);
+ copy_effects->copy_to_rect(taa_temp, internal_texture, Rect2(0, 0, internal_size.x, internal_size.y));
+ }
+
+ copy_effects->copy_to_rect(internal_texture, taa_history, Rect2(0, 0, internal_size.x, internal_size.y));
+ copy_effects->copy_to_rect(velocity_buffer, taa_prev_velocity, Rect2(0, 0, target_size.x, target_size.y));
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/effects/taa.h b/servers/rendering/renderer_rd/effects/taa.h
new file mode 100644
index 0000000000..ce4af18866
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/taa.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* taa.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef TAA_RD_H
+#define TAA_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class TAA {
+public:
+ TAA();
+ ~TAA();
+
+ void msaa_resolve(Ref<RenderSceneBuffersRD> p_render_buffers);
+ void process(Ref<RenderSceneBuffersRD> p_render_buffers, RD::DataFormat p_format, float p_z_near, float p_z_far);
+
+private:
+ struct TAAResolvePushConstant {
+ float resolution_width;
+ float resolution_height;
+ float disocclusion_threshold;
+ float disocclusion_scale;
+ };
+
+ TaaResolveShaderRD taa_shader;
+ RID shader_version;
+ RID pipeline;
+
+ void resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
+};
+
+} // namespace RendererRD
+
+#endif // TAA_RD_H
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.cpp b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
index 38a4a37b8a..3a47b1420b 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.cpp
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.cpp
@@ -117,7 +117,7 @@ void ToneMapper::tonemapper(RID p_source_color, RID p_dst_framebuffer, const Ton
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.luminance_multiplier = p_settings.luminance_multiplier;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
@@ -203,7 +203,7 @@ void ToneMapper::tonemapper(RD::DrawListID p_subpass_draw_list, RID p_source_col
tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure;
tonemap.push_constant.exposure = p_settings.exposure;
tonemap.push_constant.white = p_settings.white;
- tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey;
+ tonemap.push_constant.auto_exposure_scale = p_settings.auto_exposure_scale;
tonemap.push_constant.use_color_correction = p_settings.use_color_correction;
diff --git a/servers/rendering/renderer_rd/effects/tone_mapper.h b/servers/rendering/renderer_rd/effects/tone_mapper.h
index a90849dbeb..e91118e241 100644
--- a/servers/rendering/renderer_rd/effects/tone_mapper.h
+++ b/servers/rendering/renderer_rd/effects/tone_mapper.h
@@ -77,7 +77,7 @@ private:
float exposure; // 4 - 84
float white; // 4 - 88
- float auto_exposure_grey; // 4 - 92
+ float auto_exposure_scale; // 4 - 92
float luminance_multiplier; // 4 - 96
float pixel_size[2]; // 8 - 104
@@ -124,7 +124,7 @@ public:
float white = 1.0;
bool use_auto_exposure = false;
- float auto_exposure_grey = 0.5;
+ float auto_exposure_scale = 0.5;
RID exposure_texture;
float luminance_multiplier = 1.0;
@@ -149,4 +149,4 @@ public:
} // namespace RendererRD
-#endif // !TONE_MAPPER_RD_H
+#endif // TONE_MAPPER_RD_H
diff --git a/servers/rendering/renderer_rd/effects/vrs.cpp b/servers/rendering/renderer_rd/effects/vrs.cpp
new file mode 100644
index 0000000000..5ff00aa94c
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/vrs.cpp
@@ -0,0 +1,149 @@
+/*************************************************************************/
+/* vrs.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "vrs.h"
+#include "../renderer_compositor_rd.h"
+#include "../storage_rd/texture_storage.h"
+#include "../uniform_set_cache_rd.h"
+#include "servers/xr_server.h"
+
+using namespace RendererRD;
+
+VRS::VRS() {
+ {
+ Vector<String> vrs_modes;
+ vrs_modes.push_back("\n"); // VRS_DEFAULT
+ vrs_modes.push_back("\n#define MULTIVIEW\n"); // VRS_MULTIVIEW
+
+ vrs_shader.shader.initialize(vrs_modes);
+
+ if (!RendererCompositorRD::singleton->is_xr_enabled()) {
+ vrs_shader.shader.set_variant_enabled(VRS_MULTIVIEW, false);
+ }
+
+ vrs_shader.shader_version = vrs_shader.shader.version_create();
+
+ //use additive
+
+ for (int i = 0; i < VRS_MAX; i++) {
+ if (vrs_shader.shader.is_variant_enabled(i)) {
+ vrs_shader.pipelines[i].setup(vrs_shader.shader.version_get_shader(vrs_shader.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
+ } else {
+ vrs_shader.pipelines[i].clear();
+ }
+ }
+ }
+}
+
+VRS::~VRS() {
+ vrs_shader.shader.version_free(vrs_shader.shader_version);
+}
+
+void VRS::copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview) {
+ UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
+ ERR_FAIL_NULL(uniform_set_cache);
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+ ERR_FAIL_NULL(material_storage);
+
+ // setup our uniforms
+ RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+
+ RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector<RID>({ default_sampler, p_source_rd_texture }));
+
+ VRSMode mode = p_multiview ? VRS_MULTIVIEW : VRS_DEFAULT;
+
+ RID shader = vrs_shader.shader.version_get_shader(vrs_shader.shader_version, mode);
+ ERR_FAIL_COND(shader.is_null());
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector<Color>());
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, vrs_shader.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0);
+ RD::get_singleton()->draw_list_bind_index_array(draw_list, material_storage->get_quad_index_array());
+ // RD::get_singleton()->draw_list_set_push_constant(draw_list, &vrs_shader.push_constant, sizeof(VRSPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, true);
+ RD::get_singleton()->draw_list_end();
+}
+
+Size2i VRS::get_vrs_texture_size(const Size2i p_base_size) const {
+ // TODO we should find some way to store this properly, we're assuming 16x16 as this seems to be the standard but in our vrs_capacities we
+ // obtain a minimum and maximum size, and we should choose something within this range and then make sure that is consistently set when creating
+ // our frame buffer. Also it is important that we make the resulting size we calculate down below available to the end user so they know the size
+ // of the VRS buffer to supply.
+ Size2i texel_size = Size2i(16, 16);
+
+ int width = p_base_size.x / texel_size.x;
+ if (p_base_size.x % texel_size.x != 0) {
+ width++;
+ }
+ int height = p_base_size.y / texel_size.y;
+ if (p_base_size.y % texel_size.y != 0) {
+ height++;
+ }
+ return Size2i(width, height);
+}
+
+void VRS::update_vrs_texture(RID p_vrs_fb, RID p_render_target) {
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
+ RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
+
+ if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ RD::get_singleton()->draw_command_begin_label("VRS Setup");
+
+ // TODO figure out if image has changed since it was last copied so we can save some resources..
+
+ if (vrs_mode == RS::VIEWPORT_VRS_TEXTURE) {
+ RID vrs_texture = texture_storage->render_target_get_vrs_texture(p_render_target);
+ if (vrs_texture.is_valid()) {
+ RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture);
+ int layers = texture_storage->texture_get_layers(vrs_texture);
+ if (rd_texture.is_valid()) {
+ // Copy into our density buffer
+ copy_vrs(rd_texture, p_vrs_fb, layers > 1);
+ }
+ }
+ } else if (vrs_mode == RS::VIEWPORT_VRS_XR) {
+ Ref<XRInterface> interface = XRServer::get_singleton()->get_primary_interface();
+ if (interface.is_valid()) {
+ RID vrs_texture = interface->get_vrs_texture();
+ if (vrs_texture.is_valid()) {
+ RID rd_texture = texture_storage->texture_get_rd_texture(vrs_texture);
+ int layers = texture_storage->texture_get_layers(vrs_texture);
+
+ if (rd_texture.is_valid()) {
+ // Copy into our density buffer
+ copy_vrs(rd_texture, p_vrs_fb, layers > 1);
+ }
+ }
+ }
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+ }
+}
diff --git a/servers/rendering/renderer_rd/effects/vrs.h b/servers/rendering/renderer_rd/effects/vrs.h
new file mode 100644
index 0000000000..7125c6455d
--- /dev/null
+++ b/servers/rendering/renderer_rd/effects/vrs.h
@@ -0,0 +1,75 @@
+/*************************************************************************/
+/* vrs.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef VRS_RD_H
+#define VRS_RD_H
+
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/effects/vrs.glsl.gen.h"
+#include "servers/rendering/renderer_scene_render.h"
+
+#include "servers/rendering_server.h"
+
+namespace RendererRD {
+
+class VRS {
+private:
+ enum VRSMode {
+ VRS_DEFAULT,
+ VRS_MULTIVIEW,
+ VRS_MAX,
+ };
+
+ /* we have no push constant here (yet)
+ struct VRSPushConstant {
+
+ };
+ */
+
+ struct VRSShader {
+ // VRSPushConstant push_constant;
+ VrsShaderRD shader;
+ RID shader_version;
+ PipelineCacheRD pipelines[VRS_MAX];
+ } vrs_shader;
+
+public:
+ VRS();
+ ~VRS();
+
+ void copy_vrs(RID p_source_rd_texture, RID p_dest_framebuffer, bool p_multiview = false);
+
+ Size2i get_vrs_texture_size(const Size2i p_base_size) const;
+ void update_vrs_texture(RID p_vrs_fb, RID p_render_target);
+};
+
+} // namespace RendererRD
+
+#endif // VRS_RD_H
diff --git a/servers/rendering/renderer_rd/effects_rd.cpp b/servers/rendering/renderer_rd/effects_rd.cpp
index bf97c6fbe9..b03415f2e3 100644
--- a/servers/rendering/renderer_rd/effects_rd.cpp
+++ b/servers/rendering/renderer_rd/effects_rd.cpp
@@ -41,14 +41,6 @@ bool EffectsRD::get_prefer_raster_effects() {
return prefer_raster_effects;
}
-static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
- }
- }
-}
-
RID EffectsRD::_get_uniform_set_from_image(RID p_image) {
if (image_to_uniform_set_cache.has(p_image)) {
RID uniform_set = image_to_uniform_set_cache[p_image];
@@ -86,7 +78,7 @@ RID EffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps)
u.append_id(p_texture);
uniforms.push_back(u);
// anything with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0), 0);
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce_raster.shader.version_get_shader(luminance_reduce_raster.shader_version, 0), 0);
texture_to_uniform_set_cache[p_texture] = uniform_set;
@@ -116,385 +108,6 @@ RID EffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_m
return uniform_set;
}
-RID EffectsRD::_get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler) {
- TextureSamplerPair tsp;
- tsp.texture = p_texture;
- tsp.sampler = p_sampler;
-
- if (texture_sampler_to_compute_uniform_set_cache.has(tsp)) {
- RID uniform_set = texture_sampler_to_compute_uniform_set_cache[tsp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(p_sampler);
- u.append_id(p_texture);
- uniforms.push_back(u);
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.blur_shader.version_get_shader(ssao.blur_shader_version, 0), 0);
-
- texture_sampler_to_compute_uniform_set_cache[tsp] = uniform_set;
-
- return uniform_set;
-}
-
-RID EffectsRD::_get_compute_uniform_set_from_texture_pair(RID p_texture1, RID p_texture2, bool p_use_mipmaps) {
- TexturePair tp;
- tp.texture1 = p_texture1;
- tp.texture2 = p_texture2;
-
- if (texture_pair_to_compute_uniform_set_cache.has(tp)) {
- RID uniform_set = texture_pair_to_compute_uniform_set_cache[tp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.append_id(p_texture1);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(p_use_mipmaps ? default_mipmap_sampler : default_sampler);
- u.append_id(p_texture2);
- uniforms.push_back(u);
- }
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 1);
-
- texture_pair_to_compute_uniform_set_cache[tp] = uniform_set;
-
- return uniform_set;
-}
-
-RID EffectsRD::_get_compute_uniform_set_from_image_pair(RID p_texture1, RID p_texture2) {
- TexturePair tp;
- tp.texture1 = p_texture1;
- tp.texture2 = p_texture2;
-
- if (image_pair_to_compute_uniform_set_cache.has(tp)) {
- RID uniform_set = image_pair_to_compute_uniform_set_cache[tp];
- if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) {
- return uniform_set;
- }
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_texture1);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_texture2);
- uniforms.push_back(u);
- }
- //any thing with the same configuration (one texture in binding 0 for set 0), is good
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0), 3);
-
- image_pair_to_compute_uniform_set_cache[tp] = uniform_set;
-
- return uniform_set;
-}
-
-void EffectsRD::fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness) {
- memset(&FSR_upscale.push_constant, 0, sizeof(FSRUpscalePushConstant));
-
- int dispatch_x = (p_size.x + 15) / 16;
- int dispatch_y = (p_size.y + 15) / 16;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, FSR_upscale.pipeline);
-
- FSR_upscale.push_constant.resolution_width = p_internal_size.width;
- FSR_upscale.push_constant.resolution_height = p_internal_size.height;
- FSR_upscale.push_constant.upscaled_width = p_size.width;
- FSR_upscale.push_constant.upscaled_height = p_size.height;
- FSR_upscale.push_constant.sharpness = p_fsr_upscale_sharpness;
-
- //FSR Easc
- FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_EASU;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 1);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
-
- RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- //FSR Rcas
- FSR_upscale.push_constant.pass = FSR_UPSCALE_PASS_RCAS;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination_texture), 1);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &FSR_upscale.push_constant, sizeof(FSRUpscalePushConstant));
-
- RD::get_singleton()->compute_list_dispatch(compute_list, dispatch_x, dispatch_y, 1);
-
- RD::get_singleton()->compute_list_end(compute_list);
-}
-
-void EffectsRD::taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far) {
- UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton();
- ERR_FAIL_NULL(uniform_set_cache);
-
- RID shader = TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0);
- ERR_FAIL_COND(shader.is_null());
-
- memset(&TAA_resolve.push_constant, 0, sizeof(TAAResolvePushConstant));
- TAA_resolve.push_constant.resolution_width = p_resolution.width;
- TAA_resolve.push_constant.resolution_height = p_resolution.height;
- TAA_resolve.push_constant.disocclusion_threshold = 0.025f;
- TAA_resolve.push_constant.disocclusion_scale = 10.0f;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, TAA_resolve.pipeline);
-
- RD::Uniform u_frame_source(RD::UNIFORM_TYPE_IMAGE, 0, { p_frame });
- RD::Uniform u_depth(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 1, { default_sampler, p_depth });
- RD::Uniform u_velocity(RD::UNIFORM_TYPE_IMAGE, 2, { p_velocity });
- RD::Uniform u_prev_velocity(RD::UNIFORM_TYPE_IMAGE, 3, { p_prev_velocity });
- RD::Uniform u_history(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 4, { default_sampler, p_history });
- RD::Uniform u_frame_dest(RD::UNIFORM_TYPE_IMAGE, 5, { p_temp });
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set_cache->get_cache(shader, 0, u_frame_source, u_depth, u_velocity, u_prev_velocity, u_history, u_frame_dest), 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &TAA_resolve.push_constant, sizeof(TAAResolvePushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_resolution.width, p_resolution.height, 1);
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RenderingServer::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- { //scale color and depth to half
- ssr_scale.push_constant.camera_z_far = p_camera.get_z_far();
- ssr_scale.push_constant.camera_z_near = p_camera.get_z_near();
- ssr_scale.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr_scale.push_constant.filter = false; //enabling causes arctifacts
- ssr_scale.push_constant.screen_size[0] = p_screen_size.x;
- ssr_scale.push_constant.screen_size[1] = p_screen_size.y;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_scale.pipeline);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_depth, p_normal_roughness), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output_blur), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_scale_depth, p_scale_normal), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_scale.push_constant, sizeof(ScreenSpaceReflectionScalePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
-
- {
- ssr.push_constant.camera_z_far = p_camera.get_z_far();
- ssr.push_constant.camera_z_near = p_camera.get_z_near();
- ssr.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr.push_constant.screen_size[0] = p_screen_size.x;
- ssr.push_constant.screen_size[1] = p_screen_size.y;
- ssr.push_constant.curve_fade_in = p_fade_in;
- ssr.push_constant.distance_fade = p_fade_out;
- ssr.push_constant.num_steps = p_max_steps;
- ssr.push_constant.depth_tolerance = p_tolerance;
- ssr.push_constant.use_half_res = true;
- ssr.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
- ssr.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
- ssr.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
- ssr.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
- ssr.push_constant.metallic_mask[0] = CLAMP(p_metallic_mask.r * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[1] = CLAMP(p_metallic_mask.g * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[2] = CLAMP(p_metallic_mask.b * 255.0, 0, 255);
- ssr.push_constant.metallic_mask[3] = CLAMP(p_metallic_mask.a * 255.0, 0, 255);
- store_camera(p_camera, ssr.push_constant.projection);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr.pipelines[(p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) ? SCREEN_SPACE_REFLECTION_ROUGH : SCREEN_SPACE_REFLECTION_NORMAL]);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr.push_constant, sizeof(ScreenSpaceReflectionPushConstant));
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_scale_depth), 0);
-
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_metallic), 3);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 2);
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
- }
-
- if (p_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED) {
- //blur
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- ssr_filter.push_constant.orthogonal = p_camera.is_orthogonal();
- ssr_filter.push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0));
- ssr_filter.push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_camera.matrix[0][0]);
- ssr_filter.push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_camera.matrix[1][1]);
- ssr_filter.push_constant.proj_info[2] = (1.0f - p_camera.matrix[0][2]) / p_camera.matrix[0][0];
- ssr_filter.push_constant.proj_info[3] = (1.0f + p_camera.matrix[1][2]) / p_camera.matrix[1][1];
- ssr_filter.push_constant.vertical = 0;
- if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_LOW) {
- ssr_filter.push_constant.steps = p_max_steps / 3;
- ssr_filter.push_constant.increment = 3;
- } else if (p_roughness_quality == RS::ENV_SSR_ROUGHNESS_QUALITY_MEDIUM) {
- ssr_filter.push_constant.steps = p_max_steps / 2;
- ssr_filter.push_constant.increment = 2;
- } else {
- ssr_filter.push_constant.steps = p_max_steps;
- ssr_filter.push_constant.increment = 1;
- }
-
- ssr_filter.push_constant.screen_size[0] = p_screen_size.width;
- ssr_filter.push_constant.screen_size[1] = p_screen_size.height;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output, p_blur_radius), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssr_filter.pipelines[SCREEN_SPACE_REFLECTION_FILTER_VERTICAL]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_output_blur, p_blur_radius2), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_normal), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_output), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_scale_depth), 3);
-
- ssr_filter.push_constant.vertical = 1;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssr_filter.push_constant, sizeof(ScreenSpaceReflectionFilterPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
- }
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RenderingServer::SubSurfaceScatteringQuality p_quality) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- Plane p = p_camera.xform4(Plane(1, 0, -1, 1));
- p.normal /= p.d;
- float unit_size = p.normal.x;
-
- { //scale color and depth to half
- sss.push_constant.camera_z_far = p_camera.get_z_far();
- sss.push_constant.camera_z_near = p_camera.get_z_near();
- sss.push_constant.orthogonal = p_camera.is_orthogonal();
- sss.push_constant.unit_size = unit_size;
- sss.push_constant.screen_size[0] = p_screen_size.x;
- sss.push_constant.screen_size[1] = p_screen_size.y;
- sss.push_constant.vertical = false;
- sss.push_constant.scale = p_scale;
- sss.push_constant.depth_scale = p_depth_scale;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sss.pipelines[p_quality - 1]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse2), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_diffuse2), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_diffuse), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth), 2);
-
- sss.push_constant.vertical = true;
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &sss.push_constant, sizeof(SubSurfaceScatteringPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.width, p_screen_size.height, 1);
-
- RD::get_singleton()->compute_list_end();
- }
-}
-
-void EffectsRD::merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection) {
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, Vector<Color>());
-
- if (p_reflection.is_valid()) {
- if (p_base.is_valid()) {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
- } else {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_SSR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- }
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_reflection), 1);
-
- } else {
- if (p_base.is_valid()) {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_base), 2);
- } else {
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, specular_merge.pipelines[SPECULAR_MERGE_ADDITIVE_ADD].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- }
-
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_specular), 0);
- }
-
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
-void EffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip) {
- CopyToDPPushConstant push_constant;
- push_constant.screen_rect[0] = p_rect.position.x;
- push_constant.screen_rect[1] = p_rect.position.y;
- push_constant.screen_rect[2] = p_rect.size.width;
- push_constant.screen_rect[3] = p_rect.size.height;
- push_constant.z_far = p_z_far;
- push_constant.z_near = p_z_near;
- push_constant.texel_size[0] = 1.0f / p_dst_size.x;
- push_constant.texel_size[1] = 1.0f / p_dst_size.y;
- push_constant.texel_size[0] *= p_dp_flip ? -1.0f : 1.0f; // Encode dp flip as x size sign
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cube_to_dp.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant));
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_TRANSFER);
-}
-
void EffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) {
ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute version of luminance reduction with the mobile renderer.");
@@ -568,674 +181,6 @@ void EffectsRD::luminance_reduction_raster(RID p_source_texture, const Size2i p_
}
}
-void EffectsRD::downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection) {
- // Downsample and deinterleave the depth buffer for SSAO and SSIL
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- int downsample_pipeline = SS_EFFECTS_DOWNSAMPLE;
- bool use_mips = p_ssao_quality > RS::ENV_SSAO_QUALITY_MEDIUM || p_ssil_quality > RS::ENV_SSIL_QUALITY_MEDIUM;
-
- if (p_ssao_quality == RS::ENV_SSAO_QUALITY_VERY_LOW && p_ssil_quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_HALF;
- } else if (use_mips) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
- }
-
- bool use_half_size = false;
- bool use_full_mips = false;
-
- if (p_ssao_half_size && p_ssil_half_size) {
- downsample_pipeline++;
- use_half_size = true;
- } else if (p_ssao_half_size != p_ssil_half_size) {
- if (use_mips) {
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_FULL_MIPS;
- use_full_mips = true;
- } else {
- // Only need the first two mipmaps, but the cost to generate the next two is trivial
- // TODO investigate the benefit of a shader version to generate only 2 mips
- downsample_pipeline = SS_EFFECTS_DOWNSAMPLE_MIPMAP;
- use_mips = true;
- }
- }
-
- int depth_index = use_half_size ? 1 : 0;
-
- RD::get_singleton()->draw_command_begin_label("Downsample Depth");
- if (p_invalidate_uniform_set || use_full_mips != ss_effects.used_full_mips_last_frame || use_half_size != ss_effects.used_half_size_last_frame || use_mips != ss_effects.used_mips_last_frame) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_depth_mipmaps[depth_index + 1]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_depth_mipmaps[depth_index + 2]);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 2;
- u.append_id(p_depth_mipmaps[depth_index + 3]);
- uniforms.push_back(u);
- }
- if (use_full_mips) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.append_id(p_depth_mipmaps[4]);
- uniforms.push_back(u);
- }
- ss_effects.downsample_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, use_full_mips ? 6 : 2), 2);
- }
-
- float depth_linearize_mul = -p_projection.matrix[3][2];
- float depth_linearize_add = p_projection.matrix[2][2];
- if (depth_linearize_mul * depth_linearize_add < 0) {
- depth_linearize_add = -depth_linearize_add;
- }
-
- ss_effects.downsample_push_constant.orthogonal = p_projection.is_orthogonal();
- ss_effects.downsample_push_constant.z_near = depth_linearize_mul;
- ss_effects.downsample_push_constant.z_far = depth_linearize_add;
- if (ss_effects.downsample_push_constant.orthogonal) {
- ss_effects.downsample_push_constant.z_near = p_projection.get_z_near();
- ss_effects.downsample_push_constant.z_far = p_projection.get_z_far();
- }
- ss_effects.downsample_push_constant.pixel_size[0] = 1.0 / p_full_screen_size.x;
- ss_effects.downsample_push_constant.pixel_size[1] = 1.0 / p_full_screen_size.y;
- ss_effects.downsample_push_constant.radius_sq = 1.0;
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ss_effects.pipelines[downsample_pipeline]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_depth_mipmaps[depth_index + 0]), 1);
- if (use_mips) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ss_effects.downsample_uniform_set, 2);
- }
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ss_effects.downsample_push_constant, sizeof(SSEffectsDownsamplePushConstant));
-
- Size2i size(MAX(1, p_full_screen_size.x >> (use_half_size ? 2 : 1)), MAX(1, p_full_screen_size.y >> (use_half_size ? 2 : 1)));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label();
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_COMPUTE);
-
- ss_effects.used_full_mips_last_frame = use_full_mips;
- ss_effects.used_half_size_last_frame = use_half_size;
-}
-
-void EffectsRD::gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- ssao.gather_push_constant.pass_coord_offset[0] = i % 2;
- ssao.gather_push_constant.pass_coord_offset[1] = i / 2;
- ssao.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
- ssao.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
- ssao.gather_push_constant.pass = i;
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 2);
- RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant));
-
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
- }
- RD::get_singleton()->compute_list_add_barrier(p_compute_list);
-}
-
-void EffectsRD::generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set) {
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- memset(&ssao.gather_push_constant, 0, sizeof(SSAOGatherPushConstant));
- /* FIRST PASS */
-
- RD::get_singleton()->draw_command_begin_label("Process Screen Space Ambient Occlusion");
- /* SECOND PASS */
- // Sample SSAO
- {
- RD::get_singleton()->draw_command_begin_label("Gather Samples");
- ssao.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
- ssao.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
-
- ssao.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
- ssao.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
- ssao.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
- ssao.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
- ssao.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
- ssao.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
-
- ssao.gather_push_constant.half_screen_pixel_size_x025[0] = ssao.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssao.gather_push_constant.half_screen_pixel_size_x025[1] = ssao.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
- ssao.gather_push_constant.radius = p_settings.radius;
- float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSAO_QUALITY_LOW) {
- radius_near_limit *= 1.50f;
-
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- ssao.gather_push_constant.radius *= 0.8f;
- }
- }
- radius_near_limit /= tan_half_fov_y;
- ssao.gather_push_constant.intensity = p_settings.intensity;
- ssao.gather_push_constant.shadow_power = p_settings.power;
- ssao.gather_push_constant.shadow_clamp = 0.98;
- ssao.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssao.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
- ssao.gather_push_constant.horizon_angle_threshold = p_settings.horizon;
- ssao.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
- ssao.gather_push_constant.neg_inv_radius = -1.0 / ssao.gather_push_constant.radius;
-
- ssao.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
- ssao.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
-
- ssao.gather_push_constant.detail_intensity = p_settings.detail;
- ssao.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssao.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_depth_mipmaps_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 0), 0);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ao_pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_importance_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssao.importance_map_load_counter);
- uniforms.push_back(u);
- }
- r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.gather_shader.version_get_shader(ssao.gather_shader_version, 2), 1);
- }
-
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_ULTRA) {
- RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
- ssao.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- ssao.importance_map_push_constant.intensity = p_settings.intensity;
- ssao.importance_map_push_constant.power = p_settings.power;
- //base pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_BASE]);
- gather_ssao(compute_list, p_ao_pong_slices, p_settings, true, r_gather_uniform_set, RID());
- //generate importance map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GENERATE_IMPORTANCE_MAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- //process importance map A
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- //process Importance Map B
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_PROCESS_IMPORTANCE_MAPB]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssao.counter_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.importance_map_push_constant, sizeof(SSAOImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER_ADAPTIVE]);
- RD::get_singleton()->draw_command_end_label(); // Importance Map
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_GATHER]);
- }
-
- gather_ssao(compute_list, p_ao_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set);
- RD::get_singleton()->draw_command_end_label(); // Gather SSAO
- }
-
- // /* THIRD PASS */
- // // Blur
- //
- {
- RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
- ssao.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
- ssao.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssao.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
-
- int blur_passes = p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
-
- for (int pass = 0; pass < blur_passes; pass++) {
- int blur_pipeline = SSAO_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
- if (pass < blur_passes - 2) {
- blur_pipeline = SSAO_BLUR_PASS_WIDE;
- } else {
- blur_pipeline = SSAO_BLUR_PASS_SMART;
- }
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[blur_pipeline]);
- if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_slices[i], ss_effects.mirror_sampler), 0);
- }
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_pong_slices[i]), 1);
- } else {
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ao_pong_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao_slices[i]), 1);
- }
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant));
-
- Size2i size(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, size.x, size.y, 1);
- }
-
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- }
- RD::get_singleton()->draw_command_end_label(); // Blur
- }
-
- /* FOURTH PASS */
- // Interleave buffers
- // back to full size
- {
- RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
- ssao.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
- ssao.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
- ssao.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssao.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
-
- int interleave_pipeline = SSAO_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSAO_QUALITY_LOW) {
- interleave_pipeline = SSAO_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSAO_QUALITY_MEDIUM) {
- interleave_pipeline = SSAO_INTERLEAVE_SMART;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[interleave_pipeline]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 0);
- if (p_settings.quality > RS::ENV_SSAO_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao_pong), 1);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.interleave_push_constant, sizeof(SSAOInterleavePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label(); // Interleave
- }
- RD::get_singleton()->draw_command_end_label(); //SSAO
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //wait for upcoming transfer
-
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
-}
-
-void EffectsRD::gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_gather_uniform_set, 0);
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) && !p_adaptive_base_pass) {
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_importance_map_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, p_projection_uniform_set, 3);
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- ssil.gather_push_constant.pass_coord_offset[0] = i % 2;
- ssil.gather_push_constant.pass_coord_offset[1] = i / 2;
- ssil.gather_push_constant.pass_uv_offset[0] = ((i % 2) - 0.0) / p_settings.full_screen_size.x;
- ssil.gather_push_constant.pass_uv_offset[1] = ((i / 2) - 0.0) / p_settings.full_screen_size.y;
- ssil.gather_push_constant.pass = i;
- RD::get_singleton()->compute_list_bind_uniform_set(p_compute_list, _get_compute_uniform_set_from_image_pair(p_ssil_slices[i], p_edges_slices[i]), 2);
- RD::get_singleton()->compute_list_set_push_constant(p_compute_list, &ssil.gather_push_constant, sizeof(SSILGatherPushConstant));
-
- Size2i size = Size2i(p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1), p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(p_compute_list, size.x, size.y, 1);
- }
- RD::get_singleton()->compute_list_add_barrier(p_compute_list);
-}
-
-void EffectsRD::screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ssil, const Vector<RID> p_ssil_slices, RID p_ssil_pong, const Vector<RID> p_ssil_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set) {
- RD::get_singleton()->draw_command_begin_label("Process Screen Space Indirect Lighting");
- //Store projection info before starting the compute list
- SSILProjectionUniforms projection_uniforms;
- store_camera(p_last_projection, projection_uniforms.inv_last_frame_projection_matrix);
-
- RD::get_singleton()->buffer_update(ssil.projection_uniform_buffer, 0, sizeof(SSILProjectionUniforms), &projection_uniforms);
-
- memset(&ssil.gather_push_constant, 0, sizeof(SSILGatherPushConstant));
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- {
- RD::get_singleton()->draw_command_begin_label("Gather Samples");
- ssil.gather_push_constant.screen_size[0] = p_settings.full_screen_size.x;
- ssil.gather_push_constant.screen_size[1] = p_settings.full_screen_size.y;
-
- ssil.gather_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.gather_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- float tan_half_fov_x = 1.0 / p_projection.matrix[0][0];
- float tan_half_fov_y = 1.0 / p_projection.matrix[1][1];
- ssil.gather_push_constant.NDC_to_view_mul[0] = tan_half_fov_x * 2.0;
- ssil.gather_push_constant.NDC_to_view_mul[1] = tan_half_fov_y * -2.0;
- ssil.gather_push_constant.NDC_to_view_add[0] = tan_half_fov_x * -1.0;
- ssil.gather_push_constant.NDC_to_view_add[1] = tan_half_fov_y;
- ssil.gather_push_constant.z_near = p_projection.get_z_near();
- ssil.gather_push_constant.z_far = p_projection.get_z_far();
- ssil.gather_push_constant.is_orthogonal = p_projection.is_orthogonal();
-
- ssil.gather_push_constant.half_screen_pixel_size_x025[0] = ssil.gather_push_constant.half_screen_pixel_size[0] * 0.25;
- ssil.gather_push_constant.half_screen_pixel_size_x025[1] = ssil.gather_push_constant.half_screen_pixel_size[1] * 0.25;
-
- ssil.gather_push_constant.radius = p_settings.radius;
- float radius_near_limit = (p_settings.radius * 1.2f);
- if (p_settings.quality <= RS::ENV_SSIL_QUALITY_LOW) {
- radius_near_limit *= 1.50f;
-
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- ssil.gather_push_constant.radius *= 0.8f;
- }
- }
- radius_near_limit /= tan_half_fov_y;
- ssil.gather_push_constant.intensity = p_settings.intensity * Math_PI;
- ssil.gather_push_constant.fade_out_mul = -1.0 / (p_settings.fadeout_to - p_settings.fadeout_from);
- ssil.gather_push_constant.fade_out_add = p_settings.fadeout_from / (p_settings.fadeout_to - p_settings.fadeout_from) + 1.0;
- ssil.gather_push_constant.inv_radius_near_limit = 1.0f / radius_near_limit;
- ssil.gather_push_constant.neg_inv_radius = -1.0 / ssil.gather_push_constant.radius;
- ssil.gather_push_constant.normal_rejection_amount = p_settings.normal_rejection;
-
- ssil.gather_push_constant.load_counter_avg_div = 9.0 / float((p_settings.quarter_screen_size.x) * (p_settings.quarter_screen_size.y) * 255);
- ssil.gather_push_constant.adaptive_sample_limit = p_settings.adaptive_target;
-
- ssil.gather_push_constant.quality = MAX(0, p_settings.quality - 1);
- ssil.gather_push_constant.size_multiplier = p_settings.half_size ? 2 : 1;
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_mipmap_sampler);
- u.append_id(p_diffuse);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 1;
- u.append_id(ssil.projection_uniform_buffer);
- uniforms.push_back(u);
- }
- r_projection_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 3);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 0;
- u.append_id(default_sampler);
- u.append_id(p_depth_mipmaps_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 1;
- u.append_id(p_normal_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(ss_effects.gather_constants_buffer);
- uniforms.push_back(u);
- }
- r_gather_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 0), 0);
- }
-
- if (p_invalidate_uniform_sets) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 0;
- u.append_id(p_ssil_pong);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE;
- u.binding = 1;
- u.append_id(default_sampler);
- u.append_id(p_importance_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(ssil.importance_map_load_counter);
- uniforms.push_back(u);
- }
- r_importance_map_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.gather_shader.version_get_shader(ssil.gather_shader_version, 2), 1);
- }
-
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_ULTRA) {
- RD::get_singleton()->draw_command_begin_label("Generate Importance Map");
- ssil.importance_map_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.importance_map_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
- ssil.importance_map_push_constant.intensity = p_settings.intensity * Math_PI;
- //base pass
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_BASE]);
- gather_ssil(compute_list, p_ssil_pong_slices, p_edges_slices, p_settings, true, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
- //generate importance map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GENERATE_IMPORTANCE_MAP]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- // process Importance Map A
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPA]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map_pong), 1);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- // process Importance Map B
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_PROCESS_IMPORTANCE_MAPB]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_importance_map_pong), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_importance_map), 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, ssil.counter_uniform_set, 2);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.importance_map_push_constant, sizeof(SSILImportanceMapPushConstant));
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.quarter_screen_size.x, p_settings.quarter_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- RD::get_singleton()->draw_command_end_label(); // Importance Map
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER_ADAPTIVE]);
- } else {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[SSIL_GATHER]);
- }
-
- gather_ssil(compute_list, p_ssil_slices, p_edges_slices, p_settings, false, r_gather_uniform_set, r_importance_map_uniform_set, r_projection_uniform_set);
- RD::get_singleton()->draw_command_end_label(); //Gather
- }
-
- {
- RD::get_singleton()->draw_command_begin_label("Edge Aware Blur");
- ssil.blur_push_constant.edge_sharpness = 1.0 - p_settings.sharpness;
- ssil.blur_push_constant.half_screen_pixel_size[0] = 1.0 / p_settings.half_screen_size.x;
- ssil.blur_push_constant.half_screen_pixel_size[1] = 1.0 / p_settings.half_screen_size.y;
-
- int blur_passes = p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW ? p_settings.blur_passes : 1;
-
- for (int pass = 0; pass < blur_passes; pass++) {
- int blur_pipeline = SSIL_BLUR_PASS;
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
- blur_pipeline = SSIL_BLUR_PASS_SMART;
- if (pass < blur_passes - 2) {
- blur_pipeline = SSIL_BLUR_PASS_WIDE;
- }
- }
-
- for (int i = 0; i < 4; i++) {
- if ((p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) && ((i == 1) || (i == 2))) {
- continue;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[blur_pipeline]);
- if (pass % 2 == 0) {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_pong_slices[i]), 1);
- } else {
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong_slices[i]), 0);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_and_sampler(p_ssil_pong_slices[i], ss_effects.mirror_sampler), 0);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ssil_slices[i]), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges_slices[i]), 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.blur_push_constant, sizeof(SSILBlurPushConstant));
-
- int x_groups = (p_settings.full_screen_size.x >> (p_settings.half_size ? 2 : 1));
- int y_groups = (p_settings.full_screen_size.y >> (p_settings.half_size ? 2 : 1));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, x_groups, y_groups, 1);
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW) {
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- }
- }
-
- RD::get_singleton()->draw_command_end_label(); // Blur
- }
-
- {
- RD::get_singleton()->draw_command_begin_label("Interleave Buffers");
- ssil.interleave_push_constant.inv_sharpness = 1.0 - p_settings.sharpness;
- ssil.interleave_push_constant.pixel_size[0] = 1.0 / p_settings.full_screen_size.x;
- ssil.interleave_push_constant.pixel_size[1] = 1.0 / p_settings.full_screen_size.y;
- ssil.interleave_push_constant.size_modifier = uint32_t(p_settings.half_size ? 4 : 2);
-
- int interleave_pipeline = SSIL_INTERLEAVE_HALF;
- if (p_settings.quality == RS::ENV_SSIL_QUALITY_LOW) {
- interleave_pipeline = SSIL_INTERLEAVE;
- } else if (p_settings.quality >= RS::ENV_SSIL_QUALITY_MEDIUM) {
- interleave_pipeline = SSIL_INTERLEAVE_SMART;
- }
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssil.pipelines[interleave_pipeline]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_destination), 0);
-
- if (p_settings.quality > RS::ENV_SSIL_QUALITY_VERY_LOW && p_settings.blur_passes % 2 == 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil), 1);
- } else {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ssil_pong), 1);
- }
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_edges), 2);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssil.interleave_push_constant, sizeof(SSILInterleavePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_settings.full_screen_size.x, p_settings.full_screen_size.y, 1);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label(); // Interleave
- }
-
- RD::get_singleton()->draw_command_end_label(); // SSIL
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER);
-
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero, 0); //no barrier
-}
-
void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) {
roughness_limiter.push_constant.screen_size[0] = p_size.x;
roughness_limiter.push_constant.screen_size[1] = p_size.y;
@@ -1253,189 +198,6 @@ void EffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size
RD::get_singleton()->compute_list_end();
}
-void EffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap roughness with the mobile renderer.");
-
- memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
-
- roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id;
- roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in.
- roughness.push_constant.sample_count = p_sample_count;
- roughness.push_constant.use_direct_write = p_roughness == 0.0;
- roughness.push_constant.face_size = p_size;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.compute_pipeline);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture, true), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 1);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
-
- int x_groups = (p_size - 1) / 8 + 1;
- int y_groups = (p_size - 1) / 8 + 1;
-
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1);
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap roughness with the clustered renderer.");
- ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap roughness must process one side at a time.");
-
- memset(&roughness.push_constant, 0, sizeof(CubemapRoughnessPushConstant));
-
- roughness.push_constant.face_id = p_face_id;
- roughness.push_constant.roughness = p_roughness * p_roughness; // Shader expects roughness, not perceptual roughness, so multiply before passing in.
- roughness.push_constant.sample_count = p_sample_count;
- roughness.push_constant.use_direct_write = p_roughness == 0.0;
- roughness.push_constant.face_size = p_size;
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, roughness.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
-void EffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap downsample with the mobile renderer.");
-
- cubemap_downsampler.push_constant.face_size = p_size.x;
- cubemap_downsampler.push_constant.face_id = 0; // we render all 6 sides to each layer in one call
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.compute_pipeline);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1);
-
- int x_groups = (p_size.x - 1) / 8 + 1;
- int y_groups = (p_size.y - 1) / 8 + 1;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
-
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 6); // one z_group for each face
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap downsample with the clustered renderer.");
- ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap downsample must process one side at a time.");
-
- cubemap_downsampler.push_constant.face_size = p_size.x;
- cubemap_downsampler.push_constant.face_id = p_face_id;
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, cubemap_downsampler.raster_pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_cubemap), 0);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
-void EffectsRD::cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array) {
- ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use compute based cubemap filter with the mobile renderer.");
-
- Vector<RD::Uniform> uniforms;
- for (int i = 0; i < p_dest_cubemap.size(); i++) {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = i;
- u.append_id(p_dest_cubemap[i]);
- uniforms.push_back(u);
- }
- if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
- RD::get_singleton()->free(filter.image_uniform_set);
- }
- filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, 0), 2);
-
- int pipeline = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY;
- pipeline = filter.use_high_quality ? pipeline : pipeline + 1;
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.compute_pipelines[pipeline]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap, true), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2);
-
- int x_groups = p_use_array ? 1792 : 342; // (128 * 128 * 7) / 64 : (128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) / 64
-
- RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, 6, 1); // one y_group for each face
-
- RD::get_singleton()->compute_list_end();
-}
-
-void EffectsRD::cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level) {
- ERR_FAIL_COND_MSG(!prefer_raster_effects, "Can't use raster based cubemap filter with the clustered renderer.");
- ERR_FAIL_COND_MSG(p_face_id >= 6, "Raster implementation of cubemap filter must process one side at a time.");
-
- // TODO implement!
- CubemapFilterRasterPushConstant push_constant;
- push_constant.mip_level = p_mip_level;
- push_constant.face_id = p_face_id;
-
- CubemapFilterMode mode = filter.use_high_quality ? FILTER_MODE_HIGH_QUALITY : FILTER_MODE_LOW_QUALITY;
-
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, filter.raster_pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_cubemap), 0);
- RD::get_singleton()->draw_list_bind_uniform_set(draw_list, filter.uniform_set, 1);
- RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array);
-
- RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CubemapFilterRasterPushConstant));
-
- RD::get_singleton()->draw_list_draw(draw_list, true);
- RD::get_singleton()->draw_list_end();
-}
-
-void EffectsRD::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
- ResolvePushConstant push_constant;
- push_constant.screen_size[0] = p_screen_size.x;
- push_constant.screen_size[1] = p_screen_size.y;
- push_constant.samples = p_samples;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[p_source_voxel_gi.is_valid() ? RESOLVE_MODE_GI_VOXEL_GI : RESOLVE_MODE_GI]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture_pair(p_source_depth, p_source_normal_roughness), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_image_pair(p_dest_depth, p_dest_normal_roughness), 1);
- if (p_source_voxel_gi.is_valid()) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_voxel_gi), 2);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_voxel_gi), 3);
- }
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1);
-
- RD::get_singleton()->compute_list_end(p_barrier);
-}
-
-void EffectsRD::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier) {
- ResolvePushConstant push_constant;
- push_constant.screen_size[0] = p_screen_size.x;
- push_constant.screen_size[1] = p_screen_size.y;
- push_constant.samples = p_samples;
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, resolve.pipelines[RESOLVE_MODE_DEPTH]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_depth), 0);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_depth), 1);
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(ResolvePushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_screen_size.x, p_screen_size.y, 1);
-
- RD::get_singleton()->compute_list_end(p_barrier);
-}
-
void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
Sort::PushConstant push_constant;
push_constant.total_elements = p_size;
@@ -1506,51 +268,8 @@ void EffectsRD::sort_buffer(RID p_uniform_set, int p_size) {
}
EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
- {
- Vector<String> FSR_upscale_modes;
-
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- // MoltenVK does not support some of the operations used by the normal mode of FSR. Fallback works just fine though.
- FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
-#else
- // Everyone else can use normal mode when available.
- if (RD::get_singleton()->get_device_capabilities()->supports_fsr_half_float) {
- FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_NORMAL\n");
- } else {
- FSR_upscale_modes.push_back("\n#define MODE_FSR_UPSCALE_FALLBACK\n");
- }
-#endif
-
- FSR_upscale.shader.initialize(FSR_upscale_modes);
-
- FSR_upscale.shader_version = FSR_upscale.shader.version_create();
- FSR_upscale.pipeline = RD::get_singleton()->compute_pipeline_create(FSR_upscale.shader.version_get_shader(FSR_upscale.shader_version, 0));
- }
-
prefer_raster_effects = p_prefer_raster_effects;
- {
- // Initialize roughness
- Vector<String> cubemap_roughness_modes;
- cubemap_roughness_modes.push_back("");
-
- if (prefer_raster_effects) {
- roughness.raster_shader.initialize(cubemap_roughness_modes);
-
- roughness.shader_version = roughness.raster_shader.version_create();
-
- roughness.raster_pipeline.setup(roughness.raster_shader.version_get_shader(roughness.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
-
- } else {
- roughness.compute_shader.initialize(cubemap_roughness_modes);
-
- roughness.shader_version = roughness.compute_shader.version_create();
-
- roughness.compute_pipeline = RD::get_singleton()->compute_pipeline_create(roughness.compute_shader.version_get_shader(roughness.shader_version, 0));
- roughness.raster_pipeline.clear();
- }
- }
-
if (prefer_raster_effects) {
Vector<String> luminance_reduce_modes;
luminance_reduce_modes.push_back("\n#define FIRST_PASS\n"); // LUMINANCE_REDUCE_FRAGMENT_FIRST
@@ -1584,170 +303,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
}
- {
- // Initialize copier
- Vector<String> copy_modes;
- copy_modes.push_back("\n");
-
- cube_to_dp.shader.initialize(copy_modes);
-
- cube_to_dp.shader_version = cube_to_dp.shader.version_create();
- RID shader = cube_to_dp.shader.version_get_shader(cube_to_dp.shader_version, 0);
- RD::PipelineDepthStencilState dss;
- dss.enable_depth_test = true;
- dss.depth_compare_operator = RD::COMPARE_OP_ALWAYS;
- dss.enable_depth_write = true;
- cube_to_dp.pipeline.setup(shader, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), dss, RD::PipelineColorBlendState(), 0);
- }
-
- if (!prefer_raster_effects) {
- {
- // Initialize depth buffer for screen space effects
- Vector<String> downsampler_modes;
- downsampler_modes.push_back("\n");
- downsampler_modes.push_back("\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n");
- downsampler_modes.push_back("\n#define USE_HALF_BUFFERS\n#define USE_HALF_SIZE\n");
- downsampler_modes.push_back("\n#define GENERATE_MIPS\n#define GENERATE_FULL_MIPS");
-
- ss_effects.downsample_shader.initialize(downsampler_modes);
-
- ss_effects.downsample_shader_version = ss_effects.downsample_shader.version_create();
-
- for (int i = 0; i < SS_EFFECTS_MAX; i++) {
- ss_effects.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ss_effects.downsample_shader.version_get_shader(ss_effects.downsample_shader_version, i));
- }
-
- ss_effects.gather_constants_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSEffectsGatherConstants));
- SSEffectsGatherConstants gather_constants;
-
- const int sub_pass_count = 5;
- for (int pass = 0; pass < 4; pass++) {
- for (int subPass = 0; subPass < sub_pass_count; subPass++) {
- int a = pass;
- int b = subPass;
-
- int spmap[5]{ 0, 1, 4, 3, 2 };
- b = spmap[subPass];
-
- float ca, sa;
- float angle0 = (float(a) + float(b) / float(sub_pass_count)) * Math_PI * 0.5f;
-
- ca = Math::cos(angle0);
- sa = Math::sin(angle0);
-
- float scale = 1.0f + (a - 1.5f + (b - (sub_pass_count - 1.0f) * 0.5f) / float(sub_pass_count)) * 0.07f;
-
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 0] = scale * ca;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 1] = scale * -sa;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 2] = -scale * sa;
- gather_constants.rotation_matrices[pass * 20 + subPass * 4 + 3] = -scale * ca;
- }
- }
-
- RD::get_singleton()->buffer_update(ss_effects.gather_constants_buffer, 0, sizeof(SSEffectsGatherConstants), &gather_constants);
- }
-
- {
- // Initialize ssao
-
- RD::SamplerState sampler;
- sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.mip_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT;
- sampler.max_lod = 4;
-
- ss_effects.mirror_sampler = RD::get_singleton()->sampler_create(sampler);
-
- uint32_t pipeline = 0;
- {
- Vector<String> ssao_modes;
-
- ssao_modes.push_back("\n");
- ssao_modes.push_back("\n#define SSAO_BASE\n");
- ssao_modes.push_back("\n#define ADAPTIVE\n");
-
- ssao.gather_shader.initialize(ssao_modes);
-
- ssao.gather_shader_version = ssao.gather_shader.version_create();
-
- for (int i = 0; i <= SSAO_GATHER_ADAPTIVE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i));
- pipeline++;
- }
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define GENERATE_MAP\n");
- ssao_modes.push_back("\n#define PROCESS_MAPA\n");
- ssao_modes.push_back("\n#define PROCESS_MAPB\n");
-
- ssao.importance_map_shader.initialize(ssao_modes);
-
- ssao.importance_map_shader_version = ssao.importance_map_shader.version_create();
-
- for (int i = SSAO_GENERATE_IMPORTANCE_MAP; i <= SSAO_PROCESS_IMPORTANCE_MAPB; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, i - SSAO_GENERATE_IMPORTANCE_MAP));
-
- pipeline++;
- }
- ssao.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssao.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
- RD::get_singleton()->set_resource_name(ssao.importance_map_load_counter, "Importance Map Load Counter");
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(ssao.importance_map_load_counter);
- uniforms.push_back(u);
- }
- ssao.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssao.importance_map_shader.version_get_shader(ssao.importance_map_shader_version, 2), 2);
- RD::get_singleton()->set_resource_name(ssao.counter_uniform_set, "Load Counter Uniform Set");
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_WIDE\n");
-
- ssao.blur_shader.initialize(ssao_modes);
-
- ssao.blur_shader_version = ssao.blur_shader.version_create();
-
- for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_PASS_WIDE; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS));
-
- pipeline++;
- }
- }
- {
- Vector<String> ssao_modes;
- ssao_modes.push_back("\n#define MODE_NON_SMART\n");
- ssao_modes.push_back("\n#define MODE_SMART\n");
- ssao_modes.push_back("\n#define MODE_HALF\n");
-
- ssao.interleave_shader.initialize(ssao_modes);
-
- ssao.interleave_shader_version = ssao.interleave_shader.version_create();
- for (int i = SSAO_INTERLEAVE; i <= SSAO_INTERLEAVE_HALF; i++) {
- ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.interleave_shader.version_get_shader(ssao.interleave_shader_version, i - SSAO_INTERLEAVE));
- RD::get_singleton()->set_resource_name(ssao.pipelines[pipeline], "Interleave Pipeline " + itos(i));
- pipeline++;
- }
- }
-
- ERR_FAIL_COND(pipeline != SSAO_MAX);
- }
- }
-
if (!prefer_raster_effects) {
// Initialize roughness limiter
Vector<String> shader_modes;
@@ -1761,272 +316,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
{
- //Initialize cubemap downsampler
- Vector<String> cubemap_downsampler_modes;
- cubemap_downsampler_modes.push_back("");
-
- if (prefer_raster_effects) {
- cubemap_downsampler.raster_shader.initialize(cubemap_downsampler_modes);
-
- cubemap_downsampler.shader_version = cubemap_downsampler.raster_shader.version_create();
-
- cubemap_downsampler.raster_pipeline.setup(cubemap_downsampler.raster_shader.version_get_shader(cubemap_downsampler.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- } else {
- cubemap_downsampler.compute_shader.initialize(cubemap_downsampler_modes);
-
- cubemap_downsampler.shader_version = cubemap_downsampler.compute_shader.version_create();
-
- cubemap_downsampler.compute_pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.compute_shader.version_get_shader(cubemap_downsampler.shader_version, 0));
- cubemap_downsampler.raster_pipeline.clear();
- }
- }
-
- {
- // Initialize cubemap filter
- filter.use_high_quality = GLOBAL_GET("rendering/reflections/sky_reflections/fast_filter_high_quality");
-
- Vector<String> cubemap_filter_modes;
- cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n");
- cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n");
- cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n");
- cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n");
-
- if (filter.use_high_quality) {
- filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs));
- RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(high_quality_coeffs), &high_quality_coeffs[0]);
- } else {
- filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(low_quality_coeffs));
- RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0]);
- }
-
- if (prefer_raster_effects) {
- filter.raster_shader.initialize(cubemap_filter_modes);
-
- // array variants are not supported in raster
- filter.raster_shader.set_variant_enabled(FILTER_MODE_HIGH_QUALITY_ARRAY, false);
- filter.raster_shader.set_variant_enabled(FILTER_MODE_LOW_QUALITY_ARRAY, false);
-
- filter.shader_version = filter.raster_shader.version_create();
-
- for (int i = 0; i < FILTER_MODE_MAX; i++) {
- if (filter.raster_shader.is_variant_enabled(i)) {
- filter.raster_pipelines[i].setup(filter.raster_shader.version_get_shader(filter.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0);
- } else {
- filter.raster_pipelines[i].clear();
- }
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(filter.coefficient_buffer);
- uniforms.push_back(u);
- }
- filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.raster_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
- } else {
- filter.compute_shader.initialize(cubemap_filter_modes);
- filter.shader_version = filter.compute_shader.version_create();
-
- for (int i = 0; i < FILTER_MODE_MAX; i++) {
- filter.compute_pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.compute_shader.version_get_shader(filter.shader_version, i));
- filter.raster_pipelines[i].clear();
- }
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(filter.coefficient_buffer);
- uniforms.push_back(u);
- }
- filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.compute_shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1);
- }
- }
-
- if (!prefer_raster_effects) {
- Vector<String> specular_modes;
- specular_modes.push_back("\n#define MODE_MERGE\n");
- specular_modes.push_back("\n#define MODE_MERGE\n#define MODE_SSR\n");
- specular_modes.push_back("\n");
- specular_modes.push_back("\n#define MODE_SSR\n");
-
- specular_merge.shader.initialize(specular_modes);
-
- specular_merge.shader_version = specular_merge.shader.version_create();
-
- //use additive
-
- RD::PipelineColorBlendState::Attachment ba;
- ba.enable_blend = true;
- ba.src_color_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.dst_color_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
- ba.color_blend_op = RD::BLEND_OP_ADD;
- ba.alpha_blend_op = RD::BLEND_OP_ADD;
-
- RD::PipelineColorBlendState blend_additive;
- blend_additive.attachments.push_back(ba);
-
- for (int i = 0; i < SPECULAR_MERGE_MAX; i++) {
- RD::PipelineColorBlendState blend_state;
- if (i == SPECULAR_MERGE_ADDITIVE_ADD || i == SPECULAR_MERGE_ADDITIVE_SSR) {
- blend_state = blend_additive;
- } else {
- blend_state = RD::PipelineColorBlendState::create_disabled();
- }
- specular_merge.pipelines[i].setup(specular_merge.shader.version_get_shader(specular_merge.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
- }
- }
-
- if (!prefer_raster_effects) {
- {
- Vector<String> ssr_modes;
- ssr_modes.push_back("\n");
- ssr_modes.push_back("\n#define MODE_ROUGH\n");
-
- ssr.shader.initialize(ssr_modes);
-
- ssr.shader_version = ssr.shader.version_create();
-
- for (int i = 0; i < SCREEN_SPACE_REFLECTION_MAX; i++) {
- ssr.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr.shader.version_get_shader(ssr.shader_version, i));
- }
- }
-
- {
- Vector<String> ssr_filter_modes;
- ssr_filter_modes.push_back("\n");
- ssr_filter_modes.push_back("\n#define VERTICAL_PASS\n");
-
- ssr_filter.shader.initialize(ssr_filter_modes);
-
- ssr_filter.shader_version = ssr_filter.shader.version_create();
-
- for (int i = 0; i < SCREEN_SPACE_REFLECTION_FILTER_MAX; i++) {
- ssr_filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssr_filter.shader.version_get_shader(ssr_filter.shader_version, i));
- }
- }
-
- {
- Vector<String> ssr_scale_modes;
- ssr_scale_modes.push_back("\n");
-
- ssr_scale.shader.initialize(ssr_scale_modes);
-
- ssr_scale.shader_version = ssr_scale.shader.version_create();
-
- ssr_scale.pipeline = RD::get_singleton()->compute_pipeline_create(ssr_scale.shader.version_get_shader(ssr_scale.shader_version, 0));
- }
-
- {
- Vector<String> sss_modes;
- sss_modes.push_back("\n#define USE_11_SAMPLES\n");
- sss_modes.push_back("\n#define USE_17_SAMPLES\n");
- sss_modes.push_back("\n#define USE_25_SAMPLES\n");
-
- sss.shader.initialize(sss_modes);
-
- sss.shader_version = sss.shader.version_create();
-
- for (int i = 0; i < sss_modes.size(); i++) {
- sss.pipelines[i] = RD::get_singleton()->compute_pipeline_create(sss.shader.version_get_shader(sss.shader_version, i));
- }
- }
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n");
- ssil_modes.push_back("\n#define SSIL_BASE\n");
- ssil_modes.push_back("\n#define ADAPTIVE\n");
-
- ssil.gather_shader.initialize(ssil_modes);
-
- ssil.gather_shader_version = ssil.gather_shader.version_create();
-
- for (int i = SSIL_GATHER; i <= SSIL_GATHER_ADAPTIVE; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.gather_shader.version_get_shader(ssil.gather_shader_version, i));
- }
- ssil.projection_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SSILProjectionUniforms));
- }
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define GENERATE_MAP\n");
- ssil_modes.push_back("\n#define PROCESS_MAPA\n");
- ssil_modes.push_back("\n#define PROCESS_MAPB\n");
-
- ssil.importance_map_shader.initialize(ssil_modes);
-
- ssil.importance_map_shader_version = ssil.importance_map_shader.version_create();
-
- for (int i = SSIL_GENERATE_IMPORTANCE_MAP; i <= SSIL_PROCESS_IMPORTANCE_MAPB; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, i - SSIL_GENERATE_IMPORTANCE_MAP));
- }
- ssil.importance_map_load_counter = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t));
- int zero[1] = { 0 };
- RD::get_singleton()->buffer_update(ssil.importance_map_load_counter, 0, sizeof(uint32_t), &zero);
- RD::get_singleton()->set_resource_name(ssil.importance_map_load_counter, "Importance Map Load Counter");
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 0;
- u.append_id(ssil.importance_map_load_counter);
- uniforms.push_back(u);
- }
- ssil.counter_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, ssil.importance_map_shader.version_get_shader(ssil.importance_map_shader_version, 2), 2);
- RD::get_singleton()->set_resource_name(ssil.counter_uniform_set, "Load Counter Uniform Set");
- }
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define MODE_NON_SMART\n");
- ssil_modes.push_back("\n#define MODE_SMART\n");
- ssil_modes.push_back("\n#define MODE_WIDE\n");
-
- ssil.blur_shader.initialize(ssil_modes);
-
- ssil.blur_shader_version = ssil.blur_shader.version_create();
- for (int i = SSIL_BLUR_PASS; i <= SSIL_BLUR_PASS_WIDE; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.blur_shader.version_get_shader(ssil.blur_shader_version, i - SSIL_BLUR_PASS));
- }
- }
-
- {
- Vector<String> ssil_modes;
- ssil_modes.push_back("\n#define MODE_NON_SMART\n");
- ssil_modes.push_back("\n#define MODE_SMART\n");
- ssil_modes.push_back("\n#define MODE_HALF\n");
-
- ssil.interleave_shader.initialize(ssil_modes);
-
- ssil.interleave_shader_version = ssil.interleave_shader.version_create();
- for (int i = SSIL_INTERLEAVE; i <= SSIL_INTERLEAVE_HALF; i++) {
- ssil.pipelines[i] = RD::get_singleton()->compute_pipeline_create(ssil.interleave_shader.version_get_shader(ssil.interleave_shader_version, i - SSIL_INTERLEAVE));
- }
- }
-
- {
- Vector<String> resolve_modes;
- resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n");
- resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n");
- resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n");
-
- resolve.shader.initialize(resolve_modes);
-
- resolve.shader_version = resolve.shader.version_create();
-
- for (int i = 0; i < RESOLVE_MODE_MAX; i++) {
- resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i));
- }
- }
- }
-
- {
Vector<String> sort_modes;
sort_modes.push_back("\n#define MODE_SORT_BLOCK\n");
sort_modes.push_back("\n#define MODE_SORT_STEP\n");
@@ -2041,14 +330,6 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
}
- {
- Vector<String> taa_modes;
- taa_modes.push_back("\n#define MODE_TAA_RESOLVE");
- TAA_resolve.shader.initialize(taa_modes);
- TAA_resolve.shader_version = TAA_resolve.shader.version_create();
- TAA_resolve.pipeline = RD::get_singleton()->compute_pipeline_create(TAA_resolve.shader.version_get_shader(TAA_resolve.shader_version, 0));
- }
-
RD::SamplerState sampler;
sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR;
sampler.min_filter = RD::SAMPLER_FILTER_LINEAR;
@@ -2083,56 +364,17 @@ EffectsRD::EffectsRD(bool p_prefer_raster_effects) {
}
EffectsRD::~EffectsRD() {
- if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) {
- RD::get_singleton()->free(filter.image_uniform_set);
- }
-
- if (RD::get_singleton()->uniform_set_is_valid(filter.uniform_set)) {
- RD::get_singleton()->free(filter.uniform_set);
- }
-
RD::get_singleton()->free(default_sampler);
RD::get_singleton()->free(default_mipmap_sampler);
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
- RD::get_singleton()->free(filter.coefficient_buffer);
- FSR_upscale.shader.version_free(FSR_upscale.shader_version);
- TAA_resolve.shader.version_free(TAA_resolve.shader_version);
if (prefer_raster_effects) {
luminance_reduce_raster.shader.version_free(luminance_reduce_raster.shader_version);
- roughness.raster_shader.version_free(roughness.shader_version);
- cubemap_downsampler.raster_shader.version_free(cubemap_downsampler.shader_version);
- filter.raster_shader.version_free(filter.shader_version);
} else {
luminance_reduce.shader.version_free(luminance_reduce.shader_version);
- roughness.compute_shader.version_free(roughness.shader_version);
- cubemap_downsampler.compute_shader.version_free(cubemap_downsampler.shader_version);
- filter.compute_shader.version_free(filter.shader_version);
}
if (!prefer_raster_effects) {
- resolve.shader.version_free(resolve.shader_version);
- specular_merge.shader.version_free(specular_merge.shader_version);
- ss_effects.downsample_shader.version_free(ss_effects.downsample_shader_version);
- ssao.blur_shader.version_free(ssao.blur_shader_version);
- ssao.gather_shader.version_free(ssao.gather_shader_version);
- ssao.interleave_shader.version_free(ssao.interleave_shader_version);
- ssao.importance_map_shader.version_free(ssao.importance_map_shader_version);
- ssil.blur_shader.version_free(ssil.blur_shader_version);
- ssil.gather_shader.version_free(ssil.gather_shader_version);
- ssil.interleave_shader.version_free(ssil.interleave_shader_version);
- ssil.importance_map_shader.version_free(ssil.importance_map_shader_version);
roughness_limiter.shader.version_free(roughness_limiter.shader_version);
- ssr.shader.version_free(ssr.shader_version);
- ssr_filter.shader.version_free(ssr_filter.shader_version);
- ssr_scale.shader.version_free(ssr_scale.shader_version);
- sss.shader.version_free(sss.shader_version);
-
- RD::get_singleton()->free(ss_effects.mirror_sampler);
- RD::get_singleton()->free(ss_effects.gather_constants_buffer);
- RD::get_singleton()->free(ssao.importance_map_load_counter);
- RD::get_singleton()->free(ssil.importance_map_load_counter);
- RD::get_singleton()->free(ssil.projection_uniform_buffer);
}
- cube_to_dp.shader.version_free(cube_to_dp.shader_version);
sort.shader.version_free(sort.shader_version);
}
diff --git a/servers/rendering/renderer_rd/effects_rd.h b/servers/rendering/renderer_rd/effects_rd.h
index 787873642e..b05af73cf3 100644
--- a/servers/rendering/renderer_rd/effects_rd.h
+++ b/servers/rendering/renderer_rd/effects_rd.h
@@ -31,36 +31,12 @@
#ifndef EFFECTS_RD_H
#define EFFECTS_RD_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
-#include "servers/rendering/renderer_rd/shaders/cube_to_dp.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/cubemap_filter.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/fsr_upscale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/luminance_reduce_raster.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/resolve.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/roughness_limiter.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/sort.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/specular_merge.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_blur.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssao_interleave.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_blur.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/ssil_interleave.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/taa_resolve.glsl.gen.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering_server.h"
@@ -69,60 +45,6 @@ class EffectsRD {
private:
bool prefer_raster_effects;
- enum FSRUpscalePass {
- FSR_UPSCALE_PASS_EASU = 0,
- FSR_UPSCALE_PASS_RCAS = 1
- };
-
- struct FSRUpscalePushConstant {
- float resolution_width;
- float resolution_height;
- float upscaled_width;
- float upscaled_height;
- float sharpness;
- int pass;
- int _unused0, _unused1;
- };
-
- struct FSRUpscale {
- FSRUpscalePushConstant push_constant;
- FsrUpscaleShaderRD shader;
- RID shader_version;
- RID pipeline;
- } FSR_upscale;
-
- struct TAAResolvePushConstant {
- float resolution_width;
- float resolution_height;
- float disocclusion_threshold;
- float disocclusion_scale;
- };
-
- struct TAAResolve {
- TAAResolvePushConstant push_constant;
- TaaResolveShaderRD shader;
- RID shader_version;
- RID pipeline;
- } TAA_resolve;
-
- struct CubemapRoughnessPushConstant {
- uint32_t face_id;
- uint32_t sample_count;
- float roughness;
- uint32_t use_direct_write;
- float face_size;
- float pad[3];
- };
-
- struct CubemapRoughness {
- CubemapRoughnessPushConstant push_constant;
- CubemapRoughnessShaderRD compute_shader;
- CubemapRoughnessRasterShaderRD raster_shader;
- RID shader_version;
- RID compute_pipeline;
- PipelineCacheRD raster_pipeline;
- } roughness;
-
enum LuminanceReduceMode {
LUMINANCE_REDUCE_READ,
LUMINANCE_REDUCE,
@@ -168,244 +90,6 @@ private:
PipelineCacheRD pipelines[LUMINANCE_REDUCE_FRAGMENT_MAX];
} luminance_reduce_raster;
- struct CopyToDPPushConstant {
- float z_far;
- float z_near;
- float texel_size[2];
- float screen_rect[4];
- };
-
- struct CoptToDP {
- CubeToDpShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipeline;
- } cube_to_dp;
-
- struct SSEffectsDownsamplePushConstant {
- float pixel_size[2];
- float z_far;
- float z_near;
- uint32_t orthogonal;
- float radius_sq;
- uint32_t pad[2];
- };
-
- enum SSEffectsMode {
- SS_EFFECTS_DOWNSAMPLE,
- SS_EFFECTS_DOWNSAMPLE_HALF_RES,
- SS_EFFECTS_DOWNSAMPLE_MIPMAP,
- SS_EFFECTS_DOWNSAMPLE_MIPMAP_HALF_RES,
- SS_EFFECTS_DOWNSAMPLE_HALF,
- SS_EFFECTS_DOWNSAMPLE_HALF_RES_HALF,
- SS_EFFECTS_DOWNSAMPLE_FULL_MIPS,
- SS_EFFECTS_MAX
- };
-
- struct SSEffectsGatherConstants {
- float rotation_matrices[80]; //5 vec4s * 4
- };
-
- struct SSEffects {
- SSEffectsDownsamplePushConstant downsample_push_constant;
- SsEffectsDownsampleShaderRD downsample_shader;
- RID downsample_shader_version;
- RID downsample_uniform_set;
- bool used_half_size_last_frame = false;
- bool used_mips_last_frame = false;
- bool used_full_mips_last_frame = false;
-
- RID gather_constants_buffer;
-
- RID mirror_sampler;
-
- RID pipelines[SS_EFFECTS_MAX];
- } ss_effects;
-
- enum SSAOMode {
- SSAO_GATHER,
- SSAO_GATHER_BASE,
- SSAO_GATHER_ADAPTIVE,
- SSAO_GENERATE_IMPORTANCE_MAP,
- SSAO_PROCESS_IMPORTANCE_MAPA,
- SSAO_PROCESS_IMPORTANCE_MAPB,
- SSAO_BLUR_PASS,
- SSAO_BLUR_PASS_SMART,
- SSAO_BLUR_PASS_WIDE,
- SSAO_INTERLEAVE,
- SSAO_INTERLEAVE_SMART,
- SSAO_INTERLEAVE_HALF,
- SSAO_MAX
- };
-
- struct SSAOGatherPushConstant {
- int32_t screen_size[2];
- int pass;
- int quality;
-
- float half_screen_pixel_size[2];
- int size_multiplier;
- float detail_intensity;
-
- float NDC_to_view_mul[2];
- float NDC_to_view_add[2];
-
- float pad[2];
- float half_screen_pixel_size_x025[2];
-
- float radius;
- float intensity;
- float shadow_power;
- float shadow_clamp;
-
- float fade_out_mul;
- float fade_out_add;
- float horizon_angle_threshold;
- float inv_radius_near_limit;
-
- uint32_t is_orthogonal;
- float neg_inv_radius;
- float load_counter_avg_div;
- float adaptive_sample_limit;
-
- int32_t pass_coord_offset[2];
- float pass_uv_offset[2];
- };
-
- struct SSAOImportanceMapPushConstant {
- float half_screen_pixel_size[2];
- float intensity;
- float power;
- };
-
- struct SSAOBlurPushConstant {
- float edge_sharpness;
- float pad;
- float half_screen_pixel_size[2];
- };
-
- struct SSAOInterleavePushConstant {
- float inv_sharpness;
- uint32_t size_modifier;
- float pixel_size[2];
- };
-
- struct SSAO {
- SSAOGatherPushConstant gather_push_constant;
- SsaoShaderRD gather_shader;
- RID gather_shader_version;
-
- SSAOImportanceMapPushConstant importance_map_push_constant;
- SsaoImportanceMapShaderRD importance_map_shader;
- RID importance_map_shader_version;
- RID importance_map_load_counter;
- RID counter_uniform_set;
-
- SSAOBlurPushConstant blur_push_constant;
- SsaoBlurShaderRD blur_shader;
- RID blur_shader_version;
-
- SSAOInterleavePushConstant interleave_push_constant;
- SsaoInterleaveShaderRD interleave_shader;
- RID interleave_shader_version;
-
- RID pipelines[SSAO_MAX];
- } ssao;
-
- enum SSILMode {
- SSIL_GATHER,
- SSIL_GATHER_BASE,
- SSIL_GATHER_ADAPTIVE,
- SSIL_GENERATE_IMPORTANCE_MAP,
- SSIL_PROCESS_IMPORTANCE_MAPA,
- SSIL_PROCESS_IMPORTANCE_MAPB,
- SSIL_BLUR_PASS,
- SSIL_BLUR_PASS_SMART,
- SSIL_BLUR_PASS_WIDE,
- SSIL_INTERLEAVE,
- SSIL_INTERLEAVE_SMART,
- SSIL_INTERLEAVE_HALF,
- SSIL_MAX
- };
-
- struct SSILGatherPushConstant {
- int32_t screen_size[2];
- int pass;
- int quality;
-
- float half_screen_pixel_size[2];
- float half_screen_pixel_size_x025[2];
-
- float NDC_to_view_mul[2];
- float NDC_to_view_add[2];
-
- float pad2[2];
- float z_near;
- float z_far;
-
- float radius;
- float intensity;
- int size_multiplier;
- int pad;
-
- float fade_out_mul;
- float fade_out_add;
- float normal_rejection_amount;
- float inv_radius_near_limit;
-
- uint32_t is_orthogonal;
- float neg_inv_radius;
- float load_counter_avg_div;
- float adaptive_sample_limit;
-
- int32_t pass_coord_offset[2];
- float pass_uv_offset[2];
- };
-
- struct SSILImportanceMapPushConstant {
- float half_screen_pixel_size[2];
- float intensity;
- float pad;
- };
-
- struct SSILBlurPushConstant {
- float edge_sharpness;
- float pad;
- float half_screen_pixel_size[2];
- };
-
- struct SSILInterleavePushConstant {
- float inv_sharpness;
- uint32_t size_modifier;
- float pixel_size[2];
- };
-
- struct SSILProjectionUniforms {
- float inv_last_frame_projection_matrix[16];
- };
-
- struct SSIL {
- SSILGatherPushConstant gather_push_constant;
- SsilShaderRD gather_shader;
- RID gather_shader_version;
- RID projection_uniform_buffer;
-
- SSILImportanceMapPushConstant importance_map_push_constant;
- SsilImportanceMapShaderRD importance_map_shader;
- RID importance_map_shader_version;
- RID importance_map_load_counter;
- RID counter_uniform_set;
-
- SSILBlurPushConstant blur_push_constant;
- SsilBlurShaderRD blur_shader;
- RID blur_shader_version;
-
- SSILInterleavePushConstant interleave_push_constant;
- SsilInterleaveShaderRD interleave_shader;
- RID interleave_shader_version;
-
- RID pipelines[SSIL_MAX];
- } ssil;
-
struct RoughnessLimiterPushConstant {
int32_t screen_size[2];
float curve;
@@ -420,185 +104,6 @@ private:
} roughness_limiter;
- struct CubemapDownsamplerPushConstant {
- uint32_t face_size;
- uint32_t face_id;
- float pad[2];
- };
-
- struct CubemapDownsampler {
- CubemapDownsamplerPushConstant push_constant;
- CubemapDownsamplerShaderRD compute_shader;
- CubemapDownsamplerRasterShaderRD raster_shader;
- RID shader_version;
- RID compute_pipeline;
- PipelineCacheRD raster_pipeline;
- } cubemap_downsampler;
-
- enum CubemapFilterMode {
- FILTER_MODE_HIGH_QUALITY,
- FILTER_MODE_LOW_QUALITY,
- FILTER_MODE_HIGH_QUALITY_ARRAY,
- FILTER_MODE_LOW_QUALITY_ARRAY,
- FILTER_MODE_MAX,
- };
-
- struct CubemapFilterRasterPushConstant {
- uint32_t mip_level;
- uint32_t face_id;
- float pad[2];
- };
-
- struct CubemapFilter {
- CubemapFilterShaderRD compute_shader;
- CubemapFilterRasterShaderRD raster_shader;
- RID shader_version;
- RID compute_pipelines[FILTER_MODE_MAX];
- PipelineCacheRD raster_pipelines[FILTER_MODE_MAX];
-
- RID uniform_set;
- RID image_uniform_set;
- RID coefficient_buffer;
- bool use_high_quality;
-
- } filter;
-
- enum SpecularMergeMode {
- SPECULAR_MERGE_ADD,
- SPECULAR_MERGE_SSR,
- SPECULAR_MERGE_ADDITIVE_ADD,
- SPECULAR_MERGE_ADDITIVE_SSR,
- SPECULAR_MERGE_MAX
- };
-
- /* Specular merge must be done using raster, rather than compute
- * because it must continue the existing color buffer
- */
-
- struct SpecularMerge {
- SpecularMergeShaderRD shader;
- RID shader_version;
- PipelineCacheRD pipelines[SPECULAR_MERGE_MAX];
-
- } specular_merge;
-
- enum ScreenSpaceReflectionMode {
- SCREEN_SPACE_REFLECTION_NORMAL,
- SCREEN_SPACE_REFLECTION_ROUGH,
- SCREEN_SPACE_REFLECTION_MAX,
- };
-
- struct ScreenSpaceReflectionPushConstant {
- float proj_info[4];
-
- int32_t screen_size[2];
- float camera_z_near;
- float camera_z_far;
-
- int32_t num_steps;
- float depth_tolerance;
- float distance_fade;
- float curve_fade_in;
-
- uint32_t orthogonal;
- float filter_mipmap_levels;
- uint32_t use_half_res;
- uint8_t metallic_mask[4];
-
- float projection[16];
- };
-
- struct ScreenSpaceReflection {
- ScreenSpaceReflectionPushConstant push_constant;
- ScreenSpaceReflectionShaderRD shader;
- RID shader_version;
- RID pipelines[SCREEN_SPACE_REFLECTION_MAX];
-
- } ssr;
-
- struct ScreenSpaceReflectionFilterPushConstant {
- float proj_info[4];
-
- uint32_t orthogonal;
- float edge_tolerance;
- int32_t increment;
- uint32_t pad;
-
- int32_t screen_size[2];
- uint32_t vertical;
- uint32_t steps;
- };
- enum {
- SCREEN_SPACE_REFLECTION_FILTER_HORIZONTAL,
- SCREEN_SPACE_REFLECTION_FILTER_VERTICAL,
- SCREEN_SPACE_REFLECTION_FILTER_MAX,
- };
-
- struct ScreenSpaceReflectionFilter {
- ScreenSpaceReflectionFilterPushConstant push_constant;
- ScreenSpaceReflectionFilterShaderRD shader;
- RID shader_version;
- RID pipelines[SCREEN_SPACE_REFLECTION_FILTER_MAX];
- } ssr_filter;
-
- struct ScreenSpaceReflectionScalePushConstant {
- int32_t screen_size[2];
- float camera_z_near;
- float camera_z_far;
-
- uint32_t orthogonal;
- uint32_t filter;
- uint32_t pad[2];
- };
-
- struct ScreenSpaceReflectionScale {
- ScreenSpaceReflectionScalePushConstant push_constant;
- ScreenSpaceReflectionScaleShaderRD shader;
- RID shader_version;
- RID pipeline;
- } ssr_scale;
-
- struct SubSurfaceScatteringPushConstant {
- int32_t screen_size[2];
- float camera_z_far;
- float camera_z_near;
-
- uint32_t vertical;
- uint32_t orthogonal;
- float unit_size;
- float scale;
-
- float depth_scale;
- uint32_t pad[3];
- };
-
- struct SubSurfaceScattering {
- SubSurfaceScatteringPushConstant push_constant;
- SubsurfaceScatteringShaderRD shader;
- RID shader_version;
- RID pipelines[3]; //3 quality levels
- } sss;
-
- struct ResolvePushConstant {
- int32_t screen_size[2];
- int32_t samples;
- uint32_t pad;
- };
-
- enum ResolveMode {
- RESOLVE_MODE_GI,
- RESOLVE_MODE_GI_VOXEL_GI,
- RESOLVE_MODE_DEPTH,
- RESOLVE_MODE_MAX
- };
-
- struct Resolve {
- ResolvePushConstant push_constant;
- ResolveShaderRD shader;
- RID shader_version;
- RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels
- } resolve;
-
enum SortMode {
SORT_MODE_BLOCK,
SORT_MODE_STEP,
@@ -661,80 +166,14 @@ private:
RID _get_uniform_set_from_image(RID p_texture);
RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false);
- RID _get_compute_uniform_set_from_texture_and_sampler(RID p_texture, RID p_sampler);
- RID _get_compute_uniform_set_from_texture_pair(RID p_texture, RID p_texture2, bool p_use_mipmaps = false);
- RID _get_compute_uniform_set_from_image_pair(RID p_texture, RID p_texture2);
public:
bool get_prefer_raster_effects();
- void fsr_upscale(RID p_source_rd_texture, RID p_secondary_texture, RID p_destination_texture, const Size2i &p_internal_size, const Size2i &p_size, float p_fsr_upscale_sharpness);
- void taa_resolve(RID p_frame, RID p_temp, RID p_depth, RID p_velocity, RID p_prev_velocity, RID p_history, Size2 p_resolution, float p_z_near, float p_z_far);
-
- void cubemap_roughness(RID p_source_rd_texture, RID p_dest_texture, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
- void cubemap_roughness_raster(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size);
- void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dst_framebuffer, const Rect2 &p_rect, const Vector2 &p_dst_size, float p_z_near, float p_z_far, bool p_dp_flip);
void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
void luminance_reduction_raster(RID p_source_texture, const Size2i p_source_size, const Vector<RID> p_reduce, Vector<RID> p_fb, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false);
- struct SSAOSettings {
- float radius = 1.0;
- float intensity = 2.0;
- float power = 1.5;
- float detail = 0.5;
- float horizon = 0.06;
- float sharpness = 0.98;
-
- RS::EnvironmentSSAOQuality quality = RS::ENV_SSAO_QUALITY_MEDIUM;
- bool half_size = false;
- float adaptive_target = 0.5;
- int blur_passes = 2;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
- Size2i half_screen_size = Size2i();
- Size2i quarter_screen_size = Size2i();
- };
-
- struct SSILSettings {
- float radius = 1.0;
- float intensity = 2.0;
- float sharpness = 0.98;
- float normal_rejection = 1.0;
-
- RS::EnvironmentSSILQuality quality = RS::ENV_SSIL_QUALITY_MEDIUM;
- bool half_size = true;
- float adaptive_target = 0.5;
- int blur_passes = 4;
- float fadeout_from = 50.0;
- float fadeout_to = 300.0;
-
- Size2i full_screen_size = Size2i();
- Size2i half_screen_size = Size2i();
- Size2i quarter_screen_size = Size2i();
- };
-
- void downsample_depth(RID p_depth_buffer, const Vector<RID> &p_depth_mipmaps, RS::EnvironmentSSAOQuality p_ssao_quality, RS::EnvironmentSSILQuality p_ssil_quality, bool p_invalidate_uniform_set, bool p_ssao_half_size, bool p_ssil_half_size, Size2i p_full_screen_size, const CameraMatrix &p_projection);
-
- void gather_ssao(RD::ComputeListID p_compute_list, const Vector<RID> p_ao_slices, const SSAOSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set);
- void generate_ssao(RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_upscale_buffer, RID p_importance_map, RID p_importance_map_pong, const CameraMatrix &p_projection, const SSAOSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set);
-
- void gather_ssil(RD::ComputeListID p_compute_list, const Vector<RID> p_ssil_slices, const Vector<RID> p_edges_slices, const SSILSettings &p_settings, bool p_adaptive_base_pass, RID p_gather_uniform_set, RID p_importance_map_uniform_set, RID p_projection_uniform_set);
- void screen_space_indirect_lighting(RID p_diffuse, RID p_destination, RID p_normal_buffer, RID p_depth_mipmaps_texture, RID p_ao, const Vector<RID> p_ao_slices, RID p_ao_pong, const Vector<RID> p_ao_pong_slices, RID p_importance_map, RID p_importance_map_pong, RID p_edges, const Vector<RID> p_edges_slices, const CameraMatrix &p_projection, const CameraMatrix &p_last_projection, const SSILSettings &p_settings, bool p_invalidate_uniform_sets, RID &r_gather_uniform_set, RID &r_importance_map_uniform_set, RID &r_projection_uniform_set);
-
void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve);
- void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size);
- void cubemap_downsample_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, const Size2i &p_size);
- void cubemap_filter(RID p_source_cubemap, Vector<RID> p_dest_cubemap, bool p_use_array);
- void cubemap_filter_raster(RID p_source_cubemap, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_mip_level);
-
- void screen_space_reflection(RID p_diffuse, RID p_normal_roughness, RS::EnvironmentSSRRoughnessQuality p_roughness_quality, RID p_blur_radius, RID p_blur_radius2, RID p_metallic, const Color &p_metallic_mask, RID p_depth, RID p_scale_depth, RID p_scale_normal, RID p_output, RID p_output_blur, const Size2i &p_screen_size, int p_max_steps, float p_fade_in, float p_fade_out, float p_tolerance, const CameraMatrix &p_camera);
- void merge_specular(RID p_dest_framebuffer, RID p_specular, RID p_base, RID p_reflection);
- void sub_surface_scattering(RID p_diffuse, RID p_diffuse2, RID p_depth, const CameraMatrix &p_camera, const Size2i &p_screen_size, float p_scale, float p_depth_scale, RS::SubSurfaceScatteringQuality p_quality);
-
- void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
void sort_buffer(RID p_uniform_set, int p_size);
@@ -742,4 +181,4 @@ public:
~EffectsRD();
};
-#endif // !RASTERIZER_EFFECTS_RD_H
+#endif // EFFECTS_RD_H
diff --git a/servers/rendering/renderer_rd/environment/SCsub b/servers/rendering/renderer_rd/environment/SCsub
new file mode 100644
index 0000000000..86681f9c74
--- /dev/null
+++ b/servers/rendering/renderer_rd/environment/SCsub
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+Import("env")
+
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp
new file mode 100644
index 0000000000..74082906c4
--- /dev/null
+++ b/servers/rendering/renderer_rd/environment/fog.cpp
@@ -0,0 +1,1212 @@
+/*************************************************************************/
+/* fog.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "fog.h"
+
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/rendering_server_default.h"
+
+using namespace RendererRD;
+
+Fog *Fog::singleton = nullptr;
+
+Fog::Fog() {
+ singleton = this;
+}
+
+Fog::~Fog() {
+ singleton = nullptr;
+}
+
+/* FOG VOLUMES */
+
+RID Fog::fog_volume_allocate() {
+ return fog_volume_owner.allocate_rid();
+}
+
+void Fog::fog_volume_initialize(RID p_rid) {
+ fog_volume_owner.initialize_rid(p_rid, FogVolume());
+}
+
+void Fog::fog_volume_free(RID p_rid) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
+ fog_volume->dependency.deleted_notify(p_rid);
+ fog_volume_owner.free(p_rid);
+}
+
+Dependency *Fog::fog_volume_get_dependency(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_NULL_V(fog_volume, nullptr);
+
+ return &fog_volume->dependency;
+}
+
+void Fog::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ if (p_shape == fog_volume->shape) {
+ return;
+ }
+
+ fog_volume->shape = p_shape;
+ fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+}
+
+void Fog::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+
+ fog_volume->extents = p_extents;
+ fog_volume->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+}
+
+void Fog::fog_volume_set_material(RID p_fog_volume, RID p_material) {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND(!fog_volume);
+ fog_volume->material = p_material;
+}
+
+RID Fog::fog_volume_get_material(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RID());
+
+ return fog_volume->material;
+}
+
+RS::FogVolumeShape Fog::fog_volume_get_shape(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX);
+
+ return fog_volume->shape;
+}
+
+AABB Fog::fog_volume_get_aabb(RID p_fog_volume) const {
+ FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, AABB());
+
+ switch (fog_volume->shape) {
+ case RS::FOG_VOLUME_SHAPE_ELLIPSOID:
+ case RS::FOG_VOLUME_SHAPE_CONE:
+ case RS::FOG_VOLUME_SHAPE_CYLINDER:
+ case RS::FOG_VOLUME_SHAPE_BOX: {
+ AABB aabb;
+ aabb.position = -fog_volume->extents;
+ aabb.size = fog_volume->extents * 2;
+ return aabb;
+ }
+ default: {
+ // Need some size otherwise will get culled
+ return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
+ }
+ }
+}
+
+Vector3 Fog::fog_volume_get_extents(RID p_fog_volume) const {
+ const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
+ ERR_FAIL_COND_V(!fog_volume, Vector3());
+ return fog_volume->extents;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Fog material
+
+bool Fog::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ uniform_set_updated = true;
+
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, Fog::get_singleton()->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL, true);
+}
+
+Fog::FogMaterialData::~FogMaterialData() {
+ free_parameters_uniform_set(uniform_set);
+}
+
+RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_func() {
+ FogShaderData *shader_data = memnew(FogShaderData);
+ return shader_data;
+}
+
+RendererRD::MaterialStorage::ShaderData *Fog::_create_fog_shader_funcs() {
+ return Fog::get_singleton()->_create_fog_shader_func();
+};
+
+RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_func(FogShaderData *p_shader) {
+ FogMaterialData *material_data = memnew(FogMaterialData);
+ material_data->shader_data = p_shader;
+ //update will happen later anyway so do nothing.
+ return material_data;
+}
+
+RendererRD::MaterialStorage::MaterialData *Fog::_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
+ return Fog::get_singleton()->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// FOG VOLUMES INSTANCE
+
+RID Fog::fog_volume_instance_create(RID p_fog_volume) {
+ FogVolumeInstance fvi;
+ fvi.volume = p_fog_volume;
+ return fog_volume_instance_owner.make_rid(fvi);
+}
+
+void Fog::fog_instance_free(RID p_rid) {
+ fog_volume_instance_owner.free(p_rid);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog Shader
+
+void Fog::init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array) {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ {
+ // Initialize local fog shader
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("");
+ volumetric_fog.shader.initialize(volumetric_fog_modes);
+
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_FOG, _create_fog_material_funcs);
+ volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
+ }
+
+ {
+ ShaderCompiler::DefaultIdentifierActions actions;
+
+ actions.renames["TIME"] = "scene_params.time";
+ actions.renames["PI"] = _MKSTR(Math_PI);
+ actions.renames["TAU"] = _MKSTR(Math_TAU);
+ actions.renames["E"] = _MKSTR(Math_E);
+ actions.renames["WORLD_POSITION"] = "world.xyz";
+ actions.renames["OBJECT_POSITION"] = "params.position";
+ actions.renames["UVW"] = "uvw";
+ actions.renames["EXTENTS"] = "params.extents";
+ actions.renames["ALBEDO"] = "albedo";
+ actions.renames["DENSITY"] = "density";
+ actions.renames["EMISSION"] = "emission";
+ actions.renames["SDF"] = "sdf";
+
+ actions.usage_defines["SDF"] = "#define SDF_USED\n";
+ actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
+ actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
+ actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
+
+ actions.sampler_array_name = "material_samplers";
+ actions.base_texture_binding_index = 1;
+ actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
+ actions.base_uniform_string = "material.";
+
+ actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
+ actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
+ actions.global_buffer_array_variable = "global_variables.data";
+
+ volumetric_fog.compiler.initialize(actions);
+ }
+
+ {
+ // default material and shader for fog shader
+ volumetric_fog.default_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(volumetric_fog.default_shader);
+ material_storage->shader_set_code(volumetric_fog.default_shader, R"(
+// Default fog shader.
+
+shader_type fog;
+
+void fog() {
+DENSITY = 1.0;
+ALBEDO = vec3(1.0);
+}
+)");
+ volumetric_fog.default_material = material_storage->material_allocate();
+ material_storage->material_initialize(volumetric_fog.default_material);
+ material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
+
+ FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG));
+ volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
+
+ Vector<RD::Uniform> uniforms;
+
+ {
+ Vector<RID> ids;
+ ids.resize(12);
+ RID *ids_ptr = ids.ptrw();
+ ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+ ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
+
+ RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
+ uniforms.push_back(u);
+ }
+
+ volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ }
+ {
+ String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(p_max_directional_lights) + "\n";
+ defines += "\n#define MAX_SKY_LOD " + itos(p_roughness_layers - 1) + ".0\n";
+ if (p_is_using_radiance_cubemap_array) {
+ defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
+ }
+ Vector<String> volumetric_fog_modes;
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
+ volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
+ volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
+ volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
+
+ volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
+ volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
+ for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
+ volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
+ }
+ volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
+ }
+}
+
+void Fog::free_fog_shader() {
+ MaterialStorage *material_storage = MaterialStorage::get_singleton();
+
+ volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
+ RD::get_singleton()->free(volumetric_fog.volume_ubo);
+ RD::get_singleton()->free(volumetric_fog.params_ubo);
+ material_storage->shader_free(volumetric_fog.default_shader);
+ material_storage->material_free(volumetric_fog.default_material);
+}
+
+void Fog::FogShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
+void Fog::FogShaderData::set_code(const String &p_code) {
+ //compile
+
+ code = p_code;
+ valid = false;
+ ubo_size = 0;
+ uniforms.clear();
+
+ if (code.is_empty()) {
+ return; //just invalid, but no error
+ }
+
+ ShaderCompiler::GeneratedCode gen_code;
+ ShaderCompiler::IdentifierActions actions;
+ actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE;
+
+ uses_time = false;
+
+ actions.usage_flag_pointers["TIME"] = &uses_time;
+
+ actions.uniforms = &uniforms;
+
+ Fog *fog_singleton = Fog::get_singleton();
+
+ Error err = fog_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
+ ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
+
+ if (version.is_null()) {
+ version = fog_singleton->volumetric_fog.shader.version_create();
+ }
+
+ fog_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
+ ERR_FAIL_COND(!fog_singleton->volumetric_fog.shader.version_is_valid(version));
+
+ ubo_size = gen_code.uniform_total_size;
+ ubo_offsets = gen_code.uniform_offsets;
+ texture_uniforms = gen_code.texture_uniforms;
+
+ pipeline = RD::get_singleton()->compute_pipeline_create(fog_singleton->volumetric_fog.shader.version_get_shader(version, 0));
+
+ valid = true;
+}
+
+void Fog::FogShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
+ if (!p_texture.is_valid()) {
+ if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
+ default_texture_params[p_name].erase(p_index);
+
+ if (default_texture_params[p_name].is_empty()) {
+ default_texture_params.erase(p_name);
+ }
+ }
+ } else {
+ if (!default_texture_params.has(p_name)) {
+ default_texture_params[p_name] = HashMap<int, RID>();
+ }
+ default_texture_params[p_name][p_index] = p_texture;
+ }
+}
+
+void Fog::FogShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
+ RBMap<int, StringName> order;
+
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ if (E.value.texture_order >= 0) {
+ order[E.value.texture_order + 100000] = E.key;
+ } else {
+ order[E.value.order] = E.key;
+ }
+ }
+
+ String last_group;
+ for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
+ PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
+ pi.name = E.value;
+ p_param_list->push_back(pi);
+ }
+}
+
+void Fog::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+ for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
+ continue;
+ }
+
+ RendererMaterialStorage::InstanceShaderParam p;
+ p.info = ShaderLanguage::uniform_to_property_info(E.value);
+ p.info.name = E.key; //supply name
+ p.index = E.value.instance_index;
+ p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
+ p_param_list->push_back(p);
+ }
+}
+
+bool Fog::FogShaderData::is_parameter_texture(const StringName &p_param) const {
+ if (!uniforms.has(p_param)) {
+ return false;
+ }
+
+ return uniforms[p_param].texture_order >= 0;
+}
+
+bool Fog::FogShaderData::is_animated() const {
+ return false;
+}
+
+bool Fog::FogShaderData::casts_shadows() const {
+ return false;
+}
+
+Variant Fog::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
+ if (uniforms.has(p_parameter)) {
+ ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
+ Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
+ return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
+ }
+ return Variant();
+}
+
+RS::ShaderNativeSourceCode Fog::FogShaderData::get_native_source_code() const {
+ Fog *fog_singleton = Fog::get_singleton();
+
+ return fog_singleton->volumetric_fog.shader.version_get_native_source_code(version);
+}
+
+Fog::FogShaderData::~FogShaderData() {
+ Fog *fog_singleton = Fog::get_singleton();
+ ERR_FAIL_COND(!fog_singleton);
+ //pipeline variants will clear themselves if shader is gone
+ if (version.is_valid()) {
+ fog_singleton->volumetric_fog.shader.version_free(version);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Volumetric Fog
+
+void Fog::VolumetricFog::init(const Vector3i &fog_size, RID p_sky_shader) {
+ width = fog_size.x;
+ height = fog_size.y;
+ depth = fog_size.z;
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ tf.width = fog_size.x;
+ tf.height = fog_size.y;
+ tf.depth = fog_size.z;
+ tf.texture_type = RD::TEXTURE_TYPE_3D;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+
+ light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(light_density_map, "Fog light-density map");
+
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+
+ prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(prev_light_density_map, "Fog previous light-density map");
+ RD::get_singleton()->texture_clear(prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(fog_map, "Fog map");
+
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ Vector<uint8_t> dm;
+ dm.resize(fog_size.x * fog_size.y * fog_size.z * 4);
+ dm.fill(0);
+
+ density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(density_map, "Fog density map");
+ light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(light_map, "Fog light map");
+ emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
+ RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map");
+#else
+ tf.format = RD::DATA_FORMAT_R32_UINT;
+ tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(density_map, "Fog density map");
+ RD::get_singleton()->texture_clear(density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(light_map, "Fog light map");
+ RD::get_singleton()->texture_clear(light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+ emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(emissive_map, "Fog emissive map");
+ RD::get_singleton()->texture_clear(emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
+#endif
+
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 0;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.append_id(fog_map);
+ uniforms.push_back(u);
+ }
+
+ sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_sky_shader, RendererRD::SkyRD::SKY_SET_FOG);
+}
+
+Fog::VolumetricFog::~VolumetricFog() {
+ RD::get_singleton()->free(prev_light_density_map);
+ RD::get_singleton()->free(light_density_map);
+ RD::get_singleton()->free(fog_map);
+ RD::get_singleton()->free(density_map);
+ RD::get_singleton()->free(light_map);
+ RD::get_singleton()->free(emissive_map);
+
+ if (fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(fog_uniform_set)) {
+ RD::get_singleton()->free(fog_uniform_set);
+ }
+ if (process_uniform_set_density.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set_density)) {
+ RD::get_singleton()->free(process_uniform_set_density);
+ }
+ if (process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set)) {
+ RD::get_singleton()->free(process_uniform_set);
+ }
+ if (process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(process_uniform_set2)) {
+ RD::get_singleton()->free(process_uniform_set2);
+ }
+ if (sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sdfgi_uniform_set)) {
+ RD::get_singleton()->free(sdfgi_uniform_set);
+ }
+ if (sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_uniform_set)) {
+ RD::get_singleton()->free(sky_uniform_set);
+ }
+}
+
+Vector3i Fog::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
+ Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
+ view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
+ Vector3 fog_position = Vector3(0, 0, 0);
+
+ view_position.y = -view_position.y;
+ fog_position.z = -view_position.z / fog_end;
+ fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
+ fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
+ fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
+ fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
+
+ fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
+ fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
+ fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
+
+ return Vector3i(fog_position);
+}
+
+void Fog::volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ RENDER_TIMESTAMP("> Volumetric Fog");
+ RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
+
+ Ref<VolumetricFog> fog = p_settings.vfog;
+
+ if (p_fog_volumes.size() > 0) {
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
+
+ RENDER_TIMESTAMP("Render FogVolumes");
+
+ VolumetricFogShader::VolumeUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.fog_frustum_end = fog_end;
+ params.z_near = z_near;
+ params.z_far = z_far;
+ params.time = p_settings.time;
+
+ params.fog_volume_size[0] = fog->width;
+ params.fog_volume_size[1] = fog->height;
+ params.fog_volume_size[2] = fog->depth;
+
+ params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+ params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+ params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env);
+
+ Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
+ RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
+ RendererRD::MaterialStorage::store_transform(p_cam_transform, params.transform);
+
+ RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
+
+ if (fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 1;
+ u.append_id(fog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 2;
+ u.append_id(volumetric_fog.volume_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 3;
+ u.append_id(fog->density_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 4;
+ u.append_id(fog->light_map);
+ uniforms.push_back(u);
+ }
+
+ fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ }
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ bool any_uses_time = false;
+
+ for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
+ FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
+ ERR_FAIL_COND(!fog_volume_instance);
+ RID fog_volume = fog_volume_instance->volume;
+
+ RID fog_material = RendererRD::Fog::get_singleton()->fog_volume_get_material(fog_volume);
+
+ FogMaterialData *material = nullptr;
+
+ if (fog_material.is_valid()) {
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG));
+ if (!material || !material->shader_data->valid) {
+ material = nullptr;
+ }
+ }
+
+ if (!material) {
+ fog_material = volumetric_fog.default_material;
+ material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::MaterialStorage::SHADER_TYPE_FOG));
+ }
+
+ ERR_FAIL_COND(!material);
+
+ FogShaderData *shader_data = material->shader_data;
+
+ ERR_FAIL_COND(!shader_data);
+
+ any_uses_time |= shader_data->uses_time;
+
+ Vector3i min = Vector3i();
+ Vector3i max = Vector3i();
+ Vector3i kernel_size = Vector3i();
+
+ Vector3 position = fog_volume_instance->transform.get_origin();
+ RS::FogVolumeShape volume_type = RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume);
+ Vector3 extents = RendererRD::Fog::get_singleton()->fog_volume_get_extents(fog_volume);
+
+ if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
+ // Local fog volume.
+ Vector3i points[8];
+ Vector3 fog_size = Vector3(fog->width, fog->height, fog->depth);
+ float volumetric_fog_detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+ points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+ points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, volumetric_fog_detail_spread, fog_size, p_cam_transform);
+
+ min = Vector3i(int32_t(fog->width) - 1, int32_t(fog->height) - 1, int32_t(fog->depth) - 1);
+ max = Vector3i(1, 1, 1);
+
+ for (int j = 0; j < 8; j++) {
+ min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
+ max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
+ }
+
+ kernel_size = max - min;
+ } else {
+ // Volume type global runs on all cells
+ extents = Vector3(fog->width, fog->height, fog->depth);
+ min = Vector3i(0, 0, 0);
+ kernel_size = Vector3i(int32_t(fog->width), int32_t(fog->height), int32_t(fog->depth));
+ }
+
+ if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
+ continue;
+ }
+
+ VolumetricFogShader::FogPushConstant push_constant;
+ push_constant.position[0] = position.x;
+ push_constant.position[1] = position.y;
+ push_constant.position[2] = position.z;
+ push_constant.extents[0] = extents.x;
+ push_constant.extents[1] = extents.y;
+ push_constant.extents[2] = extents.z;
+ push_constant.corner[0] = min.x;
+ push_constant.corner[1] = min.y;
+ push_constant.corner[2] = min.z;
+ push_constant.shape = uint32_t(RendererRD::Fog::get_singleton()->fog_volume_get_shape(fog_volume));
+ RendererRD::MaterialStorage::store_transform(fog_volume_instance->transform.affine_inverse(), push_constant.transform);
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(VolumetricFogShader::FogPushConstant));
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
+ if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
+ }
+
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
+ }
+ if (any_uses_time || RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
+ RenderingServerDefault::redraw_request();
+ }
+
+ RD::get_singleton()->draw_command_end_label();
+
+ RD::get_singleton()->compute_list_end();
+ }
+
+ if (fog->process_uniform_set_density.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->process_uniform_set_density)) {
+ //re create uniform set if needed
+ Vector<RD::Uniform> uniforms;
+ Vector<RD::Uniform> copy_uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ if (p_settings.shadow_atlas_depth.is_null()) {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
+ } else {
+ u.append_id(p_settings.shadow_atlas_depth);
+ }
+
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ if (p_settings.directional_shadow_depth.is_valid()) {
+ u.append_id(p_settings.directional_shadow_depth);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
+ }
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 3;
+ u.append_id(p_settings.omni_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 4;
+ u.append_id(p_settings.spot_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 5;
+ u.append_id(p_settings.directional_light_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 6;
+ u.append_id(p_settings.cluster_builder->get_cluster_buffer());
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 7;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 8;
+ u.append_id(fog->light_density_map);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.append_id(fog->fog_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.append_id(fog->prev_light_density_map);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 10;
+ u.append_id(p_settings.shadow_sampler);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 11;
+ u.append_id(p_settings.voxel_gi_buffer);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 12;
+ for (int i = 0; i < RendererRD::GI::MAX_VOXEL_GI_INSTANCES; i++) {
+ u.append_id(p_settings.rbgi->voxel_gi_textures[i]);
+ }
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 13;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 14;
+ u.append_id(volumetric_fog.params_ubo);
+ uniforms.push_back(u);
+ copy_uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 15;
+ u.append_id(fog->prev_light_density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 16;
+ u.append_id(fog->density_map);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 17;
+ u.append_id(fog->light_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+#else
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+#endif
+ u.binding = 18;
+ u.append_id(fog->emissive_map);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 19;
+ RID radiance_texture = texture_storage->texture_rd_get_default(p_settings.is_using_radiance_cubemap_array ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ RID sky_texture = RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env).is_valid() ? p_settings.sky->sky_get_radiance_texture_rd(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_settings.env)) : RID();
+ u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
+ uniforms.push_back(u);
+ }
+
+ fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
+
+ fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+
+ RID aux7 = uniforms.write[7].get_id(0);
+ RID aux8 = uniforms.write[8].get_id(0);
+
+ uniforms.write[7].set_id(0, aux8);
+ uniforms.write[8].set_id(0, aux7);
+
+ fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG), 0);
+
+ uniforms.remove_at(8);
+ uniforms.write[7].set_id(0, aux7);
+ fog->process_uniform_set_density = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
+ }
+
+ bool using_sdfgi = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.0001 && RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_enabled(p_settings.env) && (p_settings.sdfgi.is_valid());
+
+ if (using_sdfgi) {
+ if (fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fog->sdfgi_uniform_set)) {
+ Vector<RD::Uniform> uniforms;
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 0;
+ u.append_id(p_settings.gi->sdfgi_ubo);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 1;
+ u.append_id(p_settings.sdfgi->ambient_texture);
+ uniforms.push_back(u);
+ }
+
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 2;
+ u.append_id(p_settings.sdfgi->occlusion_texture);
+ uniforms.push_back(u);
+ }
+
+ fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
+ }
+ }
+
+ fog->length = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
+ fog->spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+
+ VolumetricFogShader::ParamsUBO params;
+
+ Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
+ Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
+ float z_near = p_cam_projection.get_z_near();
+ float z_far = p_cam_projection.get_z_far();
+ float fog_end = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_length(p_settings.env);
+
+ Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
+ Vector2 fog_near_size;
+ if (p_cam_projection.is_orthogonal()) {
+ fog_near_size = fog_far_size;
+ } else {
+ fog_near_size = Vector2();
+ }
+
+ params.fog_frustum_size_begin[0] = fog_near_size.x;
+ params.fog_frustum_size_begin[1] = fog_near_size.y;
+
+ params.fog_frustum_size_end[0] = fog_far_size.x;
+ params.fog_frustum_size_end[1] = fog_far_size.y;
+
+ params.ambient_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_ambient_inject(p_settings.env) * RendererSceneRenderRD::get_singleton()->environment_get_ambient_light_energy(p_settings.env);
+ params.z_far = z_far;
+
+ params.fog_frustum_end = fog_end;
+
+ Color ambient_color = RendererSceneRenderRD::get_singleton()->environment_get_ambient_light(p_settings.env).srgb_to_linear();
+ params.ambient_color[0] = ambient_color.r;
+ params.ambient_color[1] = ambient_color.g;
+ params.ambient_color[2] = ambient_color.b;
+ params.sky_contribution = RendererSceneRenderRD::get_singleton()->environment_get_ambient_sky_contribution(p_settings.env);
+
+ params.fog_volume_size[0] = fog->width;
+ params.fog_volume_size[1] = fog->height;
+ params.fog_volume_size[2] = fog->depth;
+
+ params.directional_light_count = p_directional_light_count;
+
+ Color emission = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission(p_settings.env).srgb_to_linear();
+ params.base_emission[0] = emission.r * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env);
+ params.base_emission[1] = emission.g * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env);
+ params.base_emission[2] = emission.b * RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_emission_energy(p_settings.env);
+ params.base_density = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_density(p_settings.env);
+
+ Color base_scattering = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_scattering(p_settings.env).srgb_to_linear();
+ params.base_scattering[0] = base_scattering.r;
+ params.base_scattering[1] = base_scattering.g;
+ params.base_scattering[2] = base_scattering.b;
+ params.phase_g = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_anisotropy(p_settings.env);
+
+ params.detail_spread = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_detail_spread(p_settings.env);
+ params.gi_inject = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env);
+
+ params.cam_rotation[0] = p_cam_transform.basis[0][0];
+ params.cam_rotation[1] = p_cam_transform.basis[1][0];
+ params.cam_rotation[2] = p_cam_transform.basis[2][0];
+ params.cam_rotation[3] = 0;
+ params.cam_rotation[4] = p_cam_transform.basis[0][1];
+ params.cam_rotation[5] = p_cam_transform.basis[1][1];
+ params.cam_rotation[6] = p_cam_transform.basis[2][1];
+ params.cam_rotation[7] = 0;
+ params.cam_rotation[8] = p_cam_transform.basis[0][2];
+ params.cam_rotation[9] = p_cam_transform.basis[1][2];
+ params.cam_rotation[10] = p_cam_transform.basis[2][2];
+ params.cam_rotation[11] = 0;
+ params.filter_axis = 0;
+ params.max_voxel_gi_instances = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_gi_inject(p_settings.env) > 0.001 ? p_voxel_gi_count : 0;
+ params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
+
+ Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
+ RendererRD::MaterialStorage::store_transform(to_prev_cam_view, params.to_prev_view);
+
+ params.use_temporal_reprojection = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env);
+ params.temporal_blend = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection_amount(p_settings.env);
+
+ {
+ uint32_t cluster_size = p_settings.cluster_builder->get_cluster_size();
+ params.cluster_shift = get_shift_from_power_of_2(cluster_size);
+
+ uint32_t cluster_screen_width = (p_settings.rb_size.x - 1) / cluster_size + 1;
+ uint32_t cluster_screen_height = (p_settings.rb_size.y - 1) / cluster_size + 1;
+ params.max_cluster_element_count_div_32 = p_settings.max_cluster_elements / 32;
+ params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
+ params.cluster_width = cluster_screen_width;
+
+ params.screen_size[0] = p_settings.rb_size.x;
+ params.screen_size[1] = p_settings.rb_size.y;
+ }
+
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_settings.env);
+ sky_transform = sky_transform.inverse() * p_cam_transform.basis;
+ RendererRD::MaterialStorage::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
+
+ RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
+
+ RENDER_TIMESTAMP("Render Fog");
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, RD::BARRIER_MASK_COMPUTE);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
+
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set_density, 0);
+
+ if (using_sdfgi) {
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->sdfgi_uniform_set, 1);
+ }
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+
+ // Copy fog to history buffer
+ if (RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_temporal_reprojection(p_settings.env)) {
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->copy_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ }
+ RD::get_singleton()->draw_command_end_label();
+
+ if (p_settings.volumetric_fog_filter_active) {
+ RD::get_singleton()->draw_command_begin_label("Filter Fog");
+
+ RENDER_TIMESTAMP("Filter Fog");
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
+
+ RD::get_singleton()->compute_list_end();
+ //need restart for buffer update
+
+ params.filter_axis = 1;
+ RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
+
+ compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set2, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, fog->depth);
+
+ RD::get_singleton()->compute_list_add_barrier(compute_list);
+ RD::get_singleton()->draw_command_end_label();
+ }
+
+ RENDER_TIMESTAMP("Integrate Fog");
+ RD::get_singleton()->draw_command_begin_label("Integrate Fog");
+
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, fog->process_uniform_set, 0);
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, fog->width, fog->height, 1);
+
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
+
+ RENDER_TIMESTAMP("< Volumetric Fog");
+ RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_command_end_label();
+}
diff --git a/servers/rendering/renderer_rd/environment/fog.h b/servers/rendering/renderer_rd/environment/fog.h
new file mode 100644
index 0000000000..0ade995758
--- /dev/null
+++ b/servers/rendering/renderer_rd/environment/fog.h
@@ -0,0 +1,360 @@
+/*************************************************************************/
+/* fog.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef FOG_RD_H
+#define FOG_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/environment/renderer_fog.h"
+#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/environment/gi.h"
+#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
+#include "servers/rendering/storage/utilities.h"
+
+#define RB_SCOPE_FOG SNAME("Fog")
+
+namespace RendererRD {
+
+class Fog : public RendererFog {
+private:
+ static Fog *singleton;
+
+ /* FOG VOLUMES */
+
+ struct FogVolume {
+ RID material;
+ Vector3 extents = Vector3(1, 1, 1);
+
+ RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
+
+ Dependency dependency;
+ };
+
+ mutable RID_Owner<FogVolume, true> fog_volume_owner;
+
+ struct FogVolumeInstance {
+ RID volume;
+ Transform3D transform;
+ bool active = false;
+ };
+
+ mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
+
+ /* Volumetric Fog */
+ struct VolumetricFogShader {
+ enum FogSet {
+ FOG_SET_BASE,
+ FOG_SET_UNIFORMS,
+ FOG_SET_MATERIAL,
+ FOG_SET_MAX,
+ };
+
+ struct FogPushConstant {
+ float position[3];
+ float pad;
+
+ float extents[3];
+ float pad2;
+
+ int32_t corner[3];
+ uint32_t shape;
+
+ float transform[16];
+ };
+
+ struct VolumeUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float z_near;
+ float z_far;
+ float time;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float detail_spread;
+ float temporal_blend;
+
+ float to_prev_view[16];
+ float transform[16];
+ };
+
+ ShaderCompiler compiler;
+ VolumetricFogShaderRD shader;
+ RID volume_ubo;
+
+ RID default_shader;
+ RID default_material;
+ RID default_shader_rd;
+
+ RID base_uniform_set;
+
+ RID params_ubo;
+
+ enum {
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
+ VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
+ VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
+ VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
+ };
+
+ struct ParamsUBO {
+ float fog_frustum_size_begin[2];
+ float fog_frustum_size_end[2];
+
+ float fog_frustum_end;
+ float ambient_inject;
+ float z_far;
+ uint32_t filter_axis;
+
+ float ambient_color[3];
+ float sky_contribution;
+
+ int32_t fog_volume_size[3];
+ uint32_t directional_light_count;
+
+ float base_emission[3];
+ float base_density;
+
+ float base_scattering[3];
+ float phase_g;
+
+ float detail_spread;
+ float gi_inject;
+ uint32_t max_voxel_gi_instances;
+ uint32_t cluster_type_size;
+
+ float screen_size[2];
+ uint32_t cluster_shift;
+ uint32_t cluster_width;
+
+ uint32_t max_cluster_element_count_div_32;
+ uint32_t use_temporal_reprojection;
+ uint32_t temporal_frame;
+ float temporal_blend;
+
+ float cam_rotation[12];
+ float to_prev_view[16];
+ float radiance_inverse_xform[12];
+ };
+
+ VolumetricFogProcessShaderRD process_shader;
+
+ RID process_shader_version;
+ RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
+
+ } volumetric_fog;
+
+ Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
+
+ struct FogShaderData : public RendererRD::MaterialStorage::ShaderData {
+ bool valid = false;
+ RID version;
+
+ RID pipeline;
+ HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
+ Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
+
+ Vector<uint32_t> ubo_offsets;
+ uint32_t ubo_size = 0;
+
+ String path;
+ String code;
+ HashMap<StringName, HashMap<int, RID>> default_texture_params;
+
+ bool uses_time = false;
+
+ virtual void set_path_hint(const String &p_hint);
+ virtual void set_code(const String &p_Code);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
+ virtual bool is_parameter_texture(const StringName &p_param) const;
+ virtual bool is_animated() const;
+ virtual bool casts_shadows() const;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const;
+
+ FogShaderData() {}
+ virtual ~FogShaderData();
+ };
+
+ struct FogMaterialData : public RendererRD::MaterialStorage::MaterialData {
+ FogShaderData *shader_data = nullptr;
+ RID uniform_set;
+ bool uniform_set_updated;
+
+ virtual void set_render_priority(int p_priority) {}
+ virtual void set_next_pass(RID p_pass) {}
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
+ virtual ~FogMaterialData();
+ };
+
+ RendererRD::MaterialStorage::ShaderData *_create_fog_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_fog_shader_funcs();
+
+ RendererRD::MaterialStorage::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_fog_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);
+
+public:
+ static Fog *get_singleton() { return singleton; }
+
+ Fog();
+ ~Fog();
+
+ /* FOG VOLUMES */
+
+ bool owns_fog_volume(RID p_rid) { return fog_volume_owner.owns(p_rid); };
+
+ virtual RID fog_volume_allocate() override;
+ virtual void fog_volume_initialize(RID p_rid) override;
+ virtual void fog_volume_free(RID p_rid) override;
+ Dependency *fog_volume_get_dependency(RID p_fog_volume) const;
+
+ virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) override;
+ virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) override;
+ virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) override;
+ virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const override;
+ RID fog_volume_get_material(RID p_fog_volume) const;
+ virtual AABB fog_volume_get_aabb(RID p_fog_volume) const override;
+ Vector3 fog_volume_get_extents(RID p_fog_volume) const;
+
+ /* FOG VOLUMES INSTANCE */
+
+ bool owns_fog_volume_instance(RID p_rid) { return fog_volume_instance_owner.owns(p_rid); };
+
+ RID fog_volume_instance_create(RID p_fog_volume);
+ void fog_instance_free(RID p_rid);
+
+ void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
+ Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND(!fvi);
+ fvi->transform = p_transform;
+ }
+
+ void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
+ Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND(!fvi);
+ fvi->active = p_active;
+ }
+
+ RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
+ Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND_V(!fvi, RID());
+ return fvi->volume;
+ }
+
+ Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const {
+ Fog::FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
+ ERR_FAIL_COND_V(!fvi, Vector3());
+ return fvi->transform.get_origin();
+ }
+
+ /* Volumetric FOG */
+ class VolumetricFog : public RenderBufferCustomDataRD {
+ GDCLASS(VolumetricFog, RenderBufferCustomDataRD)
+
+ public:
+ enum {
+ MAX_TEMPORAL_FRAMES = 16
+ };
+
+ uint32_t width = 0;
+ uint32_t height = 0;
+ uint32_t depth = 0;
+
+ float length;
+ float spread;
+
+ RID light_density_map;
+ RID prev_light_density_map;
+ RID fog_map;
+ RID density_map;
+ RID light_map;
+ RID emissive_map;
+
+ RID fog_uniform_set;
+ RID copy_uniform_set;
+ RID process_uniform_set_density;
+ RID process_uniform_set;
+ RID process_uniform_set2;
+ RID sdfgi_uniform_set;
+ RID sky_uniform_set;
+
+ int last_shadow_filter = -1;
+
+ virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
+ virtual void free_data() override{};
+
+ void init(const Vector3i &fog_size, RID p_sky_shader);
+ ~VolumetricFog();
+ };
+
+ void init_fog_shader(uint32_t p_max_directional_lights, int p_roughness_layers, bool p_is_using_radiance_cubemap_array);
+ void free_fog_shader();
+
+ struct VolumetricFogSettings {
+ Vector2i rb_size;
+ double time;
+ bool is_using_radiance_cubemap_array;
+ uint32_t max_cluster_elements;
+ bool volumetric_fog_filter_active;
+ RID shadow_sampler;
+ RID voxel_gi_buffer;
+ RID shadow_atlas_depth;
+ RID omni_light_buffer;
+ RID spot_light_buffer;
+ RID directional_shadow_depth;
+ RID directional_light_buffer;
+
+ // Objects related to our render buffer
+ Ref<VolumetricFog> vfog;
+ ClusterBuilderRD *cluster_builder;
+ GI *gi;
+ Ref<GI::SDFGI> sdfgi;
+ Ref<GI::RenderBuffersGI> rbgi;
+ RID env;
+ SkyRD *sky;
+ };
+ void volumetric_fog_update(const VolumetricFogSettings &p_settings, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+};
+
+} // namespace RendererRD
+
+#endif // FOG_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp b/servers/rendering/renderer_rd/environment/gi.cpp
index 7aede6bb48..550fe27e4c 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.cpp
+++ b/servers/rendering/renderer_rd/environment/gi.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_gi_rd.cpp */
+/* gi.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,29 +28,382 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_scene_gi_rd.h"
+#include "gi.h"
#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
-const Vector3i RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
+using namespace RendererRD;
+
+const Vector3i GI::SDFGI::Cascade::DIRTY_ALL = Vector3i(0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF);
+
+GI *GI::singleton = nullptr;
+
+////////////////////////////////////////////////////////////////////////////////
+// VOXEL GI STORAGE
+
+RID GI::voxel_gi_allocate() {
+ return voxel_gi_owner.allocate_rid();
+}
+
+void GI::voxel_gi_free(RID p_voxel_gi) {
+ voxel_gi_allocate_data(p_voxel_gi, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ voxel_gi->dependency.deleted_notify(p_voxel_gi);
+ voxel_gi_owner.free(p_voxel_gi);
+}
+
+void GI::voxel_gi_initialize(RID p_voxel_gi) {
+ voxel_gi_owner.initialize_rid(p_voxel_gi, VoxelGI());
+}
+
+void GI::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ if (voxel_gi->octree_buffer.is_valid()) {
+ RD::get_singleton()->free(voxel_gi->octree_buffer);
+ RD::get_singleton()->free(voxel_gi->data_buffer);
+ if (voxel_gi->sdf_texture.is_valid()) {
+ RD::get_singleton()->free(voxel_gi->sdf_texture);
+ }
+
+ voxel_gi->sdf_texture = RID();
+ voxel_gi->octree_buffer = RID();
+ voxel_gi->data_buffer = RID();
+ voxel_gi->octree_buffer_size = 0;
+ voxel_gi->data_buffer_size = 0;
+ voxel_gi->cell_count = 0;
+ }
+
+ voxel_gi->to_cell_xform = p_to_cell_xform;
+ voxel_gi->bounds = p_aabb;
+ voxel_gi->octree_size = p_octree_size;
+ voxel_gi->level_counts = p_level_counts;
+
+ if (p_octree_cells.size()) {
+ ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32
+
+ uint32_t cell_count = p_octree_cells.size() / 32;
+
+ ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches
+
+ voxel_gi->cell_count = cell_count;
+ voxel_gi->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells);
+ voxel_gi->octree_buffer_size = p_octree_cells.size();
+ voxel_gi->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells);
+ voxel_gi->data_buffer_size = p_data_cells.size();
+
+ if (p_distance_field.size()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = voxel_gi->octree_size.x;
+ tf.height = voxel_gi->octree_size.y;
+ tf.depth = voxel_gi->octree_size.z;
+ tf.texture_type = RD::TEXTURE_TYPE_3D;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ Vector<Vector<uint8_t>> s;
+ s.push_back(p_distance_field);
+ voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
+ RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
+ }
+#if 0
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R8_UNORM;
+ tf.width = voxel_gi->octree_size.x;
+ tf.height = voxel_gi->octree_size.y;
+ tf.depth = voxel_gi->octree_size.z;
+ tf.type = RD::TEXTURE_TYPE_3D;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM);
+ tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT);
+ voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(voxel_gi->sdf_texture, "VoxelGI SDF Texture");
+ }
+ RID shared_tex;
+ {
+ RD::TextureView tv;
+ tv.format_override = RD::DATA_FORMAT_R8_UINT;
+ shared_tex = RD::get_singleton()->texture_create_shared(tv, voxel_gi->sdf_texture);
+ }
+ //update SDF texture
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 1;
+ u.append_id(voxel_gi->octree_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
+ u.binding = 2;
+ u.append_id(voxel_gi->data_buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 3;
+ u.append_id(shared_tex);
+ uniforms.push_back(u);
+ }
+
+ RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, voxel_gi_sdf_shader_version_shader, 0);
+
+ {
+ uint32_t push_constant[4] = { 0, 0, 0, 0 };
+
+ for (int i = 0; i < voxel_gi->level_counts.size() - 1; i++) {
+ push_constant[0] += voxel_gi->level_counts[i];
+ }
+ push_constant[1] = push_constant[0] + voxel_gi->level_counts[voxel_gi->level_counts.size() - 1];
+
+ print_line("offset: " + itos(push_constant[0]));
+ print_line("size: " + itos(push_constant[1]));
+ //create SDF
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, voxel_gi_sdf_shader_pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4);
+ RD::get_singleton()->compute_list_dispatch(compute_list, voxel_gi->octree_size.x / 4, voxel_gi->octree_size.y / 4, voxel_gi->octree_size.z / 4);
+ RD::get_singleton()->compute_list_end();
+ }
+
+ RD::get_singleton()->free(uniform_set);
+ RD::get_singleton()->free(shared_tex);
+ }
+#endif
+ }
+
+ voxel_gi->version++;
+ voxel_gi->data_version++;
+
+ voxel_gi->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+}
+
+AABB GI::voxel_gi_get_bounds(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, AABB());
+
+ return voxel_gi->bounds;
+}
+
+Vector3i GI::voxel_gi_get_octree_size(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector3i());
+ return voxel_gi->octree_size;
+}
+
+Vector<uint8_t> GI::voxel_gi_get_octree_cells(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
+
+ if (voxel_gi->octree_buffer.is_valid()) {
+ return RD::get_singleton()->buffer_get_data(voxel_gi->octree_buffer);
+ }
+ return Vector<uint8_t>();
+}
+
+Vector<uint8_t> GI::voxel_gi_get_data_cells(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
+
+ if (voxel_gi->data_buffer.is_valid()) {
+ return RD::get_singleton()->buffer_get_data(voxel_gi->data_buffer);
+ }
+ return Vector<uint8_t>();
+}
+
+Vector<uint8_t> GI::voxel_gi_get_distance_field(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
+
+ if (voxel_gi->data_buffer.is_valid()) {
+ return RD::get_singleton()->texture_get_data(voxel_gi->sdf_texture, 0);
+ }
+ return Vector<uint8_t>();
+}
+
+Vector<int> GI::voxel_gi_get_level_counts(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Vector<int>());
+
+ return voxel_gi->level_counts;
+}
+
+Transform3D GI::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, Transform3D());
+
+ return voxel_gi->to_cell_xform;
+}
+
+void GI::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->dynamic_range = p_range;
+ voxel_gi->version++;
+}
+
+float GI::voxel_gi_get_dynamic_range(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+
+ return voxel_gi->dynamic_range;
+}
+
+void GI::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->propagation = p_range;
+ voxel_gi->version++;
+}
+
+float GI::voxel_gi_get_propagation(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->propagation;
+}
+
+void GI::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->energy = p_energy;
+}
+
+float GI::voxel_gi_get_energy(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->energy;
+}
+
+void GI::voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->baked_exposure = p_baked_exposure;
+}
+
+float GI::voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->baked_exposure;
+}
+
+void GI::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->bias = p_bias;
+}
+
+float GI::voxel_gi_get_bias(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->bias;
+}
+
+void GI::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->normal_bias = p_normal_bias;
+}
+
+float GI::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->normal_bias;
+}
+
+void GI::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->interior = p_enable;
+}
+
+void GI::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND(!voxel_gi);
+
+ voxel_gi->use_two_bounces = p_enable;
+ voxel_gi->version++;
+}
+
+bool GI::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, false);
+ return voxel_gi->use_two_bounces;
+}
+
+bool GI::voxel_gi_is_interior(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->interior;
+}
+
+uint32_t GI::voxel_gi_get_version(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->version;
+}
+
+uint32_t GI::voxel_gi_get_data_version(RID p_voxel_gi) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, 0);
+ return voxel_gi->data_version;
+}
+
+RID GI::voxel_gi_get_octree_buffer(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, RID());
+ return voxel_gi->octree_buffer;
+}
+
+RID GI::voxel_gi_get_data_buffer(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, RID());
+ return voxel_gi->data_buffer;
+}
+
+RID GI::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, RID());
+
+ return voxel_gi->sdf_texture;
+}
+
+Dependency *GI::voxel_gi_get_dependency(RID p_voxel_gi) const {
+ VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
+ ERR_FAIL_COND_V(!voxel_gi, nullptr);
+
+ return &voxel_gi->dependency;
+}
////////////////////////////////////////////////////////////////////////////////
// SDFGI
-void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi) {
+void GI::SDFGI::create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_gi->storage;
gi = p_gi;
- num_cascades = p_env->sdfgi_cascades;
- min_cell_size = p_env->sdfgi_min_cell_size;
- uses_occlusion = p_env->sdfgi_use_occlusion;
- y_scale_mode = p_env->sdfgi_y_scale;
+ num_cascades = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_cascades(p_env);
+ min_cell_size = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_min_cell_size(p_env);
+ uses_occlusion = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_use_occlusion(p_env);
+ y_scale_mode = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_y_scale(p_env);
static const float y_scale[3] = { 2.0, 1.5, 1.0 };
y_mult = y_scale[y_scale_mode];
cascades.resize(num_cascades);
@@ -72,29 +425,38 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
RD::TextureFormat tf_render = tf_sdf;
tf_render.format = RD::DATA_FORMAT_R16_UINT;
render_albedo = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_albedo, "VoxelGI Render Albedo");
tf_render.format = RD::DATA_FORMAT_R32_UINT;
render_emission = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_emission, "VoxelGI Render Emission");
render_emission_aniso = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_emission_aniso, "VoxelGI Render Emission Aniso");
tf_render.format = RD::DATA_FORMAT_R8_UNORM; //at least its easy to visualize
for (int i = 0; i < 8; i++) {
render_occlusion[i] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_occlusion[i], String("VoxelGI Render Occlusion ") + itos(i));
}
tf_render.format = RD::DATA_FORMAT_R32_UINT;
render_geom_facing = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_geom_facing, "VoxelGI Render Geometry Facing");
tf_render.format = RD::DATA_FORMAT_R8G8B8A8_UINT;
render_sdf[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf[0], "VoxelGI Render SDF 0");
render_sdf[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf[1], "VoxelGI Render SDF 1");
tf_render.width /= 2;
tf_render.height /= 2;
tf_render.depth /= 2;
render_sdf_half[0] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf_half[0], "VoxelGI Render SDF Half 0");
render_sdf_half[1] = RD::get_singleton()->texture_create(tf_render, RD::TextureView());
+ RD::get_singleton()->set_resource_name(render_sdf_half[1], "VoxelGI Render SDF Half 1");
}
RD::TextureFormat tf_occlusion = tf_sdf;
@@ -135,7 +497,9 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
tf_probe_average.texture_type = RD::TEXTURE_TYPE_2D;
lightprobe_history_scroll = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_history_scroll, "VoxelGI LightProbe History Scroll");
lightprobe_average_scroll = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_average_scroll, "VoxelGI LightProbe Average Scroll");
{
//octahedral lightprobes
@@ -149,6 +513,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
//lightprobe texture is an octahedral texture
lightprobe_data = RD::get_singleton()->texture_create(tf_octprobes, RD::TextureView());
+ RD::get_singleton()->set_resource_name(lightprobe_data, "VoxelGI LightProbe Data");
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
lightprobe_texture = RD::get_singleton()->texture_create_shared(tv, lightprobe_data);
@@ -162,11 +527,13 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
tf_ambient.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
//lightprobe texture is an octahedral texture
ambient_texture = RD::get_singleton()->texture_create(tf_ambient, RD::TextureView());
+ RD::get_singleton()->set_resource_name(ambient_texture, "VoxelGI Ambient Texture");
}
cascades_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES);
occlusion_data = RD::get_singleton()->texture_create(tf_occlusion, RD::TextureView());
+ RD::get_singleton()->set_resource_name(occlusion_data, "VoxelGI Occlusion Data");
{
RD::TextureView tv;
tv.format_override = RD::DATA_FORMAT_R4G4B4A4_UNORM_PACK16;
@@ -179,11 +546,15 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
/* 3D Textures */
cascade.sdf_tex = RD::get_singleton()->texture_create(tf_sdf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.sdf_tex, "VoxelGI Cascade SDF Texture");
cascade.light_data = RD::get_singleton()->texture_create(tf_light, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_data, "VoxelGI Cascade Light Data");
cascade.light_aniso_0_tex = RD::get_singleton()->texture_create(tf_aniso0, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_aniso_0_tex, "VoxelGI Cascade Light Aniso 0 Texture");
cascade.light_aniso_1_tex = RD::get_singleton()->texture_create(tf_aniso1, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.light_aniso_1_tex, "VoxelGI Cascade Light Aniso 1 Texture");
{
RD::TextureView tv;
@@ -210,9 +581,11 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
/* Probe History */
cascade.lightprobe_history_tex = RD::get_singleton()->texture_create(tf_probe_history, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_history_tex, "VoxelGI Cascade LightProbe History Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_history_tex, Color(0, 0, 0, 0), 0, 1, 0, tf_probe_history.array_layers); //needs to be cleared for average to work
cascade.lightprobe_average_tex = RD::get_singleton()->texture_create(tf_probe_average, RD::TextureView());
+ RD::get_singleton()->set_resource_name(cascade.lightprobe_average_tex, "VoxelGI Cascade LightProbe Average Texture");
RD::get_singleton()->texture_clear(cascade.lightprobe_average_tex, Color(0, 0, 0, 0), 0, 1, 0, 1); //needs to be cleared for average to work
/* Buffers */
@@ -382,7 +755,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
if (j < cascades.size()) {
u.append_id(cascades[j].sdf_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -458,7 +831,8 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
uniforms.push_back(u);
}
- cascade.sdf_direct_light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, 0), 0);
+ cascade.sdf_direct_light_static_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_STATIC), 0);
+ cascade.sdf_direct_light_dynamic_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.direct_light.version_get_shader(gi->sdfgi_shader.direct_light_shader, SDFGIShader::DIRECT_LIGHT_MODE_DYNAMIC), 0);
}
//preprocess initialize uniform set
@@ -625,7 +999,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
if (j < cascades.size()) {
u.append_id(cascades[j].sdf_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -638,7 +1012,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
if (j < cascades.size()) {
u.append_id(cascades[j].light_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -651,7 +1025,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
if (j < cascades.size()) {
u.append_id(cascades[j].light_aniso_0_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -664,7 +1038,7 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
if (j < cascades.size()) {
u.append_id(cascades[j].light_aniso_1_tex);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
}
uniforms.push_back(u);
@@ -748,14 +1122,18 @@ void RendererSceneGIRD::SDFGI::create(RendererSceneEnvironmentRD *p_env, const V
cascades[i].integrate_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.integrate.version_get_shader(gi->sdfgi_shader.integrate_shader, 0), 0);
}
- bounce_feedback = p_env->sdfgi_bounce_feedback;
- energy = p_env->sdfgi_energy;
- normal_bias = p_env->sdfgi_normal_bias;
- probe_bias = p_env->sdfgi_probe_bias;
- reads_sky = p_env->sdfgi_read_sky_light;
+ bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env);
+ energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env);
+ normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env);
+ probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env);
+ reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
+}
+
+void GI::SDFGI::free_data() {
+ // we don't free things here, we handle SDFGI differently at the moment destructing the object when it needs to change.
}
-void RendererSceneGIRD::SDFGI::erase() {
+GI::SDFGI::~SDFGI() {
for (uint32_t i = 0; i < cascades.size(); i++) {
const SDFGI::Cascade &c = cascades[i];
RD::get_singleton()->free(c.light_data);
@@ -787,18 +1165,36 @@ void RendererSceneGIRD::SDFGI::erase() {
RD::get_singleton()->free(lightprobe_data);
RD::get_singleton()->free(lightprobe_history_scroll);
+ RD::get_singleton()->free(lightprobe_average_scroll);
RD::get_singleton()->free(occlusion_data);
RD::get_singleton()->free(ambient_texture);
RD::get_singleton()->free(cascades_ubo);
+
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ if (RD::get_singleton()->uniform_set_is_valid(debug_uniform_set[v])) {
+ RD::get_singleton()->free(debug_uniform_set[v]);
+ }
+ debug_uniform_set[v] = RID();
+ }
+
+ if (RD::get_singleton()->uniform_set_is_valid(debug_probes_uniform_set)) {
+ RD::get_singleton()->free(debug_probes_uniform_set);
+ }
+ debug_probes_uniform_set = RID();
+
+ if (debug_probes_scene_data_ubo.is_valid()) {
+ RD::get_singleton()->free(debug_probes_scene_data_ubo);
+ debug_probes_scene_data_ubo = RID();
+ }
}
-void RendererSceneGIRD::SDFGI::update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position) {
- bounce_feedback = p_env->sdfgi_bounce_feedback;
- energy = p_env->sdfgi_energy;
- normal_bias = p_env->sdfgi_normal_bias;
- probe_bias = p_env->sdfgi_probe_bias;
- reads_sky = p_env->sdfgi_read_sky_light;
+void GI::SDFGI::update(RID p_env, const Vector3 &p_world_position) {
+ bounce_feedback = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_bounce_feedback(p_env);
+ energy = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_energy(p_env);
+ normal_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_normal_bias(p_env);
+ probe_bias = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_probe_bias(p_env);
+ reads_sky = RendererSceneRenderRD::get_singleton()->environment_get_sdfgi_read_sky_light(p_env);
int32_t drag_margin = (cascade_size / SDFGI::PROBE_DIVISOR) / 2;
@@ -851,7 +1247,7 @@ void RendererSceneGIRD::SDFGI::update(RendererSceneEnvironmentRD *p_env, const V
}
}
-void RendererSceneGIRD::SDFGI::update_light() {
+void GI::SDFGI::update_light() {
RD::get_singleton()->draw_command_begin_label("SDFGI Update dynamic Light");
/* Update dynamic light */
@@ -890,7 +1286,7 @@ void RendererSceneGIRD::SDFGI::update_light() {
}
cascades[i].all_dynamic_lights_dirty = false;
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_dynamic_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cascade.solid_cell_dispatch_buffer, 0);
}
@@ -898,7 +1294,7 @@ void RendererSceneGIRD::SDFGI::update_light() {
RD::get_singleton()->draw_command_end_label();
}
-void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky) {
+void GI::SDFGI::update_probes(RID p_env, SkyRD::Sky *p_sky) {
RD::get_singleton()->draw_command_begin_label("SDFGI Update Probes");
SDFGIShader::IntegratePushConstant push_constant;
@@ -914,29 +1310,29 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
push_constant.ray_bias = probe_bias;
push_constant.image_size[0] = probe_axis_count * probe_axis_count;
push_constant.image_size[1] = probe_axis_count;
- push_constant.store_ambient_texture = p_env->volumetric_fog_enabled;
+ push_constant.store_ambient_texture = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_enabled(p_env);
RID sky_uniform_set = gi->sdfgi_shader.integrate_default_sky_uniform_set;
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_DISABLED;
push_constant.y_mult = y_mult;
- if (reads_sky && p_env) {
- push_constant.sky_energy = p_env->bg_energy;
+ if (reads_sky && p_env.is_valid()) {
+ push_constant.sky_energy = RendererSceneRenderRD::get_singleton()->environment_get_bg_energy_multiplier(p_env);
- if (p_env->background == RS::ENV_BG_CLEAR_COLOR) {
+ if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_CLEAR_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = storage->get_default_clear_color().srgb_to_linear();
+ Color c = RSG::texture_storage->get_default_clear_color().srgb_to_linear();
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
- } else if (p_env->background == RS::ENV_BG_COLOR) {
+ } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_COLOR) {
push_constant.sky_mode = SDFGIShader::IntegratePushConstant::SKY_MODE_COLOR;
- Color c = p_env->bg_color;
+ Color c = RendererSceneRenderRD::get_singleton()->environment_get_bg_color(p_env);
push_constant.sky_color[0] = c.r;
push_constant.sky_color[1] = c.g;
push_constant.sky_color[2] = c.b;
- } else if (p_env->background == RS::ENV_BG_SKY) {
+ } else if (RendererSceneRenderRD::get_singleton()->environment_get_background(p_env) == RS::ENV_BG_SKY) {
if (p_sky && p_sky->radiance.is_valid()) {
if (integrate_sky_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(integrate_sky_uniform_set)) {
Vector<RD::Uniform> uniforms;
@@ -990,7 +1386,7 @@ void RendererSceneGIRD::SDFGI::update_probes(RendererSceneEnvironmentRD *p_env,
RD::get_singleton()->draw_command_end_label();
}
-void RendererSceneGIRD::SDFGI::store_probes() {
+void GI::SDFGI::store_probes() {
RD::get_singleton()->barrier(RD::BARRIER_MASK_COMPUTE, RD::BARRIER_MASK_COMPUTE);
RD::get_singleton()->draw_command_begin_label("SDFGI Store Probes");
@@ -1035,7 +1431,7 @@ void RendererSceneGIRD::SDFGI::store_probes() {
RD::get_singleton()->draw_command_end_label();
}
-int RendererSceneGIRD::SDFGI::get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const {
+int GI::SDFGI::get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const {
int dirty_count = 0;
for (uint32_t i = 0; i < cascades.size(); i++) {
const SDFGI::Cascade &c = cascades[i];
@@ -1091,7 +1487,7 @@ int RendererSceneGIRD::SDFGI::get_pending_region_data(int p_region, Vector3i &r_
return -1;
}
-void RendererSceneGIRD::SDFGI::update_cascades() {
+void GI::SDFGI::update_cascades() {
//update cascades
SDFGI::Cascade::UBO cascade_data[SDFGI::MAX_CASCADES];
int32_t probe_divisor = cascade_size / SDFGI::PROBE_DIVISOR;
@@ -1112,160 +1508,167 @@ void RendererSceneGIRD::SDFGI::update_cascades() {
RD::get_singleton()->buffer_update(cascades_ubo, 0, sizeof(SDFGI::Cascade::UBO) * SDFGI::MAX_CASCADES, cascade_data, RD::BARRIER_MASK_COMPUTE);
}
-void RendererSceneGIRD::SDFGI::debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture) {
+void GI::SDFGI::debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
- if (!debug_uniform_set.is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set)) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < cascades.size()) {
- u.append_id(cascades[i].sdf_tex);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ if (!debug_uniform_set[v].is_valid() || !RD::get_singleton()->uniform_set_is_valid(debug_uniform_set[v])) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.append_id(cascades[i].sdf_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < cascades.size()) {
- u.append_id(cascades[i].light_tex);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.append_id(cascades[i].light_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < cascades.size()) {
- u.append_id(cascades[i].light_aniso_0_tex);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.append_id(cascades[i].light_aniso_0_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
- if (i < cascades.size()) {
- u.append_id(cascades[i].light_aniso_1_tex);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t i = 0; i < SDFGI::MAX_CASCADES; i++) {
+ if (i < cascades.size()) {
+ u.append_id(cascades[i].light_aniso_1_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 5;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.append_id(occlusion_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 8;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 9;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.append_id(cascades_ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 10;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.append_id(p_texture);
- uniforms.push_back(u);
+ {
+ RD::Uniform u;
+ u.binding = 5;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.append_id(occlusion_texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 8;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 9;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.append_id(cascades_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 10;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.append_id(p_texture_views[v]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 11;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.append_id(lightprobe_texture);
+ uniforms.push_back(u);
+ }
+ debug_uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_shader_version, 0);
}
- {
- RD::Uniform u;
- u.binding = 11;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.append_id(lightprobe_texture);
- uniforms.push_back(u);
+
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.debug_pipeline);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set[v], 0);
+
+ SDFGIShader::DebugPushConstant push_constant;
+ push_constant.grid_size[0] = cascade_size;
+ push_constant.grid_size[1] = cascade_size;
+ push_constant.grid_size[2] = cascade_size;
+ push_constant.max_cascades = cascades.size();
+ push_constant.screen_size[0] = p_width;
+ push_constant.screen_size[1] = p_height;
+ push_constant.y_mult = y_mult;
+
+ push_constant.z_near = -p_projections[v].get_z_near();
+
+ for (int i = 0; i < 3; i++) {
+ for (int j = 0; j < 3; j++) {
+ push_constant.cam_basis[i][j] = p_transform.basis.rows[j][i];
+ }
}
- debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_shader_version, 0);
- }
+ push_constant.cam_origin[0] = p_transform.origin[0];
+ push_constant.cam_origin[1] = p_transform.origin[1];
+ push_constant.cam_origin[2] = p_transform.origin[2];
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, gi->sdfgi_shader.debug_pipeline);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, debug_uniform_set, 0);
+ // need to properly unproject for asymmetric projection matrices in stereo..
+ Projection inv_projection = p_projections[v].inverse();
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 3; j++) {
+ push_constant.inv_projection[j][i] = inv_projection.columns[i][j];
+ }
+ }
- SDFGIShader::DebugPushConstant push_constant;
- push_constant.grid_size[0] = cascade_size;
- push_constant.grid_size[1] = cascade_size;
- push_constant.grid_size[2] = cascade_size;
- push_constant.max_cascades = cascades.size();
- push_constant.screen_size[0] = p_width;
- push_constant.screen_size[1] = p_height;
- push_constant.probe_axis_size = probe_axis_count;
- push_constant.use_occlusion = uses_occlusion;
- push_constant.y_mult = y_mult;
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DebugPushConstant));
- Vector2 vp_half = p_projection.get_viewport_half_extents();
- push_constant.cam_extent[0] = vp_half.x;
- push_constant.cam_extent[1] = vp_half.y;
- push_constant.cam_extent[2] = -p_projection.get_z_near();
-
- push_constant.cam_transform[0] = p_transform.basis.rows[0][0];
- push_constant.cam_transform[1] = p_transform.basis.rows[1][0];
- push_constant.cam_transform[2] = p_transform.basis.rows[2][0];
- push_constant.cam_transform[3] = 0;
- push_constant.cam_transform[4] = p_transform.basis.rows[0][1];
- push_constant.cam_transform[5] = p_transform.basis.rows[1][1];
- push_constant.cam_transform[6] = p_transform.basis.rows[2][1];
- push_constant.cam_transform[7] = 0;
- push_constant.cam_transform[8] = p_transform.basis.rows[0][2];
- push_constant.cam_transform[9] = p_transform.basis.rows[1][2];
- push_constant.cam_transform[10] = p_transform.basis.rows[2][2];
- push_constant.cam_transform[11] = 0;
- push_constant.cam_transform[12] = p_transform.origin.x;
- push_constant.cam_transform[13] = p_transform.origin.y;
- push_constant.cam_transform[14] = p_transform.origin.z;
- push_constant.cam_transform[15] = 1;
-
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(SDFGIShader::DebugPushConstant));
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1);
- RD::get_singleton()->compute_list_end();
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, p_width, p_height, 1);
+ RD::get_singleton()->compute_list_end();
+ }
- Size2 rtsize = texture_storage->render_target_get_size(p_render_target);
- copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2(Vector2(), rtsize), true);
+ Size2i rtsize = texture_storage->render_target_get_size(p_render_target);
+ copy_effects->copy_to_fb_rect(p_texture, texture_storage->render_target_get_rd_framebuffer(p_render_target), Rect2i(Point2i(), rtsize), true, false, false, false, RID(), p_view_count > 1);
}
-void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
+void GI::SDFGI::debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- SDFGIShader::DebugProbesPushConstant push_constant;
+ // setup scene data
+ {
+ SDFGIShader::DebugProbesSceneData scene_data;
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- push_constant.projection[i * 4 + j] = p_camera_with_transform.matrix[i][j];
+ if (debug_probes_scene_data_ubo.is_null()) {
+ debug_probes_scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGIShader::DebugProbesSceneData));
+ }
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ RendererRD::MaterialStorage::store_camera(p_camera_with_transforms[v], scene_data.projection[v]);
}
+
+ RD::get_singleton()->buffer_update(debug_probes_scene_data_ubo, 0, sizeof(SDFGIShader::DebugProbesSceneData), &scene_data, RD::BARRIER_MASK_RASTER);
}
+ // setup push constant
+ SDFGIShader::DebugProbesPushConstant push_constant;
+
//gen spheres from strips
uint32_t band_points = 16;
push_constant.band_power = 4;
@@ -1314,14 +1717,26 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
u.append_id(occlusion_texture);
uniforms.push_back(u);
}
+ {
+ RD::Uniform u;
+ u.binding = 5;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.append_id(debug_probes_scene_data_ubo);
+ uniforms.push_back(u);
+ }
debug_probes_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, gi->sdfgi_shader.debug_probes.version_get_shader(gi->sdfgi_shader.debug_probes_shader, 0), 0);
}
- RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, gi->sdfgi_shader.debug_probes_pipeline[SDFGIShader::PROBE_DEBUG_PROBES].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, debug_probes_uniform_set, 0);
- RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant));
- RD::get_singleton()->draw_list_draw(p_draw_list, false, total_probes, total_points);
+ SDFGIShader::ProbeDebugMode mode = p_view_count > 1 ? SDFGIShader::PROBE_DEBUG_PROBES_MULTIVIEW : SDFGIShader::PROBE_DEBUG_PROBES;
+
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CONTINUE, p_will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
+ RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
+
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, gi->sdfgi_shader.debug_probes_pipeline[mode].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, debug_probes_uniform_set, 0);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, false, total_probes, total_points);
if (gi->sdfgi_debug_probe_dir != Vector3()) {
uint32_t cascade = 0;
@@ -1373,14 +1788,18 @@ void RendererSceneGIRD::SDFGI::debug_probes(RD::DrawListID p_draw_list, RID p_fr
uint32_t cell_count = probe_cells * 2 * probe_cells * 2 * probe_cells * 2;
- RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, gi->sdfgi_shader.debug_probes_pipeline[SDFGIShader::PROBE_DEBUG_VISIBILITY].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
- RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, debug_probes_uniform_set, 0);
- RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant));
- RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, total_points);
+ RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, gi->sdfgi_shader.debug_probes_pipeline[p_view_count > 1 ? SDFGIShader::PROBE_DEBUG_VISIBILITY_MULTIVIEW : SDFGIShader::PROBE_DEBUG_VISIBILITY].get_render_pipeline(RD::INVALID_FORMAT_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer)));
+ RD::get_singleton()->draw_list_bind_uniform_set(draw_list, debug_probes_uniform_set, 0);
+ RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SDFGIShader::DebugProbesPushConstant));
+ RD::get_singleton()->draw_list_draw(draw_list, false, cell_count, total_points);
}
+
+ RD::get_singleton()->draw_command_end_label();
+ RD::get_singleton()->draw_list_end();
}
-void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render) {
+void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
/* Update general SDFGI Buffer */
SDFGIData sdfgi_data;
@@ -1447,6 +1866,11 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
c.probe_world_offset[2] = probe_ofs.z;
c.to_cell = 1.0 / cascades[i].cell_size;
+ c.exposure_normalization = 1.0;
+ if (p_render_data->camera_attributes.is_valid()) {
+ float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ c.exposure_normalization = exposure_normalization / cascades[i].baked_exposure_normalization;
+ }
}
RD::get_singleton()->buffer_update(gi->sdfgi_ubo, 0, sizeof(SDFGIData), &sdfgi_data, RD::BARRIER_MASK_COMPUTE);
@@ -1458,32 +1882,43 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
SDFGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS];
uint32_t idx = 0;
- for (uint32_t j = 0; j < (uint32_t)p_scene_render->render_state.sdfgi_update_data->directional_lights->size(); j++) {
+ for (uint32_t j = 0; j < (uint32_t)p_render_data->sdfgi_update_data->directional_lights->size(); j++) {
if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
break;
}
- RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->directional_lights->get(j));
- ERR_CONTINUE(!li);
+ RID light_instance = p_render_data->sdfgi_update_data->directional_lights->get(j);
+ ERR_CONTINUE(!light_storage->owns_light_instance(light_instance));
+
+ RID light = light_storage->light_instance_get_base_light(light_instance);
+ Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance);
- if (RSG::light_storage->light_directional_get_sky_mode(li->light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+ if (RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
continue;
}
- Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
+ Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z);
dir.y *= y_mult;
dir.normalize();
lights[idx].direction[0] = dir.x;
lights[idx].direction[1] = dir.y;
lights[idx].direction[2] = dir.z;
- Color color = RSG::light_storage->light_get_color(li->light);
+ Color color = RSG::light_storage->light_get_color(light);
color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
lights[idx].type = RS::LIGHT_DIRECTIONAL;
- lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
+ lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY);
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light);
idx++;
}
@@ -1492,47 +1927,69 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(cascade_size >> 1) + cascade.position)) * cascade.cell_size;
cascade_aabb.size = Vector3(1, 1, 1) * cascade_size * cascade.cell_size;
- for (uint32_t j = 0; j < p_scene_render->render_state.sdfgi_update_data->positional_light_count; j++) {
+ for (uint32_t j = 0; j < p_render_data->sdfgi_update_data->positional_light_count; j++) {
if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) {
break;
}
- RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_scene_render->render_state.sdfgi_update_data->positional_light_instances[j]);
- ERR_CONTINUE(!li);
+ RID light_instance = p_render_data->sdfgi_update_data->positional_light_instances[j];
+ ERR_CONTINUE(!light_storage->owns_light_instance(light_instance));
+
+ RID light = light_storage->light_instance_get_base_light(light_instance);
+ AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance);
+ Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance);
- uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
+ uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light);
if (i > max_sdfgi_cascade) {
continue;
}
- if (!cascade_aabb.intersects(li->aabb)) {
+ if (!cascade_aabb.intersects(light_aabb)) {
continue;
}
- Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
+ Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z);
//faster to not do this here
//dir.y *= y_mult;
//dir.normalize();
lights[idx].direction[0] = dir.x;
lights[idx].direction[1] = dir.y;
lights[idx].direction[2] = dir.z;
- Vector3 pos = li->transform.origin;
+ Vector3 pos = light_transform.origin;
pos.y *= y_mult;
lights[idx].position[0] = pos.x;
lights[idx].position[1] = pos.y;
lights[idx].position[2] = pos.z;
- Color color = RSG::light_storage->light_get_color(li->light);
+ Color color = RSG::light_storage->light_get_color(light);
color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
- lights[idx].type = RSG::light_storage->light_get_type(li->light);
- lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
- lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+ lights[idx].type = RSG::light_storage->light_get_type(light);
+
+ lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY);
+
+ // Convert from Luminous Power to Luminous Intensity
+ if (lights[idx].type == RS::LIGHT_OMNI) {
+ lights[idx].energy *= 1.0 / (Math_PI * 4.0);
+ } else if (lights[idx].type == RS::LIGHT_SPOT) {
+ // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle.
+ // We make this assumption to keep them easy to control.
+ lights[idx].energy *= 1.0 / Math_PI;
+ }
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light);
+ lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -1545,10 +2002,9 @@ void RendererSceneGIRD::SDFGI::pre_process_gi(const Transform3D &p_transform, Re
}
}
-void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render) {
+void GI::SDFGI::render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization) {
//print_line("rendering region " + itos(p_region));
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
+ ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
AABB bounds;
Vector3i from;
Vector3i size;
@@ -1567,7 +2023,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
}
//print_line("rendering cascade " + itos(p_region) + " objects: " + itos(p_cull_count) + " bounds: " + bounds + " from: " + from + " size: " + size + " cell size: " + rtos(cascades[cascade].cell_size));
- p_scene_render->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing);
+ RendererSceneRenderRD::get_singleton()->_render_sdfgi(p_render_buffers, from, size, bounds, p_instances, render_albedo, render_emission, render_emission_aniso, render_geom_facing, p_exposure_normalization);
if (cascade_next != cascade) {
RD::get_singleton()->draw_command_begin_label("SDFGI Pre-Process Cascade");
@@ -1596,6 +2052,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
}
cascades[cascade].all_dynamic_lights_dirty = true;
+ cascades[cascade].baked_exposure_normalization = p_exposure_normalization;
push_constant.grid_size = cascade_size;
push_constant.cascade = cascade;
@@ -1878,7 +2335,7 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
img.instantiate();
for (uint32_t i = 0; i < cascade_size; i++) {
Vector<uint8_t> subarr = data.slice(128 * 128 * i, 128 * 128 * (i + 1));
- img->create(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr);
+ img->set_data(cascade_size, cascade_size, false, Image::FORMAT_L8, subarr);
img->save_png("res://cascade_sdf_" + itos(cascade) + "_" + itos(i) + ".png");
}
@@ -1904,9 +2361,10 @@ void RendererSceneGIRD::SDFGI::render_region(RID p_render_buffers, int p_region,
}
}
-void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render) {
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb); // we wouldn't be here if this failed but...
+void GI::SDFGI::render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result) {
+ ERR_FAIL_COND(p_render_buffers.is_null()); // we wouldn't be here if this failed but...
+
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RD::get_singleton()->draw_command_begin_label("SDFGI Render Static Lights");
@@ -1933,21 +2391,25 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
break;
}
- RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_positional_light_cull_result[i][j]);
- ERR_CONTINUE(!li);
+ RID light_instance = p_positional_light_cull_result[i][j];
+ ERR_CONTINUE(!light_storage->owns_light_instance(light_instance));
- uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(li->light);
+ RID light = light_storage->light_instance_get_base_light(light_instance);
+ AABB light_aabb = light_storage->light_instance_get_base_aabb(light_instance);
+ Transform3D light_transform = light_storage->light_instance_get_base_transform(light_instance);
+
+ uint32_t max_sdfgi_cascade = RSG::light_storage->light_get_max_sdfgi_cascade(light);
if (p_cascade_indices[i] > max_sdfgi_cascade) {
continue;
}
- if (!cascade_aabb.intersects(li->aabb)) {
+ if (!cascade_aabb.intersects(light_aabb)) {
continue;
}
- lights[idx].type = RSG::light_storage->light_get_type(li->light);
+ lights[idx].type = RSG::light_storage->light_get_type(light);
- Vector3 dir = -li->transform.basis.get_column(Vector3::AXIS_Z);
+ Vector3 dir = -light_transform.basis.get_column(Vector3::AXIS_Z);
if (lights[idx].type == RS::LIGHT_DIRECTIONAL) {
dir.y *= y_mult; //only makes sense for directional
dir.normalize();
@@ -1955,22 +2417,40 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
lights[idx].direction[0] = dir.x;
lights[idx].direction[1] = dir.y;
lights[idx].direction[2] = dir.z;
- Vector3 pos = li->transform.origin;
+ Vector3 pos = light_transform.origin;
pos.y *= y_mult;
lights[idx].position[0] = pos.x;
lights[idx].position[1] = pos.y;
lights[idx].position[2] = pos.z;
- Color color = RSG::light_storage->light_get_color(li->light);
+ Color color = RSG::light_storage->light_get_color(light);
color = color.srgb_to_linear();
lights[idx].color[0] = color.r;
lights[idx].color[1] = color.g;
lights[idx].color[2] = color.b;
- lights[idx].energy = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
- lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light);
- lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION);
- lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE);
- lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)));
- lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
+
+ lights[idx].energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ lights[idx].energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY);
+
+ // Convert from Luminous Power to Luminous Intensity
+ if (lights[idx].type == RS::LIGHT_OMNI) {
+ lights[idx].energy *= 1.0 / (Math_PI * 4.0);
+ } else if (lights[idx].type == RS::LIGHT_SPOT) {
+ // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle.
+ // We make this assumption to keep them easy to control.
+ lights[idx].energy *= 1.0 / Math_PI;
+ }
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ lights[idx].energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
+ lights[idx].has_shadow = RSG::light_storage->light_has_shadow(light);
+ lights[idx].attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
+ lights[idx].radius = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE);
+ lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
idx++;
}
@@ -2012,7 +2492,7 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
dl_push_constant.cascade = p_cascade_indices[i];
if (dl_push_constant.light_count > 0) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_uniform_set, 0);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cc.sdf_direct_light_static_uniform_set, 0);
RD::get_singleton()->compute_list_set_push_constant(compute_list, &dl_push_constant, sizeof(SDFGIShader::DirectLightPushConstant));
RD::get_singleton()->compute_list_dispatch_indirect(compute_list, cc.solid_cell_dispatch_buffer, 0);
}
@@ -2026,33 +2506,23 @@ void RendererSceneGIRD::SDFGI::render_static_lights(RID p_render_buffers, uint32
////////////////////////////////////////////////////////////////////////////////
// VoxelGIInstance
-void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
+void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- uint32_t data_version = storage->voxel_gi_get_data_version(probe);
+ uint32_t data_version = gi->voxel_gi_get_data_version(probe);
// (RE)CREATE IF NEEDED
if (last_probe_data_version != data_version) {
//need to re-create everything
- if (texture.is_valid()) {
- RD::get_singleton()->free(texture);
- RD::get_singleton()->free(write_buffer);
- mipmaps.clear();
- }
-
- for (int i = 0; i < dynamic_maps.size(); i++) {
- RD::get_singleton()->free(dynamic_maps[i].texture);
- RD::get_singleton()->free(dynamic_maps[i].depth);
- }
+ free_resources();
- dynamic_maps.clear();
-
- Vector3i octree_size = storage->voxel_gi_get_octree_size(probe);
+ Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
if (octree_size != Vector3i()) {
//can create a 3D texture
- Vector<int> levels = storage->voxel_gi_get_level_counts(probe);
+ Vector<int> levels = gi->voxel_gi_get_level_counts(probe);
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -2065,6 +2535,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(texture, "VoxelGI Instance Texture");
RD::get_singleton()->texture_clear(texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1);
@@ -2092,14 +2563,14 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.append_id(storage->voxel_gi_get_octree_buffer(probe));
+ u.append_id(gi->voxel_gi_get_octree_buffer(probe));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(storage->voxel_gi_get_data_buffer(probe));
+ u.append_id(gi->voxel_gi_get_data_buffer(probe));
uniforms.push_back(u);
}
@@ -2114,7 +2585,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.append_id(storage->voxel_gi_get_sdf_texture(probe));
+ u.append_id(gi->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
@@ -2194,6 +2665,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.texture, "VoxelGI Instance DMap Texture");
if (dynamic_maps.size() == 0) {
// Render depth for first one.
@@ -2201,6 +2673,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D16_UNORM, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.fb_depth, "VoxelGI Instance DMap FB Depth");
}
//just use depth as-is
@@ -2208,13 +2681,17 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.depth, "VoxelGI Instance DMap Depth");
if (dynamic_maps.size() == 0) {
dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.albedo, "VoxelGI Instance DMap Albedo");
dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.normal, "VoxelGI Instance DMap Normal");
dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(dmap.orm, "VoxelGI Instance DMap ORM");
Vector<RID> fb;
fb.push_back(dmap.albedo);
@@ -2268,7 +2745,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.append_id(storage->voxel_gi_get_sdf_texture(probe));
+ u.append_id(gi->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
@@ -2337,7 +2814,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 9;
- u.append_id(storage->voxel_gi_get_sdf_texture(probe));
+ u.append_id(gi->voxel_gi_get_sdf_texture(probe));
uniforms.push_back(u);
}
{
@@ -2372,7 +2849,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
last_probe_data_version = data_version;
p_update_light_instances = true; //just in case
- p_scene_render->_base_uniforms_changed();
+ RendererSceneRenderRD::get_singleton()->base_uniforms_changed();
}
// UDPDATE TIME
@@ -2388,14 +2865,15 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
light_count = MIN(gi->voxel_gi_max_lights, (uint32_t)p_light_instances.size());
{
- Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(probe);
- Transform3D to_probe_xform = (transform * to_cell.affine_inverse()).affine_inverse();
+ Transform3D to_cell = gi->voxel_gi_get_to_cell_xform(probe);
+ Transform3D to_probe_xform = to_cell * transform.affine_inverse();
+
//update lights
for (uint32_t i = 0; i < light_count; i++) {
VoxelGILight &l = gi->voxel_gi_lights[i];
RID light_instance = p_light_instances[i];
- RID light = p_scene_render->light_instance_get_base_light(light_instance);
+ RID light = light_storage->light_instance_get_base_light(light_instance);
l.type = RSG::light_storage->light_get_type(light);
if (l.type == RS::LIGHT_DIRECTIONAL && RSG::light_storage->light_directional_get_sky_mode(light) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
@@ -2405,16 +2883,32 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
l.attenuation = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION);
l.energy = RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY);
+
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ l.energy *= RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_INTENSITY);
+
+ l.energy *= gi->voxel_gi_get_baked_exposure_normalization(probe);
+
+ // Convert from Luminous Power to Luminous Intensity
+ if (l.type == RS::LIGHT_OMNI) {
+ l.energy *= 1.0 / (Math_PI * 4.0);
+ } else if (l.type == RS::LIGHT_SPOT) {
+ // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle.
+ // We make this assumption to keep them easy to control.
+ l.energy *= 1.0 / Math_PI;
+ }
+ }
+
l.radius = to_cell.basis.xform(Vector3(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length();
Color color = RSG::light_storage->light_get_color(light).srgb_to_linear();
l.color[0] = color.r;
l.color[1] = color.g;
l.color[2] = color.b;
- l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
+ l.cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)));
l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION);
- Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance);
+ Transform3D xform = light_storage->light_instance_get_base_transform(light_instance);
Vector3 pos = to_probe_xform.xform(xform.origin);
Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_column(2)).normalized();
@@ -2439,7 +2933,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
if (mipmaps.size()) {
//can update mipmaps
- Vector3i probe_size = storage->voxel_gi_get_octree_size(probe);
+ Vector3i probe_size = gi->voxel_gi_get_octree_size(probe);
VoxelGIPushConstant push_constant;
@@ -2448,8 +2942,8 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
push_constant.limits[2] = probe_size.z;
push_constant.stack_size = mipmaps.size();
push_constant.emission_scale = 1.0;
- push_constant.propagation = storage->voxel_gi_get_propagation(probe);
- push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe);
+ push_constant.propagation = gi->voxel_gi_get_propagation(probe);
+ push_constant.dynamic_range = gi->voxel_gi_get_dynamic_range(probe);
push_constant.light_count = light_count;
push_constant.aniso_strength = 0;
@@ -2461,7 +2955,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
int passes;
if (p_update_light_instances) {
- passes = storage->voxel_gi_is_using_two_bounces(probe) ? 2 : 1;
+ passes = gi->voxel_gi_is_using_two_bounces(probe) ? 2 : 1;
} else {
passes = 1; //only re-blitting is necessary
}
@@ -2528,13 +3022,13 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
has_dynamic_object_data = false; //clear until dynamic object data is used again
if (p_dynamic_objects.size() && dynamic_maps.size()) {
- Vector3i octree_size = storage->voxel_gi_get_octree_size(probe);
+ Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
int multiplier = dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z);
Transform3D oversample_scale;
oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier));
- Transform3D to_cell = oversample_scale * storage->voxel_gi_get_to_cell_xform(probe);
+ Transform3D to_cell = oversample_scale * gi->voxel_gi_get_to_cell_xform(probe);
Transform3D to_world_xform = transform * to_cell.affine_inverse();
Transform3D to_probe_xform = to_world_xform.affine_inverse();
@@ -2542,10 +3036,10 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
//this could probably be better parallelized in compute..
for (int i = 0; i < (int)p_dynamic_objects.size(); i++) {
- RendererSceneRender::GeometryInstance *instance = p_dynamic_objects[i];
+ RenderGeometryInstance *instance = p_dynamic_objects[i];
//transform aabb to voxel_gi
- AABB aabb = (to_probe_xform * p_scene_render->geometry_instance_get_transform(instance)).xform(p_scene_render->geometry_instance_get_aabb(instance));
+ AABB aabb = (to_probe_xform * instance->get_transform()).xform(instance->get_aabb());
//this needs to wrap to grid resolution to avoid jitter
//also extend margin a bit just in case
@@ -2606,15 +3100,20 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(1)) < 0);
bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_column(2)) > 0);
- CameraMatrix cm;
+ Projection cm;
cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]);
- if (p_scene_render->cull_argument.size() == 0) {
- p_scene_render->cull_argument.push_back(nullptr);
+ if (RendererSceneRenderRD::get_singleton()->cull_argument.size() == 0) {
+ RendererSceneRenderRD::get_singleton()->cull_argument.push_back(nullptr);
+ }
+ RendererSceneRenderRD::get_singleton()->cull_argument[0] = instance;
+
+ float exposure_normalization = 1.0;
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ exposure_normalization = gi->voxel_gi_get_baked_exposure_normalization(probe);
}
- p_scene_render->cull_argument[0] = instance;
- p_scene_render->_render_material(to_world_xform * xform, cm, true, p_scene_render->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size));
+ RendererSceneRenderRD::get_singleton()->_render_material(to_world_xform * xform, cm, true, RendererSceneRenderRD::get_singleton()->cull_argument, dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size), exposure_normalization);
VoxelGIDynamicPushConstant push_constant;
memset(&push_constant, 0, sizeof(VoxelGIDynamicPushConstant));
@@ -2634,7 +3133,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
push_constant.z_base = xform.origin[z_axis];
push_constant.z_sign = (z_flip ? -1.0 : 1.0);
push_constant.pos_multiplier = float(1.0) / multiplier;
- push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe);
+ push_constant.dynamic_range = gi->voxel_gi_get_dynamic_range(probe);
push_constant.flip_x = x_flip;
push_constant.flip_y = y_flip;
push_constant.rect_pos[0] = rect.position[0];
@@ -2646,7 +3145,7 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
push_constant.prev_rect_size[0] = 0;
push_constant.prev_rect_size[1] = 0;
push_constant.on_mipmap = false;
- push_constant.propagation = storage->voxel_gi_get_propagation(probe);
+ push_constant.propagation = gi->voxel_gi_get_propagation(probe);
push_constant.pad[0] = 0;
push_constant.pad[1] = 0;
push_constant.pad[2] = 0;
@@ -2728,24 +3227,55 @@ void RendererSceneGIRD::VoxelGIInstance::update(bool p_update_light_instances, c
has_dynamic_object_data = true; //clear until dynamic object data is used again
}
- last_probe_version = storage->voxel_gi_get_version(probe);
+ last_probe_version = gi->voxel_gi_get_version(probe);
+}
+
+void GI::VoxelGIInstance::free_resources() {
+ if (texture.is_valid()) {
+ RD::get_singleton()->free(texture);
+ RD::get_singleton()->free(write_buffer);
+
+ texture = RID();
+ write_buffer = RID();
+ mipmaps.clear();
+ }
+
+ for (int i = 0; i < dynamic_maps.size(); i++) {
+ RD::get_singleton()->free(dynamic_maps[i].texture);
+ RD::get_singleton()->free(dynamic_maps[i].depth);
+
+ // these only exist on the first level...
+ if (dynamic_maps[i].fb_depth.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].fb_depth);
+ }
+ if (dynamic_maps[i].albedo.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].albedo);
+ }
+ if (dynamic_maps[i].normal.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].normal);
+ }
+ if (dynamic_maps[i].orm.is_valid()) {
+ RD::get_singleton()->free(dynamic_maps[i].orm);
+ }
+ }
+ dynamic_maps.clear();
}
-void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+void GI::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
if (mipmaps.size() == 0) {
return;
}
- CameraMatrix cam_transform = (p_camera_with_transform * CameraMatrix(transform)) * CameraMatrix(storage->voxel_gi_get_to_cell_xform(probe).affine_inverse());
+ Projection cam_transform = (p_camera_with_transform * Projection(transform)) * Projection(gi->voxel_gi_get_to_cell_xform(probe).affine_inverse());
int level = 0;
- Vector3i octree_size = storage->voxel_gi_get_octree_size(probe);
+ Vector3i octree_size = gi->voxel_gi_get_octree_size(probe);
VoxelGIDebugPushConstant push_constant;
push_constant.alpha = p_alpha;
- push_constant.dynamic_range = storage->voxel_gi_get_dynamic_range(probe);
+ push_constant.dynamic_range = gi->voxel_gi_get_dynamic_range(probe);
push_constant.cell_offset = mipmaps[level].cell_offset;
push_constant.level = level;
@@ -2756,7 +3286,7 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
- push_constant.projection[i * 4 + j] = cam_transform.matrix[i][j];
+ push_constant.projection[i * 4 + j] = cam_transform.columns[i][j];
}
}
@@ -2768,7 +3298,7 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.append_id(storage->voxel_gi_get_data_buffer(probe));
+ u.append_id(gi->voxel_gi_get_data_buffer(probe));
uniforms.push_back(u);
}
{
@@ -2810,23 +3340,24 @@ void RendererSceneGIRD::VoxelGIInstance::debug(RD::DrawListID p_draw_list, RID p
}
////////////////////////////////////////////////////////////////////////////////
-// GIRD
+// GI
+
+GI::GI() {
+ singleton = this;
-RendererSceneGIRD::RendererSceneGIRD() {
sdfgi_ray_count = RS::EnvironmentSDFGIRayCount(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/probe_ray_count")), 0, int32_t(RS::ENV_SDFGI_RAY_COUNT_MAX - 1)));
sdfgi_frames_to_converge = RS::EnvironmentSDFGIFramesToConverge(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_converge")), 0, int32_t(RS::ENV_SDFGI_CONVERGE_MAX - 1)));
sdfgi_frames_to_update_light = RS::EnvironmentSDFGIFramesToUpdateLight(CLAMP(int32_t(GLOBAL_GET("rendering/global_illumination/sdfgi/frames_to_update_lights")), 0, int32_t(RS::ENV_SDFGI_UPDATE_LIGHT_MAX - 1)));
}
-RendererSceneGIRD::~RendererSceneGIRD() {
+GI::~GI() {
+ singleton = nullptr;
}
-void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky) {
+void GI::init(SkyRD *p_sky) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
-
/* GI */
{
@@ -2942,7 +3473,11 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
+ if (p_sky->sky_use_cubemap_array) {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE));
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE));
+ }
uniforms.push_back(u);
}
{
@@ -2962,17 +3497,41 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
//calculate tables
String defines = "\n#define SDFGI_OCT_SIZE " + itos(SDFGI::LIGHTPROBE_OCT_SIZE) + "\n";
Vector<String> gi_modes;
- gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n");
- gi_modes.push_back("\n#define USE_SDFGI\n");
- gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_VOXEL_GI_INSTANCES\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n");
- gi_modes.push_back("\n#define MODE_HALF_RES\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n");
+
+ gi_modes.push_back("\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_VOXEL_GI
+ gi_modes.push_back("\n#define USE_SDFGI\n"); // MODE_SDFGI
+ gi_modes.push_back("\n#define USE_SDFGI\n\n#define USE_VOXEL_GI_INSTANCES\n"); // MODE_COMBINED
shader.initialize(gi_modes, defines);
shader_version = shader.version_create();
- for (int i = 0; i < MODE_MAX; i++) {
- pipelines[i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i));
+
+ Vector<RD::PipelineSpecializationConstant> specialization_constants;
+
+ {
+ RD::PipelineSpecializationConstant sc;
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 0; // SHADER_SPECIALIZATION_HALF_RES
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 1; // SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+
+ sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
+ sc.constant_id = 2; // SHADER_SPECIALIZATION_USE_VRS
+ sc.bool_value = false;
+ specialization_constants.push_back(sc);
+ }
+
+ for (int v = 0; v < SHADER_SPECIALIZATION_VARIATIONS; v++) {
+ specialization_constants.ptrw()[0].bool_value = (v & SHADER_SPECIALIZATION_HALF_RES) ? true : false;
+ specialization_constants.ptrw()[1].bool_value = (v & SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX) ? true : false;
+ specialization_constants.ptrw()[2].bool_value = (v & SHADER_SPECIALIZATION_USE_VRS) ? true : false;
+ for (int i = 0; i < MODE_MAX; i++) {
+ pipelines[v][i] = RD::get_singleton()->compute_pipeline_create(shader.version_get_shader(shader_version, i), specialization_constants);
+ }
}
sdfgi_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SDFGIData));
@@ -2991,9 +3550,14 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
Vector<String> versions;
versions.push_back("\n#define MODE_PROBES\n");
+ versions.push_back("\n#define MODE_PROBES\n#define USE_MULTIVIEW\n");
versions.push_back("\n#define MODE_VISIBILITY\n");
+ versions.push_back("\n#define MODE_VISIBILITY\n#define USE_MULTIVIEW\n");
sdfgi_shader.debug_probes.initialize(versions, defines);
+
+ // TODO disable multiview versions if turned off
+
sdfgi_shader.debug_probes_shader = sdfgi_shader.debug_probes.version_create();
{
@@ -3004,6 +3568,8 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
ds.enable_depth_write = true;
ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL;
for (int i = 0; i < SDFGIShader::PROBE_DEBUG_MAX; i++) {
+ // TODO check if version is enabled
+
RID debug_probes_shader_version = sdfgi_shader.debug_probes.version_get_shader(sdfgi_shader.debug_probes_shader, i);
sdfgi_shader.debug_probes_pipeline[i].setup(debug_probes_shader_version, RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0);
}
@@ -3013,7 +3579,7 @@ void RendererSceneGIRD::init(RendererStorageRD *p_storage, RendererSceneSkyRD *p
half_resolution = GLOBAL_GET("rendering/global_illumination/gi/use_half_resolution");
}
-void RendererSceneGIRD::free() {
+void GI::free() {
RD::get_singleton()->free(default_voxel_gi_buffer);
RD::get_singleton()->free(voxel_gi_lights_uniform);
RD::get_singleton()->free(sdfgi_ubo);
@@ -3032,25 +3598,27 @@ void RendererSceneGIRD::free() {
}
}
-RendererSceneGIRD::SDFGI *RendererSceneGIRD::create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
- SDFGI *sdfgi = memnew(SDFGI);
+Ref<GI::SDFGI> GI::create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size) {
+ Ref<SDFGI> sdfgi;
+ sdfgi.instantiate();
sdfgi->create(p_env, p_world_position, p_requested_history_size, this);
return sdfgi;
}
-void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render) {
+void GI::setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ ERR_FAIL_NULL(texture_storage);
r_voxel_gi_instances_used = 0;
- // feels a little dirty to use our container this way but....
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(rb == nullptr);
-
- RID voxel_gi_buffer = p_scene_render->render_buffers_get_voxel_gi_buffer(p_render_buffers);
+ Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
+ ERR_FAIL_COND(rbgi.is_null());
+ RID voxel_gi_buffer = rbgi->get_voxel_gi_buffer();
VoxelGIData voxel_gi_data[MAX_VOXEL_GI_INSTANCES];
bool voxel_gi_instances_changed = false;
@@ -3061,7 +3629,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
RID texture;
if (i < (int)p_voxel_gi_instances.size()) {
- VoxelGIInstance *gipi = get_probe_instance(p_voxel_gi_instances[i]);
+ VoxelGIInstance *gipi = voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]);
if (gipi) {
texture = gipi->texture;
@@ -3069,7 +3637,7 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
RID base_probe = gipi->probe;
- Transform3D to_cell = storage->voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
+ Transform3D to_cell = voxel_gi_get_to_cell_xform(gipi->probe) * gipi->transform.affine_inverse() * to_camera;
gipd.xform[0] = to_cell.basis.rows[0][0];
gipd.xform[1] = to_cell.basis.rows[1][0];
@@ -3088,46 +3656,55 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
gipd.xform[14] = to_cell.origin.z;
gipd.xform[15] = 1;
- Vector3 bounds = storage->voxel_gi_get_octree_size(base_probe);
+ Vector3 bounds = voxel_gi_get_octree_size(base_probe);
gipd.bounds[0] = bounds.x;
gipd.bounds[1] = bounds.y;
gipd.bounds[2] = bounds.z;
- gipd.dynamic_range = storage->voxel_gi_get_dynamic_range(base_probe) * storage->voxel_gi_get_energy(base_probe);
- gipd.bias = storage->voxel_gi_get_bias(base_probe);
- gipd.normal_bias = storage->voxel_gi_get_normal_bias(base_probe);
- gipd.blend_ambient = !storage->voxel_gi_is_interior(base_probe);
+ gipd.dynamic_range = voxel_gi_get_dynamic_range(base_probe) * voxel_gi_get_energy(base_probe);
+ gipd.bias = voxel_gi_get_bias(base_probe);
+ gipd.normal_bias = voxel_gi_get_normal_bias(base_probe);
+ gipd.blend_ambient = !voxel_gi_is_interior(base_probe);
gipd.mipmaps = gipi->mipmaps.size();
+ gipd.exposure_normalization = 1.0;
+ if (p_render_data->camera_attributes.is_valid()) {
+ float exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ gipd.exposure_normalization = exposure_normalization / voxel_gi_get_baked_exposure_normalization(base_probe);
+ }
}
r_voxel_gi_instances_used++;
}
if (texture == RID()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
- if (texture != rb->gi.voxel_gi_textures[i]) {
+ if (texture != rbgi->voxel_gi_textures[i]) {
voxel_gi_instances_changed = true;
- rb->gi.voxel_gi_textures[i] = texture;
+ rbgi->voxel_gi_textures[i] = texture;
}
}
if (voxel_gi_instances_changed) {
- if (RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) {
- RD::get_singleton()->free(rb->gi.uniform_set);
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ if (RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
+ RD::get_singleton()->free(rbgi->uniform_set[v]);
+ }
+ rbgi->uniform_set[v] = RID();
}
- rb->gi.uniform_set = RID();
- if (rb->volumetric_fog) {
- if (RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
+ if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+ Ref<Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
+
+ if (RD::get_singleton()->uniform_set_is_valid(fog->fog_uniform_set)) {
+ RD::get_singleton()->free(fog->fog_uniform_set);
+ RD::get_singleton()->free(fog->process_uniform_set);
+ RD::get_singleton()->free(fog->process_uniform_set2);
}
- rb->volumetric_fog->fog_uniform_set = RID();
- rb->volumetric_fog->process_uniform_set = RID();
- rb->volumetric_fog->process_uniform_set2 = RID();
+ fog->fog_uniform_set = RID();
+ fog->process_uniform_set = RID();
+ fog->process_uniform_set2 = RID();
}
}
@@ -3140,275 +3717,364 @@ void RendererSceneGIRD::setup_voxel_gi_instances(RID p_render_buffers, const Tra
}
}
-void RendererSceneGIRD::process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render) {
+RID GI::RenderBuffersGI::get_voxel_gi_buffer() {
+ if (voxel_gi_buffer.is_null()) {
+ voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GI::VoxelGIData) * GI::MAX_VOXEL_GI_INSTANCES);
+ }
+ return voxel_gi_buffer;
+}
+
+void GI::RenderBuffersGI::free_data() {
+ for (uint32_t v = 0; v < RendererSceneRender::MAX_RENDER_VIEWS; v++) {
+ if (RD::get_singleton()->uniform_set_is_valid(uniform_set[v])) {
+ RD::get_singleton()->free(uniform_set[v]);
+ }
+ uniform_set[v] = RID();
+ }
+
+ if (scene_data_ubo.is_valid()) {
+ RD::get_singleton()->free(scene_data_ubo);
+ scene_data_ubo = RID();
+ }
+
+ if (voxel_gi_buffer.is_valid()) {
+ RD::get_singleton()->free(voxel_gi_buffer);
+ voxel_gi_buffer = RID();
+ }
+}
+
+void GI::process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ ERR_FAIL_COND_MSG(p_view_count > 2, "Maximum of 2 views supported for Processing GI.");
+
RD::get_singleton()->draw_command_begin_label("GI Render");
- RendererSceneRenderRD::RenderBuffers *rb = p_scene_render->render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(rb == nullptr);
+ ERR_FAIL_COND(p_render_buffers.is_null());
- if (rb->ambient_buffer.is_null() || rb->gi.using_half_size_gi != half_resolution) {
- if (rb->ambient_buffer.is_valid()) {
- RD::get_singleton()->free(rb->ambient_buffer);
- RD::get_singleton()->free(rb->reflection_buffer);
- }
+ Ref<RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
+ ERR_FAIL_COND(rbgi.is_null());
+
+ Size2i internal_size = p_render_buffers->get_internal_size();
+
+ if (rbgi->using_half_size_gi != half_resolution) {
+ p_render_buffers->clear_context(RB_SCOPE_GI);
+ }
+
+ if (!p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) {
+ Size2i size = internal_size;
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
if (half_resolution) {
- tf.width >>= 1;
- tf.height >>= 1;
+ size.x >>= 1;
+ size.y >>= 1;
}
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->reflection_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->ambient_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->gi.using_half_size_gi = half_resolution;
+
+ p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_AMBIENT, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
+ p_render_buffers->create_texture(RB_SCOPE_GI, RB_TEX_REFLECTION, RD::DATA_FORMAT_R16G16B16A16_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1, size);
+
+ rbgi->using_half_size_gi = half_resolution;
}
+ // Setup our scene data
+ {
+ SceneData scene_data;
+
+ if (rbgi->scene_data_ubo.is_null()) {
+ rbgi->scene_data_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(SceneData));
+ }
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ RendererRD::MaterialStorage::store_camera(p_projections[v].inverse(), scene_data.inv_projection[v]);
+ scene_data.eye_offset[v][0] = p_eye_offsets[v].x;
+ scene_data.eye_offset[v][1] = p_eye_offsets[v].y;
+ scene_data.eye_offset[v][2] = p_eye_offsets[v].z;
+ scene_data.eye_offset[v][3] = 0.0;
+ }
+
+ // Note that we will be ignoring the origin of this transform.
+ RendererRD::MaterialStorage::store_transform(p_cam_transform, scene_data.cam_transform);
+
+ scene_data.screen_size[0] = internal_size.x;
+ scene_data.screen_size[1] = internal_size.y;
+
+ RD::get_singleton()->buffer_update(rbgi->scene_data_ubo, 0, sizeof(SceneData), &scene_data, RD::BARRIER_MASK_COMPUTE);
+ }
+
+ // Now compute the contents of our buffers.
+ RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
+
+ // Render each eye separately.
+ // We need to look into whether we can make our compute shader use Multiview but not sure that works or makes a difference..
+
+ // setup our push constant
+
PushConstant push_constant;
- push_constant.screen_size[0] = rb->internal_width;
- push_constant.screen_size[1] = rb->internal_height;
- push_constant.z_near = p_projection.get_z_near();
- push_constant.z_far = p_projection.get_z_far();
- push_constant.orthogonal = p_projection.is_orthogonal();
- push_constant.proj_info[0] = -2.0f / (rb->internal_width * p_projection.matrix[0][0]);
- push_constant.proj_info[1] = -2.0f / (rb->internal_height * p_projection.matrix[1][1]);
- push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0];
- push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1];
push_constant.max_voxel_gi_instances = MIN((uint64_t)MAX_VOXEL_GI_INSTANCES, p_voxel_gi_instances.size());
push_constant.high_quality_vct = voxel_gi_quality == RS::VOXEL_GI_QUALITY_HIGH;
- bool use_sdfgi = rb->sdfgi != nullptr;
+ // these should be the same for all views
+ push_constant.orthogonal = p_projections[0].is_orthogonal();
+ push_constant.z_near = p_projections[0].get_z_near();
+ push_constant.z_far = p_projections[0].get_z_far();
+
+ // these are only used if we have 1 view, else we use the projections in our scene data
+ push_constant.proj_info[0] = -2.0f / (internal_size.x * p_projections[0].columns[0][0]);
+ push_constant.proj_info[1] = -2.0f / (internal_size.y * p_projections[0].columns[1][1]);
+ push_constant.proj_info[2] = (1.0f - p_projections[0].columns[0][2]) / p_projections[0].columns[0][0];
+ push_constant.proj_info[3] = (1.0f + p_projections[0].columns[1][2]) / p_projections[0].columns[1][1];
+
+ bool use_sdfgi = p_render_buffers->has_custom_data(RB_SCOPE_SDFGI);
bool use_voxel_gi_instances = push_constant.max_voxel_gi_instances > 0;
- push_constant.cam_rotation[0] = p_transform.basis[0][0];
- push_constant.cam_rotation[1] = p_transform.basis[1][0];
- push_constant.cam_rotation[2] = p_transform.basis[2][0];
- push_constant.cam_rotation[3] = 0;
- push_constant.cam_rotation[4] = p_transform.basis[0][1];
- push_constant.cam_rotation[5] = p_transform.basis[1][1];
- push_constant.cam_rotation[6] = p_transform.basis[2][1];
- push_constant.cam_rotation[7] = 0;
- push_constant.cam_rotation[8] = p_transform.basis[0][2];
- push_constant.cam_rotation[9] = p_transform.basis[1][2];
- push_constant.cam_rotation[10] = p_transform.basis[2][2];
- push_constant.cam_rotation[11] = 0;
-
- if (rb->gi.uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->gi.uniform_set)) {
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 1;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.append_id(rb->sdfgi->cascades[j].sdf_tex);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ Ref<SDFGI> sdfgi;
+ if (use_sdfgi) {
+ sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI);
+ }
+
+ uint32_t pipeline_specialization = 0;
+ if (rbgi->using_half_size_gi) {
+ pipeline_specialization |= SHADER_SPECIALIZATION_HALF_RES;
+ }
+ if (p_view_count > 1) {
+ pipeline_specialization |= SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX;
+ }
+ bool has_vrs_texture = p_render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE);
+ if (has_vrs_texture) {
+ pipeline_specialization |= SHADER_SPECIALIZATION_USE_VRS;
+ }
+
+ Mode mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
+
+ for (uint32_t v = 0; v < p_view_count; v++) {
+ push_constant.view_index = v;
+
+ // setup our uniform set
+ if (rbgi->uniform_set[v].is_null() || !RD::get_singleton()->uniform_set_is_valid(rbgi->uniform_set[v])) {
+ Vector<RD::Uniform> uniforms;
+ {
+ RD::Uniform u;
+ u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (use_sdfgi && j < sdfgi->cascades.size()) {
+ u.append_id(sdfgi->cascades[j].sdf_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 2;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.append_id(rb->sdfgi->cascades[j].light_tex);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ {
+ RD::Uniform u;
+ u.binding = 2;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (use_sdfgi && j < sdfgi->cascades.size()) {
+ u.append_id(sdfgi->cascades[j].light_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 3;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.append_id(rb->sdfgi->cascades[j].light_aniso_0_tex);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ {
+ RD::Uniform u;
+ u.binding = 3;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (use_sdfgi && j < sdfgi->cascades.size()) {
+ u.append_id(sdfgi->cascades[j].light_aniso_0_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.binding = 4;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
- if (rb->sdfgi && j < rb->sdfgi->cascades.size()) {
- u.append_id(rb->sdfgi->cascades[j].light_aniso_1_tex);
+ {
+ RD::Uniform u;
+ u.binding = 4;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ for (uint32_t j = 0; j < SDFGI::MAX_CASCADES; j++) {
+ if (use_sdfgi && j < sdfgi->cascades.size()) {
+ u.append_id(sdfgi->cascades[j].light_aniso_1_tex);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
+ }
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 5;
+ if (use_sdfgi) {
+ u.append_id(sdfgi->occlusion_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE));
}
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 5;
- if (rb->sdfgi) {
- u.append_id(rb->sdfgi->occlusion_texture);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 6;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
+ u.binding = 7;
+ u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 6;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 7;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.append_id(rb->ambient_buffer);
- uniforms.push_back(u);
- }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 9;
+ u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_AMBIENT, v, 0));
+ uniforms.push_back(u);
+ }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 10;
- u.append_id(rb->reflection_buffer);
- uniforms.push_back(u);
- }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 10;
+ u.append_id(p_render_buffers->get_texture_slice(RB_SCOPE_GI, RB_TEX_REFLECTION, v, 0));
+ uniforms.push_back(u);
+ }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 11;
- if (rb->sdfgi) {
- u.append_id(rb->sdfgi->lightprobe_texture);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 11;
+ if (use_sdfgi) {
+ u.append_id(sdfgi->lightprobe_texture);
+ } else {
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE));
+ }
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 12;
- u.append_id(rb->depth_texture);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 13;
- u.append_id(p_normal_roughness_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 14;
- RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- u.append_id(buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 15;
- u.append_id(sdfgi_ubo);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 16;
- u.append_id(rb->gi.voxel_gi_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 17;
- for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
- u.append_id(rb->gi.voxel_gi_textures[i]);
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 12;
+ u.append_id(p_render_buffers->get_depth_texture(v));
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 13;
+ u.append_id(p_normal_roughness_slices[v]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 14;
+ RID buffer = p_voxel_gi_buffer.is_valid() ? p_voxel_gi_buffer : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(buffer);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 15;
+ u.append_id(sdfgi_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 16;
+ u.append_id(rbgi->get_voxel_gi_buffer());
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ u.binding = 17;
+ for (int i = 0; i < MAX_VOXEL_GI_INSTANCES; i++) {
+ u.append_id(rbgi->voxel_gi_textures[i]);
+ }
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.binding = 18;
+ u.append_id(rbgi->scene_data_ubo);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
+ u.binding = 19;
+ RID buffer = has_vrs_texture ? p_render_buffers->get_texture_slice(RB_SCOPE_VRS, RB_TEXTURE, v, 0) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_VRS);
+ u.append_id(buffer);
+ uniforms.push_back(u);
}
- uniforms.push_back(u);
- }
- rb->gi.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
- }
+ rbgi->uniform_set[v] = RD::get_singleton()->uniform_set_create(uniforms, shader.version_get_shader(shader_version, 0), 0);
+ }
- Mode mode;
+ RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[pipeline_specialization][mode]);
+ RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rbgi->uniform_set[v], 0);
+ RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
- if (rb->gi.using_half_size_gi) {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_HALF_RES_COMBINED : (use_sdfgi ? MODE_HALF_RES_SDFGI : MODE_HALF_RES_VOXEL_GI);
- } else {
- mode = (use_sdfgi && use_voxel_gi_instances) ? MODE_COMBINED : (use_sdfgi ? MODE_SDFGI : MODE_VOXEL_GI);
+ if (rbgi->using_half_size_gi) {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x >> 1, internal_size.y >> 1, 1);
+ } else {
+ RD::get_singleton()->compute_list_dispatch_threads(compute_list, internal_size.x, internal_size.y, 1);
+ }
}
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(true);
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, pipelines[mode]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->gi.uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));
-
- if (rb->gi.using_half_size_gi) {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width >> 1, rb->internal_height >> 1, 1);
- } else {
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->internal_width, rb->internal_height, 1);
- }
//do barrier later to allow oeverlap
//RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //no barriers, let other compute, raster and transfer happen at the same time
RD::get_singleton()->draw_command_end_label();
}
-RID RendererSceneGIRD::voxel_gi_instance_create(RID p_base) {
+RID GI::voxel_gi_instance_create(RID p_base) {
VoxelGIInstance voxel_gi;
voxel_gi.gi = this;
- voxel_gi.storage = storage;
voxel_gi.probe = p_base;
RID rid = voxel_gi_instance_owner.make_rid(voxel_gi);
return rid;
}
-void RendererSceneGIRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
- VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+void GI::voxel_gi_instance_free(RID p_rid) {
+ GI::VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_rid);
+ voxel_gi->free_resources();
+ voxel_gi_instance_owner.free(p_rid);
+}
+
+void GI::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
+ VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND(!voxel_gi);
voxel_gi->transform = p_xform;
}
-bool RendererSceneGIRD::voxel_gi_needs_update(RID p_probe) const {
- VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+bool GI::voxel_gi_needs_update(RID p_probe) const {
+ VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!voxel_gi, false);
- return voxel_gi->last_probe_version != storage->voxel_gi_get_version(voxel_gi->probe);
+ return voxel_gi->last_probe_version != voxel_gi_get_version(voxel_gi->probe);
}
-void RendererSceneGIRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render) {
- VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+void GI::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) {
+ VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND(!voxel_gi);
- voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects, p_scene_render);
+ voxel_gi->update(p_update_light_instances, p_light_instances, p_dynamic_objects);
}
-void RendererSceneGIRD::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
+void GI::debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) {
VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_voxel_gi);
ERR_FAIL_COND(!voxel_gi);
diff --git a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h b/servers/rendering/renderer_rd/environment/gi.h
index 122644498b..2182ca6a20 100644
--- a/servers/rendering/renderer_rd/renderer_scene_gi_rd.h
+++ b/servers/rendering/renderer_rd/environment/gi.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_gi_rd.h */
+/* gi.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,36 +28,139 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_GI_RD_H
-#define RENDERING_SERVER_SCENE_GI_RD_H
+#ifndef GI_RD_H
+#define GI_RD_H
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
+#include "servers/rendering/environment/renderer_gi.h"
#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/gi.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/voxel_gi.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl.gen.h"
+#include "servers/rendering/renderer_rd/environment/sky.h"
+#include "servers/rendering/renderer_rd/shaders/environment/gi.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/storage/utilities.h"
+
+#define RB_SCOPE_GI SNAME("rbgi")
+#define RB_SCOPE_SDFGI SNAME("sdfgi")
+
+#define RB_TEX_AMBIENT SNAME("ambient")
+#define RB_TEX_REFLECTION SNAME("reflection")
// Forward declare RenderDataRD and RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
struct RenderDataRD;
class RendererSceneRenderRD;
-class RendererSceneGIRD {
+namespace RendererRD {
+
+class GI : public RendererGI {
+public:
+ /* VOXEL GI STORAGE */
+
+ struct VoxelGI {
+ RID octree_buffer;
+ RID data_buffer;
+ RID sdf_texture;
+
+ uint32_t octree_buffer_size = 0;
+ uint32_t data_buffer_size = 0;
+
+ Vector<int> level_counts;
+
+ int cell_count = 0;
+
+ Transform3D to_cell_xform;
+ AABB bounds;
+ Vector3i octree_size;
+
+ float dynamic_range = 2.0;
+ float energy = 1.0;
+ float baked_exposure = 1.0;
+ float bias = 1.4;
+ float normal_bias = 0.0;
+ float propagation = 0.5;
+ bool interior = false;
+ bool use_two_bounces = true;
+
+ uint32_t version = 1;
+ uint32_t data_version = 1;
+
+ Dependency dependency;
+ };
+
+ /* VOXEL_GI INSTANCE */
+
+ //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
+
+ struct VoxelGIInstance {
+ // access to our containers
+ GI *gi = nullptr;
+
+ RID probe;
+ RID texture;
+ RID write_buffer;
+
+ struct Mipmap {
+ RID texture;
+ RID uniform_set;
+ RID second_bounce_uniform_set;
+ RID write_uniform_set;
+ uint32_t level;
+ uint32_t cell_offset;
+ uint32_t cell_count;
+ };
+ Vector<Mipmap> mipmaps;
+
+ struct DynamicMap {
+ RID texture; //color normally, or emission on first pass
+ RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
+ RID depth; //actual depth buffer for the first pass, float depth for later passes
+ RID normal; //normal buffer for the first pass
+ RID albedo; //emission buffer for the first pass
+ RID orm; //orm buffer for the first pass
+ RID fb; //used for rendering, only valid on first map
+ RID uniform_set;
+ uint32_t size;
+ int mipmap; // mipmap to write to, -1 if no mipmap assigned
+ };
+
+ Vector<DynamicMap> dynamic_maps;
+
+ int slot = -1;
+ uint32_t last_probe_version = 0;
+ uint32_t last_probe_data_version = 0;
+
+ //uint64_t last_pass = 0;
+ uint32_t render_index = 0;
+
+ bool has_dynamic_object_data = false;
+
+ Transform3D transform;
+
+ void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects);
+ void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ void free_resources();
+ };
+
private:
- RendererStorageRD *storage = nullptr;
+ static GI *singleton;
+
+ /* VOXEL GI STORAGE */
+
+ mutable RID_Owner<VoxelGI, true> voxel_gi_owner;
/* VOXEL_GI INSTANCE */
+ mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
+
struct VoxelGILight {
uint32_t type;
float energy;
@@ -193,13 +296,13 @@ private:
uint32_t max_cascades;
int32_t screen_size[2];
- uint32_t use_occlusion;
float y_mult;
- float cam_extent[3];
- uint32_t probe_axis_size;
+ float z_near;
- float cam_transform[16];
+ float inv_projection[3][4];
+ float cam_basis[3][3];
+ float cam_origin[3];
};
SdfgiDebugShaderRD debug;
@@ -209,13 +312,17 @@ private:
enum ProbeDebugMode {
PROBE_DEBUG_PROBES,
+ PROBE_DEBUG_PROBES_MULTIVIEW,
PROBE_DEBUG_VISIBILITY,
+ PROBE_DEBUG_VISIBILITY_MULTIVIEW,
PROBE_DEBUG_MAX
};
- struct DebugProbesPushConstant {
- float projection[16];
+ struct DebugProbesSceneData {
+ float projection[2][16];
+ };
+ struct DebugProbesPushConstant {
uint32_t band_power;
uint32_t sections_in_band;
uint32_t band_mask;
@@ -324,77 +431,122 @@ private:
} sdfgi_shader;
public:
- /* VOXEL_GI INSTANCE */
-
- //@TODO VoxelGIInstance is still directly used in the render code, we'll address this when we refactor the render code itself.
+ static GI *get_singleton() { return singleton; }
- struct VoxelGIInstance {
- // access to our containers
- RendererStorageRD *storage = nullptr;
- RendererSceneGIRD *gi = nullptr;
+ /* GI */
- RID probe;
- RID texture;
- RID write_buffer;
+ enum {
+ MAX_VOXEL_GI_INSTANCES = 8
+ };
- struct Mipmap {
- RID texture;
- RID uniform_set;
- RID second_bounce_uniform_set;
- RID write_uniform_set;
- uint32_t level;
- uint32_t cell_offset;
- uint32_t cell_count;
- };
- Vector<Mipmap> mipmaps;
+ // Struct for use in render buffer
+ class RenderBuffersGI : public RenderBufferCustomDataRD {
+ GDCLASS(RenderBuffersGI, RenderBufferCustomDataRD)
- struct DynamicMap {
- RID texture; //color normally, or emission on first pass
- RID fb_depth; //actual depth buffer for the first pass, float depth for later passes
- RID depth; //actual depth buffer for the first pass, float depth for later passes
- RID normal; //normal buffer for the first pass
- RID albedo; //emission buffer for the first pass
- RID orm; //orm buffer for the first pass
- RID fb; //used for rendering, only valid on first map
- RID uniform_set;
- uint32_t size;
- int mipmap; // mipmap to write to, -1 if no mipmap assigned
- };
+ private:
+ RID voxel_gi_buffer;
- Vector<DynamicMap> dynamic_maps;
+ public:
+ RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
- int slot = -1;
- uint32_t last_probe_version = 0;
- uint32_t last_probe_data_version = 0;
+ RID full_buffer;
+ RID full_dispatch;
+ RID full_mask;
- //uint64_t last_pass = 0;
- uint32_t render_index = 0;
+ /* GI buffers */
+ bool using_half_size_gi = false;
- bool has_dynamic_object_data = false;
+ RID uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID scene_data_ubo;
- Transform3D transform;
+ RID get_voxel_gi_buffer();
- void update(bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
- void debug(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
+ virtual void free_data() override;
};
- mutable RID_Owner<VoxelGIInstance> voxel_gi_instance_owner;
+ /* VOXEL GI API */
- _FORCE_INLINE_ VoxelGIInstance *get_probe_instance(RID p_probe) const {
- return voxel_gi_instance_owner.get_or_null(p_probe);
- };
+ bool owns_voxel_gi(RID p_rid) { return voxel_gi_owner.owns(p_rid); };
+
+ virtual RID voxel_gi_allocate() override;
+ virtual void voxel_gi_free(RID p_voxel_gi) override;
+ virtual void voxel_gi_initialize(RID p_voxel_gi) override;
+
+ virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) override;
+
+ virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const override;
+ virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const override;
+ virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const override;
+ virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const override;
+ virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const override;
+
+ virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const override;
+ virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_propagation(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) override;
+ virtual float voxel_gi_get_energy(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) override;
+ virtual float voxel_gi_get_baked_exposure_normalization(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) override;
+ virtual float voxel_gi_get_bias(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) override;
+ virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) override;
+ virtual bool voxel_gi_is_interior(RID p_voxel_gi) const override;
+
+ virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) override;
+ virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const override;
+
+ virtual uint32_t voxel_gi_get_version(RID p_probe) const override;
+ uint32_t voxel_gi_get_data_version(RID p_probe);
+
+ RID voxel_gi_get_octree_buffer(RID p_voxel_gi) const;
+ RID voxel_gi_get_data_buffer(RID p_voxel_gi) const;
+
+ RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
+
+ Dependency *voxel_gi_get_dependency(RID p_voxel_gi) const;
+
+ /* VOXEL_GI INSTANCE */
_FORCE_INLINE_ RID voxel_gi_instance_get_texture(RID p_probe) {
- VoxelGIInstance *voxel_gi = get_probe_instance(p_probe);
+ VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!voxel_gi, RID());
return voxel_gi->texture;
};
+ _FORCE_INLINE_ void voxel_gi_instance_set_render_index(RID p_probe, uint32_t p_index) {
+ VoxelGIInstance *voxel_gi = voxel_gi_instance_owner.get_or_null(p_probe);
+ ERR_FAIL_NULL(voxel_gi);
+
+ voxel_gi->render_index = p_index;
+ };
+
+ bool voxel_gi_instance_owns(RID p_rid) const {
+ return voxel_gi_instance_owner.owns(p_rid);
+ }
+
+ void voxel_gi_instance_free(RID p_rid);
+
RS::VoxelGIQuality voxel_gi_quality = RS::VOXEL_GI_QUALITY_LOW;
/* SDFGI */
- struct SDFGI {
+ class SDFGI : public RenderBufferCustomDataRD {
+ GDCLASS(SDFGI, RenderBufferCustomDataRD)
+
+ public:
enum {
MAX_CASCADES = 8,
CASCADE_SIZE = 128,
@@ -412,6 +564,7 @@ public:
float to_cell;
int32_t probe_offset[3];
uint32_t pad;
+ float pad2[4];
};
//cascade blocks are full-size for volume (128^3), half size for albedo/emission
@@ -444,18 +597,20 @@ public:
Vector3i dirty_regions; //(0,0,0 is not dirty, negative is refresh from the end, DIRTY_ALL is refresh all.
RID sdf_store_uniform_set;
- RID sdf_direct_light_uniform_set;
+ RID sdf_direct_light_static_uniform_set;
+ RID sdf_direct_light_dynamic_uniform_set;
RID scroll_uniform_set;
RID scroll_occlusion_uniform_set;
RID integrate_uniform_set;
RID lights_buffer;
+ float baked_exposure_normalization = 1.0;
+
bool all_dynamic_lights_dirty = true;
};
// access to our containers
- RendererStorageRD *storage = nullptr;
- RendererSceneGIRD *gi = nullptr;
+ GI *gi = nullptr;
// used for rendering (voxelization)
RID render_albedo;
@@ -497,7 +652,8 @@ public:
float min_cell_size = 0;
uint32_t probe_axis_count = 0; //amount of probes per axis, this is an odd number because it encloses endpoints
- RID debug_uniform_set;
+ RID debug_uniform_set[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID debug_probes_scene_data_ubo;
RID debug_probes_uniform_set;
RID cascades_ubo;
@@ -516,21 +672,24 @@ public:
int32_t cascade_dynamic_light_count[SDFGI::MAX_CASCADES]; //used dynamically
RID integrate_sky_uniform_set;
- void create(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, RendererSceneGIRD *p_gi);
- void erase();
- void update(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position);
+ virtual void configure(RenderSceneBuffersRD *p_render_buffers) override{};
+ virtual void free_data() override;
+ ~SDFGI();
+
+ void create(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size, GI *p_gi);
+ void update(RID p_env, const Vector3 &p_world_position);
void update_light();
- void update_probes(RendererSceneEnvironmentRD *p_env, RendererSceneSkyRD::Sky *p_sky);
+ void update_probes(RID p_env, RendererRD::SkyRD::Sky *p_sky);
void store_probes();
int get_pending_region_data(int p_region, Vector3i &r_local_offset, Vector3i &r_local_size, AABB &r_bounds) const;
void update_cascades();
- void debug_draw(const CameraMatrix &p_projection, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture);
- void debug_probes(RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
+ void debug_draw(uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, int p_width, int p_height, RID p_render_target, RID p_texture, const Vector<RID> &p_texture_views);
+ void debug_probes(RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
- void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data, RendererSceneRenderRD *p_scene_render);
- void render_region(RID p_render_buffers, int p_region, const PagedArray<RendererSceneRender::GeometryInstance *> &p_instances, RendererSceneRenderRD *p_scene_render);
- void render_static_lights(RID p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result, RendererSceneRenderRD *p_scene_render);
+ void pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_render_data);
+ void render_region(Ref<RenderSceneBuffersRD> p_render_buffers, int p_region, const PagedArray<RenderGeometryInstance *> &p_instances, float p_exposure_normalization);
+ void render_static_lights(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, uint32_t p_cascade_count, const uint32_t *p_cascade_indices, const PagedArray<RID> *p_positional_light_cull_result);
};
RS::EnvironmentSDFGIRayCount sdfgi_ray_count = RS::ENV_SDFGI_RAY_COUNT_16;
@@ -547,24 +706,6 @@ public:
int sdfgi_get_lightprobe_octahedron_size() const { return SDFGI::LIGHTPROBE_OCT_SIZE; }
- /* GI */
- enum {
- MAX_VOXEL_GI_INSTANCES = 8
- };
-
- // Struct for use in render buffer
- struct RenderBuffersGI {
- RID voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
- RID voxel_gi_buffer;
-
- RID full_buffer;
- RID full_dispatch;
- RID full_mask;
-
- RID uniform_set;
- bool using_half_size_gi = false;
- };
-
struct SDFGIData {
float grid_size[3];
uint32_t max_cascades;
@@ -594,6 +735,8 @@ public:
float to_probe; // 1/bounds * grid_size
int32_t probe_world_offset[3];
float to_cell; // 1/bounds * grid_size
+ float pad[3];
+ float exposure_normalization;
};
ProbeCascadeData cascades[SDFGI::MAX_CASCADES];
@@ -609,57 +752,76 @@ public:
float normal_bias; // 4 - 88
uint32_t blend_ambient; // 4 - 92
uint32_t mipmaps; // 4 - 96
+
+ float pad[3]; // 12 - 108
+ float exposure_normalization; // 4 - 112
};
- struct PushConstant {
- int32_t screen_size[2];
- float z_near;
- float z_far;
+ struct SceneData {
+ float inv_projection[2][16];
+ float cam_transform[16];
+ float eye_offset[2][4];
- float proj_info[4];
+ int32_t screen_size[2];
+ float pad1;
+ float pad2;
+ };
+ struct PushConstant {
uint32_t max_voxel_gi_instances;
uint32_t high_quality_vct;
uint32_t orthogonal;
- uint32_t pad;
+ uint32_t view_index;
- float cam_rotation[12];
+ float proj_info[4];
+
+ float z_near;
+ float z_far;
+ float pad2;
+ float pad3;
};
RID sdfgi_ubo;
+
enum Mode {
MODE_VOXEL_GI,
MODE_SDFGI,
MODE_COMBINED,
- MODE_HALF_RES_VOXEL_GI,
- MODE_HALF_RES_SDFGI,
- MODE_HALF_RES_COMBINED,
MODE_MAX
};
+ enum ShaderSpecializations {
+ SHADER_SPECIALIZATION_HALF_RES = 1 << 0,
+ SHADER_SPECIALIZATION_USE_FULL_PROJECTION_MATRIX = 1 << 1,
+ SHADER_SPECIALIZATION_USE_VRS = 1 << 2,
+ SHADER_SPECIALIZATION_VARIATIONS = 8,
+ };
+
RID default_voxel_gi_buffer;
bool half_resolution = false;
GiShaderRD shader;
RID shader_version;
- RID pipelines[MODE_MAX];
+ RID pipelines[SHADER_SPECIALIZATION_VARIATIONS][MODE_MAX];
- RendererSceneGIRD();
- ~RendererSceneGIRD();
+ GI();
+ ~GI();
- void init(RendererStorageRD *p_storage, RendererSceneSkyRD *p_sky);
+ void init(RendererRD::SkyRD *p_sky);
void free();
- SDFGI *create_sdfgi(RendererSceneEnvironmentRD *p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
+ Ref<SDFGI> create_sdfgi(RID p_env, const Vector3 &p_world_position, uint32_t p_requested_history_size);
- void setup_voxel_gi_instances(RID p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used, RendererSceneRenderRD *p_scene_render);
- void process_gi(RID p_render_buffers, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer, RID p_environment, const CameraMatrix &p_projection, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, RendererSceneRenderRD *p_scene_render);
+ void setup_voxel_gi_instances(RenderDataRD *p_render_data, Ref<RenderSceneBuffersRD> p_render_buffers, const Transform3D &p_transform, const PagedArray<RID> &p_voxel_gi_instances, uint32_t &r_voxel_gi_instances_used);
+ void process_gi(Ref<RenderSceneBuffersRD> p_render_buffers, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer, RID p_environment, uint32_t p_view_count, const Projection *p_projections, const Vector3 *p_eye_offsets, const Transform3D &p_cam_transform, const PagedArray<RID> &p_voxel_gi_instances);
RID voxel_gi_instance_create(RID p_base);
void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform);
bool voxel_gi_needs_update(RID p_probe) const;
- void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects, RendererSceneRenderRD *p_scene_render);
- void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
+ void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects);
+ void debug_voxel_gi(RID p_voxel_gi, RD::DrawListID p_draw_list, RID p_framebuffer, const Projection &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha);
};
-#endif /* !RENDERING_SERVER_SCENE_GI_RD_H */
+} // namespace RendererRD
+
+#endif // GI_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp b/servers/rendering/renderer_rd/environment/sky.cpp
index 3a237dbd8c..0acd48c22a 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.cpp
+++ b/servers/rendering/renderer_rd/environment/sky.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_sky_rd.cpp */
+/* sky.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,20 +28,28 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_scene_sky_rd.h"
+#include "sky.h"
#include "core/config/project_settings.h"
#include "core/math/math_defs.h"
-#include "renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/rendering_server_globals.h"
+
+using namespace RendererRD;
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
-void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
+void SkyRD::SkyShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
+void SkyRD::SkyShaderData::set_code(const String &p_code) {
//compile
code = p_code;
@@ -107,12 +115,16 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- // print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- // print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
scene_singleton->sky.sky_shader.shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
@@ -140,7 +152,7 @@ void RendererSceneSkyRD::SkyShaderData::set_code(const String &p_code) {
valid = true;
}
-void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void SkyRD::SkyShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -157,7 +169,7 @@ void RendererSceneSkyRD::SkyShaderData::set_default_texture_param(const StringNa
}
}
-void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SkyRD::SkyShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -171,15 +183,29 @@ void RendererSceneSkyRD::SkyShaderData::get_param_list(List<PropertyInfo> *p_par
order[E.value.order] = E.key;
}
}
-
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
}
}
-void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
+void SkyRD::SkyShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
continue;
@@ -194,7 +220,7 @@ void RendererSceneSkyRD::SkyShaderData::get_instance_param_list(List<RendererMat
}
}
-bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_param) const {
+bool SkyRD::SkyShaderData::is_parameter_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -202,15 +228,15 @@ bool RendererSceneSkyRD::SkyShaderData::is_param_texture(const StringName &p_par
return uniforms[p_param].texture_order >= 0;
}
-bool RendererSceneSkyRD::SkyShaderData::is_animated() const {
+bool SkyRD::SkyShaderData::is_animated() const {
return false;
}
-bool RendererSceneSkyRD::SkyShaderData::casts_shadows() const {
+bool SkyRD::SkyShaderData::casts_shadows() const {
return false;
}
-Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
+Variant SkyRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const {
if (uniforms.has(p_parameter)) {
ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
@@ -219,13 +245,13 @@ Variant RendererSceneSkyRD::SkyShaderData::get_default_parameter(const StringNam
return Variant();
}
-RS::ShaderNativeSourceCode RendererSceneSkyRD::SkyShaderData::get_native_source_code() const {
+RS::ShaderNativeSourceCode SkyRD::SkyShaderData::get_native_source_code() const {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
return scene_singleton->sky.sky_shader.shader.version_get_native_source_code(version);
}
-RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
+SkyRD::SkyShaderData::~SkyShaderData() {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
ERR_FAIL_COND(!scene_singleton);
//pipeline variants will clear themselves if shader is gone
@@ -237,15 +263,15 @@ RendererSceneSkyRD::SkyShaderData::~SkyShaderData() {
////////////////////////////////////////////////////////////////////////////////
// Sky material
-bool RendererSceneSkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+bool SkyRD::SkyMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
uniform_set_updated = true;
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->sky.sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL, true);
}
-RendererSceneSkyRD::SkyMaterialData::~SkyMaterialData() {
+SkyRD::SkyMaterialData::~SkyMaterialData() {
free_parameters_uniform_set(uniform_set);
}
@@ -267,22 +293,21 @@ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_ar
p_array[11] = 0;
}
-void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier) {
+void SkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier) {
SkyPushConstant sky_push_constant;
memset(&sky_push_constant, 0, sizeof(SkyPushConstant));
for (uint32_t v = 0; v < p_view_count; v++) {
// We only need key components of our projection matrix
- sky_push_constant.projections[v][0] = p_projections[v].matrix[2][0];
- sky_push_constant.projections[v][1] = p_projections[v].matrix[0][0];
- sky_push_constant.projections[v][2] = p_projections[v].matrix[2][1];
- sky_push_constant.projections[v][3] = p_projections[v].matrix[1][1];
+ sky_push_constant.projections[v][0] = p_projections[v].columns[2][0];
+ sky_push_constant.projections[v][1] = p_projections[v].columns[0][0];
+ sky_push_constant.projections[v][2] = p_projections[v].columns[2][1];
+ sky_push_constant.projections[v][3] = p_projections[v].columns[1][1];
}
sky_push_constant.position[0] = p_position.x;
sky_push_constant.position[1] = p_position.y;
sky_push_constant.position[2] = p_position.z;
- sky_push_constant.multiplier = p_multiplier;
sky_push_constant.time = p_time;
sky_push_constant.luminance_multiplier = p_luminance_multiplier;
store_transform_3x3(p_orientation, sky_push_constant.orientation);
@@ -318,7 +343,7 @@ void RendererSceneSkyRD::_render_sky(RD::DrawListID p_list, float p_time, RID p_
////////////////////////////////////////////////////////////////////////////////
// ReflectionData
-void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
+void SkyRD::ReflectionData::clear_reflection_data() {
layers.clear();
radiance_base_cubemap = RID();
if (downsampled_radiance_cubemap.is_valid()) {
@@ -329,14 +354,14 @@ void RendererSceneSkyRD::ReflectionData::clear_reflection_data() {
coefficient_buffer = RID();
}
-void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
+void SkyRD::ReflectionData::update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format) {
//recreate radiance and all data
int mipmaps = p_mipmaps;
uint32_t w = p_size, h = p_size;
- EffectsRD *effects = p_storage->get_effects();
- ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
+ EffectsRD *effects = RendererCompositorRD::singleton->get_effects();
+ ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialized");
bool prefer_raster_effects = effects->get_prefer_raster_effects();
if (p_use_array) {
@@ -398,21 +423,22 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, 1, RD::TEXTURE_SLICE_CUBEMAP);
RD::get_singleton()->set_resource_name(radiance_base_cubemap, "radiance base cubemap");
+
RD::TextureFormat tf;
tf.format = p_texture_format;
- tf.width = 64; // Always 64x64
- tf.height = 64;
+ tf.width = p_low_quality ? 64 : p_size >> 1; // Always 64x64 when using REALTIME.
+ tf.height = p_low_quality ? 64 : p_size >> 1;
tf.texture_type = RD::TEXTURE_TYPE_CUBE;
tf.array_layers = 6;
- tf.mipmaps = 7;
+ tf.mipmaps = p_low_quality ? 7 : mipmaps - 1;
tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
RD::get_singleton()->set_resource_name(downsampled_radiance_cubemap, "downsampled radiance cubemap");
{
- uint32_t mmw = 64;
- uint32_t mmh = 64;
- downsampled_layer.mipmaps.resize(7);
+ uint32_t mmw = tf.width;
+ uint32_t mmh = tf.height;
+ downsampled_layer.mipmaps.resize(tf.mipmaps);
for (int j = 0; j < downsampled_layer.mipmaps.size(); j++) {
ReflectionData::DownsampleLayer::Mipmap &mm = downsampled_layer.mipmaps.write[j];
mm.size.width = mmw;
@@ -437,20 +463,20 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_data(RendererStorageR
}
}
-void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays) {
- EffectsRD *effects = p_storage->get_effects();
- ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
- bool prefer_raster_effects = effects->get_prefer_raster_effects();
+void SkyRD::ReflectionData::create_reflection_fast_filter(bool p_use_arrays) {
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+ ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized");
+ bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
if (prefer_raster_effects) {
RD::get_singleton()->draw_command_begin_label("Downsample radiance map");
for (int k = 0; k < 6; k++) {
- effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size);
+ copy_effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size);
}
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
for (int k = 0; k < 6; k++) {
- effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size);
+ copy_effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size);
}
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
@@ -459,24 +485,24 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererS
RD::get_singleton()->draw_command_begin_label("filter radiance map into array heads");
for (int i = 0; i < layers.size(); i++) {
for (int k = 0; k < 6; k++) {
- effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[i].mipmaps[0].framebuffers[k], k, i);
+ copy_effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[i].mipmaps[0].framebuffers[k], k, i);
}
}
} else {
RD::get_singleton()->draw_command_begin_label("filter radiance map into mipmaps directly");
for (int j = 0; j < layers[0].mipmaps.size(); j++) {
for (int k = 0; k < 6; k++) {
- effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[0].mipmaps[j].framebuffers[k], k, j);
+ copy_effects->cubemap_filter_raster(downsampled_radiance_cubemap, layers[0].mipmaps[j].framebuffers[k], k, j);
}
}
}
RD::get_singleton()->draw_command_end_label(); // Filter radiance
} else {
RD::get_singleton()->draw_command_begin_label("Downsample radiance map");
- effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
+ copy_effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
- effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
+ copy_effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
Vector<RID> views;
@@ -490,26 +516,26 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_fast_filter(RendererS
}
}
RD::get_singleton()->draw_command_begin_label("Fast filter radiance");
- effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
+ copy_effects->cubemap_filter(downsampled_radiance_cubemap, views, p_use_arrays);
RD::get_singleton()->draw_command_end_label(); // Filter radiance
}
}
-void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
- EffectsRD *effects = p_storage->get_effects();
- ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
- bool prefer_raster_effects = effects->get_prefer_raster_effects();
+void SkyRD::ReflectionData::create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality) {
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+ ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized");
+ bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
if (prefer_raster_effects) {
if (p_base_layer == 1) {
RD::get_singleton()->draw_command_begin_label("Downsample radiance map");
for (int k = 0; k < 6; k++) {
- effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size);
+ copy_effects->cubemap_downsample_raster(radiance_base_cubemap, downsampled_layer.mipmaps[0].framebuffers[k], k, downsampled_layer.mipmaps[0].size);
}
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
for (int k = 0; k < 6; k++) {
- effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size);
+ copy_effects->cubemap_downsample_raster(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].framebuffers[k], k, downsampled_layer.mipmaps[i].size);
}
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
@@ -518,7 +544,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren
RD::get_singleton()->draw_command_begin_label("High Quality filter radiance");
if (p_use_arrays) {
for (int k = 0; k < 6; k++) {
- effects->cubemap_roughness_raster(
+ copy_effects->cubemap_roughness_raster(
downsampled_radiance_cubemap,
layers[p_base_layer].mipmaps[0].framebuffers[k],
k,
@@ -528,7 +554,7 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren
}
} else {
for (int k = 0; k < 6; k++) {
- effects->cubemap_roughness_raster(
+ copy_effects->cubemap_roughness_raster(
downsampled_radiance_cubemap,
layers[0].mipmaps[p_base_layer].framebuffers[k],
k,
@@ -540,19 +566,19 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren
} else {
if (p_base_layer == 1) {
RD::get_singleton()->draw_command_begin_label("Downsample radiance map");
- effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
+ copy_effects->cubemap_downsample(radiance_base_cubemap, downsampled_layer.mipmaps[0].view, downsampled_layer.mipmaps[0].size);
for (int i = 1; i < downsampled_layer.mipmaps.size(); i++) {
- effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
+ copy_effects->cubemap_downsample(downsampled_layer.mipmaps[i - 1].view, downsampled_layer.mipmaps[i].view, downsampled_layer.mipmaps[i].size);
}
RD::get_singleton()->draw_command_end_label(); // Downsample Radiance
}
RD::get_singleton()->draw_command_begin_label("High Quality filter radiance");
if (p_use_arrays) {
- effects->cubemap_roughness(downsampled_radiance_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
+ copy_effects->cubemap_roughness(downsampled_radiance_cubemap, layers[p_base_layer].views[0], p_cube_side, p_sky_ggx_samples_quality, float(p_base_layer) / (layers.size() - 1.0), layers[p_base_layer].mipmaps[0].size.x);
} else {
- effects->cubemap_roughness(
+ copy_effects->cubemap_roughness(
downsampled_radiance_cubemap,
layers[0].views[p_base_layer],
p_cube_side,
@@ -564,10 +590,10 @@ void RendererSceneSkyRD::ReflectionData::create_reflection_importance_sample(Ren
RD::get_singleton()->draw_command_end_label(); // Filter radiance
}
-void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end) {
- EffectsRD *effects = p_storage->get_effects();
- ERR_FAIL_NULL_MSG(effects, "Effects haven't been initialised");
- bool prefer_raster_effects = effects->get_prefer_raster_effects();
+void SkyRD::ReflectionData::update_reflection_mipmaps(int p_start, int p_end) {
+ RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+ ERR_FAIL_NULL_MSG(copy_effects, "Effects haven't been initialized");
+ bool prefer_raster_effects = copy_effects->get_prefer_raster_effects();
RD::get_singleton()->draw_command_begin_label("Update Radiance Cubemap Array Mipmaps");
for (int i = p_start; i < p_end; i++) {
@@ -577,11 +603,11 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStora
if (prefer_raster_effects) {
for (int k = 0; k < 6; k++) {
RID framebuffer = layers[i].mipmaps[j + 1].framebuffers[k];
- effects->cubemap_downsample_raster(view, framebuffer, k, size);
+ copy_effects->cubemap_downsample_raster(view, framebuffer, k, size);
}
} else {
RID texture = layers[i].views[j + 1];
- effects->cubemap_downsample(view, texture, size);
+ copy_effects->cubemap_downsample(view, texture, size);
}
}
}
@@ -589,9 +615,9 @@ void RendererSceneSkyRD::ReflectionData::update_reflection_mipmaps(RendererStora
}
////////////////////////////////////////////////////////////////////////////////
-// RendererSceneSkyRD::Sky
+// SkyRD::Sky
-void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
+void SkyRD::Sky::free() {
if (radiance.is_valid()) {
RD::get_singleton()->free(radiance);
radiance = RID();
@@ -614,12 +640,12 @@ void RendererSceneSkyRD::Sky::free(RendererStorageRD *p_storage) {
}
if (material.is_valid()) {
- p_storage->free(material);
+ RSG::material_storage->material_free(material);
material = RID();
}
}
-RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd) {
+RID SkyRD::Sky::get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
if (texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(texture_uniform_sets[p_version])) {
@@ -633,7 +659,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
if (radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) {
u.append_id(radiance);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
uniforms.push_back(u);
}
@@ -649,9 +675,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
}
} else {
if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
}
uniforms.push_back(u);
@@ -668,9 +694,9 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
}
} else {
if (p_version < SKY_TEXTURE_SET_CUBEMAP) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
}
}
uniforms.push_back(u);
@@ -680,7 +706,7 @@ RID RendererSceneSkyRD::Sky::get_textures(RendererStorageRD *p_storage, SkyTextu
return texture_uniform_sets[p_version];
}
-bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) {
+bool SkyRD::Sky::set_radiance_size(int p_radiance_size) {
ERR_FAIL_COND_V(p_radiance_size < 32 || p_radiance_size > 2048, false);
if (radiance_size == p_radiance_size) {
return false;
@@ -701,7 +727,7 @@ bool RendererSceneSkyRD::Sky::set_radiance_size(int p_radiance_size) {
return true;
}
-bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) {
+bool SkyRD::Sky::set_mode(RS::SkyMode p_mode) {
if (mode == p_mode) {
return false;
}
@@ -722,7 +748,7 @@ bool RendererSceneSkyRD::Sky::set_mode(RS::SkyMode p_mode) {
return true;
}
-bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
+bool SkyRD::Sky::set_material(RID p_material) {
if (material == p_material) {
return false;
}
@@ -731,12 +757,12 @@ bool RendererSceneSkyRD::Sky::set_material(RID p_material) {
return true;
}
-Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
+Ref<Image> SkyRD::Sky::bake_panorama(float p_energy, int p_roughness_layers, const Size2i &p_size) {
if (radiance.is_valid()) {
RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;
+ tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; // Could be RGBA16
tf.width = p_size.width;
tf.height = p_size.height;
tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
@@ -746,9 +772,7 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughnes
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(rad_tex, 0);
RD::get_singleton()->free(rad_tex);
- Ref<Image> img;
- img.instantiate();
- img->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data);
+ Ref<Image> img = Image::create_from_data(p_size.width, p_size.height, false, Image::FORMAT_RGBAF, data);
for (int i = 0; i < p_size.width; i++) {
for (int j = 0; j < p_size.height; j++) {
Color c = img->get_pixel(i, j);
@@ -765,40 +789,39 @@ Ref<Image> RendererSceneSkyRD::Sky::bake_panorama(float p_energy, int p_roughnes
}
////////////////////////////////////////////////////////////////////////////////
-// RendererSceneSkyRD
+// SkyRD
-RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_func() {
+RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_func() {
SkyShaderData *shader_data = memnew(SkyShaderData);
return shader_data;
}
-RendererRD::ShaderData *RendererSceneSkyRD::_create_sky_shader_funcs() {
+RendererRD::MaterialStorage::ShaderData *SkyRD::_create_sky_shader_funcs() {
// !BAS! Why isn't _create_sky_shader_func not just static too?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_shader_func();
};
-RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_func(SkyShaderData *p_shader) {
SkyMaterialData *material_data = memnew(SkyMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
}
-RendererRD::MaterialData *RendererSceneSkyRD::_create_sky_material_funcs(RendererRD::ShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SkyRD::_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
// !BAS! same here, we could just make _create_sky_material_func static?
return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->sky._create_sky_material_func(static_cast<SkyShaderData *>(p_shader));
};
-RendererSceneSkyRD::RendererSceneSkyRD() {
+SkyRD::SkyRD() {
roughness_layers = GLOBAL_GET("rendering/reflections/sky_reflections/roughness_layers");
sky_ggx_samples_quality = GLOBAL_GET("rendering/reflections/sky_reflections/ggx_samples");
sky_use_cubemap_array = GLOBAL_GET("rendering/reflections/sky_reflections/texture_array_reflections");
}
-void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
+void SkyRD::init() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
{
// Start with the directional lights for the sky
@@ -834,8 +857,8 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
}
// register our shader funds
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_SKY, _create_sky_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_SKY, _create_sky_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -843,7 +866,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
actions.renames["COLOR"] = "color";
actions.renames["ALPHA"] = "alpha";
actions.renames["EYEDIR"] = "cube_normal";
- actions.renames["POSITION"] = "params.position_multiplier.xyz";
+ actions.renames["POSITION"] = "params.position";
actions.renames["SKY_COORDS"] = "panorama_coords";
actions.renames["SCREEN_UV"] = "uv";
actions.renames["FRAGCOORD"] = "gl_FragCoord";
@@ -882,6 +905,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n";
actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n";
actions.render_mode_defines["disable_fog"] = "#define DISABLE_FOG\n";
+ actions.render_mode_defines["use_debanding"] = "#define USE_DEBANDING\n";
actions.sampler_array_name = "material_samplers";
actions.base_texture_binding_index = 1;
@@ -891,7 +915,7 @@ void RendererSceneSkyRD::init(RendererStorageRD *p_storage) {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
sky_shader.compiler.initialize(actions);
}
@@ -916,7 +940,7 @@ void sky() {
material_storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader);
- SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY));
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND);
sky_scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkySceneState::UBO));
@@ -949,7 +973,7 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 1;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -978,7 +1002,7 @@ void sky() {
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
u.append_id(vfog);
uniforms.push_back(u);
}
@@ -1012,21 +1036,21 @@ void sky() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 0;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 1;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.binding = 2;
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE));
uniforms.push_back(u);
}
@@ -1051,15 +1075,15 @@ void sky() {
}
}
-void RendererSceneSkyRD::set_texture_format(RD::DataFormat p_texture_format) {
+void SkyRD::set_texture_format(RD::DataFormat p_texture_format) {
texture_format = p_texture_format;
}
-RendererSceneSkyRD::~RendererSceneSkyRD() {
+SkyRD::~SkyRD() {
// cleanup anything created in init...
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::SHADER_TYPE_SKY));
+ SkyMaterialData *md = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
sky_shader.shader.version_free(md->shader_data->version);
RD::get_singleton()->free(sky_scene_state.directional_light_buffer);
RD::get_singleton()->free(sky_scene_state.uniform_buffer);
@@ -1085,23 +1109,23 @@ RendererSceneSkyRD::~RendererSceneSkyRD() {
RD::get_singleton()->free(index_buffer); //array gets freed as dependency
}
-void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
+void SkyRD::setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
SkyMaterialData *material = nullptr;
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
RID sky_material;
SkyShaderData *shader_data = nullptr;
if (sky) {
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1109,7 +1133,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1174,18 +1198,17 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
// This can't be done in RenderSceneRenderRD::_setup lights because that needs to be called
// after the depth prepass, but this runs before the depth prepass
for (int i = 0; i < (int)p_lights.size(); i++) {
- RendererSceneRenderRD::LightInstance *li = p_scene_render->light_instance_owner.get_or_null(p_lights[i]);
- if (!li) {
+ if (!light_storage->owns_light_instance(p_lights[i])) {
continue;
}
- RID base = li->light;
+ RID base = light_storage->light_instance_get_base_light(p_lights[i]);
ERR_CONTINUE(base.is_null());
RS::LightType type = light_storage->light_get_type(base);
if (type == RS::LIGHT_DIRECTIONAL && light_storage->light_directional_get_sky_mode(base) != RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY) {
SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.ubo.directional_light_count];
- Transform3D light_transform = li->transform;
+ Transform3D light_transform = light_storage->light_instance_get_base_transform(p_lights[i]);
Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized();
sky_light_data.direction[0] = world_direction.x;
@@ -1195,6 +1218,14 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
float sign = light_storage->light_is_negative(base) ? -1 : 1;
sky_light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY);
+ if (p_scene_render->is_using_physical_light_units()) {
+ sky_light_data.energy *= light_storage->light_get_param(base, RS::LIGHT_PARAM_INTENSITY);
+ }
+
+ if (p_camera_attributes.is_valid()) {
+ sky_light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes);
+ }
+
Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
sky_light_data.color[0] = linear_col.r;
sky_light_data.color[1] = linear_col.g;
@@ -1207,7 +1238,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
// I know tan(0) is 0, but let's not risk it with numerical precision.
// technically this will keep expanding until reaching the sun, but all we care
// is expand until we reach the radius of the near plane (there can't be more occluders than that)
- angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
+ angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));
} else {
angular_diameter = 0.0;
}
@@ -1227,6 +1258,7 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
light_data_dirty = true;
for (uint32_t i = sky_scene_state.ubo.directional_light_count; i < sky_scene_state.max_directional_lights; i++) {
sky_scene_state.directional_lights[i].enabled = false;
+ sky_scene_state.last_frame_directional_lights[i].enabled = false;
}
}
@@ -1262,54 +1294,58 @@ void RendererSceneSkyRD::setup(RendererSceneEnvironmentRD *p_env, RID p_render_b
//setup fog variables
sky_scene_state.ubo.volumetric_fog_enabled = false;
if (p_render_buffers.is_valid()) {
- if (p_scene_render->render_buffers_has_volumetric_fog(p_render_buffers)) {
+ if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+ Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
sky_scene_state.ubo.volumetric_fog_enabled = true;
- float fog_end = p_scene_render->render_buffers_get_volumetric_fog_end(p_render_buffers);
+ float fog_end = fog->length;
if (fog_end > 0.0) {
sky_scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
} else {
sky_scene_state.ubo.volumetric_fog_inv_length = 1.0;
}
- float fog_detail_spread = p_scene_render->render_buffers_get_volumetric_fog_detail_spread(p_render_buffers); //reverse lookup
+ float fog_detail_spread = fog->spread; //reverse lookup
if (fog_detail_spread > 0.0) {
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
} else {
sky_scene_state.ubo.volumetric_fog_detail_spread = 1.0;
}
- sky_scene_state.fog_uniform_set = p_scene_render->render_buffers_get_volumetric_fog_sky_uniform_set(p_render_buffers);
+ sky_scene_state.fog_uniform_set = fog->sky_uniform_set;
}
}
sky_scene_state.ubo.z_far = p_projection.get_z_far();
- sky_scene_state.ubo.fog_enabled = p_env->fog_enabled;
- sky_scene_state.ubo.fog_density = p_env->fog_density;
- sky_scene_state.ubo.fog_aerial_perspective = p_env->fog_aerial_perspective;
- Color fog_color = p_env->fog_light_color.srgb_to_linear();
- float fog_energy = p_env->fog_light_energy;
+ sky_scene_state.ubo.fog_enabled = RendererSceneRenderRD::get_singleton()->environment_get_fog_enabled(p_env);
+ sky_scene_state.ubo.fog_density = RendererSceneRenderRD::get_singleton()->environment_get_fog_density(p_env);
+ sky_scene_state.ubo.fog_aerial_perspective = RendererSceneRenderRD::get_singleton()->environment_get_fog_aerial_perspective(p_env);
+ Color fog_color = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_color(p_env).srgb_to_linear();
+ float fog_energy = RendererSceneRenderRD::get_singleton()->environment_get_fog_light_energy(p_env);
sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
sky_scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
sky_scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
- sky_scene_state.ubo.fog_sun_scatter = p_env->fog_sun_scatter;
+ sky_scene_state.ubo.fog_sun_scatter = RendererSceneRenderRD::get_singleton()->environment_get_fog_sun_scatter(p_env);
+
+ sky_scene_state.ubo.fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_fog_sky_affect(p_env);
+ sky_scene_state.ubo.volumetric_fog_sky_affect = RendererSceneRenderRD::get_singleton()->environment_get_volumetric_fog_sky_affect(p_env);
RD::get_singleton()->buffer_update(sky_scene_state.uniform_buffer, 0, sizeof(SkySceneState::UBO), &sky_scene_state.ubo);
}
-void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
ERR_FAIL_COND(!sky);
- RID sky_material = sky_get_material(p_env->sky);
+ RID sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1317,7 +1353,7 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1326,8 +1362,6 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
ERR_FAIL_COND(!shader_data);
- float multiplier = p_env->bg_energy;
-
bool update_single_frame = sky->mode == RS::SKY_MODE_REALTIME || sky->mode == RS::SKY_MODE_QUALITY;
RS::SkyMode sky_mode = sky->mode;
@@ -1371,9 +1405,9 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
Vector3(0, -1, 0)
};
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, 0.01, 10.0);
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
cm = correction * cm;
@@ -1387,10 +1421,10 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1406,10 +1440,10 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP_HALF_RES, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
@@ -1421,44 +1455,44 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
RD::get_singleton()->draw_command_begin_label("Render Sky Cubemap");
for (int i = 0; i < 6; i++) {
Basis local_view = Basis::looking_at(view_normals[i], view_up[i]);
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_CUBEMAP, sky_shader.default_shader_rd);
cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD);
- _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, multiplier, p_transform.origin, p_luminance_multiplier);
+ _render_sky(cubemap_draw_list, p_time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], pipeline, material->uniform_set, texture_uniform_set, 1, &cm, local_view, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
RD::get_singleton()->draw_command_end_label();
if (sky_mode == RS::SKY_MODE_REALTIME) {
- sky->reflection.create_reflection_fast_filter(storage, sky_use_cubemap_array);
+ sky->reflection.create_reflection_fast_filter(sky_use_cubemap_array);
if (sky_use_cubemap_array) {
- sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size());
+ sky->reflection.update_reflection_mipmaps(0, sky->reflection.layers.size());
}
} else {
if (update_single_frame) {
for (int i = 1; i < max_processing_layer; i++) {
- sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, i, sky_ggx_samples_quality);
+ sky->reflection.create_reflection_importance_sample(sky_use_cubemap_array, 10, i, sky_ggx_samples_quality);
}
if (sky_use_cubemap_array) {
- sky->reflection.update_reflection_mipmaps(storage, 0, sky->reflection.layers.size());
+ sky->reflection.update_reflection_mipmaps(0, sky->reflection.layers.size());
}
} else {
if (sky_use_cubemap_array) {
// Multi-Frame so just update the first array level
- sky->reflection.update_reflection_mipmaps(storage, 0, 1);
+ sky->reflection.update_reflection_mipmaps(0, 1);
}
}
sky->processing_layer = 1;
}
-
+ sky->baked_exposure = p_luminance_multiplier;
sky->reflection.dirty = false;
} else {
if (sky_mode == RS::SKY_MODE_INCREMENTAL && sky->processing_layer < max_processing_layer) {
- sky->reflection.create_reflection_importance_sample(storage, sky_use_cubemap_array, 10, sky->processing_layer, sky_ggx_samples_quality);
+ sky->reflection.create_reflection_importance_sample(sky_use_cubemap_array, 10, sky->processing_layer, sky_ggx_samples_quality);
if (sky_use_cubemap_array) {
- sky->reflection.update_reflection_mipmaps(storage, sky->processing_layer, sky->processing_layer + 1);
+ sky->reflection.update_reflection_mipmaps(sky->processing_layer, sky->processing_layer + 1);
}
sky->processing_layer++;
@@ -1466,26 +1500,26 @@ void RendererSceneSkyRD::update(RendererSceneEnvironmentRD *p_env, const CameraM
}
}
-void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time) {
+void SkyRD::draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
ERR_FAIL_COND(p_view_count == 0);
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
RID sky_material;
- RS::EnvironmentBG background = p_env->background;
+ RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env);
if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
ERR_FAIL_COND(!sky);
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1493,13 +1527,13 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1508,16 +1542,15 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
ERR_FAIL_COND(!shader_data);
- Basis sky_transform = p_env->sky_orientation;
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
- float multiplier = p_env->bg_energy;
- float custom_fov = p_env->sky_custom_fov;
+ float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1536,26 +1569,26 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
if (shader_data->uses_quarter_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
if (shader_data->uses_half_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
@@ -1563,33 +1596,33 @@ void RendererSceneSkyRD::draw(RendererSceneEnvironmentRD *p_env, bool p_can_cont
RID texture_uniform_set;
if (sky) {
- texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
+ texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
} else {
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, 1.0);
+ _render_sky(draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
-void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
ERR_FAIL_COND(p_view_count == 0);
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
ERR_FAIL_COND(!sky);
SkyMaterialData *material = nullptr;
RID sky_material;
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1597,7 +1630,7 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1606,16 +1639,15 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
ERR_FAIL_COND(!shader_data);
- Basis sky_transform = p_env->sky_orientation;
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
- float multiplier = p_env->bg_energy;
- float custom_fov = p_env->sky_custom_fov;
+ float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1634,50 +1666,50 @@ void RendererSceneSkyRD::update_res_buffers(RendererSceneEnvironmentRD *p_env, u
if (shader_data->uses_quarter_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_QUARTER_RES_MULTIVIEW : SKY_VERSION_QUARTER_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_QUARTER_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
+ _render_sky(draw_list, p_time, sky->quarter_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
if (shader_data->uses_half_res) {
PipelineCacheRD *pipeline = &shader_data->pipelines[view_count > 1 ? SKY_VERSION_HALF_RES_MULTIVIEW : SKY_VERSION_HALF_RES];
- RID texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
+ RID texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_HALF_RES, sky_shader.default_shader_rd);
Vector<Color> clear_colors;
clear_colors.push_back(Color(0.0, 0.0, 0.0));
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors);
- _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
+ _render_sky(draw_list, p_time, sky->half_res_framebuffer, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
RD::get_singleton()->draw_list_end();
}
}
-void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
+void SkyRD::draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- ERR_FAIL_COND(!p_env);
+ ERR_FAIL_COND(p_env.is_null());
ERR_FAIL_COND(p_view_count == 0);
ERR_FAIL_COND(p_view_count > RendererSceneRender::MAX_RENDER_VIEWS);
- Sky *sky = get_sky(p_env->sky);
+ Sky *sky = get_sky(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
SkyMaterialData *material = nullptr;
RID sky_material;
- RS::EnvironmentBG background = p_env->background;
+ RS::EnvironmentBG background = RendererSceneRenderRD::get_singleton()->environment_get_background(p_env);
if (!(background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) || sky) {
ERR_FAIL_COND(!sky);
- sky_material = sky_get_material(p_env->sky);
+ sky_material = sky_get_material(RendererSceneRenderRD::get_singleton()->environment_get_sky(p_env));
if (sky_material.is_valid()) {
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -1685,13 +1717,13 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
if (!material) {
sky_material = sky_shader.default_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
}
if (background == RS::ENV_BG_CLEAR_COLOR || background == RS::ENV_BG_COLOR) {
sky_material = sky_scene_state.fog_material;
- material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::SHADER_TYPE_SKY));
+ material = static_cast<SkyMaterialData *>(material_storage->material_get_data(sky_material, RendererRD::MaterialStorage::SHADER_TYPE_SKY));
}
ERR_FAIL_COND(!material);
@@ -1700,16 +1732,15 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
ERR_FAIL_COND(!shader_data);
- Basis sky_transform = p_env->sky_orientation;
+ Basis sky_transform = RendererSceneRenderRD::get_singleton()->environment_get_sky_orientation(p_env);
sky_transform.invert();
- float multiplier = p_env->bg_energy;
- float custom_fov = p_env->sky_custom_fov;
+ float custom_fov = RendererSceneRenderRD::get_singleton()->environment_get_sky_custom_fov(p_env);
// Camera
- CameraMatrix camera;
+ Projection camera;
uint32_t view_count = p_view_count;
- const CameraMatrix *projections = p_projections;
+ const Projection *projections = p_projections;
if (custom_fov) {
// With custom fov we don't support stereo...
@@ -1729,15 +1760,15 @@ void RendererSceneSkyRD::draw(RD::DrawListID p_draw_list, RendererSceneEnvironme
RID texture_uniform_set;
if (sky) {
- texture_uniform_set = sky->get_textures(storage, SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
+ texture_uniform_set = sky->get_textures(SKY_TEXTURE_SET_BACKGROUND, sky_shader.default_shader_rd);
} else {
texture_uniform_set = sky_scene_state.fog_only_texture_uniform_set;
}
- _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, multiplier, p_transform.origin, p_luminance_multiplier);
+ _render_sky(p_draw_list, p_time, p_fb, pipeline, material->uniform_set, texture_uniform_set, view_count, projections, sky_transform, p_transform.origin, p_luminance_multiplier);
}
-void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
+void SkyRD::invalidate_sky(Sky *p_sky) {
if (!p_sky->dirty) {
p_sky->dirty = true;
p_sky->dirty_list = dirty_sky_list;
@@ -1745,7 +1776,7 @@ void RendererSceneSkyRD::invalidate_sky(Sky *p_sky) {
}
}
-void RendererSceneSkyRD::update_dirty_skys() {
+void SkyRD::update_dirty_skys() {
Sky *sky = dirty_sky_list;
while (sky) {
@@ -1777,7 +1808,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
- sky->reflection.update_reflection_data(storage, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
+ sky->reflection.update_reflection_data(sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
} else {
//regular cubemap, lower quality (aliasing, less memory)
@@ -1792,7 +1823,7 @@ void RendererSceneSkyRD::update_dirty_skys() {
sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView());
- sky->reflection.update_reflection_data(storage, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
+ sky->reflection.update_reflection_data(sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME, roughness_layers, texture_format);
}
texture_set_dirty = true;
}
@@ -1849,34 +1880,41 @@ void RendererSceneSkyRD::update_dirty_skys() {
dirty_sky_list = nullptr;
}
-RID RendererSceneSkyRD::sky_get_material(RID p_sky) const {
+RID SkyRD::sky_get_material(RID p_sky) const {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, RID());
return sky->material;
}
-RID RendererSceneSkyRD::allocate_sky_rid() {
+float SkyRD::sky_get_baked_exposure(RID p_sky) const {
+ Sky *sky = get_sky(p_sky);
+ ERR_FAIL_COND_V(!sky, 1.0);
+
+ return sky->baked_exposure;
+}
+
+RID SkyRD::allocate_sky_rid() {
return sky_owner.allocate_rid();
}
-void RendererSceneSkyRD::initialize_sky_rid(RID p_rid) {
+void SkyRD::initialize_sky_rid(RID p_rid) {
sky_owner.initialize_rid(p_rid, Sky());
}
-RendererSceneSkyRD::Sky *RendererSceneSkyRD::get_sky(RID p_sky) const {
+SkyRD::Sky *SkyRD::get_sky(RID p_sky) const {
return sky_owner.get_or_null(p_sky);
}
-void RendererSceneSkyRD::free_sky(RID p_sky) {
+void SkyRD::free_sky(RID p_sky) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
- sky->free(storage);
+ sky->free();
sky_owner.free(p_sky);
}
-void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
+void SkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1885,7 +1923,7 @@ void RendererSceneSkyRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) {
}
}
-void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
+void SkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1894,7 +1932,7 @@ void RendererSceneSkyRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) {
}
}
-void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) {
+void SkyRD::sky_set_material(RID p_sky, RID p_material) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND(!sky);
@@ -1903,7 +1941,7 @@ void RendererSceneSkyRD::sky_set_material(RID p_sky, RID p_material) {
}
}
-Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
+Ref<Image> SkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size) {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, Ref<Image>());
@@ -1912,7 +1950,7 @@ Ref<Image> RendererSceneSkyRD::sky_bake_panorama(RID p_sky, float p_energy, bool
return sky->bake_panorama(p_energy, p_bake_irradiance ? roughness_layers : 0, p_size);
}
-RID RendererSceneSkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
+RID SkyRD::sky_get_radiance_texture_rd(RID p_sky) const {
Sky *sky = get_sky(p_sky);
ERR_FAIL_COND_V(!sky, RID());
diff --git a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h b/servers/rendering/renderer_rd/environment/sky.h
index 83a8fe6e77..45c4f9bda7 100644
--- a/servers/rendering/renderer_rd/renderer_scene_sky_rd.h
+++ b/servers/rendering/renderer_rd/environment/sky.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene_sky_rd.h */
+/* sky.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,21 +28,25 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_SKY_RD_H
-#define RENDERING_SERVER_SCENE_SKY_RD_H
+#ifndef SKY_RD_H
+#define SKY_RD_H
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/sky.glsl.gen.h"
+#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
+#include "servers/rendering/renderer_rd/shaders/environment/sky.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/shader_compiler.h"
// Forward declare RendererSceneRenderRD so we can pass it into some of our methods, these classes are pretty tightly bound
class RendererSceneRenderRD;
+class RenderSceneBuffersRD;
-class RendererSceneSkyRD {
+namespace RendererRD {
+
+class SkyRD {
public:
enum SkySet {
SKY_SET_UNIFORMS,
@@ -63,7 +67,6 @@ public:
};
private:
- RendererStorageRD *storage = nullptr;
RD::DataFormat texture_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
RID index_buffer;
@@ -98,14 +101,13 @@ private:
float orientation[12]; // 48 - 48
float projections[RendererSceneRender::MAX_RENDER_VIEWS][4]; // 2 x 16 - 80
float position[3]; // 12 - 92
- float multiplier; // 4 - 96
- float time; // 4 - 100
- float luminance_multiplier; // 4 - 104
- float pad[2]; // 8 - 112 // Using pad to align on 16 bytes
+ float time; // 4 - 96
+ float pad[3]; // 12 - 108
+ float luminance_multiplier; // 4 - 112
// 128 is the max size of a push constant. We can replace "pad" but we can't add any more.
};
- struct SkyShaderData : public RendererRD::ShaderData {
+ struct SkyShaderData : public RendererRD::MaterialStorage::ShaderData {
bool valid = false;
RID version;
@@ -127,10 +129,11 @@ private:
bool uses_light = false;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void set_path_hint(const String &p_hint);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_parameter_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
@@ -140,25 +143,28 @@ private:
virtual ~SkyShaderData();
};
- void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const CameraMatrix *p_projections, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position, float p_luminance_multiplier);
+ void _render_sky(RD::DrawListID p_list, float p_time, RID p_fb, PipelineCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, uint32_t p_view_count, const Projection *p_projections, const Basis &p_orientation, const Vector3 &p_position, float p_luminance_multiplier);
public:
struct SkySceneState {
struct UBO {
- uint32_t volumetric_fog_enabled;
- float volumetric_fog_inv_length;
- float volumetric_fog_detail_spread;
-
- float fog_aerial_perspective;
-
- float fog_light_color[3];
- float fog_sun_scatter;
-
- uint32_t fog_enabled;
- float fog_density;
-
- float z_far;
- uint32_t directional_light_count;
+ uint32_t volumetric_fog_enabled; // 4 - 4
+ float volumetric_fog_inv_length; // 4 - 8
+ float volumetric_fog_detail_spread; // 4 - 12
+ float volumetric_fog_sky_affect; // 4 - 16
+
+ uint32_t fog_enabled; // 4 - 20
+ float fog_sky_affect; // 4 - 24
+ float fog_density; // 4 - 28
+ float fog_sun_scatter; // 4 - 32
+
+ float fog_light_color[3]; // 12 - 44
+ float fog_aerial_perspective; // 4 - 48
+
+ float z_far; // 4 - 52
+ uint32_t directional_light_count; // 4 - 56
+ uint32_t pad1; // 4 - 60
+ uint32_t pad2; // 4 - 64
};
UBO ubo;
@@ -211,10 +217,10 @@ public:
Vector<Layer> layers;
void clear_reflection_data();
- void update_reflection_data(RendererStorageRD *p_storage, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
- void create_reflection_fast_filter(RendererStorageRD *p_storage, bool p_use_arrays);
- void create_reflection_importance_sample(RendererStorageRD *p_storage, bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
- void update_reflection_mipmaps(RendererStorageRD *p_storage, int p_start, int p_end);
+ void update_reflection_data(int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality, int p_roughness_layers, RD::DataFormat p_texture_format);
+ void create_reflection_fast_filter(bool p_use_arrays);
+ void create_reflection_importance_sample(bool p_use_arrays, int p_cube_side, int p_base_layer, uint32_t p_sky_ggx_samples_quality);
+ void update_reflection_mipmaps(int p_start, int p_end);
};
/* Sky shader */
@@ -228,7 +234,7 @@ public:
RID default_shader_rd;
} sky_shader;
- struct SkyMaterialData : public RendererRD::MaterialData {
+ struct SkyMaterialData : public RendererRD::MaterialStorage::MaterialData {
SkyShaderData *shader_data = nullptr;
RID uniform_set;
bool uniform_set_updated;
@@ -261,15 +267,16 @@ public:
bool dirty = false;
int processing_layer = 0;
Sky *dirty_list = nullptr;
+ float baked_exposure = 1.0;
//State to track when radiance cubemap needs updating
SkyMaterialData *prev_material = nullptr;
Vector3 prev_position;
float prev_time;
- void free(RendererStorageRD *p_storage);
+ void free();
- RID get_textures(RendererStorageRD *p_storage, SkyTextureSetVersion p_version, RID p_default_shader_rd);
+ RID get_textures(SkyTextureSetVersion p_version, RID p_default_shader_rd);
bool set_radiance_size(int p_radiance_size);
bool set_mode(RS::SkyMode p_mode);
bool set_material(RID p_material);
@@ -282,27 +289,29 @@ public:
mutable RID_Owner<Sky, true> sky_owner;
int roughness_layers;
- RendererRD::ShaderData *_create_sky_shader_func();
- static RendererRD::ShaderData *_create_sky_shader_funcs();
+ RendererRD::MaterialStorage::ShaderData *_create_sky_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_sky_shader_funcs();
- RendererRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
- static RendererRD::MaterialData *_create_sky_material_funcs(RendererRD::ShaderData *p_shader);
+ RendererRD::MaterialStorage::MaterialData *_create_sky_material_func(SkyShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_sky_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader);
- RendererSceneSkyRD();
- void init(RendererStorageRD *p_storage);
+ SkyRD();
+ void init();
void set_texture_format(RD::DataFormat p_texture_format);
- ~RendererSceneSkyRD();
+ ~SkyRD();
- void setup(RendererSceneEnvironmentRD *p_env, RID p_render_buffers, const PagedArray<RID> &p_lights, const CameraMatrix &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
- void update(RendererSceneEnvironmentRD *p_env, const CameraMatrix &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
- void draw(RendererSceneEnvironmentRD *p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time); // only called by clustered renderer
- void update_res_buffers(RendererSceneEnvironmentRD *p_env, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
- void draw(RD::DrawListID p_draw_list, RendererSceneEnvironmentRD *p_env, RID p_fb, uint32_t p_view_count, const CameraMatrix *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void setup(RID p_env, Ref<RenderSceneBuffersRD> p_render_buffers, const PagedArray<RID> &p_lights, RID p_camera_attributes, const Projection &p_projection, const Transform3D &p_transform, const Size2i p_screen_size, RendererSceneRenderRD *p_scene_render);
+ void update(RID p_env, const Projection &p_projection, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RID p_env, bool p_can_continue_color, bool p_can_continue_depth, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0); // only called by clustered renderer
+ void update_res_buffers(RID p_env, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
+ void draw(RD::DrawListID p_draw_list, RID p_env, RID p_fb, uint32_t p_view_count, const Projection *p_projections, const Transform3D &p_transform, double p_time, float p_luminance_multiplier = 1.0);
void invalidate_sky(Sky *p_sky);
void update_dirty_skys();
RID sky_get_material(RID p_sky) const;
+ RID sky_get_radiance_texture_rd(RID p_sky) const;
+ float sky_get_baked_exposure(RID p_sky) const;
RID allocate_sky_rid();
void initialize_sky_rid(RID p_rid);
@@ -312,8 +321,8 @@ public:
void sky_set_mode(RID p_sky, RS::SkyMode p_mode);
void sky_set_material(RID p_sky, RID p_material);
Ref<Image> sky_bake_panorama(RID p_sky, float p_energy, bool p_bake_irradiance, const Size2i &p_size);
-
- RID sky_get_radiance_texture_rd(RID p_sky) const;
};
-#endif /* RENDERING_SERVER_SCENE_SKY_RD_H */
+} // namespace RendererRD
+
+#endif // SKY_RD_H
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
index 2d3998bd90..86425512b8 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp
@@ -30,6 +30,8 @@
#include "render_forward_clustered.h"
#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
@@ -40,207 +42,113 @@
using namespace RendererSceneRenderImplementation;
-RenderForwardClustered::RenderBufferDataForwardClustered::~RenderBufferDataForwardClustered() {
- clear();
-}
-
void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_specular() {
- if (!specular.is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = width;
- tf.height = height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- } else {
- tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- }
-
- specular = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- if (msaa == RS::VIEWPORT_MSAA_DISABLED) {
- {
- Vector<RID> fb;
- fb.push_back(specular);
-
- specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
- }
+ ERR_FAIL_NULL(render_buffers);
+ if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR)) {
+ RD::DataFormat format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
} else {
- tf.samples = texture_samples;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
- specular_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
- {
- Vector<RID> fb;
- fb.push_back(specular_msaa);
+ render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR, format, usage_bits);
- specular_only_fb = RD::get_singleton()->framebuffer_create(fb);
- }
+ if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, format, usage_bits, texture_samples);
}
}
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_velocity() {
- if (!velocity_buffer.is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16_SFLOAT;
- tf.width = width;
- tf.height = height;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-
- if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::TextureFormat tf_aa = tf;
- tf_aa.samples = texture_samples;
- tf_aa.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
- velocity_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView());
+void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_normal_roughness_texture() {
+ ERR_FAIL_NULL(render_buffers);
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- }
-
- velocity_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-}
+ if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS)) {
+ RD::DataFormat format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
-void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() {
- if (!voxelgi_buffer.is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UINT;
- tf.width = width;
- tf.height = height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::TextureFormat tf_aa = tf;
- tf_aa.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- tf_aa.samples = texture_samples;
- voxelgi_buffer_msaa = RD::get_singleton()->texture_create(tf_aa, RD::TextureView());
+ if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
} else {
- tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
- tf.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
-
- voxelgi_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, format, usage_bits);
- Vector<RID> fb;
- if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
- fb.push_back(depth_msaa);
- fb.push_back(normal_roughness_buffer_msaa);
- fb.push_back(voxelgi_buffer_msaa);
- } else {
- fb.push_back(depth);
- fb.push_back(normal_roughness_buffer);
- fb.push_back(voxelgi_buffer);
+ if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, format, usage_bits, texture_samples);
}
-
- depth_normal_roughness_voxelgi_fb = RD::get_singleton()->framebuffer_create(fb);
}
}
-void RenderForwardClustered::RenderBufferDataForwardClustered::clear() {
- if (voxelgi_buffer != RID()) {
- RD::get_singleton()->free(voxelgi_buffer);
- voxelgi_buffer = RID();
+void RenderForwardClustered::RenderBufferDataForwardClustered::ensure_voxelgi() {
+ ERR_FAIL_NULL(render_buffers);
- if (voxelgi_buffer_msaa.is_valid()) {
- RD::get_singleton()->free(voxelgi_buffer_msaa);
- voxelgi_buffer_msaa = RID();
+ if (!render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI)) {
+ RD::DataFormat format = RD::DATA_FORMAT_R8G8_UINT;
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ if (render_buffers->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED) {
+ usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
}
- depth_normal_roughness_voxelgi_fb = RID();
- }
+ render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, format, usage_bits);
- if (color_msaa.is_valid()) {
- RD::get_singleton()->free(color_msaa);
- color_msaa = RID();
- }
-
- if (depth_msaa.is_valid()) {
- RD::get_singleton()->free(depth_msaa);
- depth_msaa = RID();
- }
-
- if (specular.is_valid()) {
- if (specular_msaa.is_valid()) {
- RD::get_singleton()->free(specular_msaa);
- specular_msaa = RID();
+ if (render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, format, usage_bits, texture_samples);
}
- RD::get_singleton()->free(specular);
- specular = RID();
}
+}
- color = RID();
- depth = RID();
- depth_fb = RID();
-
- color_framebuffers.clear(); // Color pass framebuffers are freed automatically by their dependency relations
+void RenderForwardClustered::RenderBufferDataForwardClustered::free_data() {
+ // JIC, should already have been cleared
+ if (render_buffers) {
+ render_buffers->clear_context(RB_SCOPE_FORWARD_CLUSTERED);
+ }
- if (normal_roughness_buffer.is_valid()) {
- RD::get_singleton()->free(normal_roughness_buffer);
- if (normal_roughness_buffer_msaa.is_valid()) {
- RD::get_singleton()->free(normal_roughness_buffer_msaa);
- normal_roughness_buffer_msaa = RID();
- }
- normal_roughness_buffer = RID();
- depth_normal_roughness_fb = RID();
+ if (cluster_builder) {
+ memdelete(cluster_builder);
+ cluster_builder = nullptr;
}
if (!render_sdfgi_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_sdfgi_uniform_set)) {
RD::get_singleton()->free(render_sdfgi_uniform_set);
}
- if (velocity_buffer != RID()) {
- RD::get_singleton()->free(velocity_buffer);
- velocity_buffer = RID();
+ if (ss_effects_data.linear_depth.is_valid()) {
+ RD::get_singleton()->free(ss_effects_data.linear_depth);
+ ss_effects_data.linear_depth = RID();
+ ss_effects_data.linear_depth_slices.clear();
}
- if (velocity_buffer_msaa != RID()) {
- RD::get_singleton()->free(velocity_buffer_msaa);
- velocity_buffer_msaa = RID();
+ if (ss_effects_data.downsample_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(ss_effects_data.downsample_uniform_set)) {
+ RD::get_singleton()->free(ss_effects_data.downsample_uniform_set);
+ ss_effects_data.downsample_uniform_set = RID();
}
-}
-
-void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
- clear();
- msaa = p_msaa;
- use_taa = p_use_taa;
-
- width = p_width;
- height = p_height;
- view_count = p_view_count;
+ RenderForwardClustered::get_singleton()->get_ss_effects()->ssao_free(ss_effects_data.ssao);
+ RenderForwardClustered::get_singleton()->get_ss_effects()->ssil_free(ss_effects_data.ssil);
+ RenderForwardClustered::get_singleton()->get_ss_effects()->ssr_free(ss_effects_data.ssr);
+}
- color = p_color_buffer;
- depth = p_depth_buffer;
+void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RenderSceneBuffersRD *p_render_buffers) {
+ if (render_buffers) {
+ // JIC
+ free_data();
+ }
- if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
- {
- Vector<RID> fb;
- fb.push_back(p_color_buffer);
- fb.push_back(depth);
+ render_buffers = p_render_buffers;
+ ERR_FAIL_NULL(render_buffers);
- color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
- }
- {
- Vector<RID> fb;
- fb.push_back(depth);
+ RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
- depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
- }
- } else {
- RD::TextureFormat tf;
- if (view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- } else {
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- }
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = p_width;
- tf.height = p_height;
- tf.array_layers = view_count; // create a layer for every view
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
+ RD::DataFormat format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
RD::TEXTURE_SAMPLES_1,
@@ -249,102 +157,120 @@ void RenderForwardClustered::RenderBufferDataForwardClustered::configure(RID p_c
RD::TEXTURE_SAMPLES_8,
};
- texture_samples = ts[p_msaa];
- tf.samples = texture_samples;
+ texture_samples = ts[msaa_3d];
- color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ p_render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples);
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
- tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
- depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ p_render_buffers->create_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples);
+ }
- {
- Vector<RID> fb;
- fb.push_back(color_msaa);
- fb.push_back(depth_msaa);
+ if (cluster_builder == nullptr) {
+ cluster_builder = memnew(ClusterBuilderRD);
+ }
+ cluster_builder->set_shared(RenderForwardClustered::get_singleton()->get_cluster_builder_shared());
- color_only_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
- }
- {
- Vector<RID> fb;
- fb.push_back(depth_msaa);
+ RID sampler = RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ cluster_builder->setup(p_render_buffers->get_internal_size(), p_render_buffers->get_max_cluster_elements(), p_render_buffers->get_depth_texture(), sampler, p_render_buffers->get_internal_texture());
+}
- depth_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, view_count);
- }
+RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_only_fb() {
+ ERR_FAIL_NULL_V(render_buffers, RID());
+
+ bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED;
+
+ RID color = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA) : render_buffers->get_internal_texture();
+ RID depth = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA) : render_buffers->get_depth_texture();
+
+ if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
+ RID vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
+
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), color, depth, vrs_texture);
+ } else {
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), color, depth);
}
}
RID RenderForwardClustered::RenderBufferDataForwardClustered::get_color_pass_fb(uint32_t p_color_pass_flags) {
- if (color_framebuffers.has(p_color_pass_flags)) {
- return color_framebuffers[p_color_pass_flags];
- }
+ ERR_FAIL_NULL_V(render_buffers, RID());
+ bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED;
- bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED;
-
- Vector<RID> fb;
- fb.push_back(use_msaa ? color_msaa : color);
+ int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? render_buffers->get_view_count() : 1;
+ RID color = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA) : render_buffers->get_internal_texture();
+ RID specular;
if (p_color_pass_flags & COLOR_PASS_FLAG_SEPARATE_SPECULAR) {
ensure_specular();
- fb.push_back(use_msaa ? specular_msaa : specular);
- } else {
- fb.push_back(RID());
+ specular = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_SPECULAR_MSAA : RB_TEX_SPECULAR);
}
+ RID velocity_buffer;
if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) {
- ensure_velocity();
- fb.push_back(use_msaa ? velocity_buffer_msaa : velocity_buffer);
- } else {
- fb.push_back(RID());
+ render_buffers->ensure_velocity();
+ velocity_buffer = render_buffers->get_velocity_buffer(use_msaa);
}
- fb.push_back(use_msaa ? depth_msaa : depth);
+ RID depth = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA) : render_buffers->get_depth_texture();
- int v_count = (p_color_pass_flags & COLOR_PASS_FLAG_MULTIVIEW) ? view_count : 1;
- RID framebuffer = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, v_count);
- color_framebuffers[p_color_pass_flags] = framebuffer;
- return framebuffer;
-}
+ if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
+ RID vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
-void RenderForwardClustered::_allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb) {
- if (rb->normal_roughness_buffer.is_valid()) {
- return;
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(v_count, color, specular, velocity_buffer, depth, vrs_texture);
+ } else {
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(v_count, color, specular, velocity_buffer, depth);
}
+}
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
- tf.width = rb->width;
- tf.height = rb->height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+RID RenderForwardClustered::RenderBufferDataForwardClustered::get_depth_fb(DepthFrameBufferType p_type) {
+ ERR_FAIL_NULL_V(render_buffers, RID());
+ bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED;
- if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- } else {
- tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- }
+ RID depth = use_msaa ? render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA) : render_buffers->get_depth_texture();
- rb->normal_roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ switch (p_type) {
+ case DEPTH_FB: {
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth);
+ } break;
+ case DEPTH_FB_ROUGHNESS: {
+ ensure_normal_roughness_texture();
- if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
- Vector<RID> fb;
- fb.push_back(rb->depth);
- fb.push_back(rb->normal_roughness_buffer);
- rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb);
- } else {
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- tf.samples = rb->texture_samples;
- rb->normal_roughness_buffer_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_ROUGHNESS_MSAA : RB_TEX_ROUGHNESS);
- Vector<RID> fb;
- fb.push_back(rb->depth_msaa);
- fb.push_back(rb->normal_roughness_buffer_msaa);
- rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb);
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth, normal_roughness_buffer);
+ } break;
+ case DEPTH_FB_ROUGHNESS_VOXELGI: {
+ ensure_normal_roughness_texture();
+ ensure_voxelgi();
+
+ RID normal_roughness_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_ROUGHNESS_MSAA : RB_TEX_ROUGHNESS);
+ RID voxelgi_buffer = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_VOXEL_GI_MSAA : RB_TEX_VOXEL_GI);
+
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), depth, normal_roughness_buffer, voxelgi_buffer);
+ } break;
+ default: {
+ ERR_FAIL_V(RID());
+ } break;
}
}
-RendererSceneRenderRD::RenderBufferData *RenderForwardClustered::_create_render_buffer_data() {
- return memnew(RenderBufferDataForwardClustered);
+RID RenderForwardClustered::RenderBufferDataForwardClustered::get_specular_only_fb() {
+ bool use_msaa = render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED;
+
+ RID specular = render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, use_msaa ? RB_TEX_SPECULAR_MSAA : RB_TEX_SPECULAR);
+
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(render_buffers->get_view_count(), specular);
+}
+
+void RenderForwardClustered::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ Ref<RenderBufferDataForwardClustered> data;
+ data.instantiate();
+ p_render_buffers->set_custom_data(RB_SCOPE_FORWARD_CLUSTERED, data);
+
+ Ref<RendererRD::GI::RenderBuffersGI> rbgi;
+ rbgi.instantiate();
+ p_render_buffers->set_custom_data(RB_SCOPE_GI, rbgi);
}
bool RenderForwardClustered::free(RID p_rid) {
@@ -378,7 +304,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
SceneState::PushConstant push_constant;
- if (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) {
+ if constexpr (p_pass_mode == PASS_MODE_DEPTH_MATERIAL) {
push_constant.uv_offset = Math::make_half_float(p_params->uv_offset.y) << 16;
push_constant.uv_offset |= Math::make_half_float(p_params->uv_offset.x);
} else {
@@ -457,7 +383,7 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
uint32_t pipeline_color_pass_flags = 0;
uint32_t pipeline_specialization = 0;
- if (p_pass_mode == PASS_MODE_COLOR) {
+ if constexpr (p_pass_mode == PASS_MODE_COLOR) {
if (element_info.uses_softshadow) {
pipeline_specialization |= SceneShaderForwardClustered::SHADER_SPECIALIZATION_SOFT_SHADOWS;
}
@@ -503,22 +429,21 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS;
} break;
case PASS_MODE_SHADOW_DP: {
- ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass");
+ ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for shadow DP pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_DP;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
- ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for depth/roughness pass");
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
+ pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS;
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
- ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for voxel GI pass");
- pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
+ pipeline_version = p_params->view_count > 1 ? SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW : SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI;
} break;
case PASS_MODE_DEPTH_MATERIAL: {
ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for material pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL;
} break;
case PASS_MODE_SDF: {
+ // Note, SDF is prepared in world space, this shouldn't be a multiview buffer even when stereoscopic rendering is used.
ERR_FAIL_COND_MSG(p_params->view_count > 1, "Multiview not supported for SDF pass");
pipeline_version = SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF;
} break;
@@ -580,6 +505,13 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p
prev_material_uniform_set = material_uniform_set;
}
+ if ((surf->owner->base_flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH) {
+ mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset);
+ } else {
+ push_constant.multimesh_motion_vectors_current_offset = 0;
+ push_constant.multimesh_motion_vectors_previous_offset = 0;
+ }
+
RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SceneState::PushConstant));
uint32_t instance_count = surf->owner->instance_count > 1 ? surf->owner->instance_count : element_info.repeat;
@@ -650,7 +582,7 @@ void RenderForwardClustered::_render_list(RenderingDevice::DrawListID p_draw_lis
void RenderForwardClustered::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
uint32_t render_total = p_params->element_count;
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t render_from = p_thread * render_total / total_threads;
uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
@@ -662,9 +594,10 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p
if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardClustered::_render_list_thread_function, p_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardClustered::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardClusteredRenderList"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
RD::get_singleton()->draw_list_end(p_params->barrier);
} else {
//single threaded
@@ -675,41 +608,24 @@ void RenderForwardClustered::_render_list_with_threads(RenderListParameters *p_p
}
void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) {
- //CameraMatrix projection = p_render_data->cam_projection;
- //projection.flip_y(); // Vulkan and modern APIs use Y-Down
- CameraMatrix correction;
- correction.set_depth_correction(p_flip_y);
- correction.add_jitter_offset(p_render_data->taa_jitter);
- CameraMatrix projection = correction * p_render_data->cam_projection;
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- //store camera into ubo
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
+ Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers;
+ RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID();
+ RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID();
- for (uint32_t v = 0; v < p_render_data->view_count; v++) {
- projection = correction * p_render_data->view_projection[v];
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
+ // May do this earlier in RenderSceneRenderRD::render_scene
+ if (p_index >= (int)scene_state.uniform_buffers.size()) {
+ uint32_t from = scene_state.uniform_buffers.size();
+ scene_state.uniform_buffers.resize(p_index + 1);
+ for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) {
+ scene_state.uniform_buffers[i] = p_render_data->scene_data->create_uniform_buffer();
+ }
}
- scene_state.ubo.taa_jitter[0] = p_render_data->taa_jitter.x;
- scene_state.ubo.taa_jitter[1] = p_render_data->taa_jitter.y;
+ p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers);
- scene_state.ubo.z_far = p_render_data->z_far;
- scene_state.ubo.z_near = p_render_data->z_near;
-
- scene_state.ubo.pancake_shadows = p_pancake_shadows;
-
- RendererStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
-
- Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
- scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
- scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y;
+ // now do implementation UBO
scene_state.ubo.cluster_shift = get_shift_from_power_of_2(p_render_data->cluster_size);
scene_state.ubo.max_cluster_element_count_div_32 = p_render_data->cluster_max_elements / 32;
@@ -720,39 +636,26 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
scene_state.ubo.cluster_width = cluster_screen_width;
}
- if (p_render_data->shadow_atlas.is_valid()) {
- Vector2 sas = shadow_atlas_get_size(p_render_data->shadow_atlas);
- scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x;
- scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y;
- }
- {
- Vector2 dss = directional_shadow_get_size();
- scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x;
- scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y;
- }
- //time global variables
- scene_state.ubo.time = time;
-
scene_state.ubo.gi_upscale_for_msaa = false;
scene_state.ubo.volumetric_fog_enabled = false;
- scene_state.ubo.fog_enabled = false;
- if (p_render_data->render_buffers.is_valid()) {
- RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
- if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rd.is_valid()) {
+ if (rd->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
scene_state.ubo.gi_upscale_for_msaa = true;
}
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
+ if (rd->has_custom_data(RB_SCOPE_FOG)) {
+ Ref<RendererRD::Fog::VolumetricFog> fog = rd->get_custom_data(RB_SCOPE_FOG);
+
scene_state.ubo.volumetric_fog_enabled = true;
- float fog_end = render_buffers_get_volumetric_fog_end(p_render_data->render_buffers);
+ float fog_end = fog->length;
if (fog_end > 0.0) {
scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
} else {
scene_state.ubo.volumetric_fog_inv_length = 1.0;
}
- float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_data->render_buffers); //reverse lookup
+ float fog_detail_spread = fog->spread; //reverse lookup
if (fog_detail_spread > 0.0) {
scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
} else {
@@ -762,139 +665,29 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat
}
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
- scene_state.ubo.use_ambient_light = true;
- scene_state.ubo.ambient_light_color_energy[0] = 1;
- scene_state.ubo.ambient_light_color_energy[1] = 1;
- scene_state.ubo.ambient_light_color_energy[2] = 1;
- scene_state.ubo.ambient_light_color_energy[3] = 1.0;
- scene_state.ubo.use_ambient_cubemap = false;
- scene_state.ubo.use_reflection_cubemap = false;
scene_state.ubo.ss_effects_flags = 0;
-
} else if (is_environment(p_render_data->environment)) {
- RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
- RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment);
-
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
- scene_state.ubo.ambient_light_color_energy[3] = bg_energy;
-
- scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment);
-
- //ambient
- if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
- Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
- color = color.srgb_to_linear();
-
- scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
- scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
- scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy;
- scene_state.ubo.use_ambient_light = true;
- scene_state.ubo.use_ambient_cubemap = false;
- } else {
- float energy = environment_get_ambient_light_energy(p_render_data->environment);
- Color color = environment_get_ambient_light_color(p_render_data->environment);
- color = color.srgb_to_linear();
- scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
- scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
- scene_state.ubo.ambient_light_color_energy[2] = color.b * energy;
-
- Basis sky_transform = environment_get_sky_orientation(p_render_data->environment);
- sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis;
- RendererStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
-
- scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
- scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
- }
-
- //specular
- RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_render_data->environment);
- if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) {
- scene_state.ubo.use_reflection_cubemap = true;
- } else {
- scene_state.ubo.use_reflection_cubemap = false;
- }
-
- scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment);
- scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment);
+ scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_channel_affect(p_render_data->environment);
+ scene_state.ubo.ssao_light_affect = environment_get_ssao_direct_light_affect(p_render_data->environment);
uint32_t ss_flags = 0;
if (p_opaque_render_buffers) {
- ss_flags |= environment_is_ssao_enabled(p_render_data->environment) ? 1 : 0;
- ss_flags |= environment_is_ssil_enabled(p_render_data->environment) ? 2 : 0;
+ ss_flags |= environment_get_ssao_enabled(p_render_data->environment) ? 1 : 0;
+ ss_flags |= environment_get_ssil_enabled(p_render_data->environment) ? 2 : 0;
}
scene_state.ubo.ss_effects_flags = ss_flags;
-
- scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment);
- scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
- scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
- scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
- scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
-
- Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
- float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
-
- scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
- scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
- scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
-
- scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
-
} else {
- if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
- scene_state.ubo.use_ambient_light = false;
- } else {
- scene_state.ubo.use_ambient_light = true;
- Color clear_color = p_default_bg_color;
- clear_color = clear_color.srgb_to_linear();
- scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
- scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
- scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
- scene_state.ubo.ambient_light_color_energy[3] = 1.0;
- }
-
- scene_state.ubo.use_ambient_cubemap = false;
- scene_state.ubo.use_reflection_cubemap = false;
scene_state.ubo.ss_effects_flags = 0;
}
- scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
- scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
- scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();
-
- if (p_render_data->render_buffers.is_valid()) {
- RenderBufferDataForwardClustered *render_buffers = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
- if (render_buffers->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
- memcpy(&scene_state.prev_ubo, &scene_state.ubo, sizeof(SceneState::UBO));
-
- CameraMatrix prev_correction;
- prev_correction.set_depth_correction(true);
- prev_correction.add_jitter_offset(p_render_data->prev_taa_jitter);
- CameraMatrix prev_projection = prev_correction * p_render_data->prev_cam_projection;
-
- //store camera into ubo
- RendererStorageRD::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix);
- RendererStorageRD::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->prev_cam_transform, scene_state.prev_ubo.inv_view_matrix);
- RendererStorageRD::store_transform(p_render_data->prev_cam_transform.affine_inverse(), scene_state.prev_ubo.view_matrix);
-
- for (uint32_t v = 0; v < p_render_data->view_count; v++) {
- prev_projection = prev_correction * p_render_data->view_projection[v];
- RendererStorageRD::store_camera(prev_projection, scene_state.prev_ubo.projection_matrix_view[v]);
- RendererStorageRD::store_camera(prev_projection.inverse(), scene_state.prev_ubo.inv_projection_matrix_view[v]);
- }
- scene_state.prev_ubo.taa_jitter[0] = p_render_data->prev_taa_jitter.x;
- scene_state.prev_ubo.taa_jitter[1] = p_render_data->prev_taa_jitter.y;
- scene_state.prev_ubo.time -= time_step;
+ if (p_index >= (int)scene_state.implementation_uniform_buffers.size()) {
+ uint32_t from = scene_state.implementation_uniform_buffers.size();
+ scene_state.implementation_uniform_buffers.resize(p_index + 1);
+ for (uint32_t i = from; i < scene_state.implementation_uniform_buffers.size(); i++) {
+ scene_state.implementation_uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
}
}
- if (p_index >= (int)scene_state.uniform_buffers.size()) {
- uint32_t from = scene_state.uniform_buffers.size();
- scene_state.uniform_buffers.resize(p_index + 1);
- for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) {
- scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO) * 2);
- }
- }
- RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO) * 2, &scene_state.ubo_data, RD::BARRIER_MASK_RASTER);
+ RD::get_singleton()->buffer_update(scene_state.implementation_uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER);
}
void RenderForwardClustered::_update_instance_data_buffer(RenderListType p_render_list) {
@@ -935,25 +728,33 @@ void RenderForwardClustered::_fill_instance_data(RenderListType p_render_list, i
}
if (inst->store_transform_cache) {
- RendererStorageRD::store_transform(inst->transform, instance_data.transform);
- RendererStorageRD::store_transform(inst->prev_transform, instance_data.prev_transform);
+ RendererRD::MaterialStorage::store_transform(inst->transform, instance_data.transform);
+ RendererRD::MaterialStorage::store_transform(inst->prev_transform, instance_data.prev_transform);
} else {
- RendererStorageRD::store_transform(Transform3D(), instance_data.transform);
- RendererStorageRD::store_transform(Transform3D(), instance_data.prev_transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), instance_data.prev_transform);
}
instance_data.flags = inst->flags_cache;
instance_data.gi_offset = inst->gi_offset_cache;
instance_data.layer_mask = inst->layer_mask;
- instance_data.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset);
+ instance_data.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset);
instance_data.lightmap_uv_scale[0] = inst->lightmap_uv_scale.position.x;
instance_data.lightmap_uv_scale[1] = inst->lightmap_uv_scale.position.y;
instance_data.lightmap_uv_scale[2] = inst->lightmap_uv_scale.size.x;
instance_data.lightmap_uv_scale[3] = inst->lightmap_uv_scale.size.y;
+#ifdef REAL_T_IS_DOUBLE
+ // Split the origin into two components, the float approximation and the missing precision
+ // In the shader we will combine these back together to restore the lost precision.
+ RendererRD::MaterialStorage::split_double(inst->transform.origin.x, &instance_data.transform[12], &instance_data.transform[3]);
+ RendererRD::MaterialStorage::split_double(inst->transform.origin.y, &instance_data.transform[13], &instance_data.transform[7]);
+ RendererRD::MaterialStorage::split_double(inst->transform.origin.z, &instance_data.transform[14], &instance_data.transform[11]);
+#endif
+
bool cant_repeat = instance_data.flags & INSTANCE_DATA_FLAG_MULTIMESH || inst->mesh_instance.is_valid();
- if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && repeats < RenderElementInfo::MAX_REPEATS) {
+ if (prev_surface != nullptr && !cant_repeat && prev_surface->sort.sort_key1 == surface->sort.sort_key1 && prev_surface->sort.sort_key2 == surface->sort.sort_key2 && inst->mirror == prev_surface->owner->mirror && repeats < RenderElementInfo::MAX_REPEATS) {
//this element is the same as the previous one, count repeats to draw it using instancing
repeats++;
} else {
@@ -999,7 +800,7 @@ _FORCE_INLINE_ static uint32_t _indices_to_primitives(RS::PrimitiveType p_primit
static const uint32_t subtractor[RS::PRIMITIVE_MAX] = { 0, 0, 1, 0, 1 };
return (p_indices - subtractor[p_primitive]) / divisor[p_primitive];
}
-void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) {
+void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, uint32_t p_color_pass_flags = 0, bool p_using_sdfgi, bool p_using_opaque_gi, bool p_append) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
if (p_render_list == RENDER_LIST_OPAQUE) {
@@ -1010,9 +811,9 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane = Plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
- near_plane.d += p_render_data->cam_projection.get_z_near();
- float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
+ Plane near_plane = Plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin);
+ near_plane.d += p_render_data->scene_data->cam_projection.get_z_near();
+ float z_max = p_render_data->scene_data->cam_projection.get_z_far() - p_render_data->scene_data->cam_projection.get_z_near();
RenderList *rl = &render_list[p_render_list];
_update_dirty_geometry_instances();
@@ -1043,7 +844,7 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
float fade_alpha = 1.0;
if (inst->fade_near || inst->fade_far) {
- float fade_dist = inst->transform.origin.distance_to(p_render_data->cam_transform.origin);
+ float fade_dist = inst->transform.origin.distance_to(p_render_data->scene_data->cam_transform.origin);
// Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
if (inst->fade_far && fade_dist > inst->fade_far_begin) {
fade_alpha = Math::smoothstep(0.0f, 1.0f, 1.0f - (fade_dist - inst->fade_far_begin) / (inst->fade_far_end - inst->fade_far_begin));
@@ -1138,13 +939,14 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
- //lod
- Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
- Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
+ if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
+ // Get the LOD support points on the mesh AABB.
+ Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
+ Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
- float distance_min = p_render_data->lod_camera_plane.distance_to(lod_support_min);
- float distance_max = p_render_data->lod_camera_plane.distance_to(lod_support_max);
+ // Get the distances to those points on the AABB from the camera origin.
+ float distance_min = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_min);
+ float distance_max = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_max);
float distance = 0.0;
@@ -1157,12 +959,12 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
distance = -distance_max;
}
- if (p_render_data->cam_orthogonal) {
+ if (p_render_data->scene_data->cam_orthogonal) {
distance = 1.0;
}
- uint32_t indices;
- surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ uint32_t indices = 0;
+ surf->sort.lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1224,6 +1026,12 @@ void RenderForwardClustered::_fill_render_list(RenderListType p_render_list, con
scene_state.used_depth_texture = true;
}
+ if (p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) {
+ if ((flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH && RendererRD::MeshStorage::get_singleton()->_multimesh_enable_motion_vectors(inst->data->base)) {
+ inst->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(inst->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
+ }
+ }
+
} else if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) {
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_PASS_SHADOW) {
rl->add_element(surf);
@@ -1252,20 +1060,29 @@ void RenderForwardClustered::_setup_voxelgis(const PagedArray<RID> &p_voxelgis)
}
}
-void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
+void RenderForwardClustered::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
if (i >= (int)scene_state.max_lightmaps) {
break;
}
- RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]);
+ RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]);
- Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
+ Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
- RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ scene_state.lightmaps[i].exposure_normalization = 1.0;
+ if (p_render_data->camera_attributes.is_valid()) {
+ float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
+ float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
+ }
+
scene_state.lightmap_ids[i] = p_lightmaps[i];
- scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
+ scene_state.lightmap_has_sh[i] = light_storage->lightmap_uses_spherical_harmonics(lightmap);
scene_state.lightmaps_used++;
}
@@ -1274,22 +1091,524 @@ void RenderForwardClustered::_setup_lightmaps(const PagedArray<RID> &p_lightmaps
}
}
+/* SDFGI */
+
+void RenderForwardClustered::_update_sdfgi(RenderDataRD *p_render_data) {
+ Ref<RenderSceneBuffersRD> rb;
+ if (p_render_data && p_render_data->render_buffers.is_valid()) {
+ rb = p_render_data->render_buffers;
+ }
+
+ if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ float exposure_normalization = 1.0;
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+ for (int i = 0; i < p_render_data->render_sdfgi_region_count; i++) {
+ sdfgi->render_region(rb, p_render_data->render_sdfgi_regions[i].region, p_render_data->render_sdfgi_regions[i].instances, exposure_normalization);
+ }
+ if (p_render_data->sdfgi_update_data->update_static) {
+ sdfgi->render_static_lights(p_render_data, rb, p_render_data->sdfgi_update_data->static_cascade_count, p_render_data->sdfgi_update_data->static_cascade_indices, p_render_data->sdfgi_update_data->static_positional_lights);
+ }
+ }
+}
+
+/* Debug */
+
+void RenderForwardClustered::_debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) {
+ RS::ViewportDebugDraw dd = get_debug_draw_mode();
+
+ if (dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
+ ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX;
+ switch (dd) {
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT;
+ break;
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_SPOT_LIGHT;
+ break;
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_DECAL;
+ break;
+ case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES:
+ elem_type = ClusterBuilderRD::ELEMENT_TYPE_REFLECTION_PROBE;
+ break;
+ default: {
+ }
+ }
+ current_cluster_builder->debug(elem_type);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// FOG SHADER
+
+void RenderForwardClustered::_update_volumetric_fog(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
+ Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+
+ ERR_FAIL_COND(!p_render_buffers->has_custom_data(RB_SCOPE_GI));
+ Ref<RendererRD::GI::RenderBuffersGI> rbgi = p_render_buffers->get_custom_data(RB_SCOPE_GI);
+
+ Ref<RendererRD::GI::SDFGI> sdfgi;
+ if (p_render_buffers->has_custom_data(RB_SCOPE_SDFGI)) {
+ sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI);
+ }
+
+ Size2i size = p_render_buffers->get_internal_size();
+ float ratio = float(size.x) / float((size.x + size.y) / 2);
+ uint32_t target_width = uint32_t(float(get_volumetric_fog_size()) * ratio);
+ uint32_t target_height = uint32_t(float(get_volumetric_fog_size()) / ratio);
+
+ if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+ Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
+ //validate
+ if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment) || fog->width != target_width || fog->height != target_height || fog->depth != get_volumetric_fog_depth()) {
+ p_render_buffers->set_custom_data(RB_SCOPE_FOG, Ref<RenderBufferCustomDataRD>());
+ }
+ }
+
+ if (p_environment.is_null() || !environment_get_volumetric_fog_enabled(p_environment)) {
+ //no reason to enable or update, bye
+ return;
+ }
+
+ if (p_environment.is_valid() && environment_get_volumetric_fog_enabled(p_environment) && !p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+ //required volumetric fog but not existing, create
+ Ref<RendererRD::Fog::VolumetricFog> fog;
+
+ fog.instantiate();
+ fog->init(Vector3i(target_width, target_height, get_volumetric_fog_depth()), sky.sky_shader.default_shader_rd);
+
+ p_render_buffers->set_custom_data(RB_SCOPE_FOG, fog);
+ }
+
+ if (p_render_buffers->has_custom_data(RB_SCOPE_FOG)) {
+ Ref<RendererRD::Fog::VolumetricFog> fog = p_render_buffers->get_custom_data(RB_SCOPE_FOG);
+
+ RendererRD::Fog::VolumetricFogSettings settings;
+ settings.rb_size = size;
+ settings.time = time;
+ settings.is_using_radiance_cubemap_array = is_using_radiance_cubemap_array();
+ settings.max_cluster_elements = RendererRD::LightStorage::get_singleton()->get_max_cluster_elements();
+ settings.volumetric_fog_filter_active = get_volumetric_fog_filter_active();
+
+ settings.shadow_sampler = shadow_sampler;
+ settings.shadow_atlas_depth = RendererRD::LightStorage::get_singleton()->owns_shadow_atlas(p_shadow_atlas) ? RendererRD::LightStorage::get_singleton()->shadow_atlas_get_texture(p_shadow_atlas) : RID();
+ settings.voxel_gi_buffer = rbgi->get_voxel_gi_buffer();
+ settings.omni_light_buffer = RendererRD::LightStorage::get_singleton()->get_omni_light_buffer();
+ settings.spot_light_buffer = RendererRD::LightStorage::get_singleton()->get_spot_light_buffer();
+ settings.directional_shadow_depth = RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture();
+ settings.directional_light_buffer = RendererRD::LightStorage::get_singleton()->get_directional_light_buffer();
+
+ settings.vfog = fog;
+ settings.cluster_builder = rb_data->cluster_builder;
+ settings.rbgi = rbgi;
+ settings.sdfgi = sdfgi;
+ settings.env = p_environment;
+ settings.sky = &sky;
+ settings.gi = &gi;
+
+ RendererRD::Fog::get_singleton()->volumetric_fog_update(settings, p_cam_projection, p_cam_transform, p_prev_cam_inv_transform, p_shadow_atlas, p_directional_light_count, p_use_directional_shadows, p_positional_light_count, p_voxel_gi_count, p_fog_volumes);
+ }
+}
+
+/* Lighting */
+
+void RenderForwardClustered::setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) {
+ if (current_cluster_builder != nullptr) {
+ current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, p_transform, p_half_extents);
+ }
+}
+
+void RenderForwardClustered::setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) {
+ if (current_cluster_builder != nullptr) {
+ current_cluster_builder->add_light(p_type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, p_transform, p_radius, p_spot_aperture);
+ }
+}
+
+void RenderForwardClustered::setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) {
+ if (current_cluster_builder != nullptr) {
+ current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, p_transform, p_half_extents);
+ }
+}
+
+/* Render scene */
+
+void RenderForwardClustered::_process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection) {
+ ERR_FAIL_NULL(ss_effects);
+ ERR_FAIL_COND(p_render_buffers.is_null());
+ ERR_FAIL_COND(p_environment.is_null());
+
+ Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ ERR_FAIL_COND(rb_data.is_null());
+
+ RENDER_TIMESTAMP("Process SSAO");
+
+ RendererRD::SSEffects::SSAOSettings settings;
+ settings.radius = environment_get_ssao_radius(p_environment);
+ settings.intensity = environment_get_ssao_intensity(p_environment);
+ settings.power = environment_get_ssao_power(p_environment);
+ settings.detail = environment_get_ssao_detail(p_environment);
+ settings.horizon = environment_get_ssao_horizon(p_environment);
+ settings.sharpness = environment_get_ssao_sharpness(p_environment);
+ settings.full_screen_size = p_render_buffers->get_internal_size();
+
+ ss_effects->ssao_allocate_buffers(rb_data->ss_effects_data.ssao, settings, rb_data->ss_effects_data.linear_depth);
+ ss_effects->generate_ssao(rb_data->ss_effects_data.ssao, p_normal_buffer, p_projection, settings);
+}
+
+void RenderForwardClustered::_process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform) {
+ ERR_FAIL_NULL(ss_effects);
+ ERR_FAIL_COND(p_render_buffers.is_null());
+ ERR_FAIL_COND(p_environment.is_null());
+
+ Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ ERR_FAIL_COND(rb_data.is_null());
+
+ RENDER_TIMESTAMP("Process SSIL");
+
+ RendererRD::SSEffects::SSILSettings settings;
+ settings.radius = environment_get_ssil_radius(p_environment);
+ settings.intensity = environment_get_ssil_intensity(p_environment);
+ settings.sharpness = environment_get_ssil_sharpness(p_environment);
+ settings.normal_rejection = environment_get_ssil_normal_rejection(p_environment);
+ settings.full_screen_size = p_render_buffers->get_internal_size();
+
+ Projection correction;
+ correction.set_depth_correction(true);
+ Projection projection = correction * p_projection;
+ Transform3D transform = p_transform;
+ transform.set_origin(Vector3(0.0, 0.0, 0.0));
+ Projection last_frame_projection = rb_data->ss_effects_data.last_frame_projection * Projection(rb_data->ss_effects_data.last_frame_transform.affine_inverse()) * Projection(transform) * projection.inverse();
+
+ ss_effects->ssil_allocate_buffers(rb_data->ss_effects_data.ssil, settings, rb_data->ss_effects_data.linear_depth);
+ ss_effects->screen_space_indirect_lighting(rb_data->ss_effects_data.ssil, p_normal_buffer, p_projection, last_frame_projection, settings);
+ rb_data->ss_effects_data.last_frame_projection = projection;
+ rb_data->ss_effects_data.last_frame_transform = transform;
+}
+
+void RenderForwardClustered::_copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
+ Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ ERR_FAIL_COND(rb_data.is_null());
+
+ if (rb_data->ss_effects_data.ssil.last_frame.is_valid()) {
+ Size2i size = p_render_buffers->get_internal_size();
+ RID texture = p_render_buffers->get_internal_texture();
+ copy_effects->copy_to_rect(texture, rb_data->ss_effects_data.ssil.last_frame, Rect2i(0, 0, size.x, size.y));
+
+ int width = size.x;
+ int height = size.y;
+ for (int i = 0; i < rb_data->ss_effects_data.ssil.last_frame_slices.size() - 1; i++) {
+ width = MAX(1, width >> 1);
+ height = MAX(1, height >> 1);
+ copy_effects->make_mipmap(rb_data->ss_effects_data.ssil.last_frame_slices[i], rb_data->ss_effects_data.ssil.last_frame_slices[i + 1], Size2i(width, height));
+ }
+ }
+}
+
+void RenderForwardClustered::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer) {
+ // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ Ref<RenderBufferDataForwardClustered> rb_data;
+ if (rb.is_valid()) {
+ rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ }
+
+ if (rb.is_valid() && p_use_gi && rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ sdfgi->store_probes();
+ }
+
+ p_render_data->cube_shadows.clear();
+ p_render_data->shadows.clear();
+ p_render_data->directional_shadows.clear();
+
+ Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin);
+ float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier();
+ {
+ for (int i = 0; i < p_render_data->render_shadow_count; i++) {
+ RID li = p_render_data->render_shadows[i].light;
+ RID base = light_storage->light_instance_get_base_light(li);
+
+ if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) {
+ p_render_data->directional_shadows.push_back(i);
+ } else if (light_storage->light_get_type(base) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ p_render_data->cube_shadows.push_back(i);
+ } else {
+ p_render_data->shadows.push_back(i);
+ }
+ }
+
+ //cube shadows are rendered in their own way
+ for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) {
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info);
+ }
+
+ if (p_render_data->directional_shadows.size()) {
+ //open the pass for directional shadows
+ light_storage->update_directional_shadow_atlas();
+ RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
+
+ // Render GI
+
+ bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size();
+ bool render_gi = rb.is_valid() && p_use_gi;
+
+ if (render_shadows && render_gi) {
+ RENDER_TIMESTAMP("Render GI + Render Shadows (Parallel)");
+ } else if (render_shadows) {
+ RENDER_TIMESTAMP("Render Shadows");
+ } else if (render_gi) {
+ RENDER_TIMESTAMP("Render GI");
+ }
+
+ //prepare shadow rendering
+ if (render_shadows) {
+ _render_shadow_begin();
+
+ //render directional shadows
+ for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) {
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info);
+ }
+ //render positional shadows
+ for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) {
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info);
+ }
+
+ _render_shadow_process();
+ }
+
+ //start GI
+ if (render_gi) {
+ gi.process_gi(rb, p_normal_roughness_slices, p_voxel_gi_buffer, p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances);
+ }
+
+ //Do shadow rendering (in parallel with GI)
+ if (render_shadows) {
+ _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER);
+ }
+
+ if (render_gi) {
+ RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier
+ }
+
+ if (rb_data.is_valid() && ss_effects) {
+ if (p_use_ssao || p_use_ssil) {
+ Size2i size = rb->get_internal_size();
+
+ bool invalidate_uniform_set = false;
+ if (rb_data->ss_effects_data.linear_depth.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16_SFLOAT;
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ tf.width = (size.x + 1) / 2;
+ tf.height = (size.y + 1) / 2;
+ tf.mipmaps = 5;
+ tf.array_layers = 4;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ rb_data->ss_effects_data.linear_depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ RD::get_singleton()->set_resource_name(rb_data->ss_effects_data.linear_depth, "SS Effects Depth");
+ for (uint32_t i = 0; i < tf.mipmaps; i++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb_data->ss_effects_data.linear_depth, 0, i, 1, RD::TEXTURE_SLICE_2D_ARRAY);
+ rb_data->ss_effects_data.linear_depth_slices.push_back(slice);
+ RD::get_singleton()->set_resource_name(slice, "SS Effects Depth Mip " + itos(i) + " ");
+ }
+ invalidate_uniform_set = true;
+ }
+
+ RID depth_texture = rb->get_depth_texture();
+ ss_effects->downsample_depth(depth_texture, rb_data->ss_effects_data.linear_depth_slices, invalidate_uniform_set, size, p_render_data->scene_data->cam_projection);
+ }
+
+ if (p_use_ssao) {
+ // TODO make these proper stereo
+ _process_ssao(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection);
+ }
+
+ if (p_use_ssil) {
+ // TODO make these proper stereo
+ _process_ssil(rb, p_render_data->environment, p_normal_roughness_slices[0], p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform);
+ }
+ }
+
+ //full barrier here, we need raster, transfer and compute and it depends from the previous work
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL);
+
+ if (current_cluster_builder) {
+ current_cluster_builder->begin(p_render_data->scene_data->cam_transform, p_render_data->scene_data->cam_projection, !p_render_data->reflection_probe.is_valid());
+ }
+
+ bool using_shadows = true;
+
+ if (p_render_data->reflection_probe.is_valid()) {
+ if (!RSG::light_storage->reflection_probe_renders_shadows(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ using_shadows = false;
+ }
+ } else {
+ //do not render reflections when rendering a reflection probe
+ light_storage->update_reflection_probe_buffer(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment);
+ }
+
+ uint32_t directional_light_count = 0;
+ uint32_t positional_light_count = 0;
+ light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
+ texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse());
+
+ p_render_data->directional_light_count = directional_light_count;
+
+ if (current_cluster_builder) {
+ current_cluster_builder->bake_cluster();
+ }
+
+ if (rb.is_valid()) {
+ bool directional_shadows = RendererRD::LightStorage::get_singleton()->has_directional_shadows(directional_light_count);
+ _update_volumetric_fog(rb, p_render_data->environment, p_render_data->scene_data->cam_projection, p_render_data->scene_data->cam_transform, p_render_data->scene_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, p_render_data->voxel_gi_count, *p_render_data->fog_volumes);
+ }
+}
+
+void RenderForwardClustered::_process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive) {
+ ERR_FAIL_NULL(ss_effects);
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
+ Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ ERR_FAIL_COND(rb_data.is_null());
+
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8;
+ uint32_t view_count = p_render_buffers->get_view_count();
+
+ if (!can_use_effects) {
+ //just copy
+ copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), RID(), view_count);
+ return;
+ }
+
+ ERR_FAIL_COND(p_environment.is_null());
+ ERR_FAIL_COND(!environment_get_ssr_enabled(p_environment));
+
+ Size2i half_size = Size2i(internal_size.x / 2, internal_size.y / 2);
+ ss_effects->ssr_allocate_buffers(rb_data->ss_effects_data.ssr, _render_buffers_get_color_format(), half_size, view_count);
+
+ RID texture_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ RID depth_slices[RendererSceneRender::MAX_RENDER_VIEWS];
+ for (uint32_t v = 0; v < view_count; v++) {
+ texture_slices[v] = p_render_buffers->get_internal_texture(v);
+ depth_slices[v] = p_render_buffers->get_depth_texture(v);
+ }
+ ss_effects->screen_space_reflection(rb_data->ss_effects_data.ssr, texture_slices, p_normal_slices, p_metallic_slices, depth_slices, half_size, environment_get_ssr_max_steps(p_environment), environment_get_ssr_fade_in(p_environment), environment_get_ssr_fade_out(p_environment), environment_get_ssr_depth_tolerance(p_environment), view_count, p_projections, p_eye_offsets);
+ copy_effects->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : p_render_buffers->get_internal_texture(), rb_data->ss_effects_data.ssr.output, view_count);
+}
+
+void RenderForwardClustered::_process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
+ Size2i internal_size = p_render_buffers->get_internal_size();
+ bool can_use_effects = internal_size.x >= 8 && internal_size.y >= 8;
+
+ if (!can_use_effects) {
+ //just copy
+ return;
+ }
+
+ p_render_buffers->allocate_blur_textures();
+
+ for (uint32_t v = 0; v < p_render_buffers->get_view_count(); v++) {
+ RID internal_texture = p_render_buffers->get_internal_texture(v);
+ RID depth_texture = p_render_buffers->get_depth_texture(v);
+ ss_effects->sub_surface_scattering(p_render_buffers, internal_texture, depth_texture, p_camera, internal_size);
+ }
+}
+
void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
- RenderBufferDataForwardClustered *render_buffer = nullptr;
- if (p_render_data->render_buffers.is_valid()) {
- render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+
+ Ref<RenderSceneBuffersRD> rb;
+ Ref<RenderBufferDataForwardClustered> rb_data;
+ if (p_render_data && p_render_data->render_buffers.is_valid()) {
+ rb = p_render_data->render_buffers;
+ rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
}
- RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 };
//first of all, make a new render pass
//fill up ubo
+ RENDER_TIMESTAMP("Prepare 3D Scene");
+
+ // sdfgi first
+ _update_sdfgi(p_render_data);
+
+ // assign render indices to voxel_gi_instances
+ for (uint32_t i = 0; i < (uint32_t)p_render_data->voxel_gi_instances->size(); i++) {
+ RID voxel_gi_instance = (*p_render_data->voxel_gi_instances)[i];
+ gi.voxel_gi_instance_set_render_index(voxel_gi_instance, i);
+ }
+
+ // obtain cluster builder
+ if (rb_data.is_valid()) {
+ current_cluster_builder = rb_data->cluster_builder;
+ } else if (light_storage->owns_reflection_probe_instance(p_render_data->reflection_probe)) {
+ current_cluster_builder = light_storage->reflection_probe_instance_get_cluster_builder(p_render_data->reflection_probe, &cluster_builder_shared);
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ light_storage->reflection_probe_set_baked_exposure(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe), RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes));
+ }
+ } else {
+ ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
+ current_cluster_builder = nullptr;
+ }
+
+ p_render_data->voxel_gi_count = 0;
+
+ if (rb.is_valid()) {
+ if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ if (sdfgi.is_valid()) {
+ sdfgi->update_cascades();
+ sdfgi->pre_process_gi(p_render_data->scene_data->cam_transform, p_render_data);
+ sdfgi->update_light();
+ }
+ }
+
+ gi.setup_voxel_gi_instances(p_render_data, p_render_data->render_buffers, p_render_data->scene_data->cam_transform, *p_render_data->voxel_gi_instances, p_render_data->voxel_gi_count);
+ }
+
+ if (current_cluster_builder != nullptr) {
+ p_render_data->cluster_buffer = current_cluster_builder->get_cluster_buffer();
+ p_render_data->cluster_size = current_cluster_builder->get_cluster_size();
+ p_render_data->cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
+ }
+
+ _update_vrs(rb);
+
RENDER_TIMESTAMP("Setup 3D Scene");
- //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size;
- scene_state.ubo.directional_light_count = 0;
- scene_state.ubo.opaque_prepass_threshold = 0.99f;
+ // check if we need motion vectors
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
+ p_render_data->scene_data->calculate_motion_vectors = true;
+ } else if (rb.is_valid() && rb->get_use_taa()) {
+ p_render_data->scene_data->calculate_motion_vectors = true;
+ } else {
+ p_render_data->scene_data->calculate_motion_vectors = false;
+ }
+
+ //p_render_data->scene_data->subsurface_scatter_width = subsurface_scatter_size;
+ p_render_data->scene_data->directional_light_count = 0;
+ p_render_data->scene_data->opaque_prepass_threshold = 0.99f;
Size2i screen_size;
RID color_framebuffer;
@@ -1304,13 +1623,12 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool using_sdfgi = false;
bool using_voxelgi = false;
bool reverse_cull = false;
- bool using_ssil = p_render_data->environment.is_valid() && environment_is_ssil_enabled(p_render_data->environment);
+ bool using_ssil = p_render_data->environment.is_valid() && environment_get_ssil_enabled(p_render_data->environment);
- if (render_buffer) {
- screen_size.x = render_buffer->width;
- screen_size.y = render_buffer->height;
+ if (rb.is_valid()) {
+ screen_size = rb->get_internal_size();
- if (render_buffer->use_taa || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
+ if (rb->get_use_taa() || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
color_pass_flags |= COLOR_PASS_FLAG_MOTION_VECTORS;
}
@@ -1318,39 +1636,34 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
using_voxelgi = true;
}
- if (p_render_data->view_count > 1) {
- depth_pass_mode = PASS_MODE_DEPTH;
- } else if (!p_render_data->environment.is_valid() && using_voxelgi) {
+ if (p_render_data->environment.is_null() && using_voxelgi) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI;
- } else if (p_render_data->environment.is_valid() && (environment_is_ssr_enabled(p_render_data->environment) || environment_is_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
- if (environment_is_sdfgi_enabled(p_render_data->environment)) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_ssr_enabled(p_render_data->environment) || environment_get_sdfgi_enabled(p_render_data->environment) || using_voxelgi)) {
+ if (environment_get_sdfgi_enabled(p_render_data->environment)) {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS; // also voxelgi
using_sdfgi = true;
} else {
depth_pass_mode = using_voxelgi ? PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI : PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
- if (environment_is_ssr_enabled(p_render_data->environment)) {
+ if (environment_get_ssr_enabled(p_render_data->environment)) {
using_separate_specular = true;
using_ssr = true;
color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
}
- } else if (p_render_data->environment.is_valid() && (environment_is_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_ssao_enabled(p_render_data->environment) || using_ssil || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) {
depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS;
}
switch (depth_pass_mode) {
case PASS_MODE_DEPTH: {
- depth_framebuffer = render_buffer->depth_fb;
+ depth_framebuffer = rb_data->get_depth_fb();
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: {
- _allocate_normal_roughness_texture(render_buffer);
- depth_framebuffer = render_buffer->depth_normal_roughness_fb;
+ depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS);
depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0));
} break;
case PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI: {
- _allocate_normal_roughness_texture(render_buffer);
- render_buffer->ensure_voxelgi();
- depth_framebuffer = render_buffer->depth_normal_roughness_voxelgi_fb;
+ depth_framebuffer = rb_data->get_depth_fb(RenderBufferDataForwardClustered::DEPTH_FB_ROUGHNESS_VOXELGI);
depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0));
depth_pass_clear.push_back(Color(0, 0, 0, 0));
} break;
@@ -1358,24 +1671,23 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
};
}
- if (p_render_data->view_count > 1) {
+ if (p_render_data->scene_data->view_count > 1) {
color_pass_flags |= COLOR_PASS_FLAG_MULTIVIEW;
}
- color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
- color_only_framebuffer = render_buffer->color_only_fb;
+ color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
+ color_only_framebuffer = rb_data->get_color_only_fb();
} else if (p_render_data->reflection_probe.is_valid()) {
- uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
+ uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
- color_framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ color_framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
color_only_framebuffer = color_framebuffer;
- depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ depth_framebuffer = light_storage->reflection_probe_instance_get_depth_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
- env = nullptr;
}
reverse_cull = true; // for some reason our views are inverted
@@ -1383,18 +1695,17 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
ERR_FAIL(); //bug?
}
- scene_state.ubo.viewport_size[0] = screen_size.x;
- scene_state.ubo.viewport_size[1] = screen_size.y;
+ p_render_data->scene_data->emissive_exposure_normalization = -1.0;
RD::get_singleton()->draw_command_begin_label("Render Setup");
- _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
+ _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform);
_setup_voxelgis(*p_render_data->voxel_gi_instances);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
- _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, using_sdfgi, using_sdfgi || using_voxelgi);
+ _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, color_pass_flags, using_sdfgi, using_sdfgi || using_voxelgi);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
render_list[RENDER_LIST_ALPHA].sort_by_reverse_depth_and_priority();
_fill_instance_data(RENDER_LIST_OPAQUE, p_render_data->render_info ? p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE] : (int *)nullptr);
@@ -1402,16 +1713,18 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_end_label();
- bool using_sss = render_buffer && scene_state.used_sss && sub_surface_scattering_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
+ bool using_sss = rb_data.is_valid() && scene_state.used_sss && ss_effects->sss_get_quality() != RS::SUB_SURFACE_SCATTERING_QUALITY_DISABLED;
if (using_sss && !using_separate_specular) {
using_separate_specular = true;
color_pass_flags |= COLOR_PASS_FLAG_SEPARATE_SPECULAR;
- color_framebuffer = render_buffer->get_color_pass_fb(color_pass_flags);
+ color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
}
RID radiance_texture;
bool draw_sky = false;
bool draw_sky_fog_only = false;
+ // We invert luminance_multiplier for sky so that we can combine it with exposure value.
+ float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
Color clear_color;
bool keep_color = false;
@@ -1420,24 +1733,30 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
+ bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
clear_color = p_default_bg_color;
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
- if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) {
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
+ if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(p_render_data->environment);
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
- if ((p_render_data->render_buffers.is_valid() && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) || environment_is_fog_enabled(p_render_data->environment)) {
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
+ if ((rb.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -1460,18 +1779,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ Projection projection = p_render_data->scene_data->cam_projection;
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- projection = correction * p_render_data->cam_projection;
+ projection = correction * p_render_data->scene_data->cam_projection;
}
- sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
+ sky.setup(p_render_data->environment, rb, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this);
+
+ sky_energy_multiplier *= bg_energy_multiplier;
- RID sky_rid = env->sky;
+ RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(env, projection, p_render_data->cam_transform, time);
+ sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -1487,7 +1808,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool debug_sdfgi_probes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI_PROBES;
bool depth_pre_pass = bool(GLOBAL_GET("rendering/driver/depth_prepass/enable")) && depth_framebuffer.is_valid();
- bool using_ssao = depth_pre_pass && p_render_data->render_buffers.is_valid() && p_render_data->environment.is_valid() && environment_is_ssao_enabled(p_render_data->environment);
+ bool using_ssao = depth_pre_pass && rb.is_valid() && p_render_data->environment.is_valid() && environment_get_ssao_enabled(p_render_data->environment);
bool continue_depth = false;
if (depth_pre_pass) { //depth pre pass
@@ -1510,7 +1831,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID());
bool finish_depth = using_ssao || using_sdfgi || using_voxelgi;
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
_render_list_with_threads(&render_list_params, depth_framebuffer, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, needs_pre_resolve ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, finish_depth ? RD::FINAL_ACTION_READ : RD::FINAL_ACTION_CONTINUE, needs_pre_resolve ? Vector<Color>() : depth_pass_clear);
RD::get_singleton()->draw_command_end_label();
@@ -1519,16 +1840,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
_pre_resolve_render(p_render_data, using_sdfgi || using_voxelgi);
}
- if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
RENDER_TIMESTAMP("Resolve Depth Pre-Pass (MSAA)");
RD::get_singleton()->draw_command_begin_label("Resolve Depth Pre-Pass (MSAA)");
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS_VOXEL_GI) {
if (needs_pre_resolve) {
RD::get_singleton()->barrier(RD::BARRIER_MASK_RASTER, RD::BARRIER_MASK_COMPUTE);
}
- storage->get_effects()->resolve_gi(render_buffer->depth_msaa, render_buffer->normal_roughness_buffer_msaa, using_voxelgi ? render_buffer->voxelgi_buffer_msaa : RID(), render_buffer->depth, render_buffer->normal_roughness_buffer, using_voxelgi ? render_buffer->voxelgi_buffer : RID(), Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ resolve_effects->resolve_gi(rb_data->get_depth_msaa(v), rb_data->get_normal_roughness_msaa(v), using_voxelgi ? rb_data->get_voxelgi_msaa(v) : RID(), rb->get_depth_texture(v), rb_data->get_normal_roughness(v), using_voxelgi ? rb_data->get_voxelgi(v) : RID(), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]);
+ }
} else if (finish_depth) {
- storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]);
+ }
}
RD::get_singleton()->draw_command_end_label();
}
@@ -1536,14 +1861,20 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
continue_depth = !finish_depth;
}
- _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, render_buffer ? render_buffer->normal_roughness_buffer : RID(), render_buffer ? render_buffer->voxelgi_buffer : RID());
+ RID normal_roughness_views[RendererSceneRender::MAX_RENDER_VIEWS];
+ if (rb_data.is_valid() && rb_data->has_normal_roughness()) {
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ normal_roughness_views[v] = rb_data->get_normal_roughness(v);
+ }
+ }
+ _pre_opaque_render(p_render_data, using_ssao, using_ssil, using_sdfgi || using_voxelgi, normal_roughness_views, rb_data.is_valid() && rb_data->has_voxelgi() ? rb_data->get_voxelgi() : RID());
RD::get_singleton()->draw_command_begin_label("Render Opaque Pass");
- scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
- scene_state.ubo.opaque_prepass_threshold = 0.0f;
+ p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
+ p_render_data->scene_data->opaque_prepass_threshold = 0.0f;
- _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
+ _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, rb.is_valid());
RENDER_TIMESTAMP("Render Opaque Pass");
@@ -1559,22 +1890,22 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
Vector<Color> c;
{
Color cc = clear_color.srgb_to_linear();
- if (using_separate_specular || render_buffer) {
+ if (using_separate_specular || rb_data.is_valid()) {
cc.a = 0; //subsurf scatter must be 0
}
c.push_back(cc);
- if (render_buffer) {
+ if (rb_data.is_valid()) {
c.push_back(Color(0, 0, 0, 0)); // Separate specular
c.push_back(Color(0, 0, 0, 0)); // Motion vectors
}
}
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
_render_list_with_threads(&render_list_params, color_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? (continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP) : RD::INITIAL_ACTION_CLEAR, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
if (will_continue_color && using_separate_specular) {
// close the specular framebuffer, as it's no longer used
- RD::get_singleton()->draw_list_begin(render_buffer->specular_only_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
+ RD::get_singleton()->draw_list_begin(rb_data->get_specular_only_fb(), RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_CONTINUE);
RD::get_singleton()->draw_list_end();
}
}
@@ -1586,9 +1917,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
- CameraMatrix dc;
+ Projection dc;
dc.set_depth_correction(true);
- CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
+ Projection cm = (dc * p_render_data->scene_data->cam_projection) * Projection(p_render_data->scene_data->cam_transform.affine_inverse());
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
RD::get_singleton()->draw_command_begin_label("Debug VoxelGIs");
for (int i = 0; i < (int)p_render_data->voxel_gi_instances->size(); i++) {
@@ -1599,18 +1930,17 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
}
if (debug_sdfgi_probes) {
- //debug voxelgis
+ //debug sdfgi
bool will_continue_color = (can_continue_color || draw_sky || draw_sky_fog_only);
bool will_continue_depth = (can_continue_depth || draw_sky || draw_sky_fog_only);
- CameraMatrix dc;
+ Projection dc;
dc.set_depth_correction(true);
- CameraMatrix cm = (dc * p_render_data->cam_projection) * CameraMatrix(p_render_data->cam_transform.affine_inverse());
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(color_only_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ);
- RD::get_singleton()->draw_command_begin_label("Debug SDFGI");
- _debug_sdfgi_probes(p_render_data->render_buffers, draw_list, color_only_framebuffer, cm);
- RD::get_singleton()->draw_command_end_label();
- RD::get_singleton()->draw_list_end();
+ Projection cms[RendererSceneRender::MAX_RENDER_VIEWS];
+ for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) {
+ cms[v] = (dc * p_render_data->scene_data->view_projection[v]) * Projection(p_render_data->scene_data->cam_transform.affine_inverse());
+ }
+ _debug_sdfgi_probes(rb, color_only_framebuffer, p_render_data->scene_data->view_count, cms, will_continue_color, will_continue_depth);
}
if (draw_sky || draw_sky_fog_only) {
@@ -1619,44 +1949,55 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Draw Sky");
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->cam_transform, time);
+ Projection projection = correction * p_render_data->scene_data->cam_projection;
+ sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
} else {
- sky.draw(env, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.draw(p_render_data->environment, can_continue_color, can_continue_depth, color_only_framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label();
}
- if (render_buffer && !can_continue_color && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
+ if (rb.is_valid() && !can_continue_color && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ // Handle views individual, might want to look at rewriting our resolve to do both layers in one pass.
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v));
+ }
if (using_separate_specular) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->specular_msaa, render_buffer->specular);
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ RD::get_singleton()->texture_resolve_multisample(rb_data->get_specular_msaa(v), rb_data->get_specular(v));
+ }
}
}
- if (render_buffer && !can_continue_depth && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
+ if (rb.is_valid() && !can_continue_depth && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]);
+ }
}
if (using_separate_specular) {
if (using_sss) {
RENDER_TIMESTAMP("Sub-Surface Scattering");
RD::get_singleton()->draw_command_begin_label("Process Sub-Surface Scattering");
- _process_sss(p_render_data->render_buffers, p_render_data->cam_projection);
+ _process_sss(rb, p_render_data->scene_data->cam_projection);
RD::get_singleton()->draw_command_end_label();
}
if (using_ssr) {
RENDER_TIMESTAMP("Screen-Space Reflections");
RD::get_singleton()->draw_command_begin_label("Process Screen-Space Reflections");
- _process_ssr(p_render_data->render_buffers, color_only_framebuffer, render_buffer->normal_roughness_buffer, render_buffer->specular, render_buffer->specular, Color(0, 0, 0, 1), p_render_data->environment, p_render_data->cam_projection, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED);
+ RID specular_views[RendererSceneRender::MAX_RENDER_VIEWS];
+ for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) {
+ specular_views[v] = rb_data->get_specular(v);
+ }
+ _process_ssr(rb, color_only_framebuffer, normal_roughness_views, rb_data->get_specular(), specular_views, p_render_data->environment, p_render_data->scene_data->view_projection, p_render_data->scene_data->view_eye_offset, rb->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED);
RD::get_singleton()->draw_command_end_label();
} else {
//just mix specular back
RENDER_TIMESTAMP("Merge Specular");
- storage->get_effects()->merge_specular(color_only_framebuffer, render_buffer->specular, render_buffer->msaa == RS::VIEWPORT_MSAA_DISABLED ? RID() : render_buffer->color, RID());
+ copy_effects->merge_specular(color_only_framebuffer, rb_data->get_specular(), rb->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? RID() : rb->get_internal_texture(), RID(), p_render_data->scene_data->view_count);
}
}
@@ -1680,8 +2021,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
{
uint32_t transparent_color_pass_flags = (color_pass_flags | COLOR_PASS_FLAG_TRANSPARENT) & ~(COLOR_PASS_FLAG_SEPARATE_SPECULAR);
- RID alpha_framebuffer = render_buffer ? render_buffer->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer;
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, render_buffer == nullptr, p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RID alpha_framebuffer = rb_data.is_valid() ? rb_data->get_color_pass_fb(transparent_color_pass_flags) : color_only_framebuffer;
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), false, PASS_MODE_COLOR, transparent_color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
_render_list_with_threads(&render_list_params, alpha_framebuffer, can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
}
@@ -1691,12 +2032,14 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Resolve");
- if (render_buffer && render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->color_msaa, render_buffer->color);
- if (render_buffer->use_taa) {
- RD::get_singleton()->texture_resolve_multisample(render_buffer->velocity_buffer_msaa, render_buffer->velocity_buffer);
+ if (rb.is_valid() && rb->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ RD::get_singleton()->texture_resolve_multisample(rb_data->get_color_msaa(v), rb->get_internal_texture(v));
+ resolve_effects->resolve_depth(rb_data->get_depth_msaa(v), rb->get_depth_texture(v), rb->get_internal_size(), texture_multisamples[rb->get_msaa_3d()]);
+ }
+ if (taa && rb->get_use_taa()) {
+ taa->msaa_resolve(rb);
}
- storage->get_effects()->resolve_depth(render_buffer->depth_msaa, render_buffer->depth, Vector2i(render_buffer->width, render_buffer->height), texture_multisamples[render_buffer->msaa]);
}
RD::get_singleton()->draw_command_end_label();
@@ -1704,22 +2047,245 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
RD::get_singleton()->draw_command_begin_label("Copy framebuffer for SSIL");
if (using_ssil) {
RENDER_TIMESTAMP("Copy Final Framebuffer (SSIL)");
- _copy_framebuffer_to_ssil(p_render_data->render_buffers);
+ _copy_framebuffer_to_ssil(rb);
}
RD::get_singleton()->draw_command_end_label();
- if (render_buffer && render_buffer->use_taa) {
+ if (rb.is_valid() && taa && rb->get_use_taa()) {
RENDER_TIMESTAMP("TAA")
- _process_taa(p_render_data->render_buffers, render_buffer->velocity_buffer, p_render_data->z_near, p_render_data->z_far);
+ taa->process(rb, _render_buffers_get_color_format(), p_render_data->scene_data->z_near, p_render_data->scene_data->z_far);
}
- if (p_render_data->render_buffers.is_valid()) {
- _debug_draw_cluster(p_render_data->render_buffers);
+ if (rb.is_valid()) {
+ _debug_draw_cluster(rb);
RENDER_TIMESTAMP("Tonemap");
_render_buffers_post_process_and_tonemap(p_render_data);
}
+
+ if (rb.is_valid()) {
+ _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex);
+
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ Vector<RID> view_rids;
+
+ // SDFGI renders at internal resolution, need to check if our debug correctly supports outputting upscaled.
+ Size2i size = rb->get_internal_size();
+ RID source_texture = rb->get_internal_texture();
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ view_rids.push_back(rb->get_internal_texture(v));
+ }
+
+ sdfgi->debug_draw(p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, size.x, size.y, rb->get_render_target(), source_texture, view_rids);
+ }
+ }
+}
+
+void RenderForwardClustered::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
+ Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
+ ERR_FAIL_COND(rb_data.is_null());
+
+ RendererSceneRenderRD::_render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occlusion_buffer);
+
+ RID render_target = p_render_buffers->get_render_target();
+
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb_data->ss_effects_data.ssao.ao_final.is_valid()) {
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
+ copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, true);
+ }
+
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb_data->ss_effects_data.ssil.ssil_final.is_valid()) {
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
+ copy_effects->copy_to_fb_rect(rb_data->ss_effects_data.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
+ }
+
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && p_render_buffers->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT)) {
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
+ RID ambient_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_AMBIENT);
+ RID reflection_texture = p_render_buffers->get_texture(RB_SCOPE_GI, RB_TEX_REFLECTION);
+ copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture, p_render_buffers->get_view_count() > 1);
+ }
+}
+
+void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+
+ ERR_FAIL_COND(!light_storage->owns_light_instance(p_light));
+
+ RID base = light_storage->light_instance_get_base_light(p_light);
+
+ Rect2i atlas_rect;
+ uint32_t atlas_size = 1;
+ RID atlas_fb;
+
+ bool using_dual_paraboloid = false;
+ bool using_dual_paraboloid_flip = false;
+ Vector2i dual_paraboloid_offset;
+ RID render_fb;
+ RID render_texture;
+ float zfar;
+
+ bool use_pancake = false;
+ bool render_cubemap = false;
+ bool finalize_cubemap = false;
+
+ bool flip_y = false;
+
+ Projection light_projection;
+ Transform3D light_transform;
+
+ if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) {
+ //set pssm stuff
+ uint64_t last_scene_shadow_pass = light_storage->light_instance_get_shadow_pass(p_light);
+ if (last_scene_shadow_pass != get_scene_pass()) {
+ light_storage->light_instance_set_directional_rect(p_light, light_storage->get_directional_shadow_rect());
+ light_storage->directional_shadow_increase_current_light();
+ light_storage->light_instance_set_shadow_pass(p_light, get_scene_pass());
+ }
+
+ use_pancake = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass);
+
+ atlas_rect = light_storage->light_instance_get_directional_rect(p_light);
+
+ if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+ atlas_rect.size.width /= 2;
+ atlas_rect.size.height /= 2;
+
+ if (p_pass == 1) {
+ atlas_rect.position.x += atlas_rect.size.width;
+ } else if (p_pass == 2) {
+ atlas_rect.position.y += atlas_rect.size.height;
+ } else if (p_pass == 3) {
+ atlas_rect.position += atlas_rect.size;
+ }
+ } else if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+ atlas_rect.size.height /= 2;
+
+ if (p_pass == 0) {
+ } else {
+ atlas_rect.position.y += atlas_rect.size.height;
+ }
+ }
+
+ float directional_shadow_size = light_storage->directional_shadow_get_size();
+ Rect2 atlas_rect_norm = atlas_rect;
+ atlas_rect_norm.position /= directional_shadow_size;
+ atlas_rect_norm.size /= directional_shadow_size;
+ light_storage->light_instance_set_directional_shadow_atlas_rect(p_light, p_pass, atlas_rect_norm);
+
+ zfar = RSG::light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE);
+
+ render_fb = light_storage->direction_shadow_get_fb();
+ render_texture = RID();
+ flip_y = true;
+
+ } else {
+ //set from shadow atlas
+
+ ERR_FAIL_COND(!light_storage->owns_shadow_atlas(p_shadow_atlas));
+ ERR_FAIL_COND(!light_storage->shadow_atlas_owns_light_instance(p_shadow_atlas, p_light));
+
+ RSG::light_storage->shadow_atlas_update(p_shadow_atlas);
+
+ uint32_t key = light_storage->shadow_atlas_get_light_instance_key(p_shadow_atlas, p_light);
+
+ uint32_t quadrant = (key >> RendererRD::LightStorage::QUADRANT_SHIFT) & 0x3;
+ uint32_t shadow = key & RendererRD::LightStorage::SHADOW_INDEX_MASK;
+ uint32_t subdivision = light_storage->shadow_atlas_get_quadrant_subdivision(p_shadow_atlas, quadrant);
+
+ ERR_FAIL_INDEX((int)shadow, light_storage->shadow_atlas_get_quadrant_shadow_size(p_shadow_atlas, quadrant));
+
+ uint32_t shadow_atlas_size = light_storage->shadow_atlas_get_size(p_shadow_atlas);
+ uint32_t quadrant_size = shadow_atlas_size >> 1;
+
+ atlas_rect.position.x = (quadrant & 1) * quadrant_size;
+ atlas_rect.position.y = (quadrant >> 1) * quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / subdivision);
+ atlas_rect.position.x += (shadow % subdivision) * shadow_size;
+ atlas_rect.position.y += (shadow / subdivision) * shadow_size;
+
+ atlas_rect.size.width = shadow_size;
+ atlas_rect.size.height = shadow_size;
+
+ zfar = light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE);
+
+ if (light_storage->light_get_type(base) == RS::LIGHT_OMNI) {
+ bool wrap = (shadow + 1) % subdivision == 0;
+ dual_paraboloid_offset = wrap ? Vector2i(1 - subdivision, 1) : Vector2i(1, 0);
+
+ if (light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ render_texture = light_storage->get_cubemap(shadow_size / 2);
+ render_fb = light_storage->get_cubemap_fb(shadow_size / 2, p_pass);
+
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass);
+ render_cubemap = true;
+ finalize_cubemap = p_pass == 5;
+ atlas_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas);
+
+ atlas_size = shadow_atlas_size;
+
+ if (p_pass == 0) {
+ _render_shadow_begin();
+ }
+
+ } else {
+ atlas_rect.position.x += 1;
+ atlas_rect.position.y += 1;
+ atlas_rect.size.x -= 2;
+ atlas_rect.size.y -= 2;
+
+ atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset;
+
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0);
+
+ using_dual_paraboloid = true;
+ using_dual_paraboloid_flip = p_pass == 1;
+ render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas);
+ flip_y = true;
+ }
+
+ } else if (light_storage->light_get_type(base) == RS::LIGHT_SPOT) {
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0);
+
+ render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas);
+
+ flip_y = true;
+ }
+ }
+
+ if (render_cubemap) {
+ //rendering to cubemap
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info);
+ if (finalize_cubemap) {
+ _render_shadow_process();
+ _render_shadow_end();
+ //reblit
+ Rect2 atlas_rect_norm = atlas_rect;
+ atlas_rect_norm.position /= float(atlas_size);
+ atlas_rect_norm.size /= float(atlas_size);
+ copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false);
+ atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size;
+ copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true);
+
+ //restore transform so it can be properly used
+ light_storage->light_instance_set_shadow_transform(p_light, Projection(), light_storage->light_instance_get_base_transform(p_light), zfar, 0, 0, 0);
+ }
+
+ } else {
+ //render shadow
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info);
+ }
}
void RenderForwardClustered::_render_shadow_begin() {
@@ -1731,39 +2297,42 @@ void RenderForwardClustered::_render_shadow_begin() {
scene_state.instance_data[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
+ RenderSceneDataRD scene_data;
+ scene_data.cam_projection = p_projection;
+ scene_data.cam_transform = p_transform;
+ scene_data.view_projection[0] = p_projection;
+ scene_data.z_far = p_zfar;
+ scene_data.z_near = 0.0;
+ scene_data.lod_distance_multiplier = p_lod_distance_multiplier;
+ scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_data.opaque_prepass_threshold = 0.1f;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
+
RenderDataRD render_data;
- render_data.cam_projection = p_projection;
- render_data.cam_transform = p_transform;
- render_data.view_projection[0] = p_projection;
- render_data.z_far = p_zfar;
- render_data.z_near = 0.0;
+ render_data.scene_data = &scene_data;
render_data.cluster_size = 1;
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
- render_data.lod_camera_plane = p_camera_plane;
- render_data.lod_distance_multiplier = p_lod_distance_multiplier;
render_data.render_info = p_render_info;
- scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
- scene_state.ubo.opaque_prepass_threshold = 0.1f;
-
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
- render_data.screen_mesh_lod_threshold = 0.0;
+ scene_data.screen_mesh_lod_threshold = 0.0;
} else {
- render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
+ scene_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
}
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
uint32_t render_list_from = render_list[RENDER_LIST_SECONDARY].elements.size();
- _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, false, false, true);
+ _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode, 0, false, false, true);
uint32_t render_list_size = render_list[RENDER_LIST_SECONDARY].elements.size() - render_list_from;
render_list[RENDER_LIST_SECONDARY].sort_by_key_range(render_list_from, render_list_size);
_fill_instance_data(RENDER_LIST_SECONDARY, p_render_info ? p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW] : (int *)nullptr, render_list_from, render_list_size, false);
@@ -1782,8 +2351,8 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page
shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete
shadow_pass.camera_plane = p_camera_plane;
- shadow_pass.screen_mesh_lod_threshold = render_data.screen_mesh_lod_threshold;
- shadow_pass.lod_distance_multiplier = render_data.lod_distance_multiplier;
+ shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold;
+ shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier;
shadow_pass.framebuffer = p_framebuffer;
shadow_pass.initial_depth_action = p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE : RD::INITIAL_ACTION_CONTINUE);
@@ -1811,7 +2380,7 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, 0, true, false, shadow_pass.rp_uniform_set, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -1821,24 +2390,27 @@ void RenderForwardClustered::_render_shadow_end(uint32_t p_barrier) {
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
+ RenderSceneDataRD scene_data;
+ scene_data.cam_projection = p_cam_projection;
+ scene_data.cam_transform = p_cam_transform;
+ scene_data.view_projection[0] = p_cam_projection;
+ scene_data.z_near = 0.0;
+ scene_data.z_far = p_cam_projection.get_z_far();
+ scene_data.dual_paraboloid_side = 0;
+ scene_data.opaque_prepass_threshold = 0.0;
+
RenderDataRD render_data;
- render_data.cam_projection = p_cam_projection;
- render_data.cam_transform = p_cam_transform;
- render_data.view_projection[0] = p_cam_projection;
- render_data.z_near = 0.0;
- render_data.z_far = p_cam_projection.get_z_far();
+ render_data.scene_data = &scene_data;
render_data.cluster_size = 1;
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
_update_render_base_uniform_set();
- scene_state.ubo.dual_paraboloid_side = 0;
- scene_state.ubo.opaque_prepass_threshold = 0.0;
_setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false);
@@ -1860,25 +2432,28 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
+ RenderSceneDataRD scene_data;
+ scene_data.cam_projection = p_cam_projection;
+ scene_data.cam_transform = p_cam_transform;
+ scene_data.view_projection[0] = p_cam_projection;
+ scene_data.dual_paraboloid_side = 0;
+ scene_data.material_uv2_mode = false;
+ scene_data.opaque_prepass_threshold = 0.0f;
+ scene_data.emissive_exposure_normalization = p_exposure_normalization;
+
RenderDataRD render_data;
- render_data.cam_projection = p_cam_projection;
- render_data.cam_transform = p_cam_transform;
- render_data.view_projection[0] = p_cam_projection;
+ render_data.scene_data = &scene_data;
render_data.cluster_size = 1;
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
_update_render_base_uniform_set();
- scene_state.ubo.dual_paraboloid_side = 0;
- scene_state.ubo.material_uv2_mode = false;
- scene_state.ubo.opaque_prepass_threshold = 0.0f;
-
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
@@ -1909,22 +2484,25 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardClustered::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
RD::get_singleton()->draw_command_begin_label("Render UV2");
+ RenderSceneDataRD scene_data;
+ scene_data.dual_paraboloid_side = 0;
+ scene_data.material_uv2_mode = true;
+ scene_data.opaque_prepass_threshold = 0.0;
+ scene_data.emissive_exposure_normalization = -1.0;
+
RenderDataRD render_data;
+ render_data.scene_data = &scene_data;
render_data.cluster_size = 1;
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
_update_render_base_uniform_set();
- scene_state.ubo.dual_paraboloid_side = 0;
- scene_state.ubo.material_uv2_mode = true;
- scene_state.ubo.opaque_prepass_threshold = 0.0;
-
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL;
@@ -1979,21 +2557,21 @@ void RenderForwardClustered::_render_uv2(const PagedArray<GeometryInstance *> &p
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
+void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
RENDER_TIMESTAMP("Render SDFGI");
RD::get_singleton()->draw_command_begin_label("Render SDFGI Voxel");
+ RenderSceneDataRD scene_data;
+
RenderDataRD render_data;
+ render_data.scene_data = &scene_data;
render_data.cluster_size = 1;
render_data.cluster_max_elements = 32;
render_data.instances = &p_instances;
_update_render_base_uniform_set();
- RenderBufferDataForwardClustered *render_buffer = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
- ERR_FAIL_COND(!render_buffer);
-
PassMode pass_mode = PASS_MODE_SDF;
_fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode);
render_list[RENDER_LIST_SECONDARY].sort_by_key();
@@ -2028,25 +2606,26 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
fb_size.x = p_size[right_axis];
fb_size.y = p_size[up_axis];
- render_data.cam_transform.origin = center + axis * half_extents;
- render_data.cam_transform.basis.set_column(0, right);
- render_data.cam_transform.basis.set_column(1, up);
- render_data.cam_transform.basis.set_column(2, axis);
+ scene_data.cam_transform.origin = center + axis * half_extents;
+ scene_data.cam_transform.basis.set_column(0, right);
+ scene_data.cam_transform.basis.set_column(1, up);
+ scene_data.cam_transform.basis.set_column(2, axis);
- //print_line("pass: " + itos(i) + " xform " + render_data.cam_transform);
+ //print_line("pass: " + itos(i) + " xform " + scene_data.cam_transform);
float h_size = half_extents[right_axis];
float v_size = half_extents[up_axis];
float d_size = half_extents[i] * 2.0;
- render_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size);
+ scene_data.cam_projection.set_orthogonal(-h_size, h_size, -v_size, v_size, 0, d_size);
//print_line("pass: " + itos(i) + " cam hsize: " + rtos(h_size) + " vsize: " + rtos(v_size) + " dsize " + rtos(d_size));
Transform3D to_bounds;
to_bounds.origin = p_bounds.position;
to_bounds.basis.scale(p_bounds.size);
- RendererStorageRD::store_transform(to_bounds.affine_inverse() * render_data.cam_transform, scene_state.ubo.sdf_to_bounds);
+ RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * scene_data.cam_transform, scene_state.ubo.sdf_to_bounds);
+ scene_data.emissive_exposure_normalization = p_exposure_normalization;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture);
@@ -2064,7 +2643,7 @@ void RenderForwardClustered::_render_sdfgi(RID p_render_buffers, const Vector3i
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardClustered::_base_uniforms_changed() {
+void RenderForwardClustered::base_uniforms_changed() {
if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
@@ -2125,15 +2704,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
case RS::DECAL_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::DECAL_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -2152,15 +2734,18 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -2174,14 +2759,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_omni_light_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_spot_light_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_spot_light_buffer());
uniforms.push_back(u);
}
@@ -2189,14 +2774,14 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_reflection_probe_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_reflection_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.append_id(get_directional_light_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_directional_light_buffer());
uniforms.push_back(u);
}
{
@@ -2233,7 +2818,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_decal_buffer());
+ u.append_id(RendererRD::TextureStorage::get_singleton()->get_decal_buffer());
uniforms.push_back(u);
}
@@ -2241,7 +2826,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -2261,9 +2846,11 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- RenderBufferDataForwardClustered *rb = nullptr;
+ Ref<RenderSceneBuffersRD> rb; // handy for not having to fully type out p_render_data->render_buffers all the time...
+ Ref<RenderBufferDataForwardClustered> rb_data;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_data->render_buffers));
+ rb = p_render_data->render_buffers;
+ rb_data = rb->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
}
//default render buffer and scene state uniform set
@@ -2280,6 +2867,13 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
{
RD::Uniform u;
u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.append_id(scene_state.implementation_uniform_buffers[p_index]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID instance_buffer = scene_state.instance_buffer[p_render_list];
if (instance_buffer == RID()) {
@@ -2293,62 +2887,60 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
if (p_radiance_texture.is_valid()) {
radiance_texture = p_radiance_texture;
} else {
- radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
}
RD::Uniform u;
- u.binding = 2;
+ u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.append_id(radiance_texture);
uniforms.push_back(u);
}
-
{
- RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID();
+ RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? light_storage->reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID();
RD::Uniform u;
- u.binding = 3;
+ u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (ref_texture.is_valid()) {
u.append_id(ref_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
}
uniforms.push_back(u);
}
-
{
RD::Uniform u;
- u.binding = 4;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture;
if (p_render_data && p_render_data->shadow_atlas.is_valid()) {
- texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
+ texture = RendererRD::LightStorage::get_singleton()->shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
}
u.append_id(texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 5;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
- u.append_id(directional_shadow_get_texture());
+ if (p_use_directional_shadow_atlas && RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture().is_valid()) {
+ u.append_id(RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture());
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 6;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
- RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
+ RID base = light_storage->lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
RID texture = light_storage->lightmap_get_texture(base);
RID rd_texture = texture_storage->texture_get_rd_texture(texture);
u.append_id(rd_texture);
@@ -2361,9 +2953,9 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
}
{
RD::Uniform u;
- u.binding = 7;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
if (p_render_data && i < (int)p_render_data->voxel_gi_instances->size()) {
RID tex = gi.voxel_gi_instance_get_texture((*p_render_data->voxel_gi_instances)[i]);
@@ -2381,7 +2973,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID cb = (p_render_data && p_render_data->cluster_buffer.is_valid()) ? p_render_data->cluster_buffer : scene_shader.default_vec4_xform_buffer;
u.append_id(cb);
@@ -2390,118 +2982,130 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend
{
RD::Uniform u;
- u.binding = 9;
+ u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture;
+ if (rb.is_valid() && rb->has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH)) {
+ texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH);
+ } else {
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
+ }
u.append_id(texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
- u.binding = 10;
+ u.binding = 11;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
- RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID bbt = rb_data.is_valid() ? rb->get_back_buffer_texture() : RID();
+ RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
{
- {
- RD::Uniform u;
- u.binding = 11;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = rb && rb->normal_roughness_buffer.is_valid() ? rb->normal_roughness_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_NORMAL);
- u.append_id(texture);
- uniforms.push_back(u);
- }
+ RD::Uniform u;
+ u.binding = 12;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID texture = rb_data.is_valid() && rb_data->has_normal_roughness() ? rb_data->get_normal_roughness() : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
+ u.append_id(texture);
+ uniforms.push_back(u);
+ }
- {
- RD::Uniform u;
- u.binding = 12;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID aot = rb ? render_buffers_get_ao_texture(p_render_data->render_buffers) : RID();
- RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- u.append_id(texture);
- uniforms.push_back(u);
- }
+ {
+ RD::Uniform u;
+ u.binding = 13;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID aot = rb_data.is_valid() ? rb_data->get_ao_texture() : RID();
+ RID texture = aot.is_valid() ? aot : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
+ uniforms.push_back(u);
+ }
- {
- RD::Uniform u;
- u.binding = 13;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID ambient_buffer = rb ? render_buffers_get_gi_ambient_texture(p_render_data->render_buffers) : RID();
- RID texture = ambient_buffer.is_valid() ? ambient_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- u.append_id(texture);
- uniforms.push_back(u);
- }
+ {
+ RD::Uniform u;
+ u.binding = 14;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID texture = rb_data.is_valid() && rb->has_texture(RB_SCOPE_GI, RB_TEX_AMBIENT) ? rb->get_texture(RB_SCOPE_GI, RB_TEX_AMBIENT) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
+ uniforms.push_back(u);
+ }
- {
- RD::Uniform u;
- u.binding = 14;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID reflection_buffer = rb ? render_buffers_get_gi_reflection_texture(p_render_data->render_buffers) : RID();
- RID texture = reflection_buffer.is_valid() ? reflection_buffer : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- u.append_id(texture);
- uniforms.push_back(u);
+ {
+ RD::Uniform u;
+ u.binding = 15;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID texture = rb_data.is_valid() && rb->has_texture(RB_SCOPE_GI, RB_TEX_REFLECTION) ? rb->get_texture(RB_SCOPE_GI, RB_TEX_REFLECTION) : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 16;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID t;
+ if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ t = sdfgi->lightprobe_texture;
}
- {
- RD::Uniform u;
- u.binding = 15;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID t;
- if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
- t = render_buffers_get_sdfgi_irradiance_probes(p_render_data->render_buffers);
- } else {
- t = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
- }
- u.append_id(t);
- uniforms.push_back(u);
+ if (t.is_null()) {
+ t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
}
- {
- RD::Uniform u;
- u.binding = 16;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- if (rb && render_buffers_is_sdfgi_enabled(p_render_data->render_buffers)) {
- u.append_id(render_buffers_get_sdfgi_occlusion_texture(p_render_data->render_buffers));
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE));
- }
- uniforms.push_back(u);
+ u.append_id(t);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 17;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID t;
+ if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ t = sdfgi->occlusion_texture;
}
- {
- RD::Uniform u;
- u.binding = 17;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.append_id(rb ? render_buffers_get_voxel_gi_buffer(p_render_data->render_buffers) : render_buffers_get_default_voxel_gi_buffer());
- uniforms.push_back(u);
+ if (t.is_null()) {
+ t = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
- {
- RD::Uniform u;
- u.binding = 18;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID vfog = RID();
- if (rb && render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
- vfog = render_buffers_get_volumetric_fog_texture(p_render_data->render_buffers);
- if (vfog.is_null()) {
- vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- }
- } else {
- vfog = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
- }
- u.append_id(vfog);
- uniforms.push_back(u);
+ u.append_id(t);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 18;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ RID voxel_gi;
+ if (rb.is_valid() && rb->has_custom_data(RB_SCOPE_GI)) {
+ Ref<RendererRD::GI::RenderBuffersGI> rbgi = rb->get_custom_data(RB_SCOPE_GI);
+ voxel_gi = rbgi->get_voxel_gi_buffer();
}
- {
- RD::Uniform u;
- u.binding = 19;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID ssil = rb ? render_buffers_get_ssil_texture(p_render_data->render_buffers) : RID();
- RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- u.append_id(texture);
- uniforms.push_back(u);
+ u.append_id(voxel_gi.is_valid() ? voxel_gi : render_buffers_get_default_voxel_gi_buffer());
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 19;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID vfog = RID();
+ if (rb_data.is_valid() && rb->has_custom_data(RB_SCOPE_FOG)) {
+ Ref<RendererRD::Fog::VolumetricFog> fog = rb->get_custom_data(RB_SCOPE_FOG);
+ vfog = fog->fog_map;
+ if (vfog.is_null()) {
+ vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
+ }
+ } else {
+ vfog = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
+ u.append_id(vfog);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 20;
+ u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
+ RID ssil = rb_data.is_valid() ? rb_data->get_ssil_texture() : RID();
+ RID texture = ssil.is_valid() ? ssil : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ u.append_id(texture);
+ uniforms.push_back(u);
}
return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET, uniforms);
@@ -2521,15 +3125,26 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
RD::Uniform u;
u.binding = 1;
+ u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
+ u.append_id(scene_state.implementation_uniform_buffers[0]);
+ uniforms.push_back(u);
+ }
+ {
+ RD::Uniform u;
+ u.binding = 2;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(scene_state.instance_buffer[RENDER_LIST_SECONDARY]);
+ RID instance_buffer = scene_state.instance_buffer[RENDER_LIST_SECONDARY];
+ if (instance_buffer == RID()) {
+ instance_buffer = scene_shader.default_vec4_xform_buffer; // any buffer will do since its not used
+ }
+ u.append_id(instance_buffer);
uniforms.push_back(u);
}
{
// No radiance texture.
- RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
RD::Uniform u;
- u.binding = 2;
+ u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.append_id(radiance_texture);
uniforms.push_back(u);
@@ -2537,9 +3152,9 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
// No reflection atlas.
- RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ RID ref_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
RD::Uniform u;
- u.binding = 3;
+ u.binding = 4;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.append_id(ref_texture);
uniforms.push_back(u);
@@ -2548,9 +3163,9 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
// No shadow atlas.
RD::Uniform u;
- u.binding = 4;
+ u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2558,9 +3173,9 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
// No directional shadow atlas.
RD::Uniform u;
- u.binding = 5;
+ u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -2568,10 +3183,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
// No Lightmaps
RD::Uniform u;
- u.binding = 6;
+ u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
u.append_id(default_tex);
}
@@ -2582,10 +3197,10 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
// No VoxelGIs
RD::Uniform u;
- u.binding = 7;
+ u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
u.append_id(default_tex);
}
@@ -2595,7 +3210,7 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
RD::Uniform u;
- u.binding = 8;
+ u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
RID cb = scene_shader.default_vec4_xform_buffer;
u.append_id(cb);
@@ -2607,28 +3222,28 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
+ u.binding = 10;
u.append_id(p_albedo_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 10;
+ u.binding = 11;
u.append_id(p_emission_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 11;
+ u.binding = 12;
u.append_id(p_emission_aniso_texture);
uniforms.push_back(u);
}
{
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 12;
+ u.binding = 13;
u.append_id(p_geom_facing_texture);
uniforms.push_back(u);
}
@@ -2636,38 +3251,55 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te
return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET, uniforms);
}
-RID RenderForwardClustered::_render_buffers_get_normal_texture(RID p_render_buffers) {
- RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
+RID RenderForwardClustered::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ Ref<RenderBufferDataForwardClustered> rb_data = p_render_buffers->get_custom_data(RB_SCOPE_FORWARD_CLUSTERED);
- return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->normal_roughness_buffer : rb->normal_roughness_buffer_msaa;
+ return p_render_buffers->get_msaa_3d() == RS::VIEWPORT_MSAA_DISABLED ? rb_data->get_normal_roughness() : rb_data->get_normal_roughness_msaa();
}
-RID RenderForwardClustered::_render_buffers_get_velocity_texture(RID p_render_buffers) {
- RenderBufferDataForwardClustered *rb = static_cast<RenderBufferDataForwardClustered *>(render_buffers_get_data(p_render_buffers));
+RID RenderForwardClustered::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ return p_render_buffers->get_velocity_buffer(p_render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED);
+}
+
+void RenderForwardClustered::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
+ ss_effects->ssao_set_quality(p_quality, p_half_size, p_adaptive_target, p_blur_passes, p_fadeout_from, p_fadeout_to);
+}
+
+void RenderForwardClustered::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
+ ss_effects->ssil_set_quality(p_quality, p_half_size, p_adaptive_target, p_blur_passes, p_fadeout_from, p_fadeout_to);
+}
- return rb->msaa == RS::VIEWPORT_MSAA_DISABLED ? rb->velocity_buffer : rb->velocity_buffer_msaa;
+void RenderForwardClustered::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
+ ss_effects->ssr_set_roughness_quality(p_quality);
+}
+
+void RenderForwardClustered::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
+ ss_effects->sss_set_quality(p_quality);
+}
+
+void RenderForwardClustered::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) {
+ ss_effects->sss_set_scale(p_scale, p_depth_scale);
}
RenderForwardClustered *RenderForwardClustered::singleton = nullptr;
-void RenderForwardClustered::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- if (ginstance->dirty_list_element.in_list()) {
+void RenderForwardClustered::GeometryInstanceForwardClustered::_mark_dirty() {
+ if (dirty_list_element.in_list()) {
return;
}
//clear surface caches
- GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ GeometryInstanceSurfaceDataCache *surf = surface_caches;
while (surf) {
GeometryInstanceSurfaceDataCache *next = surf->next;
- geometry_instance_surface_alloc.free(surf);
+ RenderForwardClustered::get_singleton()->geometry_instance_surface_alloc.free(surf);
surf = next;
}
- ginstance->surface_caches = nullptr;
+ surface_caches = nullptr;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ RenderForwardClustered::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element);
}
void RenderForwardClustered::_geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
@@ -2719,9 +3351,9 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
SceneShaderForwardClustered::MaterialData *material_shadow = nullptr;
void *surface_shadow = nullptr;
- if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK) {
+ if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_position && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip && p_material->shader_data->cull_mode == SceneShaderForwardClustered::ShaderData::CULL_BACK && !p_material->shader_data->uses_point_size) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material_shadow = static_cast<SceneShaderForwardClustered::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
@@ -2744,7 +3376,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
- storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
}
//shadow
@@ -2782,7 +3414,7 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material_chain(
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
break;
}
@@ -2802,7 +3434,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
SceneShaderForwardClustered::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2813,7 +3445,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2824,7 +3456,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardClustered::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
@@ -2835,7 +3467,7 @@ void RenderForwardClustered::_geometry_instance_add_surface(GeometryInstanceForw
}
}
-void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+void RenderForwardClustered::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
@@ -2942,6 +3574,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
ginstance->transforms_uniform_set = mesh_storage->multimesh_get_3d_uniform_set(ginstance->data->base, scene_shader.default_shader_rd, TRANSFORMS_UNIFORM_SET);
} else if (ginstance->data->base_type == RS::INSTANCE_PARTICLES) {
+ ginstance->base_flags |= INSTANCE_DATA_FLAG_PARTICLES;
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH;
ginstance->base_flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR;
@@ -2967,7 +3600,7 @@ void RenderForwardClustered::_geometry_instance_update(GeometryInstance *p_geome
ginstance->store_transform_cache = store_transform;
ginstance->can_sdfgi = false;
- if (!lightmap_instance_is_valid(ginstance->lightmap_instance)) {
+ if (!RendererRD::LightStorage::get_singleton()->lightmap_instance_is_valid(ginstance->lightmap_instance)) {
if (ginstance->voxel_gi_instances[0].is_null() && (ginstance->data->use_baked_light || ginstance->data->use_dynamic_gi)) {
ginstance->can_sdfgi = true;
}
@@ -2987,16 +3620,16 @@ void RenderForwardClustered::_update_dirty_geometry_instances() {
}
}
-void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+void RenderForwardClustered::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) {
switch (p_notification) {
- case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
- case RendererStorage::DEPENDENCY_CHANGED_MESH:
- case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
- static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ case Dependency::DEPENDENCY_CHANGED_MATERIAL:
+ case Dependency::DEPENDENCY_CHANGED_MESH:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
@@ -3007,12 +3640,12 @@ void RenderForwardClustered::_geometry_instance_dependency_changed(RendererStora
} break;
}
}
-void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
- static_cast<RenderForwardClustered *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+void RenderForwardClustered::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
}
-RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
- RS::InstanceType type = storage->get_base_type(p_base);
+RenderGeometryInstance *RenderForwardClustered::geometry_instance_create(RID p_base) {
+ RS::InstanceType type = RSG::utilities->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
GeometryInstanceForwardClustered *ginstance = geometry_instance_alloc.alloc();
@@ -3024,155 +3657,47 @@ RendererSceneRender::GeometryInstance *RenderForwardClustered::geometry_instance
ginstance->data->dependency_tracker.changed_callback = _geometry_instance_dependency_changed;
ginstance->data->dependency_tracker.deleted_callback = _geometry_instance_dependency_deleted;
- _geometry_instance_mark_dirty(ginstance);
+ ginstance->_mark_dirty();
return ginstance;
}
-void RenderForwardClustered::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->skeleton = p_skeleton;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_override = p_override;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_overlay = p_overlay;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->surface_materials = p_materials;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-void RenderForwardClustered::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->mesh_instance = p_mesh_instance;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) {
uint64_t frame = RSG::rasterizer->get_frame_number();
- if (frame != ginstance->prev_transform_change_frame) {
- ginstance->prev_transform = ginstance->transform;
- ginstance->prev_transform_change_frame = frame;
- ginstance->prev_transform_dirty = true;
+ if (frame != prev_transform_change_frame) {
+ prev_transform = transform;
+ prev_transform_change_frame = frame;
+ prev_transform_dirty = true;
}
- ginstance->transform = p_transform;
- ginstance->mirror = p_transform.basis.determinant() < 0;
- ginstance->data->aabb = p_aabb;
- ginstance->transformed_aabb = p_transformed_aabb;
-
- Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
- // handle non uniform scale here
- float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
- float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
-
- ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
-
- ginstance->lod_model_scale = max_scale;
-}
-void RenderForwardClustered::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lod_bias = p_lod_bias;
-}
-void RenderForwardClustered::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->fade_near = p_enable_near;
- ginstance->fade_near_begin = p_near_begin;
- ginstance->fade_near_end = p_near_end;
- ginstance->fade_far = p_enable_far;
- ginstance->fade_far_begin = p_far_begin;
- ginstance->fade_far_end = p_far_end;
+ RenderGeometryInstanceBase::set_transform(p_transform, p_aabb, p_transformed_aabbb);
}
-void RenderForwardClustered::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->parent_fade_alpha = p_alpha;
-}
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ lightmap_instance = p_lightmap_instance;
+ lightmap_uv_scale = p_lightmap_uv_scale;
+ lightmap_slice_index = p_lightmap_slice_index;
-void RenderForwardClustered::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->force_alpha = CLAMP(1.0 - p_transparency, 0, 1);
+ _mark_dirty();
}
-void RenderForwardClustered::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_baked_light = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_dynamic_gi = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lightmap_instance = p_lightmap_instance;
- ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
- ginstance->lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_lightmap_capture(const Color *p_sh9) {
if (p_sh9) {
- if (ginstance->lightmap_sh == nullptr) {
- ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ if (lightmap_sh == nullptr) {
+ lightmap_sh = RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.alloc();
}
- memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
} else {
- if (ginstance->lightmap_sh != nullptr) {
- geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
- ginstance->lightmap_sh = nullptr;
+ if (lightmap_sh != nullptr) {
+ RenderForwardClustered::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh);
+ lightmap_sh = nullptr;
}
}
- _geometry_instance_mark_dirty(ginstance);
+ _mark_dirty();
}
-void RenderForwardClustered::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->shader_parameters_offset = p_offset;
- _geometry_instance_mark_dirty(ginstance);
-}
-void RenderForwardClustered::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->cast_double_sided_shadows = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardClustered::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->layer_mask = p_layer_mask;
-}
-
-void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+void RenderForwardClustered::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) {
GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (ginstance->lightmap_sh != nullptr) {
@@ -3191,47 +3716,25 @@ void RenderForwardClustered::geometry_instance_free(GeometryInstance *p_geometry
uint32_t RenderForwardClustered::geometry_instance_get_pair_mask() {
return (1 << RS::INSTANCE_VOXEL_GI);
}
-void RenderForwardClustered::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
-}
-void RenderForwardClustered::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
-}
-void RenderForwardClustered::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
-}
-
-Transform3D RenderForwardClustered::geometry_instance_get_transform(GeometryInstance *p_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform3D());
- return ginstance->transform;
-}
-
-AABB RenderForwardClustered::geometry_instance_get_aabb(GeometryInstance *p_instance) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, AABB());
- return ginstance->data->aabb;
-}
-void RenderForwardClustered::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
if (p_voxel_gi_instance_count > 0) {
- ginstance->voxel_gi_instances[0] = p_voxel_gi_instances[0];
+ voxel_gi_instances[0] = p_voxel_gi_instances[0];
} else {
- ginstance->voxel_gi_instances[0] = RID();
+ voxel_gi_instances[0] = RID();
}
if (p_voxel_gi_instance_count > 1) {
- ginstance->voxel_gi_instances[1] = p_voxel_gi_instances[1];
+ voxel_gi_instances[1] = p_voxel_gi_instances[1];
} else {
- ginstance->voxel_gi_instances[1] = RID();
+ voxel_gi_instances[1] = RID();
}
}
-void RenderForwardClustered::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
- GeometryInstanceForwardClustered *ginstance = static_cast<GeometryInstanceForwardClustered *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->using_projectors = p_projector;
- ginstance->using_softshadows = p_softshadow;
- _geometry_instance_mark_dirty(ginstance);
+void RenderForwardClustered::GeometryInstanceForwardClustered::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) {
+ using_projectors = p_projector;
+ using_softshadows = p_softshadow;
+ _mark_dirty();
}
void RenderForwardClustered::_update_shader_quality_settings() {
@@ -3262,22 +3765,27 @@ void RenderForwardClustered::_update_shader_quality_settings() {
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
sc.constant_id = SPEC_CONSTANT_DECAL_FILTER;
- sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
sc.constant_id = SPEC_CONSTANT_PROJECTOR_FILTER;
- sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
scene_shader.set_default_specialization_constants(spec_constants);
- _base_uniforms_changed(); //also need this
+ base_uniforms_changed(); //also need this
}
-RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
- RendererSceneRenderRD(p_storage) {
+RenderForwardClustered::RenderForwardClustered() {
singleton = this;
/* SCENE SHADER */
@@ -3308,22 +3816,60 @@ RenderForwardClustered::RenderForwardClustered(RendererStorageRD *p_storage) :
{
defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n";
}
+#ifdef REAL_T_IS_DOUBLE
+ {
+ defines += "\n#define USE_DOUBLE_PRECISION \n";
+ }
+#endif
- scene_shader.init(p_storage, defines);
+ scene_shader.init(defines);
+ }
+
+ /* shadow sampler */
+ {
+ RD::SamplerState sampler;
+ sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
+ sampler.enable_compare = true;
+ sampler.compare_op = RD::COMPARE_OP_LESS;
+ shadow_sampler = RD::get_singleton()->sampler_create(sampler);
}
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
_update_shader_quality_settings();
+
+ resolve_effects = memnew(RendererRD::Resolve());
+ taa = memnew(RendererRD::TAA);
+ ss_effects = memnew(RendererRD::SSEffects);
}
RenderForwardClustered::~RenderForwardClustered() {
- directional_shadow_atlas_set_size(0);
+ if (ss_effects != nullptr) {
+ memdelete(ss_effects);
+ ss_effects = nullptr;
+ }
+
+ if (taa != nullptr) {
+ memdelete(taa);
+ taa = nullptr;
+ }
+
+ if (resolve_effects != nullptr) {
+ memdelete(resolve_effects);
+ resolve_effects = nullptr;
+ }
+
+ RD::get_singleton()->free(shadow_sampler);
+ RSG::light_storage->directional_shadow_atlas_set_size(0);
{
for (uint32_t i = 0; i < scene_state.uniform_buffers.size(); i++) {
RD::get_singleton()->free(scene_state.uniform_buffers[i]);
}
+ for (uint32_t i = 0; i < scene_state.implementation_uniform_buffers.size(); i++) {
+ RD::get_singleton()->free(scene_state.implementation_uniform_buffers[i]);
+ }
RD::get_singleton()->free(scene_state.lightmap_buffer);
RD::get_singleton()->free(scene_state.lightmap_capture_buffer);
for (uint32_t i = 0; i < RENDER_LIST_MAX; i++) {
diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
index 6ad42bf0ec..670eb93e20 100644
--- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h
@@ -28,15 +28,28 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
-#define RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
+#ifndef RENDER_FORWARD_CLUSTERED_H
+#define RENDER_FORWARD_CLUSTERED_H
#include "core/templates/paged_allocator.h"
+#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/effects/resolve.h"
+#include "servers/rendering/renderer_rd/effects/ss_effects.h"
+#include "servers/rendering/renderer_rd/effects/taa.h"
#include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
+
+#define RB_SCOPE_FORWARD_CLUSTERED SNAME("forward_clustered")
+
+#define RB_TEX_SPECULAR SNAME("specular")
+#define RB_TEX_SPECULAR_MSAA SNAME("specular_msaa")
+#define RB_TEX_ROUGHNESS SNAME("normal_roughnesss")
+#define RB_TEX_ROUGHNESS_MSAA SNAME("normal_roughnesss_msaa")
+#define RB_TEX_VOXEL_GI SNAME("voxel_gi")
+#define RB_TEX_VOXEL_GI_MSAA SNAME("voxel_gi_msaa")
namespace RendererSceneRenderImplementation {
@@ -72,7 +85,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RENDER_LIST_ALPHA, //used for transparent objects
RENDER_LIST_SECONDARY, //used for shadows and other objects
RENDER_LIST_MAX
-
};
/* Scene Shader */
@@ -81,59 +93,81 @@ class RenderForwardClustered : public RendererSceneRenderRD {
/* Framebuffer */
- struct RenderBufferDataForwardClustered : public RenderBufferData {
- //for rendering, may be MSAAd
-
- RID color;
- RID depth;
- RID specular;
- RID normal_roughness_buffer;
- RID voxelgi_buffer;
- RID velocity_buffer;
-
- RS::ViewportMSAA msaa;
- RD::TextureSamples texture_samples;
- bool use_taa;
-
- RID color_msaa;
- RID depth_msaa;
- RID specular_msaa;
- RID normal_roughness_buffer_msaa;
- RID roughness_buffer_msaa;
- RID voxelgi_buffer_msaa;
- RID velocity_buffer_msaa;
-
- RID depth_fb;
- RID depth_normal_roughness_fb;
- RID depth_normal_roughness_voxelgi_fb;
- RID color_only_fb;
- RID specular_only_fb;
- int width, height;
- HashMap<uint32_t, RID> color_framebuffers;
- uint32_t view_count;
+ class RenderBufferDataForwardClustered : public RenderBufferCustomDataRD {
+ GDCLASS(RenderBufferDataForwardClustered, RenderBufferCustomDataRD)
+
+ private:
+ RenderSceneBuffersRD *render_buffers = nullptr;
+ RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
+
+ public:
+ ClusterBuilderRD *cluster_builder = nullptr;
+
+ struct SSEffectsData {
+ RID linear_depth;
+ Vector<RID> linear_depth_slices;
+
+ RID downsample_uniform_set;
+
+ Projection last_frame_projection;
+ Transform3D last_frame_transform;
+
+ RendererRD::SSEffects::SSAORenderBuffers ssao;
+ RendererRD::SSEffects::SSILRenderBuffers ssil;
+ RendererRD::SSEffects::SSRRenderBuffers ssr;
+ } ss_effects_data;
+
+ enum DepthFrameBufferType {
+ DEPTH_FB,
+ DEPTH_FB_ROUGHNESS,
+ DEPTH_FB_ROUGHNESS_VOXELGI
+ };
RID render_sdfgi_uniform_set;
+
+ RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA); }
+ RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_COLOR_MSAA, p_layer, 0); }
+
+ RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA); }
+ RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_DEPTH_MSAA, p_layer, 0); }
+
void ensure_specular();
+ bool has_specular() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
+ RID get_specular() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR); }
+ RID get_specular(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR, p_layer, 0); }
+ RID get_specular_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_SPECULAR_MSAA, p_layer, 0); }
+
+ void ensure_normal_roughness_texture();
+ bool has_normal_roughness() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
+ RID get_normal_roughness() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS); }
+ RID get_normal_roughness(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS, p_layer, 0); }
+ RID get_normal_roughness_msaa() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA); }
+ RID get_normal_roughness_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_ROUGHNESS_MSAA, p_layer, 0); }
+
void ensure_voxelgi();
- void ensure_velocity();
- void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
+ bool has_voxelgi() const { return render_buffers->has_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
+ RID get_voxelgi() const { return render_buffers->get_texture(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI); }
+ RID get_voxelgi(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI, p_layer, 0); }
+ RID get_voxelgi_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_FORWARD_CLUSTERED, RB_TEX_VOXEL_GI_MSAA, p_layer, 0); }
+
+ RID get_color_only_fb();
RID get_color_pass_fb(uint32_t p_color_pass_flags);
+ RID get_depth_fb(DepthFrameBufferType p_type = DEPTH_FB);
+ RID get_specular_only_fb();
- ~RenderBufferDataForwardClustered();
+ RID get_ao_texture() const { return ss_effects_data.ssao.ao_final; }
+ RID get_ssil_texture() const { return ss_effects_data.ssil.ssil_final; }
+
+ virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
+ virtual void free_data() override;
};
- virtual RenderBufferData *_create_render_buffer_data() override;
- void _allocate_normal_roughness_texture(RenderBufferDataForwardClustered *rb);
+ virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
RID render_base_uniform_set;
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
- virtual void _base_uniforms_changed() override;
- virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
- virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
-
bool base_uniform_set_updated = false;
void _update_render_base_uniform_set();
RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture);
@@ -172,7 +206,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
RID render_pass_uniform_set;
bool force_wireframe = false;
Vector2 uv_offset;
- Plane lod_plane;
float lod_distance_multiplier = 0.0;
float screen_mesh_lod_threshold = 0.0;
RD::FramebufferFormatID framebuffer_format = 0;
@@ -180,7 +213,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
uint32_t barrier = RD::BARRIER_MASK_ALL;
bool use_directional_soft_shadow = false;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_no_gi, bool p_use_directional_soft_shadows, RID p_render_pass_uniform_set, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -192,7 +225,6 @@ class RenderForwardClustered : public RendererSceneRenderRD {
render_pass_uniform_set = p_render_pass_uniform_set;
force_wireframe = p_force_wireframe;
uv_offset = p_uv_offset;
- lod_plane = p_lod_plane;
lod_distance_multiplier = p_lod_distance_multiplier;
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
element_offset = p_element_offset;
@@ -203,20 +235,24 @@ class RenderForwardClustered : public RendererSceneRenderRD {
struct LightmapData {
float normal_xform[12];
+ float pad[3];
+ float exposure_normalization;
};
struct LightmapCaptureData {
float sh[9 * 4];
};
+ // When changing any of these enums, remember to change the corresponding enums in the shader files as well.
enum {
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
- INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
- INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
- INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
- INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
+ INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
+ INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 8,
+ INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 9,
+ INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 10,
+ INSTANCE_DATA_FLAG_PARTICLES = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
@@ -228,60 +264,22 @@ class RenderForwardClustered : public RendererSceneRenderRD {
};
struct SceneState {
- // This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code
+ // This struct is loaded into Set 1 - Binding 1, populated at start of rendering a frame, must match with shader code
struct UBO {
- float projection_matrix[16];
- float inv_projection_matrix[16];
- float inv_view_matrix[16];
- float view_matrix[16];
-
- float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
- float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
-
- float viewport_size[2];
- float screen_pixel_size[2];
-
uint32_t cluster_shift;
uint32_t cluster_width;
uint32_t cluster_type_size;
uint32_t max_cluster_element_count_div_32;
- float directional_penumbra_shadow_kernel[128]; //32 vec4s
- float directional_soft_shadow_kernel[128];
- float penumbra_shadow_kernel[128];
- float soft_shadow_kernel[128];
-
- float ambient_light_color_energy[4];
-
- float ambient_color_sky_mix;
- uint32_t use_ambient_light;
- uint32_t use_ambient_cubemap;
- uint32_t use_reflection_cubemap;
-
- float radiance_inverse_xform[12];
-
- float shadow_atlas_pixel_size[2];
- float directional_shadow_pixel_size[2];
-
- uint32_t directional_light_count;
- float dual_paraboloid_side;
- float z_far;
- float z_near;
-
uint32_t ss_effects_flags;
float ssao_light_affect;
float ssao_ao_affect;
- uint32_t roughness_limiter_enabled;
-
- float roughness_limiter_amount;
- float roughness_limiter_limit;
- float opaque_prepass_threshold;
- uint32_t roughness_limiter_pad;
+ uint32_t pad1;
float sdf_to_bounds[16];
int32_t sdf_offset[3];
- uint32_t material_uv2_mode;
+ uint32_t pad2;
int32_t sdf_size[3];
uint32_t gi_upscale_for_msaa;
@@ -290,31 +288,13 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float volumetric_fog_inv_length;
float volumetric_fog_detail_spread;
uint32_t volumetric_fog_pad;
-
- // Fog
- uint32_t fog_enabled;
- float fog_density;
- float fog_height;
- float fog_height_density;
-
- float fog_light_color[3];
- float fog_sun_scatter;
-
- float fog_aerial_perspective;
-
- float time;
- float reflection_multiplier;
-
- uint32_t pancake_shadows;
-
- float taa_jitter[2];
- uint32_t pad[2];
};
struct PushConstant {
uint32_t base_index; //
uint32_t uv_offset; //packed
- uint32_t pad[2];
+ uint32_t multimesh_motion_vectors_current_offset;
+ uint32_t multimesh_motion_vectors_previous_offset;
};
struct InstanceData {
@@ -327,11 +307,10 @@ class RenderForwardClustered : public RendererSceneRenderRD {
float lightmap_uv_scale[4];
};
- UBO ubo_data[2];
- UBO &ubo = ubo_data[0];
- UBO &prev_ubo = ubo_data[1];
+ UBO ubo;
LocalVector<RID> uniform_buffers;
+ LocalVector<RID> implementation_uniform_buffers;
LightmapData lightmaps[MAX_LIGHTMAPS];
RID lightmap_ids[MAX_LIGHTMAPS];
@@ -381,7 +360,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
void _setup_voxelgis(const PagedArray<RID> &p_voxelgis);
- void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
+ void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
struct RenderElementInfo {
enum { MAX_REPEATS = (1 << 20) - 1 };
@@ -406,12 +385,12 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _update_instance_data_buffer(RenderListType p_render_list);
void _fill_instance_data(RenderListType p_render_list, int *p_render_info = nullptr, uint32_t p_offset = 0, int32_t p_max_elements = -1, bool p_update_buffer = true);
- void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false);
+ void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, uint32_t p_color_pass_flags, bool p_using_sdfgi = false, bool p_using_opaque_gi = false, bool p_append = false);
HashMap<Size2i, RID> sdfgi_framebuffer_size_cache;
struct GeometryInstanceData;
- struct GeometryInstanceForwardClustered;
+ class GeometryInstanceForwardClustered;
struct GeometryInstanceLightmapSH {
Color sh[9];
@@ -471,77 +450,52 @@ class RenderForwardClustered : public RendererSceneRenderRD {
GeometryInstanceForwardClustered *owner = nullptr;
};
- struct GeometryInstanceForwardClustered : public GeometryInstance {
+ class GeometryInstanceForwardClustered : public RenderGeometryInstanceBase {
+ public:
+ // lightmap
+ RID lightmap_instance;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index;
+ GeometryInstanceLightmapSH *lightmap_sh = nullptr;
+
//used during rendering
- bool mirror = false;
- bool non_uniform_scale = false;
- float lod_bias = 0.0;
- float lod_model_scale = 1.0;
- AABB transformed_aabb; //needed for LOD
- float depth = 0;
+
uint32_t gi_offset_cache = 0;
- uint32_t flags_cache = 0;
bool store_transform_cache = true;
- int32_t shader_parameters_offset = -1;
- uint32_t lightmap_slice_index;
- Rect2 lightmap_uv_scale;
- uint32_t layer_mask = 1;
RID transforms_uniform_set;
uint32_t instance_count = 0;
uint32_t trail_steps = 1;
- RID mesh_instance;
bool can_sdfgi = false;
bool using_projectors = false;
bool using_softshadows = false;
- bool fade_near = false;
- float fade_near_begin = 0;
- float fade_near_end = 0;
- bool fade_far = false;
- float fade_far_begin = 0;
- float fade_far_end = 0;
- float force_alpha = 1.0;
- float parent_fade_alpha = 1.0;
//used during setup
- uint32_t base_flags = 0;
uint64_t prev_transform_change_frame = 0xFFFFFFFF;
bool prev_transform_dirty = true;
- Transform3D transform;
Transform3D prev_transform;
RID voxel_gi_instances[MAX_VOXEL_GI_INSTANCESS_PER_INSTANCE];
- RID lightmap_instance;
- GeometryInstanceLightmapSH *lightmap_sh = nullptr;
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
SelfList<GeometryInstanceForwardClustered> dirty_list_element;
- struct Data {
- //data used less often goes into regular heap
- RID base;
- RS::InstanceType base_type;
-
- RID skeleton;
- Vector<RID> surface_materials;
- RID material_override;
- RID material_overlay;
- AABB aabb;
+ GeometryInstanceForwardClustered() :
+ dirty_list_element(this) {}
- bool use_dynamic_gi = false;
- bool use_baked_light = false;
- bool cast_double_sided_shadows = false;
- bool mirror = false;
- bool dirty_dependencies = false;
+ virtual void _mark_dirty() override;
- RendererStorage::DependencyTracker dependency_tracker;
- };
+ virtual void set_transform(const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) override;
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void set_lightmap_capture(const Color *p_sh9) override;
- Data *data = nullptr;
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override {}
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override {}
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override {}
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
- GeometryInstanceForwardClustered() :
- dirty_list_element(this) {}
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override;
};
- static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
- static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
SelfList<GeometryInstanceForwardClustered>::List geometry_instance_dirty_list;
@@ -552,8 +506,7 @@ class RenderForwardClustered : public RendererSceneRenderRD {
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, SceneShaderForwardClustered::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardClustered *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
- void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
- void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
/* Render List */
@@ -618,61 +571,94 @@ class RenderForwardClustered : public RendererSceneRenderRD {
virtual void _update_shader_quality_settings() override;
+ /* Effects */
+
+ RendererRD::Resolve *resolve_effects = nullptr;
+ RendererRD::TAA *taa = nullptr;
+ RendererRD::SSEffects *ss_effects = nullptr;
+
+ /* Cluster builder */
+
+ ClusterBuilderSharedDataRD cluster_builder_shared;
+ ClusterBuilderRD *current_cluster_builder = nullptr;
+
+ /* SDFGI */
+ void _update_sdfgi(RenderDataRD *p_render_data);
+
+ /* Volumetric fog */
+ RID shadow_sampler;
+
+ void _update_volumetric_fog(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, const Projection &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
+
+ /* Render shadows */
+
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_begin();
+ void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_process();
+ void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+
+ /* Render Scene */
+ void _process_ssao(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection);
+ void _process_ssil(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_environment, RID p_normal_buffer, const Projection &p_projection, const Transform3D &p_transform);
+ void _copy_framebuffer_to_ssil(Ref<RenderSceneBuffersRD> p_render_buffers);
+ void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, const RID *p_normal_roughness_slices, RID p_voxel_gi_buffer);
+ void _process_ssr(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_dest_framebuffer, const RID *p_normal_buffer_slices, RID p_specular_buffer, const RID *p_metallic_slices, RID p_environment, const Projection *p_projections, const Vector3 *p_eye_offsets, bool p_use_additive);
+ void _process_sss(Ref<RenderSceneBuffersRD> p_render_buffers, const Projection &p_camera);
+
+ /* Debug */
+ void _debug_draw_cluster(Ref<RenderSceneBuffersRD> p_render_buffers);
+
protected:
- virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
+ /* setup */
+
+ virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
+ virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
- virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
- virtual void _render_shadow_process() override;
- virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
+ virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
+ virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
+ virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override;
+ virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override;
+
+ /* Rendering */
+
+ virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
+ virtual void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) override;
+
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
public:
+ static RenderForwardClustered *get_singleton() { return singleton; }
+
+ ClusterBuilderSharedDataRD *get_cluster_builder_shared() { return &cluster_builder_shared; }
+ RendererRD::SSEffects *get_ss_effects() { return ss_effects; }
+
+ /* callback from updating our lighting UBOs, used to populate cluster builder */
+ virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents) override;
+ virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture) override;
+ virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents) override;
+
+ virtual void base_uniforms_changed() override;
_FORCE_INLINE_ virtual void update_uniform_sets() override {
base_uniform_set_updated = true;
_update_render_base_uniform_set();
}
- virtual GeometryInstance *geometry_instance_create(RID p_base) override;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
virtual uint32_t geometry_instance_get_pair_mask() override;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
virtual bool free(RID p_rid) override;
- RenderForwardClustered(RendererStorageRD *p_storage);
+ RenderForwardClustered();
~RenderForwardClustered();
};
} // namespace RendererSceneRenderImplementation
-#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_CLUSTERED_H
+
+#endif // RENDER_FORWARD_CLUSTERED_H
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
index 615e2e9b7c..bd9c736d6a 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp
@@ -37,6 +37,10 @@
using namespace RendererSceneRenderImplementation;
+void SceneShaderForwardClustered::ShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
//compile
@@ -149,6 +153,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
depth_draw = DepthDraw(depth_drawi);
depth_test = DepthTest(depth_testi);
cull_mode = Cull(cull_modei);
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
#if 0
print_line("**compiling shader:");
@@ -157,11 +162,10 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element *el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -285,6 +289,8 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW,
SHADER_VERSION_COLOR_PASS,
};
@@ -352,9 +358,9 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
if (k == PIPELINE_VERSION_DEPTH_PASS || k == PIPELINE_VERSION_DEPTH_PASS_DP || k == PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW) {
//none, leave empty
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) {
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW) {
blend_state = blend_state_depth_normal_roughness;
- } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI) {
+ } else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI || k == PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW) {
blend_state = blend_state_depth_normal_roughness_giprobe;
} else if (k == PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL) {
blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way
@@ -372,7 +378,7 @@ void SceneShaderForwardClustered::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void SceneShaderForwardClustered::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -389,11 +395,15 @@ void SceneShaderForwardClustered::ShaderData::set_default_texture_param(const St
}
}
-void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderForwardClustered::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
@@ -404,7 +414,22 @@ void SceneShaderForwardClustered::ShaderData::get_param_list(List<PropertyInfo>
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -426,7 +451,7 @@ void SceneShaderForwardClustered::ShaderData::get_instance_param_list(List<Rende
}
}
-bool SceneShaderForwardClustered::ShaderData::is_param_texture(const StringName &p_param) const {
+bool SceneShaderForwardClustered::ShaderData::is_parameter_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -470,7 +495,7 @@ SceneShaderForwardClustered::ShaderData::~ShaderData() {
}
}
-RendererRD::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
+RendererRD::MaterialStorage::ShaderData *SceneShaderForwardClustered::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -487,14 +512,14 @@ void SceneShaderForwardClustered::MaterialData::set_next_pass(RID p_pass) {
bool SceneShaderForwardClustered::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardClustered *shader_singleton = (SceneShaderForwardClustered *)SceneShaderForwardClustered::singleton;
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardClustered::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER);
}
SceneShaderForwardClustered::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererRD::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SceneShaderForwardClustered::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -521,19 +546,20 @@ SceneShaderForwardClustered::~SceneShaderForwardClustered() {
material_storage->material_free(default_material);
}
-void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const String p_defines) {
+void SceneShaderForwardClustered::init(const String p_defines) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
{
Vector<String> shader_versions;
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); // SHADER_VERSION_DEPTH_PASS_DP
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS
- shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_GIPROBE
+ shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); // SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL
shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_SDF\n"); // SHADER_VERSION_DEPTH_PASS_WITH_SDF
shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n"); // SHADER_VERSION_DEPTH_PASS_MULTIVIEW
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW
+ shader_versions.push_back("\n#define USE_MULTIVIEW\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL_ROUGHNESS\n#define MODE_RENDER_VOXEL_GI\n"); // SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW
Vector<String> color_pass_flags = {
"\n#define MODE_SEPARATE_SPECULAR\n", // SHADER_COLOR_PASS_FLAG_SEPARATE_SPECULAR
@@ -556,6 +582,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
if (!RendererCompositorRD::singleton->is_xr_enabled()) {
shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_MULTIVIEW, false);
+ shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW, false);
+ shader.set_variant_enabled(SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW, false);
// TODO Add a way to enable/disable color pass flags
}
}
@@ -589,17 +617,17 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
valid_color_pass_pipelines.insert(PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS);
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
ShaderCompiler::DefaultIdentifierActions actions;
- actions.renames["MODEL_MATRIX"] = "model_matrix";
+ actions.renames["MODEL_MATRIX"] = "read_model_matrix";
actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix";
actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix";
- actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix";
+ actions.renames["INV_VIEW_MATRIX"] = "inv_view_matrix";
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions.renames["MODELVIEW_MATRIX"] = "modelview";
@@ -624,7 +652,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
//builtins
- actions.renames["TIME"] = "scene_data_block.data.time";
+ actions.renames["TIME"] = "global_time";
actions.renames["PI"] = _MKSTR(Math_PI);
actions.renames["TAU"] = _MKSTR(Math_TAU);
actions.renames["E"] = _MKSTR(Math_E);
@@ -661,7 +689,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
- actions.renames["FOG"] = "custom_fog";
+ actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
@@ -672,6 +700,11 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(read_model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
@@ -727,6 +760,8 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n";
actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n";
+ actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n";
+
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n";
@@ -767,7 +802,7 @@ void SceneShaderForwardClustered::init(RendererStorageRD *p_storage, const Strin
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "instances.data[instance_index_interp].instance_uniforms_ofs";
compiler.initialize(actions);
@@ -796,7 +831,7 @@ void fragment() {
material_storage->material_initialize(default_material);
material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_shader_sdfgi_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_DEPTH_PASS_WITH_SDF);
@@ -824,7 +859,7 @@ void fragment() {
material_storage->material_initialize(overdraw_material);
material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
index 79ccf10090..a9a9fa94de 100644
--- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
+++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h
@@ -28,12 +28,11 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RSSR_SCENE_SHADER_FC_H
-#define RSSR_SCENE_SHADER_FC_H
+#ifndef SCENE_SHADER_FORWARD_CLUSTERED_H
+#define SCENE_SHADER_FORWARD_CLUSTERED_H
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl.gen.h"
namespace RendererSceneRenderImplementation {
@@ -42,8 +41,6 @@ private:
static SceneShaderForwardClustered *singleton;
public:
- RendererStorageRD *storage = nullptr;
-
enum ShaderVersion {
SHADER_VERSION_DEPTH_PASS,
SHADER_VERSION_DEPTH_PASS_DP,
@@ -52,6 +49,8 @@ public:
SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL,
SHADER_VERSION_DEPTH_PASS_WITH_SDF,
SHADER_VERSION_DEPTH_PASS_MULTIVIEW,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW,
+ SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW,
SHADER_VERSION_COLOR_PASS,
SHADER_VERSION_MAX
};
@@ -72,6 +71,8 @@ public:
PIPELINE_VERSION_DEPTH_PASS_WITH_MATERIAL,
PIPELINE_VERSION_DEPTH_PASS_WITH_SDF,
PIPELINE_VERSION_DEPTH_PASS_MULTIVIEW,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_MULTIVIEW,
+ PIPELINE_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS_AND_VOXEL_GI_MULTIVIEW,
PIPELINE_VERSION_COLOR_PASS,
PIPELINE_VERSION_MAX
};
@@ -92,7 +93,7 @@ public:
SHADER_SPECIALIZATION_DIRECTIONAL_SOFT_SHADOWS = 1 << 3,
};
- struct ShaderData : public RendererRD::ShaderData {
+ struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -173,17 +174,19 @@ public:
bool uses_time = false;
bool writes_modelview_or_projection = false;
bool uses_world_coordinates = false;
+ bool uses_screen_texture_mipmaps = false;
Cull cull_mode = CULL_DISABLED;
uint64_t last_pass = 0;
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void set_path_hint(const String &p_path);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_parameter_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
@@ -196,12 +199,12 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererRD::ShaderData *_create_shader_func();
- static RendererRD::ShaderData *_create_shader_funcs() {
+ RendererRD::MaterialStorage::ShaderData *_create_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererRD::MaterialData {
+ struct MaterialData : public RendererRD::MaterialStorage::MaterialData {
ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
@@ -214,8 +217,8 @@ public:
virtual ~MaterialData();
};
- RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
return static_cast<SceneShaderForwardClustered *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
@@ -245,9 +248,10 @@ public:
SceneShaderForwardClustered();
~SceneShaderForwardClustered();
- void init(RendererStorageRD *p_storage, const String p_defines);
+ void init(const String p_defines);
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
};
} // namespace RendererSceneRenderImplementation
-#endif // !RSSR_SCENE_SHADER_FM_H
+
+#endif // SCENE_SHADER_FORWARD_CLUSTERED_H
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
index b2e0af06cd..16711b0d5d 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp
@@ -39,7 +39,7 @@
using namespace RendererSceneRenderImplementation;
-RenderForwardMobile::ForwardID RenderForwardMobile::_allocate_forward_id(ForwardIDType p_type) {
+RendererRD::ForwardID RenderForwardMobile::ForwardIDStorageMobile::allocate_forward_id(RendererRD::ForwardIDType p_type) {
int32_t index = -1;
for (uint32_t i = 0; i < forward_id_allocators[p_type].allocations.size(); i++) {
if (forward_id_allocators[p_type].allocations[i] == false) {
@@ -58,178 +58,237 @@ RenderForwardMobile::ForwardID RenderForwardMobile::_allocate_forward_id(Forward
return index;
}
-void RenderForwardMobile::_free_forward_id(ForwardIDType p_type, ForwardID p_id) {
- ERR_FAIL_INDEX(p_id, (ForwardID)forward_id_allocators[p_type].allocations.size());
+void RenderForwardMobile::ForwardIDStorageMobile::free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) {
+ ERR_FAIL_INDEX(p_id, (RendererRD::ForwardID)forward_id_allocators[p_type].allocations.size());
forward_id_allocators[p_type].allocations[p_id] = false;
}
-void RenderForwardMobile::_map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) {
+void RenderForwardMobile::ForwardIDStorageMobile::map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) {
forward_id_allocators[p_type].map[p_id] = p_index;
}
-/* Render buffer */
+void RenderForwardMobile::ForwardIDStorageMobile::fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) {
+ // first zero out our indices
-void RenderForwardMobile::RenderBufferDataForwardMobile::clear() {
- if (color_msaa.is_valid()) {
- RD::get_singleton()->free(color_msaa);
- color_msaa = RID();
- }
+ p_push_constant->omni_lights[0] = 0xFFFF;
+ p_push_constant->omni_lights[1] = 0xFFFF;
+
+ p_push_constant->spot_lights[0] = 0xFFFF;
+ p_push_constant->spot_lights[1] = 0xFFFF;
- if (depth_msaa.is_valid()) {
- RD::get_singleton()->free(depth_msaa);
- depth_msaa = RID();
+ p_push_constant->decals[0] = 0xFFFF;
+ p_push_constant->decals[1] = 0xFFFF;
+
+ p_push_constant->reflection_probes[0] = 0xFFFF;
+ p_push_constant->reflection_probes[1] = 0xFFFF;
+
+ if (p_instance->omni_light_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS;
+ }
+ if (p_instance->spot_light_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS;
+ }
+ if (p_instance->reflection_probe_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES;
+ }
+ if (p_instance->decals_count == 0) {
+ spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS;
}
- color = RID();
- depth = RID();
- for (int i = 0; i < FB_CONFIG_MAX; i++) {
- color_fbs[i] = RID();
+ for (uint32_t i = 0; i < MAX_RDL_CULL; i++) {
+ uint32_t ofs = i < 4 ? 0 : 1;
+ uint32_t shift = (i & 0x3) << 3;
+ uint32_t mask = ~(0xFF << shift);
+ if (i < p_instance->omni_light_count) {
+ p_push_constant->omni_lights[ofs] &= mask;
+ p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift;
+ }
+ if (i < p_instance->spot_light_count) {
+ p_push_constant->spot_lights[ofs] &= mask;
+ p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift;
+ }
+ if (i < p_instance->decals_count) {
+ p_push_constant->decals[ofs] &= mask;
+ p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift;
+ }
+ if (i < p_instance->reflection_probe_count) {
+ p_push_constant->reflection_probes[ofs] &= mask;
+ p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[RendererRD::FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift;
+ }
}
}
-void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) {
- clear();
+/* Render buffer */
- msaa = p_msaa;
+void RenderForwardMobile::RenderBufferDataForwardMobile::free_data() {
+ // this should already be done but JIC..
+ if (render_buffers) {
+ render_buffers->clear_context(RB_SCOPE_MOBILE);
+ }
+}
- Size2i target_size = RD::get_singleton()->texture_size(p_target_buffer);
+void RenderForwardMobile::RenderBufferDataForwardMobile::configure(RenderSceneBuffersRD *p_render_buffers) {
+ if (render_buffers) {
+ // JIC
+ free_data();
+ }
- width = p_width;
- height = p_height;
- bool is_scaled = (target_size.width != p_width) || (target_size.height != p_height);
- view_count = p_view_count;
+ render_buffers = p_render_buffers;
+ ERR_FAIL_NULL(render_buffers); // Huh? really?
- color = p_color_buffer;
- depth = p_depth_buffer;
+ RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
+ if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
+ // Create our MSAA textures...
- // We are creating 4 configurations here for our framebuffers.
+ RD::DataFormat format = render_buffers->get_base_data_format();
+ uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
- if (p_msaa == RS::VIEWPORT_MSAA_DISABLED) {
- Vector<RID> fb;
- fb.push_back(p_color_buffer); // 0 - color buffer
- fb.push_back(depth); // 1 - depth buffer
+ const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
+ RD::TEXTURE_SAMPLES_1,
+ RD::TEXTURE_SAMPLES_2,
+ RD::TEXTURE_SAMPLES_4,
+ RD::TEXTURE_SAMPLES_8,
+ };
- // Now define our subpasses
- Vector<RD::FramebufferPass> passes;
- RD::FramebufferPass pass;
+ texture_samples = ts[msaa_3d];
- // re-using the same attachments
- pass.color_attachments.push_back(0);
- pass.depth_attachment = 1;
+ render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, format, usage_bits, texture_samples);
- // - opaque pass
- passes.push_back(pass);
- color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+ format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
- // - add sky pass
- passes.push_back(pass);
- color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+ render_buffers->create_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, format, usage_bits, texture_samples);
+ }
+}
- // - add alpha pass
- passes.push_back(pass);
- color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
+RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) {
+ ERR_FAIL_NULL_V(render_buffers, RID());
- if (!is_scaled) {
- // - add blit to 2D pass
- fb.push_back(p_target_buffer); // 2 - target buffer
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ ERR_FAIL_NULL_V(texture_storage, RID());
- RD::FramebufferPass blit_pass;
- blit_pass.color_attachments.push_back(2);
- blit_pass.input_attachments.push_back(0);
- passes.push_back(blit_pass);
+ // We use our framebuffer cache here instead of building these in RenderBufferDataForwardMobile::configure
+ // This approach ensures we only build the framebuffers we actually need for this viewport.
+ // In the (near) future this means that if we cycle through a texture chain for our render target, we'll also support
+ // this.
- color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
- } else {
- // can't do our blit pass if resolutions don't match
- color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
- }
- } else {
- RD::DataFormat color_format = RenderForwardMobile::singleton->_render_buffers_get_color_format();
+ RS::ViewportMSAA msaa_3d = render_buffers->get_msaa_3d();
+ bool use_msaa = msaa_3d != RS::VIEWPORT_MSAA_DISABLED;
- RD::TextureFormat tf;
- if (view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- } else {
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- }
- tf.format = color_format;
- tf.width = p_width;
- tf.height = p_height;
- tf.array_layers = view_count; // create a layer for every view
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ uint32_t view_count = render_buffers->get_view_count();
- const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
- RD::TEXTURE_SAMPLES_1,
- RD::TEXTURE_SAMPLES_2,
- RD::TEXTURE_SAMPLES_4,
- RD::TEXTURE_SAMPLES_8,
- };
+ RID vrs_texture;
+ if (render_buffers->has_texture(RB_SCOPE_VRS, RB_TEXTURE)) {
+ vrs_texture = render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
+ }
- texture_samples = ts[p_msaa];
- tf.samples = texture_samples;
+ Vector<RID> textures;
+ int color_buffer_id = 0;
+ textures.push_back(use_msaa ? get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer
+ textures.push_back(use_msaa ? get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer
+ if (vrs_texture.is_valid()) {
+ textures.push_back(vrs_texture); // 2 - vrs texture
+ }
+ if (use_msaa) {
+ color_buffer_id = textures.size();
+ textures.push_back(render_buffers->get_internal_texture()); // color buffer for resolve
- color_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ // TODO add support for resolving depth buffer!!!
+ }
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
- tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ // Now define our subpasses
+ Vector<RD::FramebufferPass> passes;
- depth_msaa = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ // Define our base pass, we'll be re-using this
+ RD::FramebufferPass pass;
+ pass.color_attachments.push_back(0);
+ pass.depth_attachment = 1;
+ if (vrs_texture.is_valid()) {
+ pass.vrs_attachment = 2;
+ }
- {
- Vector<RID> fb;
- fb.push_back(color_msaa); // 0 - msaa color buffer
- fb.push_back(depth_msaa); // 1 - msaa depth buffer
+ switch (p_config_type) {
+ case FB_CONFIG_ONE_PASS: {
+ // just one pass
+ if (use_msaa) {
+ // Add resolve
+ pass.resolve_attachments.push_back(color_buffer_id);
+ }
+ passes.push_back(pass);
- // Now define our subpasses
- Vector<RD::FramebufferPass> passes;
- RD::FramebufferPass pass;
+ return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+ } break;
+ case FB_CONFIG_TWO_SUBPASSES: {
+ // - opaque pass
+ passes.push_back(pass);
- // re-using the same attachments
- pass.color_attachments.push_back(0);
- pass.depth_attachment = 1;
+ // - add sky pass
+ if (use_msaa) {
+ // add resolve
+ pass.resolve_attachments.push_back(color_buffer_id);
+ }
+ passes.push_back(pass);
+ return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+ } break;
+ case FB_CONFIG_THREE_SUBPASSES: {
// - opaque pass
passes.push_back(pass);
// - add sky pass
- fb.push_back(color); // 2 - color buffer
- passes.push_back(pass); // without resolve for our 3 + 4 subpass config
- {
- // but with resolve for our 2 subpass config
- Vector<RD::FramebufferPass> two_passes;
- two_passes.push_back(pass); // opaque subpass without resolve
- pass.resolve_attachments.push_back(2);
- two_passes.push_back(pass); // sky subpass with resolve
-
- color_fbs[FB_CONFIG_TWO_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, two_passes, RenderingDevice::INVALID_ID, view_count);
+ passes.push_back(pass);
+
+ // - add alpha pass
+ if (use_msaa) {
+ // add resolve
+ pass.resolve_attachments.push_back(color_buffer_id);
}
+ passes.push_back(pass);
+
+ return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+ } break;
+ case FB_CONFIG_FOUR_SUBPASSES: {
+ Size2i target_size = render_buffers->get_target_size();
+ Size2i internal_size = render_buffers->get_internal_size();
- // - add alpha pass (with resolve, we just added that above)
+ // can't do our blit pass if resolutions don't match
+ ERR_FAIL_COND_V(target_size != internal_size, RID());
+
+ // - opaque pass
passes.push_back(pass);
- color_fbs[FB_CONFIG_THREE_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
- {
- // we also need our one pass with resolve
- Vector<RD::FramebufferPass> one_pass_with_resolve;
- one_pass_with_resolve.push_back(pass); // note our pass configuration already has resolve..
- color_fbs[FB_CONFIG_ONE_PASS] = RD::get_singleton()->framebuffer_create_multipass(fb, one_pass_with_resolve, RenderingDevice::INVALID_ID, view_count);
+ // - add sky pass
+ passes.push_back(pass);
+
+ // - add alpha pass
+ if (use_msaa) {
+ // add resolve
+ pass.resolve_attachments.push_back(color_buffer_id);
}
+ passes.push_back(pass);
- if (!is_scaled) {
- // - add blit to 2D pass
- fb.push_back(p_target_buffer); // 3 - target buffer
- RD::FramebufferPass blit_pass;
- blit_pass.color_attachments.push_back(3);
- blit_pass.input_attachments.push_back(2);
- passes.push_back(blit_pass);
+ // - add blit to 2D pass
+ RID render_target = render_buffers->get_render_target();
+ ERR_FAIL_COND_V(render_target.is_null(), RID());
+ RID target_buffer = texture_storage->render_target_get_rd_texture(render_target);
+ ERR_FAIL_COND_V(target_buffer.is_null(), RID());
- color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RD::get_singleton()->framebuffer_create_multipass(fb, passes, RenderingDevice::INVALID_ID, view_count);
- } else {
- // can't do our blit pass if resolutions don't match
- color_fbs[FB_CONFIG_FOUR_SUBPASSES] = RID();
- }
- }
- }
+ int target_buffer_id = textures.size();
+ textures.push_back(target_buffer); // target buffer
+
+ RD::FramebufferPass blit_pass;
+ blit_pass.input_attachments.push_back(color_buffer_id); // Read from our (resolved) color buffer
+ blit_pass.color_attachments.push_back(target_buffer_id); // Write into our target buffer
+ // this doesn't need VRS
+ passes.push_back(blit_pass);
+
+ return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
+ } break;
+ default:
+ break;
+ };
+
+ return RID();
}
RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
@@ -258,12 +317,11 @@ RID RenderForwardMobile::reflection_probe_create_framebuffer(RID p_color, RID p_
return RD::get_singleton()->framebuffer_create_multipass(fb, passes);
}
-RenderForwardMobile::RenderBufferDataForwardMobile::~RenderBufferDataForwardMobile() {
- clear();
-}
+void RenderForwardMobile::setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ Ref<RenderBufferDataForwardMobile> data;
+ data.instantiate();
-RendererSceneRenderRD::RenderBufferData *RenderForwardMobile::_create_render_buffer_data() {
- return memnew(RenderBufferDataForwardMobile);
+ p_render_buffers->set_custom_data(RB_SCOPE_MOBILE, data);
}
bool RenderForwardMobile::free(RID p_rid) {
@@ -293,14 +351,17 @@ bool RenderForwardMobile::_render_buffers_can_be_storage() {
}
RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas, int p_index) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
//there should always be enough uniform buffers for render passes, otherwise bugs
ERR_FAIL_INDEX_V(p_index, (int)scene_state.uniform_buffers.size(), RID());
- RenderBufferDataForwardMobile *rb = nullptr;
+ Ref<RenderBufferDataForwardMobile> rb_data;
+ Ref<RenderSceneBuffersRD> rb;
if (p_render_data && p_render_data->render_buffers.is_valid()) {
- rb = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
+ rb = p_render_data->render_buffers;
+ rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
}
// default render buffer and scene state uniform set
@@ -321,7 +382,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
if (p_radiance_texture.is_valid()) {
radiance_texture = p_radiance_texture;
} else {
- radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
}
RD::Uniform u;
u.binding = 2;
@@ -331,14 +392,14 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
}
{
- RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID();
+ RID ref_texture = (p_render_data && p_render_data->reflection_atlas.is_valid()) ? light_storage->reflection_atlas_get_texture(p_render_data->reflection_atlas) : RID();
RD::Uniform u;
u.binding = 3;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
if (ref_texture.is_valid()) {
u.append_id(ref_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK));
}
uniforms.push_back(u);
}
@@ -349,10 +410,10 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
RID texture;
if (p_render_data && p_render_data->shadow_atlas.is_valid()) {
- texture = shadow_atlas_get_texture(p_render_data->shadow_atlas);
+ texture = light_storage->shadow_atlas_get_texture(p_render_data->shadow_atlas);
}
if (!texture.is_valid()) {
- texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
}
u.append_id(texture);
uniforms.push_back(u);
@@ -361,10 +422,10 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- if (p_use_directional_shadow_atlas && directional_shadow_get_texture().is_valid()) {
- u.append_id(directional_shadow_get_texture());
+ if (p_use_directional_shadow_atlas && light_storage->directional_shadow_get_texture().is_valid()) {
+ u.append_id(light_storage->directional_shadow_get_texture());
} else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH));
+ u.append_id(texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH));
}
uniforms.push_back(u);
}
@@ -375,11 +436,11 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
for (uint32_t i = 0; i < scene_state.max_lightmaps; i++) {
if (p_render_data && i < p_render_data->lightmaps->size()) {
- RID base = lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
- RID texture = RendererRD::LightStorage::get_singleton()->lightmap_get_texture(base);
+ RID base = light_storage->lightmap_instance_get_lightmap((*p_render_data->lightmaps)[i]);
+ RID texture = light_storage->lightmap_get_texture(base);
RID rd_texture = texture_storage->texture_get_rd_texture(texture);
u.append_id(rd_texture);
} else {
@@ -396,7 +457,7 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
u.ids.resize(MAX_VOXEL_GI_INSTANCESS);
- RID default_tex = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
+ RID default_tex = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
for (int i = 0; i < MAX_VOXEL_GI_INSTANCESS; i++) {
if (i < (int)p_voxel_gi_instances.size()) {
RID tex = gi.voxel_gi_instance_get_texture(p_voxel_gi_instances[i]);
@@ -426,8 +487,12 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 9;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID dbt = rb ? render_buffers_get_back_depth_texture(p_render_data->render_buffers) : RID();
- RID texture = (dbt.is_valid()) ? dbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_DEPTH);
+ RID texture;
+ if (rb.is_valid() && rb->has_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH)) {
+ texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH);
+ } else {
+ texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_DEPTH);
+ }
u.append_id(texture);
uniforms.push_back(u);
}
@@ -435,8 +500,8 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
RD::Uniform u;
u.binding = 10;
u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- RID bbt = rb ? render_buffers_get_back_buffer_texture(p_render_data->render_buffers) : RID();
- RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ RID bbt = rb_data.is_valid() ? rb->get_back_buffer_texture() : RID();
+ RID texture = bbt.is_valid() ? bbt : texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
u.append_id(texture);
uniforms.push_back(u);
}
@@ -453,7 +518,9 @@ RID RenderForwardMobile::_setup_render_pass_uniform_set(RenderListType p_render_
return render_pass_uniform_sets[p_index];
}
-void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
+void RenderForwardMobile::_setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+
// This probably needs to change...
scene_state.lightmaps_used = 0;
for (int i = 0; i < (int)p_lightmaps.size(); i++) {
@@ -461,13 +528,20 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
break;
}
- RID lightmap = lightmap_instance_get_lightmap(p_lightmaps[i]);
+ RID lightmap = light_storage->lightmap_instance_get_lightmap(p_lightmaps[i]);
- Basis to_lm = lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
+ Basis to_lm = light_storage->lightmap_instance_get_transform(p_lightmaps[i]).basis.inverse() * p_cam_transform.basis;
to_lm = to_lm.inverse().transposed(); //will transform normals
- RendererStorageRD::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ RendererRD::MaterialStorage::store_transform_3x3(to_lm, scene_state.lightmaps[i].normal_xform);
+ scene_state.lightmaps[i].exposure_normalization = 1.0;
+ if (p_render_data->camera_attributes.is_valid()) {
+ float baked_exposure = light_storage->lightmap_get_baked_exposure_normalization(lightmap);
+ float enf = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ scene_state.lightmaps[i].exposure_normalization = enf / baked_exposure;
+ }
+
scene_state.lightmap_ids[i] = p_lightmaps[i];
- scene_state.lightmap_has_sh[i] = RendererRD::LightStorage::get_singleton()->lightmap_uses_spherical_harmonics(lightmap);
+ scene_state.lightmap_has_sh[i] = light_storage->lightmap_uses_spherical_harmonics(lightmap);
scene_state.lightmaps_used++;
}
@@ -476,17 +550,119 @@ void RenderForwardMobile::_setup_lightmaps(const PagedArray<RID> &p_lightmaps, c
}
}
+void RenderForwardMobile::_pre_opaque_render(RenderDataRD *p_render_data) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+ p_render_data->cube_shadows.clear();
+ p_render_data->shadows.clear();
+ p_render_data->directional_shadows.clear();
+
+ Plane camera_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin);
+ float lod_distance_multiplier = p_render_data->scene_data->cam_projection.get_lod_multiplier();
+ {
+ for (int i = 0; i < p_render_data->render_shadow_count; i++) {
+ RID li = p_render_data->render_shadows[i].light;
+ RID base = light_storage->light_instance_get_base_light(li);
+
+ if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) {
+ p_render_data->directional_shadows.push_back(i);
+ } else if (light_storage->light_get_type(base) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ p_render_data->cube_shadows.push_back(i);
+ } else {
+ p_render_data->shadows.push_back(i);
+ }
+ }
+
+ //cube shadows are rendered in their own way
+ for (uint32_t i = 0; i < p_render_data->cube_shadows.size(); i++) {
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->cube_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->cube_shadows[i]].pass, p_render_data->render_shadows[p_render_data->cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info);
+ }
+
+ if (p_render_data->directional_shadows.size()) {
+ //open the pass for directional shadows
+ light_storage->update_directional_shadow_atlas();
+ RD::get_singleton()->draw_list_begin(light_storage->direction_shadow_get_fb(), RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE);
+ RD::get_singleton()->draw_list_end();
+ }
+ }
+
+ bool render_shadows = p_render_data->directional_shadows.size() || p_render_data->shadows.size();
+
+ if (render_shadows) {
+ RENDER_TIMESTAMP("Render Shadows");
+ }
+
+ //prepare shadow rendering
+ if (render_shadows) {
+ _render_shadow_begin();
+
+ //render directional shadows
+ for (uint32_t i = 0; i < p_render_data->directional_shadows.size(); i++) {
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->directional_shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->directional_shadows[i]].pass, p_render_data->render_shadows[p_render_data->directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, false, i == p_render_data->directional_shadows.size() - 1, false, p_render_data->render_info);
+ }
+ //render positional shadows
+ for (uint32_t i = 0; i < p_render_data->shadows.size(); i++) {
+ _render_shadow_pass(p_render_data->render_shadows[p_render_data->shadows[i]].light, p_render_data->shadow_atlas, p_render_data->render_shadows[p_render_data->shadows[i]].pass, p_render_data->render_shadows[p_render_data->shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, i == 0, i == p_render_data->shadows.size() - 1, true, p_render_data->render_info);
+ }
+
+ _render_shadow_process();
+
+ _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER);
+ }
+
+ //full barrier here, we need raster, transfer and compute and it depends from the previous work
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL);
+
+ bool using_shadows = true;
+
+ if (p_render_data->reflection_probe.is_valid()) {
+ if (!RSG::light_storage->reflection_probe_renders_shadows(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ using_shadows = false;
+ }
+ } else {
+ //do not render reflections when rendering a reflection probe
+ light_storage->update_reflection_probe_buffer(p_render_data, *p_render_data->reflection_probes, p_render_data->scene_data->cam_transform.affine_inverse(), p_render_data->environment);
+ }
+
+ uint32_t directional_light_count = 0;
+ uint32_t positional_light_count = 0;
+ light_storage->update_light_buffers(p_render_data, *p_render_data->lights, p_render_data->scene_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
+ texture_storage->update_decal_buffer(*p_render_data->decals, p_render_data->scene_data->cam_transform.affine_inverse());
+
+ p_render_data->directional_light_count = directional_light_count;
+}
+
void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) {
- RenderBufferDataForwardMobile *render_buffer = nullptr;
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+
+ Ref<RenderSceneBuffersRD> rb;
+ Ref<RenderBufferDataForwardMobile> rb_data;
if (p_render_data->render_buffers.is_valid()) {
- render_buffer = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
+ rb = p_render_data->render_buffers;
+ rb_data = rb->get_custom_data(RB_SCOPE_MOBILE);
}
- RendererSceneEnvironmentRD *env = get_environment(p_render_data->environment);
+
+ RENDER_TIMESTAMP("Prepare 3D Scene");
+
+ _update_vrs(rb);
RENDER_TIMESTAMP("Setup 3D Scene");
- scene_state.ubo.directional_light_count = 0;
- scene_state.ubo.opaque_prepass_threshold = 0.0;
+ /* TODO
+ // check if we need motion vectors
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS) {
+ p_render_data->scene_data->calculate_motion_vectors = true;
+ } else if (render target has velocity override) { // TODO
+ p_render_data->scene_data->calculate_motion_vectors = true;
+ } else {
+ p_render_data->scene_data->calculate_motion_vectors = false;
+ }
+ */
+ p_render_data->scene_data->calculate_motion_vectors = false; // for now, not yet supported...
+
+ p_render_data->scene_data->directional_light_count = 0;
+ p_render_data->scene_data->opaque_prepass_threshold = 0.0;
// We can only use our full subpass approach if we're:
// - not reading from SCREEN_TEXTURE/DEPTH_TEXTURE
@@ -501,9 +677,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
bool using_subpass_transparent = true;
bool using_subpass_post_process = true;
- bool using_ssr = false; // I don't think we support this in our mobile renderer so probably should phase it out
- bool using_sss = false; // I don't think we support this in our mobile renderer so probably should phase it out
-
// fill our render lists early so we can find out if we use various features
_fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR);
render_list[RENDER_LIST_OPAQUE].sort_by_key();
@@ -516,20 +689,19 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
p_render_data->render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_VISIBLE][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_render_data->instances->size();
}
- if (render_buffer) {
+ if (rb_data.is_valid()) {
// setup rendering to render buffer
- screen_size.x = render_buffer->width;
- screen_size.y = render_buffer->height;
+ screen_size = p_render_data->render_buffers->get_internal_size();
- if (render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES].is_null()) {
+ if (rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES).is_null()) {
// can't do blit subpass
using_subpass_post_process = false;
- } else if (env && (env->glow_enabled || env->auto_exposure || camera_effects_uses_dof(p_render_data->camera_effects))) {
+ } else if (p_render_data->environment.is_valid() && (environment_get_glow_enabled(p_render_data->environment) || RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) || RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes))) {
// can't do blit subpass
using_subpass_post_process = false;
}
- if (using_ssr || using_sss || scene_state.used_screen_texture || scene_state.used_depth_texture) {
+ if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
// can't use our last two subpasses
using_subpass_transparent = false;
using_subpass_post_process = false;
@@ -537,24 +709,23 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (using_subpass_post_process) {
// all as subpasses
- framebuffer = render_buffer->color_fbs[FB_CONFIG_FOUR_SUBPASSES];
+ framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_FOUR_SUBPASSES);
} else if (using_subpass_transparent) {
// our tonemap pass is separate
- framebuffer = render_buffer->color_fbs[FB_CONFIG_THREE_SUBPASSES];
+ framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_THREE_SUBPASSES);
} else {
// only opaque and sky as subpasses
- framebuffer = render_buffer->color_fbs[FB_CONFIG_TWO_SUBPASSES];
+ framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_TWO_SUBPASSES);
}
} else if (p_render_data->reflection_probe.is_valid()) {
- uint32_t resolution = reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
+ uint32_t resolution = light_storage->reflection_probe_instance_get_resolution(p_render_data->reflection_probe);
screen_size.x = resolution;
screen_size.y = resolution;
- framebuffer = reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
+ framebuffer = light_storage->reflection_probe_instance_get_framebuffer(p_render_data->reflection_probe, p_render_data->reflection_probe_pass);
- if (RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
+ if (light_storage->reflection_probe_is_interior(light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
p_render_data->environment = RID(); //no environment on interiors
- env = nullptr;
}
reverse_cull = true;
@@ -564,12 +735,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
ERR_FAIL(); //bug?
}
- scene_state.ubo.viewport_size[0] = screen_size.x;
- scene_state.ubo.viewport_size[1] = screen_size.y;
+ p_render_data->scene_data->emissive_exposure_normalization = -1.0;
RD::get_singleton()->draw_command_begin_label("Render Setup");
- _setup_lightmaps(*p_render_data->lightmaps, p_render_data->cam_transform);
+ _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform);
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
_update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example)
@@ -580,6 +750,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RID radiance_texture;
bool draw_sky = false;
bool draw_sky_fog_only = false;
+ // We invert luminance_multiplier for sky so that we can combine it with exposure value.
+ float sky_energy_multiplier = 1.0 / _render_buffers_get_luminance_multiplier();
Color clear_color = p_default_bg_color;
bool keep_color = false;
@@ -588,15 +760,21 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black
} else if (is_environment(p_render_data->environment)) {
RS::EnvironmentBG bg_mode = environment_get_background(p_render_data->environment);
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
+ float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_render_data->environment);
+ bg_energy_multiplier *= environment_get_bg_intensity(p_render_data->environment);
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ bg_energy_multiplier *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
switch (bg_mode) {
case RS::ENV_BG_CLEAR_COLOR: {
clear_color = p_default_bg_color;
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
/*
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
+ if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -604,11 +782,11 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
} break;
case RS::ENV_BG_COLOR: {
clear_color = environment_get_bg_color(p_render_data->environment);
- clear_color.r *= bg_energy;
- clear_color.g *= bg_energy;
- clear_color.b *= bg_energy;
+ clear_color.r *= bg_energy_multiplier;
+ clear_color.g *= bg_energy_multiplier;
+ clear_color.b *= bg_energy_multiplier;
/*
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers) || environment_is_fog_enabled(p_render_data->environment)) {
+ if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_FOG) || environment_get_fog_enabled(p_render_data->environment)) {
draw_sky_fog_only = true;
RendererRD::MaterialStorage::get_singleton()->material_set_param(sky.sky_scene_state.fog_material, "clear_color", Variant(clear_color.srgb_to_linear()));
}
@@ -632,18 +810,20 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (draw_sky || draw_sky_fog_only || environment_get_reflection_source(p_render_data->environment) == RS::ENV_REFLECTION_SOURCE_SKY || environment_get_ambient_source(p_render_data->environment) == RS::ENV_AMBIENT_SOURCE_SKY) {
RENDER_TIMESTAMP("Setup Sky");
RD::get_singleton()->draw_command_begin_label("Setup Sky");
- CameraMatrix projection = p_render_data->cam_projection;
+ Projection projection = p_render_data->scene_data->cam_projection;
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- projection = correction * p_render_data->cam_projection;
+ projection = correction * p_render_data->scene_data->cam_projection;
}
- sky.setup(env, p_render_data->render_buffers, *p_render_data->lights, projection, p_render_data->cam_transform, screen_size, this);
+ sky.setup(p_render_data->environment, p_render_data->render_buffers, *p_render_data->lights, p_render_data->camera_attributes, projection, p_render_data->scene_data->cam_transform, screen_size, this);
+
+ sky_energy_multiplier *= bg_energy_multiplier;
- RID sky_rid = env->sky;
+ RID sky_rid = environment_get_sky(p_render_data->environment);
if (sky_rid.is_valid()) {
- sky.update(env, projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ sky.update(p_render_data->environment, projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
radiance_texture = sky.sky_get_radiance_texture_rd(sky_rid);
} else {
// do not try to draw sky if invalid
@@ -664,18 +844,18 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Setup Sky Resolution Buffers");
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.update_res_buffers(env, 1, &projection, p_render_data->cam_transform, time);
+ Projection projection = correction * p_render_data->scene_data->cam_projection;
+ sky.update_res_buffers(p_render_data->environment, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
} else {
- sky.update_res_buffers(env, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time);
+ sky.update_res_buffers(p_render_data->environment, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label(); // Setup Sky resolution buffers
}
- _pre_opaque_render(p_render_data, false, false, false, RID(), RID());
+ _pre_opaque_render(p_render_data);
uint32_t spec_constant_base_flags = 0;
@@ -690,12 +870,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_DIRECTIONAL_LIGHTS;
}
- if (!is_environment(p_render_data->environment) || environment_is_fog_enabled(p_render_data->environment)) {
+ if (!is_environment(p_render_data->environment) || !environment_get_fog_enabled(p_render_data->environment)) {
spec_constant_base_flags |= 1 << SPEC_CONSTANT_DISABLE_FOG;
}
}
{
- if (render_buffer) {
+ if (rb_data.is_valid()) {
RD::get_singleton()->draw_command_begin_label("Render 3D Pass");
} else {
RD::get_singleton()->draw_command_begin_label("Render Reflection Probe Pass");
@@ -705,7 +885,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_begin_label("Render Opaque Subpass");
- scene_state.ubo.directional_light_count = p_render_data->directional_light_count;
+ p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count;
_setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, p_render_data->render_buffers.is_valid());
@@ -719,15 +899,15 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, true);
- bool can_continue_color = !using_subpass_transparent && !scene_state.used_screen_texture && !using_ssr && !using_sss;
- bool can_continue_depth = !using_subpass_transparent && !scene_state.used_depth_texture && !using_ssr && !using_sss;
+ bool can_continue_color = !using_subpass_transparent && !scene_state.used_screen_texture;
+ bool can_continue_depth = !using_subpass_transparent && !scene_state.used_depth_texture;
{
// regular forward for now
Vector<Color> c;
c.push_back(clear_color.srgb_to_linear()); // our render buffer
- if (render_buffer) {
- if (render_buffer->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ if (rb_data.is_valid()) {
+ if (p_render_data->render_buffers->get_msaa_3d() != RS::VIEWPORT_MSAA_DISABLED) {
c.push_back(clear_color.srgb_to_linear()); // our resolve buffer
}
if (using_subpass_post_process) {
@@ -736,14 +916,17 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderList"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, can_continue_color ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, can_continue_depth ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0);
@@ -759,12 +942,12 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
if (p_render_data->reflection_probe.is_valid()) {
- CameraMatrix correction;
+ Projection correction;
correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_render_data->cam_projection;
- sky.draw(draw_list, env, framebuffer, 1, &projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ Projection projection = correction * p_render_data->scene_data->cam_projection;
+ sky.draw(draw_list, p_render_data->environment, framebuffer, 1, &projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
} else {
- sky.draw(draw_list, env, framebuffer, p_render_data->view_count, p_render_data->view_projection, p_render_data->cam_transform, time, _render_buffers_get_luminance_multiplier());
+ sky.draw(draw_list, p_render_data->environment, framebuffer, p_render_data->scene_data->view_count, p_render_data->scene_data->view_projection, p_render_data->scene_data->cam_transform, time, sky_energy_multiplier);
}
RD::get_singleton()->draw_command_end_label(); // Draw Sky Subpass
@@ -800,15 +983,17 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (using_subpass_transparent) {
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR_TRANSPARENT, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_switch_to_next_pass_split(thread_draw_lists.size(), thread_draw_lists.ptr());
render_list_params.subpass = RD::get_singleton()->draw_list_get_current_pass();
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
} else {
//single threaded
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
@@ -821,8 +1006,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
// note if we are using MSAA we should get an automatic resolve through our subpass configuration.
// blit to tonemap
- if (render_buffer && using_subpass_post_process) {
- _post_process_subpass(render_buffer->color, framebuffer, p_render_data);
+ if (rb_data.is_valid() && using_subpass_post_process) {
+ _post_process_subpass(p_render_data->render_buffers->get_internal_texture(), framebuffer, p_render_data);
}
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
@@ -831,20 +1016,22 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
} else {
RENDER_TIMESTAMP("Render Transparent");
- framebuffer = render_buffer->color_fbs[FB_CONFIG_ONE_PASS];
+ framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_ONE_PASS);
// this may be needed if we re-introduced steps that change info, not sure which do so in the previous implementation
// _setup_environment(p_render_data, p_render_data->reflection_probe.is_valid(), screen_size, !p_render_data->reflection_probe.is_valid(), p_default_bg_color, false);
RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer);
- RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->lod_camera_plane, p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, p_render_data->view_count);
+ RenderListParameters render_list_params(render_list[RENDER_LIST_ALPHA].elements.ptr(), render_list[RENDER_LIST_ALPHA].element_info.ptr(), render_list[RENDER_LIST_ALPHA].elements.size(), reverse_cull, PASS_MODE_COLOR, rp_uniform_set, spec_constant_base_flags, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count);
render_list_params.framebuffer_format = fb_format;
if ((uint32_t)render_list_params.element_count > render_list_thread_threshold && false) {
// secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), can_continue_color ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue_depth ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, &render_list_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, &render_list_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
RD::get_singleton()->draw_list_end(RD::BARRIER_MASK_ALL);
} else {
//single threaded
@@ -857,7 +1044,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
}
- if (render_buffer && !using_subpass_post_process) {
+ if (rb_data.is_valid() && !using_subpass_post_process) {
RD::get_singleton()->draw_command_begin_label("Post process pass");
// If we need extra effects we do this in its own pass
@@ -868,13 +1055,193 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_end_label(); // Post process pass
}
- if (render_buffer) {
+ if (rb_data.is_valid()) {
_disable_clear_request(p_render_data);
}
+
+ if (rb.is_valid()) {
+ _render_buffers_debug_draw(rb, p_render_data->shadow_atlas, p_render_data->occluder_debug_tex);
+ }
}
/* these are being called from RendererSceneRenderRD::_pre_opaque_render */
+void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RenderingMethod::RenderInfo *p_render_info) {
+ RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+
+ ERR_FAIL_COND(!light_storage->owns_light_instance(p_light));
+
+ RID base = light_storage->light_instance_get_base_light(p_light);
+
+ Rect2i atlas_rect;
+ uint32_t atlas_size = 1;
+ RID atlas_fb;
+
+ bool using_dual_paraboloid = false;
+ bool using_dual_paraboloid_flip = false;
+ Vector2i dual_paraboloid_offset;
+ RID render_fb;
+ RID render_texture;
+ float zfar;
+
+ bool use_pancake = false;
+ bool render_cubemap = false;
+ bool finalize_cubemap = false;
+
+ bool flip_y = false;
+
+ Projection light_projection;
+ Transform3D light_transform;
+
+ if (light_storage->light_get_type(base) == RS::LIGHT_DIRECTIONAL) {
+ //set pssm stuff
+ uint64_t last_scene_shadow_pass = light_storage->light_instance_get_shadow_pass(p_light);
+ if (last_scene_shadow_pass != get_scene_pass()) {
+ light_storage->light_instance_set_directional_rect(p_light, light_storage->get_directional_shadow_rect());
+ light_storage->directional_shadow_increase_current_light();
+ light_storage->light_instance_set_shadow_pass(p_light, get_scene_pass());
+ }
+
+ use_pancake = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass);
+
+ atlas_rect = light_storage->light_instance_get_directional_rect(p_light);
+
+ if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
+ atlas_rect.size.width /= 2;
+ atlas_rect.size.height /= 2;
+
+ if (p_pass == 1) {
+ atlas_rect.position.x += atlas_rect.size.width;
+ } else if (p_pass == 2) {
+ atlas_rect.position.y += atlas_rect.size.height;
+ } else if (p_pass == 3) {
+ atlas_rect.position += atlas_rect.size;
+ }
+ } else if (light_storage->light_directional_get_shadow_mode(base) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
+ atlas_rect.size.height /= 2;
+
+ if (p_pass == 0) {
+ } else {
+ atlas_rect.position.y += atlas_rect.size.height;
+ }
+ }
+
+ float directional_shadow_size = light_storage->directional_shadow_get_size();
+ Rect2 atlas_rect_norm = atlas_rect;
+ atlas_rect_norm.position /= directional_shadow_size;
+ atlas_rect_norm.size /= directional_shadow_size;
+ light_storage->light_instance_set_directional_shadow_atlas_rect(p_light, p_pass, atlas_rect_norm);
+
+ zfar = RSG::light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE);
+
+ render_fb = light_storage->direction_shadow_get_fb();
+ render_texture = RID();
+ flip_y = true;
+
+ } else {
+ //set from shadow atlas
+
+ ERR_FAIL_COND(!light_storage->owns_shadow_atlas(p_shadow_atlas));
+ ERR_FAIL_COND(!light_storage->shadow_atlas_owns_light_instance(p_shadow_atlas, p_light));
+
+ RSG::light_storage->shadow_atlas_update(p_shadow_atlas);
+
+ uint32_t key = light_storage->shadow_atlas_get_light_instance_key(p_shadow_atlas, p_light);
+
+ uint32_t quadrant = (key >> RendererRD::LightStorage::QUADRANT_SHIFT) & 0x3;
+ uint32_t shadow = key & RendererRD::LightStorage::SHADOW_INDEX_MASK;
+ uint32_t subdivision = light_storage->shadow_atlas_get_quadrant_subdivision(p_shadow_atlas, quadrant);
+
+ ERR_FAIL_INDEX((int)shadow, light_storage->shadow_atlas_get_quadrant_shadow_size(p_shadow_atlas, quadrant));
+
+ uint32_t shadow_atlas_size = light_storage->shadow_atlas_get_size(p_shadow_atlas);
+ uint32_t quadrant_size = shadow_atlas_size >> 1;
+
+ atlas_rect.position.x = (quadrant & 1) * quadrant_size;
+ atlas_rect.position.y = (quadrant >> 1) * quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / subdivision);
+ atlas_rect.position.x += (shadow % subdivision) * shadow_size;
+ atlas_rect.position.y += (shadow / subdivision) * shadow_size;
+
+ atlas_rect.size.width = shadow_size;
+ atlas_rect.size.height = shadow_size;
+
+ zfar = light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE);
+
+ if (light_storage->light_get_type(base) == RS::LIGHT_OMNI) {
+ bool wrap = (shadow + 1) % subdivision == 0;
+ dual_paraboloid_offset = wrap ? Vector2i(1 - subdivision, 1) : Vector2i(1, 0);
+
+ if (light_storage->light_omni_get_shadow_mode(base) == RS::LIGHT_OMNI_SHADOW_CUBE) {
+ render_texture = light_storage->get_cubemap(shadow_size / 2);
+ render_fb = light_storage->get_cubemap_fb(shadow_size / 2, p_pass);
+
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, p_pass);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, p_pass);
+ render_cubemap = true;
+ finalize_cubemap = p_pass == 5;
+ atlas_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas);
+
+ atlas_size = shadow_atlas_size;
+
+ if (p_pass == 0) {
+ _render_shadow_begin();
+ }
+
+ } else {
+ atlas_rect.position.x += 1;
+ atlas_rect.position.y += 1;
+ atlas_rect.size.x -= 2;
+ atlas_rect.size.y -= 2;
+
+ atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset;
+
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0);
+
+ using_dual_paraboloid = true;
+ using_dual_paraboloid_flip = p_pass == 1;
+ render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas);
+ flip_y = true;
+ }
+
+ } else if (light_storage->light_get_type(base) == RS::LIGHT_SPOT) {
+ light_projection = light_storage->light_instance_get_shadow_camera(p_light, 0);
+ light_transform = light_storage->light_instance_get_shadow_transform(p_light, 0);
+
+ render_fb = light_storage->shadow_atlas_get_fb(p_shadow_atlas);
+
+ flip_y = true;
+ }
+ }
+
+ if (render_cubemap) {
+ //rendering to cubemap
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info);
+ if (finalize_cubemap) {
+ _render_shadow_process();
+ _render_shadow_end();
+ //reblit
+ Rect2 atlas_rect_norm = atlas_rect;
+ atlas_rect_norm.position /= float(atlas_size);
+ atlas_rect_norm.size /= float(atlas_size);
+ copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false);
+ atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size;
+ copy_effects->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true);
+
+ //restore transform so it can be properly used
+ light_storage->light_instance_set_shadow_transform(p_light, Projection(), light_storage->light_instance_get_base_transform(p_light), zfar, 0, 0, 0);
+ }
+
+ } else {
+ //render shadow
+ _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info);
+ }
+}
+
void RenderForwardMobile::_render_shadow_begin() {
scene_state.shadow_passes.clear();
RD::get_singleton()->draw_command_begin_label("Shadow Setup");
@@ -883,7 +1250,7 @@ void RenderForwardMobile::_render_shadow_begin() {
render_list[RENDER_LIST_SECONDARY].clear();
}
-void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RendererScene::RenderInfo *p_render_info) {
+void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info) {
uint32_t shadow_pass_index = scene_state.shadow_passes.size();
SceneState::ShadowPass shadow_pass;
@@ -892,26 +1259,30 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = p_instances.size();
p_render_info->info[RS::VIEWPORT_RENDER_INFO_TYPE_SHADOW][RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = p_instances.size();
}
+
+ RenderSceneDataRD scene_data;
+ scene_data.cam_projection = p_projection;
+ scene_data.cam_transform = p_transform;
+ scene_data.view_projection[0] = p_projection;
+ scene_data.z_near = 0.0;
+ scene_data.z_far = p_zfar;
+ scene_data.lod_distance_multiplier = p_lod_distance_multiplier;
+ scene_data.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
+ scene_data.opaque_prepass_threshold = 0.1;
+ scene_data.time = time;
+ scene_data.time_step = time_step;
+
RenderDataRD render_data;
- render_data.cam_projection = p_projection;
- render_data.cam_transform = p_transform;
- render_data.view_projection[0] = p_projection;
- render_data.z_near = 0.0;
- render_data.z_far = p_zfar;
+ render_data.scene_data = &scene_data;
render_data.instances = &p_instances;
render_data.render_info = p_render_info;
- render_data.lod_camera_plane = p_camera_plane;
- render_data.lod_distance_multiplier = p_lod_distance_multiplier;
-
- scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1;
- scene_state.ubo.opaque_prepass_threshold = 0.1;
_setup_environment(&render_data, true, Vector2(1, 1), !p_flip_y, Color(), false, p_use_pancake, shadow_pass_index);
if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
- render_data.screen_mesh_lod_threshold = 0.0;
+ scene_data.screen_mesh_lod_threshold = 0.0;
} else {
- render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
+ scene_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
}
PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW;
@@ -936,8 +1307,8 @@ void RenderForwardMobile::_render_shadow_append(RID p_framebuffer, const PagedAr
shadow_pass.rp_uniform_set = RID(); //will be filled later when instance buffer is complete
shadow_pass.camera_plane = p_camera_plane;
- shadow_pass.screen_mesh_lod_threshold = render_data.screen_mesh_lod_threshold;
- shadow_pass.lod_distance_multiplier = render_data.lod_distance_multiplier;
+ shadow_pass.screen_mesh_lod_threshold = scene_data.screen_mesh_lod_threshold;
+ shadow_pass.lod_distance_multiplier = scene_data.lod_distance_multiplier;
shadow_pass.framebuffer = p_framebuffer;
shadow_pass.initial_depth_action = p_begin ? (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR) : (p_clear_region ? RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE : RD::INITIAL_ACTION_CONTINUE);
@@ -965,7 +1336,7 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) {
SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i];
- RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.camera_plane, shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
+ RenderListParameters render_list_parameters(render_list[RENDER_LIST_SECONDARY].elements.ptr() + shadow_pass.element_from, render_list[RENDER_LIST_SECONDARY].element_info.ptr() + shadow_pass.element_from, shadow_pass.element_count, shadow_pass.flip_cull, shadow_pass.pass_mode, shadow_pass.rp_uniform_set, 0, false, Vector2(), shadow_pass.lod_distance_multiplier, shadow_pass.screen_mesh_lod_threshold, 1, shadow_pass.element_from, RD::BARRIER_MASK_NO_BARRIER);
_render_list_with_threads(&render_list_parameters, shadow_pass.framebuffer, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, shadow_pass.initial_depth_action, shadow_pass.final_depth_action, Vector<Color>(), 1.0, 0, shadow_pass.rect);
}
@@ -977,21 +1348,24 @@ void RenderForwardMobile::_render_shadow_end(uint32_t p_barrier) {
/* */
-void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) {
RENDER_TIMESTAMP("Setup Rendering 3D Material");
RD::get_singleton()->draw_command_begin_label("Render 3D Material");
_update_render_base_uniform_set();
- scene_state.ubo.dual_paraboloid_side = 0;
- scene_state.ubo.material_uv2_mode = false;
- scene_state.ubo.opaque_prepass_threshold = 0.0f;
+ RenderSceneDataRD scene_data;
+ scene_data.cam_projection = p_cam_projection;
+ scene_data.cam_transform = p_cam_transform;
+ scene_data.view_projection[0] = p_cam_projection;
+ scene_data.dual_paraboloid_side = 0;
+ scene_data.material_uv2_mode = false;
+ scene_data.opaque_prepass_threshold = 0.0f;
+ scene_data.emissive_exposure_normalization = p_exposure_normalization;
RenderDataRD render_data;
- render_data.cam_projection = p_cam_projection;
- render_data.cam_transform = p_cam_transform;
- render_data.view_projection[0] = p_cam_projection;
+ render_data.scene_data = &scene_data;
render_data.instances = &p_instances;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1023,17 +1397,20 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+void RenderForwardMobile::_render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
RENDER_TIMESTAMP("Setup Rendering UV2");
RD::get_singleton()->draw_command_begin_label("Render UV2");
_update_render_base_uniform_set();
- scene_state.ubo.dual_paraboloid_side = 0;
- scene_state.ubo.material_uv2_mode = true;
+ RenderSceneDataRD scene_data;
+ scene_data.dual_paraboloid_side = 0;
+ scene_data.material_uv2_mode = true;
+ scene_data.emissive_exposure_normalization = -1.0;
RenderDataRD render_data;
+ render_data.scene_data = &scene_data;
render_data.instances = &p_instances;
_setup_environment(&render_data, true, Vector2(1, 1), false, Color());
@@ -1090,25 +1467,28 @@ void RenderForwardMobile::_render_uv2(const PagedArray<GeometryInstance *> &p_in
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) {
- // we don't do GI in low end..
+void RenderForwardMobile::_render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) {
+ // we don't do SDFGI in low end..
}
-void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) {
+void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) {
RENDER_TIMESTAMP("Setup GPUParticlesCollisionHeightField3D");
RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield");
_update_render_base_uniform_set();
- scene_state.ubo.dual_paraboloid_side = 0;
- scene_state.ubo.opaque_prepass_threshold = 0.0;
+
+ RenderSceneDataRD scene_data;
+ scene_data.cam_projection = p_cam_projection;
+ scene_data.cam_transform = p_cam_transform;
+ scene_data.view_projection[0] = p_cam_projection;
+ scene_data.z_near = 0.0;
+ scene_data.z_far = p_cam_projection.get_z_far();
+ scene_data.dual_paraboloid_side = 0;
+ scene_data.opaque_prepass_threshold = 0.0;
RenderDataRD render_data;
- render_data.cam_projection = p_cam_projection;
- render_data.cam_transform = p_cam_transform;
- render_data.view_projection[0] = p_cam_projection;
- render_data.z_near = 0.0;
- render_data.z_far = p_cam_projection.get_z_far();
+ render_data.scene_data = &scene_data;
render_data.instances = &p_instances;
_setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false);
@@ -1131,7 +1511,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const
RD::get_singleton()->draw_command_end_label();
}
-void RenderForwardMobile::_base_uniforms_changed() {
+void RenderForwardMobile::base_uniforms_changed() {
if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) {
RD::get_singleton()->free(render_base_uniform_set);
}
@@ -1192,15 +1572,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
case RS::DECAL_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::DECAL_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -1219,15 +1602,18 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
case RS::LIGHT_PROJECTOR_FILTER_NEAREST: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
- case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
- sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
+ case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: {
+ sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
+ } break;
case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: {
sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
} break;
@@ -1241,14 +1627,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 5;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_omni_light_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_omni_light_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 6;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_spot_light_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_spot_light_buffer());
uniforms.push_back(u);
}
@@ -1256,14 +1642,14 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 7;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_reflection_probe_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_reflection_probe_buffer());
uniforms.push_back(u);
}
{
RD::Uniform u;
u.binding = 8;
u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.append_id(get_directional_light_buffer());
+ u.append_id(RendererRD::LightStorage::get_singleton()->get_directional_light_buffer());
uniforms.push_back(u);
}
{
@@ -1300,7 +1686,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.binding = 13;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(get_decal_buffer());
+ u.append_id(RendererRD::TextureStorage::get_singleton()->get_decal_buffer());
uniforms.push_back(u);
}
@@ -1308,7 +1694,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 14;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1316,15 +1702,11 @@ void RenderForwardMobile::_update_render_base_uniform_set() {
}
}
-RID RenderForwardMobile::_render_buffers_get_normal_texture(RID p_render_buffers) {
- // RenderBufferDataForwardMobile *rb = (RenderBufferDataForwardMobile *)render_buffers_get_data(p_render_buffers);
-
- // We don't have this. This is for debugging
- // return rb->normal_roughness_buffer;
+RID RenderForwardMobile::_render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
return RID();
}
-RID RenderForwardMobile::_render_buffers_get_velocity_texture(RID p_render_buffers) {
+RID RenderForwardMobile::_render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) {
return RID();
}
@@ -1345,9 +1727,9 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
uint32_t lightmap_captures_used = 0;
- Plane near_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
- near_plane.d += p_render_data->cam_projection.get_z_near();
- float z_max = p_render_data->cam_projection.get_z_far() - p_render_data->cam_projection.get_z_near();
+ Plane near_plane(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->scene_data->cam_transform.origin);
+ near_plane.d += p_render_data->scene_data->cam_projection.get_z_near();
+ float z_max = p_render_data->scene_data->cam_projection.get_z_far() - p_render_data->scene_data->cam_projection.get_z_near();
RenderList *rl = &render_list[p_render_list];
@@ -1426,13 +1808,14 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
// LOD
- if (p_render_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
- //lod
- Vector3 lod_support_min = inst->transformed_aabb.get_support(-p_render_data->lod_camera_plane.normal);
- Vector3 lod_support_max = inst->transformed_aabb.get_support(p_render_data->lod_camera_plane.normal);
+ if (p_render_data->scene_data->screen_mesh_lod_threshold > 0.0 && mesh_storage->mesh_surface_has_lod(surf->surface)) {
+ // Get the LOD support points on the mesh AABB.
+ Vector3 lod_support_min = inst->transformed_aabb.get_support(p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
+ Vector3 lod_support_max = inst->transformed_aabb.get_support(-p_render_data->scene_data->cam_transform.basis.get_column(Vector3::AXIS_Z));
- float distance_min = p_render_data->lod_camera_plane.distance_to(lod_support_min);
- float distance_max = p_render_data->lod_camera_plane.distance_to(lod_support_max);
+ // Get the distances to those points on the AABB from the camera origin.
+ float distance_min = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_min);
+ float distance_max = (float)p_render_data->scene_data->cam_transform.origin.distance_to(lod_support_max);
float distance = 0.0;
@@ -1445,12 +1828,12 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
distance = -distance_max;
}
- if (p_render_data->cam_orthogonal) {
+ if (p_render_data->scene_data->cam_orthogonal) {
distance = 1.0;
}
- uint32_t indices;
- surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, &indices);
+ uint32_t indices = 0;
+ surf->lod_index = mesh_storage->mesh_surface_get_lod(surf->surface, inst->lod_model_scale * inst->lod_bias, distance * p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, indices);
if (p_render_data->render_info) {
indices = _indices_to_primitives(surf->primitive, indices);
if (p_render_list == RENDER_LIST_OPAQUE) { //opaque
@@ -1522,190 +1905,20 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
}
void RenderForwardMobile::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_pancake_shadows, int p_index) {
- //!BAS! need to go through this and find out what we don't need anymore
-
- // This populates our UBO with main scene data that is pushed into set 1
-
- //CameraMatrix projection = p_render_data->cam_projection;
- //projection.flip_y(); // Vulkan and modern APIs use Y-Down
- CameraMatrix correction;
- correction.set_depth_correction(p_flip_y);
- CameraMatrix projection = correction * p_render_data->cam_projection;
-
- //store camera into ubo
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform, scene_state.ubo.inv_view_matrix);
- RendererStorageRD::store_transform(p_render_data->cam_transform.affine_inverse(), scene_state.ubo.view_matrix);
-
- for (uint32_t v = 0; v < p_render_data->view_count; v++) {
- projection = correction * p_render_data->view_projection[v];
- RendererStorageRD::store_camera(projection, scene_state.ubo.projection_matrix_view[v]);
- RendererStorageRD::store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix_view[v]);
- }
-
- scene_state.ubo.z_far = p_render_data->z_far;
- scene_state.ubo.z_near = p_render_data->z_near;
-
- scene_state.ubo.pancake_shadows = p_pancake_shadows;
-
- RendererStorageRD::store_soft_shadow_kernel(directional_penumbra_shadow_kernel_get(), scene_state.ubo.directional_penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(directional_soft_shadow_kernel_get(), scene_state.ubo.directional_soft_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(penumbra_shadow_kernel_get(), scene_state.ubo.penumbra_shadow_kernel);
- RendererStorageRD::store_soft_shadow_kernel(soft_shadow_kernel_get(), scene_state.ubo.soft_shadow_kernel);
-
- Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
- scene_state.ubo.screen_pixel_size[0] = screen_pixel_size.x;
- scene_state.ubo.screen_pixel_size[1] = screen_pixel_size.y;
-
- if (p_render_data->shadow_atlas.is_valid()) {
- Vector2 sas = shadow_atlas_get_size(p_render_data->shadow_atlas);
- scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x;
- scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y;
- }
- {
- Vector2 dss = directional_shadow_get_size();
- scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x;
- scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y;
- }
-
- //time global variables
- scene_state.ubo.time = time;
-
- /*
- scene_state.ubo.gi_upscale_for_msaa = false;
- scene_state.ubo.volumetric_fog_enabled = false;
- scene_state.ubo.fog_enabled = false;
-
- if (p_render_data->render_buffers.is_valid()) {
- RenderBufferDataForwardMobile *render_buffers = static_cast<RenderBufferDataForwardMobile *>(render_buffers_get_data(p_render_data->render_buffers));
- if (render_buffers->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- scene_state.ubo.gi_upscale_for_msaa = true;
- }
-
- if (render_buffers_has_volumetric_fog(p_render_data->render_buffers)) {
- scene_state.ubo.volumetric_fog_enabled = true;
- float fog_end = render_buffers_get_volumetric_fog_end(p_render_data->render_buffers);
- if (fog_end > 0.0) {
- scene_state.ubo.volumetric_fog_inv_length = 1.0 / fog_end;
- } else {
- scene_state.ubo.volumetric_fog_inv_length = 1.0;
- }
-
- float fog_detail_spread = render_buffers_get_volumetric_fog_detail_spread(p_render_data->render_buffers); //reverse lookup
- if (fog_detail_spread > 0.0) {
- scene_state.ubo.volumetric_fog_detail_spread = 1.0 / fog_detail_spread;
- } else {
- scene_state.ubo.volumetric_fog_detail_spread = 1.0;
- }
- }
- }
-
- */
-
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
- scene_state.ubo.use_ambient_light = true;
- scene_state.ubo.ambient_light_color_energy[0] = 1;
- scene_state.ubo.ambient_light_color_energy[1] = 1;
- scene_state.ubo.ambient_light_color_energy[2] = 1;
- scene_state.ubo.ambient_light_color_energy[3] = 1.0;
- scene_state.ubo.use_ambient_cubemap = false;
- scene_state.ubo.use_reflection_cubemap = false;
- scene_state.ubo.ssao_enabled = false;
-
- } else if (is_environment(p_render_data->environment)) {
- RS::EnvironmentBG env_bg = environment_get_background(p_render_data->environment);
- RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_source(p_render_data->environment);
-
- float bg_energy = environment_get_bg_energy(p_render_data->environment);
- scene_state.ubo.ambient_light_color_energy[3] = bg_energy;
-
- scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_render_data->environment);
-
- //ambient
- if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
- Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_render_data->environment);
- color = color.srgb_to_linear();
-
- scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy;
- scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy;
- scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy;
- scene_state.ubo.use_ambient_light = true;
- scene_state.ubo.use_ambient_cubemap = false;
- } else {
- float energy = environment_get_ambient_light_energy(p_render_data->environment);
- Color color = environment_get_ambient_light_color(p_render_data->environment);
- color = color.srgb_to_linear();
- scene_state.ubo.ambient_light_color_energy[0] = color.r * energy;
- scene_state.ubo.ambient_light_color_energy[1] = color.g * energy;
- scene_state.ubo.ambient_light_color_energy[2] = color.b * energy;
-
- Basis sky_transform = environment_get_sky_orientation(p_render_data->environment);
- sky_transform = sky_transform.inverse() * p_render_data->cam_transform.basis;
- RendererStorageRD::store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform);
-
- scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
- scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
- }
-
- //specular
- RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_render_data->environment);
- if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) {
- scene_state.ubo.use_reflection_cubemap = true;
- } else {
- scene_state.ubo.use_reflection_cubemap = false;
- }
-
- scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_render_data->environment);
- scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_render_data->environment);
- scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_render_data->environment);
-
- scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_render_data->environment);
- scene_state.ubo.fog_density = environment_get_fog_density(p_render_data->environment);
- scene_state.ubo.fog_height = environment_get_fog_height(p_render_data->environment);
- scene_state.ubo.fog_height_density = environment_get_fog_height_density(p_render_data->environment);
- scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_render_data->environment);
-
- Color fog_color = environment_get_fog_light_color(p_render_data->environment).srgb_to_linear();
- float fog_energy = environment_get_fog_light_energy(p_render_data->environment);
-
- scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy;
- scene_state.ubo.fog_light_color[1] = fog_color.g * fog_energy;
- scene_state.ubo.fog_light_color[2] = fog_color.b * fog_energy;
-
- scene_state.ubo.fog_sun_scatter = environment_get_fog_sun_scatter(p_render_data->environment);
-
- } else {
- if (p_render_data->reflection_probe.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
- scene_state.ubo.use_ambient_light = false;
- } else {
- scene_state.ubo.use_ambient_light = true;
- Color clear_color = p_default_bg_color;
- clear_color = clear_color.srgb_to_linear();
- scene_state.ubo.ambient_light_color_energy[0] = clear_color.r;
- scene_state.ubo.ambient_light_color_energy[1] = clear_color.g;
- scene_state.ubo.ambient_light_color_energy[2] = clear_color.b;
- scene_state.ubo.ambient_light_color_energy[3] = 1.0;
- }
-
- scene_state.ubo.use_ambient_cubemap = false;
- scene_state.ubo.use_reflection_cubemap = false;
- scene_state.ubo.ssao_enabled = false;
- }
-
- scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active();
- scene_state.ubo.roughness_limiter_amount = screen_space_roughness_limiter_get_amount();
- scene_state.ubo.roughness_limiter_limit = screen_space_roughness_limiter_get_limit();
+ Ref<RenderSceneBuffersRD> rd = p_render_data->render_buffers;
+ RID env = is_environment(p_render_data->environment) ? p_render_data->environment : RID();
+ RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID();
+ // May do this earlier in RenderSceneRenderRD::render_scene
if (p_index >= (int)scene_state.uniform_buffers.size()) {
uint32_t from = scene_state.uniform_buffers.size();
scene_state.uniform_buffers.resize(p_index + 1);
- render_pass_uniform_sets.resize(p_index + 1);
for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) {
- scene_state.uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO));
+ scene_state.uniform_buffers[i] = p_render_data->scene_data->create_uniform_buffer();
}
}
- RD::get_singleton()->buffer_update(scene_state.uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo, RD::BARRIER_MASK_RASTER);
+
+ p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_flip_y, p_pancake_shadows, p_screen_size, p_default_bg_color, _render_buffers_get_luminance_multiplier(), p_opaque_render_buffers);
}
void RenderForwardMobile::_fill_element_info(RenderListType p_render_list, uint32_t p_offset, int32_t p_max_elements) {
@@ -1749,7 +1962,7 @@ void RenderForwardMobile::_render_list(RenderingDevice::DrawListID p_draw_list,
void RenderForwardMobile::_render_list_thread_function(uint32_t p_thread, RenderListParameters *p_params) {
uint32_t render_total = p_params->element_count;
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t render_from = p_thread * render_total / total_threads;
uint32_t render_to = (p_thread + 1 == total_threads) ? render_total : ((p_thread + 1) * render_total / total_threads);
_render_list(thread_draw_lists[p_thread], p_params->framebuffer_format, p_params, render_from, render_to);
@@ -1761,9 +1974,11 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para
if ((uint32_t)p_params->element_count > render_list_thread_threshold && false) { // secondary command buffers need more testing at this time
//multi threaded
- thread_draw_lists.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ thread_draw_lists.resize(WorkerThreadPool::get_singleton()->get_thread_count());
RD::get_singleton()->draw_list_begin_split(p_framebuffer, thread_draw_lists.size(), thread_draw_lists.ptr(), p_initial_color_action, p_final_color_action, p_initial_depth_action, p_final_depth_action, p_clear_color_values, p_clear_depth, p_clear_stencil, p_region, p_storage_textures);
- RendererThreadPool::singleton->thread_work_pool.do_work(thread_draw_lists.size(), this, &RenderForwardMobile::_render_list_thread_function, p_params);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RenderForwardMobile::_render_list_thread_function, p_params, thread_draw_lists.size(), -1, true, SNAME("ForwardMobileRenderSubpass"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
RD::get_singleton()->draw_list_end(p_params->barrier);
} else {
//single threaded
@@ -1773,57 +1988,6 @@ void RenderForwardMobile::_render_list_with_threads(RenderListParameters *p_para
}
}
-void RenderForwardMobile::_fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance) {
- // first zero out our indices
-
- p_push_constant->omni_lights[0] = 0xFFFF;
- p_push_constant->omni_lights[1] = 0xFFFF;
-
- p_push_constant->spot_lights[0] = 0xFFFF;
- p_push_constant->spot_lights[1] = 0xFFFF;
-
- p_push_constant->decals[0] = 0xFFFF;
- p_push_constant->decals[1] = 0xFFFF;
-
- p_push_constant->reflection_probes[0] = 0xFFFF;
- p_push_constant->reflection_probes[1] = 0xFFFF;
-
- if (p_instance->omni_light_count == 0) {
- spec_constants |= 1 << SPEC_CONSTANT_DISABLE_OMNI_LIGHTS;
- }
- if (p_instance->spot_light_count == 0) {
- spec_constants |= 1 << SPEC_CONSTANT_DISABLE_SPOT_LIGHTS;
- }
- if (p_instance->reflection_probe_count == 0) {
- spec_constants |= 1 << SPEC_CONSTANT_DISABLE_REFLECTION_PROBES;
- }
- if (p_instance->decals_count == 0) {
- spec_constants |= 1 << SPEC_CONSTANT_DISABLE_DECALS;
- }
-
- for (uint32_t i = 0; i < MAX_RDL_CULL; i++) {
- uint32_t ofs = i < 4 ? 0 : 1;
- uint32_t shift = (i & 0x3) << 3;
- uint32_t mask = ~(0xFF << shift);
- if (i < p_instance->omni_light_count) {
- p_push_constant->omni_lights[ofs] &= mask;
- p_push_constant->omni_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_OMNI_LIGHT].map[p_instance->omni_lights[i]]) << shift;
- }
- if (i < p_instance->spot_light_count) {
- p_push_constant->spot_lights[ofs] &= mask;
- p_push_constant->spot_lights[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_SPOT_LIGHT].map[p_instance->spot_lights[i]]) << shift;
- }
- if (i < p_instance->decals_count) {
- p_push_constant->decals[ofs] &= mask;
- p_push_constant->decals[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_DECAL].map[p_instance->decals[i]]) << shift;
- }
- if (i < p_instance->reflection_probe_count) {
- p_push_constant->reflection_probes[ofs] &= mask;
- p_push_constant->reflection_probes[ofs] |= uint32_t(forward_id_allocators[FORWARD_ID_TYPE_REFLECTION_PROBE].map[p_instance->reflection_probes[i]]) << shift;
- }
- }
-}
-
template <RenderForwardMobile::PassMode p_pass_mode>
void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderListParameters *p_params, uint32_t p_from_element, uint32_t p_to_element) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
@@ -1842,6 +2006,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
RID prev_index_array_rd;
RID prev_pipeline_rd;
RID prev_xforms_uniform_set;
+ bool should_request_redraw = false;
bool shadow_pass = (p_params->pass_mode == PASS_MODE_SHADOW) || (p_params->pass_mode == PASS_MODE_SHADOW_DP);
@@ -1860,15 +2025,23 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
GeometryInstanceForwardMobile::PushConstant push_constant;
if (inst->store_transform_cache) {
- RendererStorageRD::store_transform(inst->transform, push_constant.transform);
+ RendererRD::MaterialStorage::store_transform(inst->transform, push_constant.transform);
} else {
- RendererStorageRD::store_transform(Transform3D(), push_constant.transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), push_constant.transform);
}
+#ifdef REAL_T_IS_DOUBLE
+ // Split the origin into two components, the float approximation and the missing precision
+ // In the shader we will combine these back together to restore the lost precision.
+ RendererRD::MaterialStorage::split_double(inst->transform.origin.x, &push_constant.transform[12], &push_constant.transform[3]);
+ RendererRD::MaterialStorage::split_double(inst->transform.origin.y, &push_constant.transform[13], &push_constant.transform[7]);
+ RendererRD::MaterialStorage::split_double(inst->transform.origin.z, &push_constant.transform[14], &push_constant.transform[11]);
+#endif
+
push_constant.flags = inst->flags_cache;
push_constant.gi_offset = inst->gi_offset_cache;
push_constant.layer_mask = inst->layer_mask;
- push_constant.instance_uniforms_ofs = uint32_t(inst->shader_parameters_offset);
+ push_constant.instance_uniforms_ofs = uint32_t(inst->shader_uniforms_offset);
if (p_params->pass_mode == PASS_MODE_DEPTH_MATERIAL) {
// abuse lightmap_uv_scale[0] here, should not be needed here
@@ -1897,7 +2070,7 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
if (inst->use_soft_shadow) {
base_spec_constants |= 1 << SPEC_CONSTANT_USING_SOFT_SHADOWS;
}
- _fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst);
+ forward_id_storage_mobile->fill_push_constant_instance_indices(&push_constant, base_spec_constants, inst);
#ifdef DEBUG_ENABLED
if (unlikely(get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING)) {
@@ -1920,6 +2093,11 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
continue;
}
+ //request a redraw if one of the shaders uses TIME
+ if (shader->uses_time) {
+ should_request_redraw = true;
+ }
+
//find cull variant
SceneShaderForwardMobile::ShaderData::CullVariant cull_variant;
@@ -2021,12 +2199,17 @@ void RenderForwardMobile::_render_list_template(RenderingDevice::DrawListID p_dr
RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instance_count);
}
+
+ // Make the actual redraw request
+ if (should_request_redraw) {
+ RenderingServerDefault::redraw_request();
+ }
}
/* Geometry instance */
-RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) {
- RS::InstanceType type = storage->get_base_type(p_base);
+RenderGeometryInstance *RenderForwardMobile::geometry_instance_create(RID p_base) {
+ RS::InstanceType type = RSG::utilities->get_base_type(p_base);
ERR_FAIL_COND_V(!((1 << type) & RS::INSTANCE_GEOMETRY_MASK), nullptr);
GeometryInstanceForwardMobile *ginstance = geometry_instance_alloc.alloc();
@@ -2035,165 +2218,36 @@ RendererSceneRender::GeometryInstance *RenderForwardMobile::geometry_instance_cr
ginstance->data->base = p_base;
ginstance->data->base_type = type;
- _geometry_instance_mark_dirty(ginstance);
+ ginstance->_mark_dirty();
return ginstance;
}
-void RenderForwardMobile::geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->skeleton = p_skeleton;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_override = p_override;
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
+ lightmap_instance = p_lightmap_instance;
+ lightmap_uv_scale = p_lightmap_uv_scale;
+ lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
+ _mark_dirty();
}
-void RenderForwardMobile::geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->material_overlay = p_overlay;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->surface_materials = p_materials;
-
- _geometry_instance_mark_dirty(ginstance);
- ginstance->data->dirty_dependencies = true;
-}
-
-void RenderForwardMobile::geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->mesh_instance = p_mesh_instance;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->transform = p_transform;
- ginstance->mirror = p_transform.basis.determinant() < 0;
- ginstance->data->aabb = p_aabb;
- ginstance->transformed_aabb = p_transformed_aabb;
-
- Vector3 model_scale_vec = p_transform.basis.get_scale_abs();
- // handle non uniform scale here
-
- float max_scale = MAX(model_scale_vec.x, MAX(model_scale_vec.y, model_scale_vec.z));
- float min_scale = MIN(model_scale_vec.x, MIN(model_scale_vec.y, model_scale_vec.z));
- ginstance->non_uniform_scale = max_scale >= 0.0 && (min_scale / max_scale) < 0.9;
-
- ginstance->lod_model_scale = max_scale;
-}
-
-void RenderForwardMobile::geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->layer_mask = p_layer_mask;
-}
-
-void RenderForwardMobile::geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lod_bias = p_lod_bias;
-}
-
-void RenderForwardMobile::geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) {
-}
-
-void RenderForwardMobile::geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) {
-}
-
-void RenderForwardMobile::geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) {
-}
-
-void RenderForwardMobile::geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->data->use_baked_light = p_enable;
-
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) {
- // !BAS! do we support this in mobile?
- // GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- // ERR_FAIL_COND(!ginstance);
- // ginstance->data->use_dynamic_gi = p_enable;
- // _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->lightmap_instance = p_lightmap_instance;
- ginstance->lightmap_uv_scale = p_lightmap_uv_scale;
- ginstance->lightmap_slice_index = p_lightmap_slice_index;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_lightmap_capture(const Color *p_sh9) {
if (p_sh9) {
- if (ginstance->lightmap_sh == nullptr) {
- ginstance->lightmap_sh = geometry_instance_lightmap_sh.alloc();
+ if (lightmap_sh == nullptr) {
+ lightmap_sh = RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.alloc();
}
- memcpy(ginstance->lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
+ memcpy(lightmap_sh->sh, p_sh9, sizeof(Color) * 9);
} else {
- if (ginstance->lightmap_sh != nullptr) {
- geometry_instance_lightmap_sh.free(ginstance->lightmap_sh);
- ginstance->lightmap_sh = nullptr;
+ if (lightmap_sh != nullptr) {
+ RenderForwardMobile::get_singleton()->geometry_instance_lightmap_sh.free(lightmap_sh);
+ lightmap_sh = nullptr;
}
}
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
- ginstance->shader_parameters_offset = p_offset;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-void RenderForwardMobile::geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->data->cast_double_sided_shadows = p_enable;
- _geometry_instance_mark_dirty(ginstance);
-}
-
-Transform3D RenderForwardMobile::geometry_instance_get_transform(GeometryInstance *p_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, Transform3D());
- return ginstance->transform;
+ _mark_dirty();
}
-AABB RenderForwardMobile::geometry_instance_get_aabb(GeometryInstance *p_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_instance);
- ERR_FAIL_COND_V(!ginstance, AABB());
- return ginstance->data->aabb;
-}
-
-void RenderForwardMobile::geometry_instance_free(GeometryInstance *p_geometry_instance) {
+void RenderForwardMobile::geometry_instance_free(RenderGeometryInstance *p_geometry_instance) {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
ERR_FAIL_COND(!ginstance);
if (ginstance->lightmap_sh != nullptr) {
@@ -2213,26 +2267,23 @@ uint32_t RenderForwardMobile::geometry_instance_get_pair_mask() {
return ((1 << RS::INSTANCE_LIGHT) + (1 << RS::INSTANCE_REFLECTION_PROBE) + (1 << RS::INSTANCE_DECAL));
}
-void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->omni_light_count = 0;
- ginstance->spot_light_count = 0;
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) {
+ omni_light_count = 0;
+ spot_light_count = 0;
for (uint32_t i = 0; i < p_light_instance_count; i++) {
- RS::LightType type = light_instance_get_type(p_light_instances[i]);
+ RS::LightType type = RendererRD::LightStorage::get_singleton()->light_instance_get_type(p_light_instances[i]);
switch (type) {
case RS::LIGHT_OMNI: {
- if (ginstance->omni_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->omni_lights[ginstance->omni_light_count] = light_instance_get_forward_id(p_light_instances[i]);
- ginstance->omni_light_count++;
+ if (omni_light_count < (uint32_t)MAX_RDL_CULL) {
+ omni_lights[omni_light_count] = RendererRD::LightStorage::get_singleton()->light_instance_get_forward_id(p_light_instances[i]);
+ omni_light_count++;
}
} break;
case RS::LIGHT_SPOT: {
- if (ginstance->spot_light_count < (uint32_t)MAX_RDL_CULL) {
- ginstance->spot_lights[ginstance->spot_light_count] = light_instance_get_forward_id(p_light_instances[i]);
- ginstance->spot_light_count++;
+ if (spot_light_count < (uint32_t)MAX_RDL_CULL) {
+ spot_lights[spot_light_count] = RendererRD::LightStorage::get_singleton()->light_instance_get_forward_id(p_light_instances[i]);
+ spot_light_count++;
}
} break;
default:
@@ -2241,56 +2292,42 @@ void RenderForwardMobile::geometry_instance_pair_light_instances(GeometryInstanc
}
}
-void RenderForwardMobile::geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL;
- for (uint32_t i = 0; i < ginstance->reflection_probe_count; i++) {
- ginstance->reflection_probes[i] = reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]);
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) {
+ reflection_probe_count = p_reflection_probe_instance_count < (uint32_t)MAX_RDL_CULL ? p_reflection_probe_instance_count : (uint32_t)MAX_RDL_CULL;
+ for (uint32_t i = 0; i < reflection_probe_count; i++) {
+ reflection_probes[i] = RendererRD::LightStorage::get_singleton()->reflection_probe_instance_get_forward_id(p_reflection_probe_instances[i]);
}
}
-void RenderForwardMobile::geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL;
- for (uint32_t i = 0; i < ginstance->decals_count; i++) {
- ginstance->decals[i] = decal_instance_get_forward_id(p_decal_instances[i]);
+void RenderForwardMobile::GeometryInstanceForwardMobile::pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) {
+ decals_count = p_decal_instance_count < (uint32_t)MAX_RDL_CULL ? p_decal_instance_count : (uint32_t)MAX_RDL_CULL;
+ for (uint32_t i = 0; i < decals_count; i++) {
+ decals[i] = RendererRD::TextureStorage::get_singleton()->decal_instance_get_forward_id(p_decal_instances[i]);
}
}
-void RenderForwardMobile::geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) {
- // We do not have this here!
+void RenderForwardMobile::GeometryInstanceForwardMobile::set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) {
+ use_projector = p_projector;
+ use_soft_shadow = p_softshadow;
}
-void RenderForwardMobile::geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- ERR_FAIL_COND(!ginstance);
-
- ginstance->use_projector = p_projector;
- ginstance->use_soft_shadow = p_softshadow;
-}
-
-void RenderForwardMobile::_geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance) {
- GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
- if (ginstance->dirty_list_element.in_list()) {
+void RenderForwardMobile::GeometryInstanceForwardMobile::_mark_dirty() {
+ if (dirty_list_element.in_list()) {
return;
}
//clear surface caches
- GeometryInstanceSurfaceDataCache *surf = ginstance->surface_caches;
+ GeometryInstanceSurfaceDataCache *surf = surface_caches;
while (surf) {
GeometryInstanceSurfaceDataCache *next = surf->next;
- geometry_instance_surface_alloc.free(surf);
+ RenderForwardMobile::get_singleton()->geometry_instance_surface_alloc.free(surf);
surf = next;
}
- ginstance->surface_caches = nullptr;
+ surface_caches = nullptr;
- geometry_instance_dirty_list.add(&ginstance->dirty_list_element);
+ RenderForwardMobile::get_singleton()->geometry_instance_dirty_list.add(&dirty_list_element);
}
void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh) {
@@ -2344,7 +2381,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
void *surface_shadow = nullptr;
if (!p_material->shader_data->uses_particle_trails && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass && !p_material->shader_data->uses_alpha_clip) {
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SHARED_SHADOW_MATERIAL;
- material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material_shadow = static_cast<SceneShaderForwardMobile::MaterialData *>(RendererRD::MaterialStorage::get_singleton()->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
RID shadow_mesh = mesh_storage->mesh_get_shadow_mesh(p_mesh);
@@ -2367,7 +2404,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
sdcache->surface_index = p_surface;
if (ginstance->data->dirty_dependencies) {
- storage->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_mesh, &ginstance->data->dependency_tracker);
}
//shadow
@@ -2403,7 +2440,7 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material_chain(Geo
while (material->next_pass.is_valid()) {
RID next_pass = material->next_pass;
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(next_pass, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
break;
}
@@ -2423,7 +2460,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
SceneShaderForwardMobile::MaterialData *material = nullptr;
if (m_src.is_valid()) {
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (!material || !material->shader_data->valid) {
material = nullptr;
}
@@ -2434,7 +2471,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
}
} else {
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(scene_shader.default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
m_src = scene_shader.default_material;
}
@@ -2445,7 +2482,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
if (ginstance->data->material_overlay.is_valid()) {
m_src = ginstance->data->material_overlay;
- material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::SHADER_TYPE_3D));
+ material = static_cast<SceneShaderForwardMobile::MaterialData *>(material_storage->material_get_data(m_src, RendererRD::MaterialStorage::SHADER_TYPE_3D));
if (material && material->shader_data->valid) {
if (ginstance->data->dirty_dependencies) {
material_storage->material_update_dependency(m_src, &ginstance->data->dependency_tracker);
@@ -2456,7 +2493,7 @@ void RenderForwardMobile::_geometry_instance_add_surface(GeometryInstanceForward
}
}
-void RenderForwardMobile::_geometry_instance_update(GeometryInstance *p_geometry_instance) {
+void RenderForwardMobile::_geometry_instance_update(RenderGeometryInstance *p_geometry_instance) {
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_geometry_instance);
@@ -2603,16 +2640,16 @@ void RenderForwardMobile::_update_dirty_geometry_instances() {
}
}
-void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker) {
+void RenderForwardMobile::_geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker) {
switch (p_notification) {
- case RendererStorage::DEPENDENCY_CHANGED_MATERIAL:
- case RendererStorage::DEPENDENCY_CHANGED_MESH:
- case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA: {
- static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+ case Dependency::DEPENDENCY_CHANGED_MATERIAL:
+ case Dependency::DEPENDENCY_CHANGED_MESH:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA: {
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES: {
GeometryInstanceForwardMobile *ginstance = static_cast<GeometryInstanceForwardMobile *>(p_tracker->userdata);
if (ginstance->data->base_type == RS::INSTANCE_MULTIMESH) {
ginstance->instance_count = RendererRD::MeshStorage::get_singleton()->multimesh_get_instances_to_draw(ginstance->data->base);
@@ -2623,8 +2660,8 @@ void RenderForwardMobile::_geometry_instance_dependency_changed(RendererStorage:
} break;
}
}
-void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker) {
- static_cast<RenderForwardMobile *>(singleton)->_geometry_instance_mark_dirty(static_cast<GeometryInstance *>(p_tracker->userdata));
+void RenderForwardMobile::_geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker) {
+ static_cast<RenderGeometryInstance *>(p_tracker->userdata)->_mark_dirty();
}
/* misc */
@@ -2633,10 +2670,6 @@ bool RenderForwardMobile::is_dynamic_gi_supported() const {
return false;
}
-bool RenderForwardMobile::is_clustered_enabled() const {
- return false;
-}
-
bool RenderForwardMobile::is_volumetric_supported() const {
return false;
}
@@ -2675,22 +2708,27 @@ void RenderForwardMobile::_update_shader_quality_settings() {
sc.type = RD::PIPELINE_SPECIALIZATION_CONSTANT_TYPE_BOOL;
sc.constant_id = SPEC_CONSTANT_DECAL_USE_MIPMAPS;
- sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS || decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS ||
+ decals_get_filter() == RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ decals_get_filter() == RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
sc.constant_id = SPEC_CONSTANT_PROJECTOR_USE_MIPMAPS;
- sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS || light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
+ sc.bool_value = light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC ||
+ light_projectors_get_filter() == RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC;
spec_constants.push_back(sc);
scene_shader.set_default_specialization_constants(spec_constants);
- _base_uniforms_changed(); //also need this
+ base_uniforms_changed(); //also need this
}
-RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
- RendererSceneRenderRD(p_storage) {
+RenderForwardMobile::RenderForwardMobile() {
singleton = this;
sky.set_texture_format(_render_buffers_get_color_format());
@@ -2721,8 +2759,13 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
{
defines += "\n#define MATERIAL_UNIFORM_SET " + itos(MATERIAL_UNIFORM_SET) + "\n";
}
+#ifdef REAL_T_IS_DOUBLE
+ {
+ defines += "\n#define USE_DOUBLE_PRECISION \n";
+ }
+#endif
- scene_shader.init(p_storage, defines);
+ scene_shader.init(defines);
// !BAS! maybe we need a mobile version of this setting?
render_list_thread_threshold = GLOBAL_GET("rendering/limits/forward_renderer/threaded_render_minimum_instances");
@@ -2731,7 +2774,7 @@ RenderForwardMobile::RenderForwardMobile(RendererStorageRD *p_storage) :
}
RenderForwardMobile::~RenderForwardMobile() {
- directional_shadow_atlas_set_size(0);
+ RSG::light_storage->directional_shadow_atlas_set_size(0);
//clear base uniform set if still valid
for (uint32_t i = 0; i < render_pass_uniform_sets.size(); i++) {
diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
index fc6f32ecb0..ce64d805b7 100644
--- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h
@@ -28,33 +28,28 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
-#define RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
+#ifndef RENDER_FORWARD_MOBILE_H
+#define RENDER_FORWARD_MOBILE_H
#include "core/templates/paged_allocator.h"
#include "servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
+
+#define RB_SCOPE_MOBILE SNAME("mobile")
namespace RendererSceneRenderImplementation {
class RenderForwardMobile : public RendererSceneRenderRD {
friend SceneShaderForwardMobile;
- struct ForwardIDAllocator {
- LocalVector<bool> allocations;
- LocalVector<uint8_t> map;
- };
-
- ForwardIDAllocator forward_id_allocators[FORWARD_ID_MAX];
+protected:
+ struct GeometryInstanceSurfaceDataCache;
- virtual ForwardID _allocate_forward_id(ForwardIDType p_type) override;
- virtual void _free_forward_id(ForwardIDType p_type, ForwardID p_id) override;
- virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) override;
- virtual bool _uses_forward_ids() const override { return true; }
+private:
+ static RenderForwardMobile *singleton;
-protected:
/* Scene Shader */
enum {
@@ -107,41 +102,38 @@ protected:
/* Render Buffer */
- // We can have:
- // - 4 subpasses combining the full render cycle
- // - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
- // - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
- enum RenderBufferMobileFramebufferConfigType {
- FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
- FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
- FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
- FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
- FB_CONFIG_MAX
- };
-
- struct RenderBufferDataForwardMobile : public RenderBufferData {
- RID color;
- RID depth;
- // RID normal_roughness_buffer;
-
- RS::ViewportMSAA msaa;
- RD::TextureSamples texture_samples;
+ class RenderBufferDataForwardMobile : public RenderBufferCustomDataRD {
+ GDCLASS(RenderBufferDataForwardMobile, RenderBufferCustomDataRD);
+
+ public:
+ // We can have:
+ // - 4 subpasses combining the full render cycle
+ // - 3 subpasses + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
+ // - 2 subpasses + 1 normal pass for transparent + 1 normal pass for tonemapping/glow/dof/etc (using fb for 2D buffer)
+ enum FramebufferConfigType {
+ FB_CONFIG_ONE_PASS, // Single pass frame buffer for alpha pass
+ FB_CONFIG_TWO_SUBPASSES, // Opaque + Sky sub pass
+ FB_CONFIG_THREE_SUBPASSES, // Opaque + Sky + Alpha sub pass
+ FB_CONFIG_FOUR_SUBPASSES, // Opaque + Sky + Alpha sub pass + Tonemap pass
+ FB_CONFIG_MAX
+ };
- RID color_msaa;
- RID depth_msaa;
- // RID normal_roughness_buffer_msaa;
+ RID get_color_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA); }
+ RID get_color_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_COLOR_MSAA, p_layer, 0); }
- RID color_fbs[FB_CONFIG_MAX];
- int width, height;
- uint32_t view_count;
+ RID get_depth_msaa() const { return render_buffers->get_texture(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA); }
+ RID get_depth_msaa(uint32_t p_layer) { return render_buffers->get_texture_slice(RB_SCOPE_MOBILE, RB_TEX_DEPTH_MSAA, p_layer, 0); }
- void clear();
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count);
+ RID get_color_fbs(FramebufferConfigType p_config_type);
+ virtual void free_data() override;
+ virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;
- ~RenderBufferDataForwardMobile();
+ private:
+ RenderSceneBuffersRD *render_buffers = nullptr;
+ RD::TextureSamples texture_samples = RD::TEXTURE_SAMPLES_1;
};
- virtual RenderBufferData *_create_render_buffer_data() override;
+ virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) override;
/* Rendering */
@@ -158,8 +150,6 @@ protected:
// PASS_MODE_SDF,
};
- struct GeometryInstanceForwardMobile;
- struct GeometryInstanceSurfaceDataCache;
struct RenderElementInfo;
struct RenderListParameters {
@@ -173,7 +163,6 @@ protected:
RID render_pass_uniform_set;
bool force_wireframe = false;
Vector2 uv_offset;
- Plane lod_plane;
uint32_t spec_constant_base_flags = 0;
float lod_distance_multiplier = 0.0;
float screen_mesh_lod_threshold = 0.0;
@@ -182,7 +171,7 @@ protected:
uint32_t barrier = RD::BARRIER_MASK_ALL;
uint32_t subpass = 0;
- RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), const Plane &p_lod_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
+ RenderListParameters(GeometryInstanceSurfaceDataCache **p_elements, RenderElementInfo *p_element_info, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, RID p_render_pass_uniform_set, uint32_t p_spec_constant_base_flags = 0, bool p_force_wireframe = false, const Vector2 &p_uv_offset = Vector2(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, uint32_t p_view_count = 1, uint32_t p_element_offset = 0, uint32_t p_barrier = RD::BARRIER_MASK_ALL) {
elements = p_elements;
element_info = p_element_info;
element_count = p_element_count;
@@ -193,7 +182,6 @@ protected:
render_pass_uniform_set = p_render_pass_uniform_set;
force_wireframe = p_force_wireframe;
uv_offset = p_uv_offset;
- lod_plane = p_lod_plane;
lod_distance_multiplier = p_lod_distance_multiplier;
screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
element_offset = p_element_offset;
@@ -202,38 +190,29 @@ protected:
}
};
- virtual float _render_buffers_get_luminance_multiplier() override;
- virtual RD::DataFormat _render_buffers_get_color_format() override;
- virtual bool _render_buffers_can_be_storage() override;
+ /* Render shadows */
- RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
- virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
+ void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<RenderGeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RenderingMethod::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_begin();
+ void _render_shadow_append(RID p_framebuffer, const PagedArray<RenderGeometryInstance *> &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RenderingMethod::RenderInfo *p_render_info = nullptr);
+ void _render_shadow_process();
+ void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- virtual void _render_shadow_begin() override;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) override;
- virtual void _render_shadow_process() override;
- virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) override;
+ /* Render Scene */
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) override;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) override;
+ RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0);
+ void _pre_opaque_render(RenderDataRD *p_render_data);
uint64_t lightmap_texture_array_version = 0xFFFFFFFF;
- virtual void _base_uniforms_changed() override;
void _update_render_base_uniform_set();
- virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) override;
- virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) override;
void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false);
void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1);
// void _update_instance_data_buffer(RenderListType p_render_list);
- static RenderForwardMobile *singleton;
-
void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, bool p_flip_y, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_pancake_shadows = false, int p_index = 0);
- void _setup_lightmaps(const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
+ void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);
RID render_base_uniform_set;
LocalVector<RID> render_pass_uniform_sets;
@@ -242,6 +221,8 @@ protected:
struct LightmapData {
float normal_xform[12];
+ float pad[3];
+ float exposure_normalization;
};
struct LightmapCaptureData {
@@ -251,74 +232,6 @@ protected:
/* Scene state */
struct SceneState {
- // This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code
- struct UBO {
- float projection_matrix[16];
- float inv_projection_matrix[16];
- float inv_view_matrix[16];
- float view_matrix[16];
-
- float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
- float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
-
- float viewport_size[2];
- float screen_pixel_size[2];
-
- float directional_penumbra_shadow_kernel[128]; //32 vec4s
- float directional_soft_shadow_kernel[128];
- float penumbra_shadow_kernel[128];
- float soft_shadow_kernel[128];
-
- float ambient_light_color_energy[4];
-
- float ambient_color_sky_mix;
- uint32_t use_ambient_light;
- uint32_t use_ambient_cubemap;
- uint32_t use_reflection_cubemap;
-
- float radiance_inverse_xform[12];
-
- float shadow_atlas_pixel_size[2];
- float directional_shadow_pixel_size[2];
-
- uint32_t directional_light_count;
- float dual_paraboloid_side;
- float z_far;
- float z_near;
-
- uint32_t ssao_enabled;
- float ssao_light_affect;
- float ssao_ao_affect;
- uint32_t roughness_limiter_enabled;
-
- float roughness_limiter_amount;
- float roughness_limiter_limit;
- float opaque_prepass_threshold;
- uint32_t roughness_limiter_pad;
-
- // Fog
- uint32_t fog_enabled;
- float fog_density;
- float fog_height;
- float fog_height_density;
-
- float fog_light_color[3];
- float fog_sun_scatter;
-
- float fog_aerial_perspective;
- uint32_t material_uv2_mode;
-
- float time;
- float reflection_multiplier;
-
- uint32_t pancake_shadows;
- uint32_t pad1;
- uint32_t pad2;
- uint32_t pad3;
- };
-
- UBO ubo;
-
LocalVector<RID> uniform_buffers;
// !BAS! We need to change lightmaps, we're not going to do this with a buffer but pushing the used lightmap in
@@ -436,17 +349,38 @@ protected:
RenderList render_list[RENDER_LIST_MAX];
+protected:
+ /* setup */
+ virtual void _update_shader_quality_settings() override;
+
+ virtual float _render_buffers_get_luminance_multiplier() override;
+ virtual RD::DataFormat _render_buffers_get_color_format() override;
+ virtual bool _render_buffers_can_be_storage() override;
+
+ virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
+ virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) override;
+
+ virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{};
+ virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override{};
+ virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override{};
+
+ virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override{};
+ virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override{};
+
/* Geometry instance */
- // check which ones of these apply, probably all except GI and SDFGI
+ class GeometryInstanceForwardMobile;
+
+ // When changing any of these enums, remember to change the corresponding enums in the shader files as well.
enum {
- INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 5,
- INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 6,
- INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 7,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 8,
- INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 9,
- INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 10,
- INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 11,
+ INSTANCE_DATA_FLAGS_NON_UNIFORM_SCALE = 1 << 4,
+ INSTANCE_DATA_FLAG_USE_GI_BUFFERS = 1 << 5,
+ INSTANCE_DATA_FLAG_USE_SDFGI = 1 << 6,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP_CAPTURE = 1 << 7,
+ INSTANCE_DATA_FLAG_USE_LIGHTMAP = 1 << 8,
+ INSTANCE_DATA_FLAG_USE_SH_LIGHTMAP = 1 << 9,
+ INSTANCE_DATA_FLAG_USE_VOXEL_GI = 1 << 10,
+ INSTANCE_DATA_FLAG_PARTICLES = 1 << 11,
INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12,
INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13,
INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14,
@@ -515,14 +449,8 @@ protected:
GeometryInstanceForwardMobile *owner = nullptr;
};
- // !BAS! GeometryInstanceForwardClustered and GeometryInstanceForwardMobile will likely have a lot of overlap
- // may need to think about making this its own class like GeometryInstanceRD?
-
- struct GeometryInstanceForwardMobile : public GeometryInstance {
- // setup
- uint32_t base_flags = 0;
- uint32_t flags_cache = 0;
-
+ class GeometryInstanceForwardMobile : public RenderGeometryInstanceBase {
+ public:
// this structure maps to our push constant in our shader and is populated right before our draw call
struct PushConstant {
float transform[16];
@@ -540,80 +468,94 @@ protected:
// PushConstant push_constant; // we populate this from our instance data
//used during rendering
- uint32_t layer_mask = 1;
RID transforms_uniform_set;
- float depth = 0;
- bool mirror = false;
bool use_projector = false;
bool use_soft_shadow = false;
- Transform3D transform;
bool store_transform_cache = true; // if true we copy our transform into our PushConstant, if false we use our transforms UBO and clear our PushConstants transform
- bool non_uniform_scale = false;
- AABB transformed_aabb; //needed for LOD
- float lod_bias = 0.0;
- float lod_model_scale = 1.0;
- int32_t shader_parameters_offset = -1;
uint32_t instance_count = 0;
uint32_t trail_steps = 1;
- RID mesh_instance;
// lightmap
uint32_t gi_offset_cache = 0; // !BAS! Should rename this to lightmap_offset_cache, in forward clustered this was shared between gi and lightmap
- uint32_t lightmap_slice_index;
- Rect2 lightmap_uv_scale;
RID lightmap_instance;
+ Rect2 lightmap_uv_scale;
+ uint32_t lightmap_slice_index;
GeometryInstanceLightmapSH *lightmap_sh = nullptr;
// culled light info
uint32_t reflection_probe_count = 0;
- ForwardID reflection_probes[MAX_RDL_CULL];
+ RendererRD::ForwardID reflection_probes[MAX_RDL_CULL];
uint32_t omni_light_count = 0;
- ForwardID omni_lights[MAX_RDL_CULL];
+ RendererRD::ForwardID omni_lights[MAX_RDL_CULL];
uint32_t spot_light_count = 0;
- ForwardID spot_lights[MAX_RDL_CULL];
+ RendererRD::ForwardID spot_lights[MAX_RDL_CULL];
uint32_t decals_count = 0;
- ForwardID decals[MAX_RDL_CULL];
+ RendererRD::ForwardID decals[MAX_RDL_CULL];
GeometryInstanceSurfaceDataCache *surface_caches = nullptr;
// do we use this?
SelfList<GeometryInstanceForwardMobile> dirty_list_element;
- struct Data {
- //data used less often goes into regular heap
- RID base;
- RS::InstanceType base_type;
+ GeometryInstanceForwardMobile() :
+ dirty_list_element(this) {}
+
+ virtual void _mark_dirty() override;
- RID skeleton;
- Vector<RID> surface_materials;
- RID material_override;
- RID material_overlay;
- AABB aabb;
+ virtual void set_use_lightmap(RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
+ virtual void set_lightmap_capture(const Color *p_sh9) override;
- bool use_baked_light = false;
- bool cast_double_sided_shadows = false;
- // bool mirror = false; // !BAS! Does not seem used, we already have this in the main struct
+ virtual void pair_light_instances(const RID *p_light_instances, uint32_t p_light_instance_count) override;
+ virtual void pair_reflection_probe_instances(const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
+ virtual void pair_decal_instances(const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
+ virtual void pair_voxel_gi_instances(const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override {}
- bool dirty_dependencies = false;
+ virtual void set_softshadow_projector_pairing(bool p_softshadow, bool p_projector) override;
+ };
+
+ /* Rendering */
+
+ virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) override;
+
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) override;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) override;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) override;
+
+ /* Forward ID */
- RendererStorage::DependencyTracker dependency_tracker;
+ class ForwardIDStorageMobile : public RendererRD::ForwardIDStorage {
+ public:
+ struct ForwardIDAllocator {
+ LocalVector<bool> allocations;
+ LocalVector<uint8_t> map;
};
- Data *data = nullptr;
+ ForwardIDAllocator forward_id_allocators[RendererRD::FORWARD_ID_MAX];
- GeometryInstanceForwardMobile() :
- dirty_list_element(this) {}
+ public:
+ virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) override;
+ virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) override;
+ virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) override;
+ virtual bool uses_forward_ids() const override { return true; }
+
+ void fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance);
};
- _FORCE_INLINE_ void _fill_push_constant_instance_indices(GeometryInstanceForwardMobile::PushConstant *p_push_constant, uint32_t &spec_constants, const GeometryInstanceForwardMobile *p_instance);
+ ForwardIDStorageMobile *forward_id_storage_mobile = nullptr;
- void _update_shader_quality_settings() override;
+ virtual RendererRD::ForwardIDStorage *create_forward_id_storage() override {
+ forward_id_storage_mobile = memnew(ForwardIDStorageMobile);
+ return forward_id_storage_mobile;
+ }
public:
+ static RenderForwardMobile *get_singleton() { return singleton; }
+
virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth) override;
- static void _geometry_instance_dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *p_tracker);
- static void _geometry_instance_dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *p_tracker);
+ static void _geometry_instance_dependency_deleted(const RID &p_dependency, DependencyTracker *p_tracker);
SelfList<GeometryInstanceForwardMobile>::List geometry_instance_dirty_list;
@@ -624,51 +566,25 @@ public:
void _geometry_instance_add_surface_with_material(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, uint32_t p_material_id, uint32_t p_shader_id, RID p_mesh);
void _geometry_instance_add_surface_with_material_chain(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, SceneShaderForwardMobile::MaterialData *p_material, RID p_mat_src, RID p_mesh);
void _geometry_instance_add_surface(GeometryInstanceForwardMobile *ginstance, uint32_t p_surface, RID p_material, RID p_mesh);
- void _geometry_instance_mark_dirty(GeometryInstance *p_geometry_instance);
- void _geometry_instance_update(GeometryInstance *p_geometry_instance);
+ void _geometry_instance_update(RenderGeometryInstance *p_geometry_instance);
void _update_dirty_geometry_instances();
- virtual GeometryInstance *geometry_instance_create(RID p_base) override;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) override;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) override;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_overlay) override;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_materials) override;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) override;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabb) override;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) override;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) override;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) override;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) override;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) override;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) override;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) override;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) override;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) override;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) override;
-
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) override;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) override;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) override;
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
virtual uint32_t geometry_instance_get_pair_mask() override;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) override;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) override;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) override;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) override;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) override;
virtual bool free(RID p_rid) override;
+ virtual void base_uniforms_changed() override;
+
virtual bool is_dynamic_gi_supported() const override;
- virtual bool is_clustered_enabled() const override;
virtual bool is_volumetric_supported() const override;
virtual uint32_t get_max_elements() const override;
- RenderForwardMobile(RendererStorageRD *p_storage);
+ RenderForwardMobile();
~RenderForwardMobile();
};
} // namespace RendererSceneRenderImplementation
-#endif // !RENDERING_SERVER_SCENE_RENDER_FORWARD_MOBILE_H
+
+#endif // RENDER_FORWARD_MOBILE_H
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
index 321e03cdff..db9db2fa44 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.cpp
@@ -39,6 +39,10 @@ using namespace RendererSceneRenderImplementation;
/* ShaderData */
+void SceneShaderForwardMobile::ShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
//compile
@@ -157,11 +161,10 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
print_line(gen_code.defines[i]);
}
- RBMap<String, String>::Element * el = gen_code.code.front();
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
while (el) {
- print_line("\n**code " + el->key() + ":\n" + el->value());
-
- el = el->next();
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
}
print_line("\n**uniforms:\n" + gen_code.uniforms);
@@ -331,7 +334,7 @@ void SceneShaderForwardMobile::ShaderData::set_code(const String &p_code) {
valid = true;
}
-void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void SceneShaderForwardMobile::ShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -348,11 +351,14 @@ void SceneShaderForwardMobile::ShaderData::set_default_texture_param(const Strin
}
}
-void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void SceneShaderForwardMobile::ShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
continue;
}
@@ -363,7 +369,22 @@ void SceneShaderForwardMobile::ShaderData::get_param_list(List<PropertyInfo> *p_
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -385,7 +406,7 @@ void SceneShaderForwardMobile::ShaderData::get_instance_param_list(List<Renderer
}
}
-bool SceneShaderForwardMobile::ShaderData::is_param_texture(const StringName &p_param) const {
+bool SceneShaderForwardMobile::ShaderData::is_parameter_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -429,7 +450,7 @@ SceneShaderForwardMobile::ShaderData::~ShaderData() {
}
}
-RendererRD::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
+RendererRD::MaterialStorage::ShaderData *SceneShaderForwardMobile::_create_shader_func() {
ShaderData *shader_data = memnew(ShaderData);
singleton->shader_list.add(&shader_data->shader_list_element);
return shader_data;
@@ -446,14 +467,14 @@ void SceneShaderForwardMobile::MaterialData::set_next_pass(RID p_pass) {
bool SceneShaderForwardMobile::MaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
SceneShaderForwardMobile *shader_singleton = (SceneShaderForwardMobile *)SceneShaderForwardMobile::singleton;
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, RD::BARRIER_MASK_RASTER);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, shader_singleton->shader.version_get_shader(shader_data->version, 0), RenderForwardMobile::MATERIAL_UNIFORM_SET, true, RD::BARRIER_MASK_RASTER);
}
SceneShaderForwardMobile::MaterialData::~MaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererRD::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *SceneShaderForwardMobile::_create_material_func(ShaderData *p_shader) {
MaterialData *material_data = memnew(MaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -469,8 +490,7 @@ SceneShaderForwardMobile::SceneShaderForwardMobile() {
singleton = this;
}
-void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p_defines) {
- storage = p_storage;
+void SceneShaderForwardMobile::init(const String p_defines) {
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
/* SCENE SHADER */
@@ -497,17 +517,17 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
}
}
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_3D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_3D, _create_material_funcs);
{
//shader compiler
ShaderCompiler::DefaultIdentifierActions actions;
- actions.renames["MODEL_MATRIX"] = "model_matrix";
+ actions.renames["MODEL_MATRIX"] = "read_model_matrix";
actions.renames["MODEL_NORMAL_MATRIX"] = "model_normal_matrix";
actions.renames["VIEW_MATRIX"] = "scene_data.view_matrix";
- actions.renames["INV_VIEW_MATRIX"] = "scene_data.inv_view_matrix";
+ actions.renames["INV_VIEW_MATRIX"] = "inv_view_matrix";
actions.renames["PROJECTION_MATRIX"] = "projection_matrix";
actions.renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix";
actions.renames["MODELVIEW_MATRIX"] = "modelview";
@@ -569,7 +589,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["NORMAL_ROUGHNESS_TEXTURE"] = "normal_roughness_buffer";
actions.renames["DEPTH"] = "gl_FragDepth";
actions.renames["OUTPUT_IS_SRGB"] = "true";
- actions.renames["FOG"] = "custom_fog";
+ actions.renames["FOG"] = "fog";
actions.renames["RADIANCE"] = "custom_radiance";
actions.renames["IRRADIANCE"] = "custom_irradiance";
actions.renames["BONE_INDICES"] = "bone_attrib";
@@ -580,6 +600,11 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.renames["CUSTOM3"] = "custom3_attrib";
actions.renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB";
+ actions.renames["NODE_POSITION_WORLD"] = "read_model_matrix[3].xyz";
+ actions.renames["CAMERA_POSITION_WORLD"] = "scene_data.inv_view_matrix[3].xyz";
+ actions.renames["CAMERA_DIRECTION_WORLD"] = "scene_data.view_matrix[3].xyz";
+ actions.renames["NODE_POSITION_VIEW"] = "(read_model_matrix * scene_data.view_matrix)[3].xyz";
+
actions.renames["VIEW_INDEX"] = "ViewIndex";
actions.renames["VIEW_MONO_LEFT"] = "0";
actions.renames["VIEW_RIGHT"] = "1";
@@ -635,6 +660,8 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n";
actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_USED\n";
+ actions.usage_defines["MODEL_MATRIX"] = "#define MODEL_MATRIX_USED\n";
+
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n";
actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n";
@@ -670,7 +697,7 @@ void SceneShaderForwardMobile::init(RendererStorageRD *p_storage, const String p
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
actions.instance_uniform_index_variable = "draw_call.instance_uniforms_ofs";
actions.apply_luminance_multiplier = true; // apply luminance multiplier to screen texture
@@ -701,7 +728,7 @@ void fragment() {
material_storage->material_initialize(default_material);
material_storage->material_set_shader(default_material, default_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
default_shader_rd = shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS);
default_material_shader_ptr = md->shader_data;
@@ -728,7 +755,7 @@ void fragment() {
material_storage->material_initialize(overdraw_material);
material_storage->material_set_shader(overdraw_material, overdraw_material_shader);
- MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::SHADER_TYPE_3D));
+ MaterialData *md = static_cast<MaterialData *>(material_storage->material_get_data(overdraw_material, RendererRD::MaterialStorage::SHADER_TYPE_3D));
overdraw_material_shader_ptr = md->shader_data;
overdraw_material_uniform_set = md->uniform_set;
}
diff --git a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
index f325d5c0a5..f67665a02f 100644
--- a/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
+++ b/servers/rendering/renderer_rd/forward_mobile/scene_shader_forward_mobile.h
@@ -28,19 +28,17 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RSSR_SCENE_SHADER_FM_H
-#define RSSR_SCENE_SHADER_FM_H
+#ifndef SCENE_SHADER_FORWARD_MOBILE_H
+#define SCENE_SHADER_FORWARD_MOBILE_H
#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl.gen.h"
+#include "servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl.gen.h"
namespace RendererSceneRenderImplementation {
class SceneShaderForwardMobile {
private:
static SceneShaderForwardMobile *singleton;
- RendererStorageRD *storage = nullptr;
public:
enum ShaderVersion {
@@ -57,7 +55,7 @@ public:
SHADER_VERSION_MAX
};
- struct ShaderData : public RendererRD::ShaderData {
+ struct ShaderData : public RendererRD::MaterialStorage::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -141,11 +139,13 @@ public:
uint32_t index = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void set_path_hint(const String &p_path);
+
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_parameter_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
@@ -157,12 +157,12 @@ public:
virtual ~ShaderData();
};
- RendererRD::ShaderData *_create_shader_func();
- static RendererRD::ShaderData *_create_shader_funcs() {
+ RendererRD::MaterialStorage::ShaderData *_create_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_shader_func();
}
- struct MaterialData : public RendererRD::MaterialData {
+ struct MaterialData : public RendererRD::MaterialStorage::MaterialData {
ShaderData *shader_data = nullptr;
RID uniform_set;
uint64_t last_pass = 0;
@@ -177,8 +177,8 @@ public:
SelfList<ShaderData>::List shader_list;
- RendererRD::MaterialData *_create_material_func(ShaderData *p_shader);
- static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ RendererRD::MaterialStorage::MaterialData *_create_material_func(ShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
return static_cast<SceneShaderForwardMobile *>(singleton)->_create_material_func(static_cast<ShaderData *>(p_shader));
}
@@ -207,9 +207,10 @@ public:
Vector<RD::PipelineSpecializationConstant> default_specialization_constants;
- void init(RendererStorageRD *p_storage, const String p_defines);
+ void init(const String p_defines);
void set_default_specialization_constants(const Vector<RD::PipelineSpecializationConstant> &p_constants);
};
} // namespace RendererSceneRenderImplementation
-#endif // !RSSR_SCENE_SHADER_FM_H
+
+#endif // SCENE_SHADER_FORWARD_MOBILE_H
diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp
new file mode 100644
index 0000000000..9baa86a32d
--- /dev/null
+++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.cpp
@@ -0,0 +1,64 @@
+/*************************************************************************/
+/* framebuffer_cache_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "framebuffer_cache_rd.h"
+
+FramebufferCacheRD *FramebufferCacheRD::singleton = nullptr;
+
+void FramebufferCacheRD::_invalidate(Cache *p_cache) {
+ if (p_cache->prev) {
+ p_cache->prev->next = p_cache->next;
+ } else {
+ // At beginning of table
+ uint32_t table_idx = p_cache->hash % HASH_TABLE_SIZE;
+ hash_table[table_idx] = p_cache->next;
+ }
+
+ if (p_cache->next) {
+ p_cache->next->prev = p_cache->prev;
+ }
+
+ cache_allocator.free(p_cache);
+ cache_instances_used--;
+}
+void FramebufferCacheRD::_framebuffer_invalidation_callback(void *p_userdata) {
+ singleton->_invalidate(reinterpret_cast<Cache *>(p_userdata));
+}
+
+FramebufferCacheRD::FramebufferCacheRD() {
+ ERR_FAIL_COND(singleton != nullptr);
+ singleton = this;
+}
+
+FramebufferCacheRD::~FramebufferCacheRD() {
+ if (cache_instances_used > 0) {
+ ERR_PRINT("At exit: " + itos(cache_instances_used) + " framebuffer cache instance(s) still in use.");
+ }
+}
diff --git a/servers/rendering/renderer_rd/framebuffer_cache_rd.h b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
new file mode 100644
index 0000000000..f50d6baa30
--- /dev/null
+++ b/servers/rendering/renderer_rd/framebuffer_cache_rd.h
@@ -0,0 +1,310 @@
+/*************************************************************************/
+/* framebuffer_cache_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef FRAMEBUFFER_CACHE_RD_H
+#define FRAMEBUFFER_CACHE_RD_H
+
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_allocator.h"
+#include "servers/rendering/rendering_device.h"
+
+class FramebufferCacheRD : public Object {
+ GDCLASS(FramebufferCacheRD, Object)
+
+ struct Cache {
+ Cache *prev = nullptr;
+ Cache *next = nullptr;
+ uint32_t hash = 0;
+ RID cache;
+ LocalVector<RID> textures;
+ LocalVector<RD::FramebufferPass> passes;
+ uint32_t views = 0;
+ };
+
+ PagedAllocator<Cache> cache_allocator;
+
+ enum {
+ HASH_TABLE_SIZE = 16381 // Prime
+ };
+
+ Cache *hash_table[HASH_TABLE_SIZE] = {};
+
+ static _FORCE_INLINE_ uint32_t _hash_pass(const RD::FramebufferPass &p, uint32_t h) {
+ h = hash_murmur3_one_32(p.depth_attachment, h);
+ h = hash_murmur3_one_32(p.vrs_attachment, h);
+
+ h = hash_murmur3_one_32(p.color_attachments.size(), h);
+ for (int i = 0; i < p.color_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.color_attachments[i], h);
+ }
+
+ h = hash_murmur3_one_32(p.resolve_attachments.size(), h);
+ for (int i = 0; i < p.resolve_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.resolve_attachments[i], h);
+ }
+
+ h = hash_murmur3_one_32(p.preserve_attachments.size(), h);
+ for (int i = 0; i < p.preserve_attachments.size(); i++) {
+ h = hash_murmur3_one_32(p.preserve_attachments[i], h);
+ }
+
+ return h;
+ }
+
+ static _FORCE_INLINE_ bool _compare_pass(const RD::FramebufferPass &a, const RD::FramebufferPass &b) {
+ if (a.depth_attachment != b.depth_attachment) {
+ return false;
+ }
+
+ if (a.vrs_attachment != b.vrs_attachment) {
+ return false;
+ }
+
+ if (a.color_attachments.size() != b.color_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.color_attachments.size(); i++) {
+ if (a.color_attachments[i] != b.color_attachments[i]) {
+ return false;
+ }
+ }
+
+ if (a.resolve_attachments.size() != b.resolve_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.resolve_attachments.size(); i++) {
+ if (a.resolve_attachments[i] != b.resolve_attachments[i]) {
+ return false;
+ }
+ }
+
+ if (a.preserve_attachments.size() != b.preserve_attachments.size()) {
+ return false;
+ }
+
+ for (int i = 0; i < a.preserve_attachments.size(); i++) {
+ if (a.preserve_attachments[i] != b.preserve_attachments[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ _FORCE_INLINE_ uint32_t _hash_rids(uint32_t h, const RID &arg) {
+ return hash_murmur3_one_64(arg.get_id(), h);
+ }
+
+ template <typename... Args>
+ uint32_t _hash_rids(uint32_t h, const RID &arg, Args... args) {
+ h = hash_murmur3_one_64(arg.get_id(), h);
+ return _hash_rids(h, args...);
+ }
+
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg) {
+ return textures[idx] == arg;
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ bool _compare_args(uint32_t idx, const LocalVector<RID> &textures, const RID &arg, Args... args) {
+ if (textures[idx] != arg) {
+ return false;
+ }
+ return _compare_args(idx + 1, textures, args...);
+ }
+
+ _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg) {
+ textures.push_back(arg);
+ }
+
+ template <typename... Args>
+ _FORCE_INLINE_ void _create_args(Vector<RID> &textures, const RID &arg, Args... args) {
+ textures.push_back(arg);
+ _create_args(textures, args...);
+ }
+
+ static FramebufferCacheRD *singleton;
+
+ uint32_t cache_instances_used = 0;
+
+ void _invalidate(Cache *p_cache);
+ static void _framebuffer_invalidation_callback(void *p_userdata);
+
+ RID _allocate_from_data(uint32_t p_views, uint32_t p_hash, uint32_t p_table_idx, const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes) {
+ RID rid;
+ if (p_passes.size()) {
+ rid = RD::get_singleton()->framebuffer_create_multipass(p_textures, p_passes, RD::INVALID_ID, p_views);
+ } else {
+ rid = RD::get_singleton()->framebuffer_create(p_textures, RD::INVALID_ID, p_views);
+ }
+
+ ERR_FAIL_COND_V(rid.is_null(), rid);
+
+ Cache *c = cache_allocator.alloc();
+ c->views = p_views;
+ c->cache = rid;
+ c->hash = p_hash;
+ c->textures.resize(p_textures.size());
+ for (uint32_t i = 0; i < c->textures.size(); i++) {
+ c->textures[i] = p_textures[i];
+ }
+ c->passes.resize(p_passes.size());
+ for (uint32_t i = 0; i < c->passes.size(); i++) {
+ c->passes[i] = p_passes[i];
+ }
+ c->prev = nullptr;
+ c->next = hash_table[p_table_idx];
+ if (hash_table[p_table_idx]) {
+ hash_table[p_table_idx]->prev = c;
+ }
+ hash_table[p_table_idx] = c;
+
+ RD::get_singleton()->framebuffer_set_invalidation_callback(rid, _framebuffer_invalidation_callback, c);
+
+ cache_instances_used++;
+
+ return rid;
+ }
+
+public:
+ template <typename... Args>
+ RID get_cache(Args... args) {
+ uint32_t h = hash_murmur3_one_32(1); //1 view
+ h = hash_murmur3_one_32(sizeof...(Args), h);
+ h = _hash_rids(h, args...);
+ h = hash_murmur3_one_32(0, h); // 0 passes
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == 1 && _compare_args(0, c->textures, args...)) {
+ return c->cache;
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+
+ Vector<RID> textures;
+ _create_args(textures, args...);
+
+ return _allocate_from_data(1, h, table_idx, textures, Vector<RD::FramebufferPass>());
+ }
+
+ template <typename... Args>
+ RID get_cache_multiview(uint32_t p_views, Args... args) {
+ uint32_t h = hash_murmur3_one_32(p_views);
+ h = hash_murmur3_one_32(sizeof...(Args), h);
+ h = _hash_rids(h, args...);
+ h = hash_murmur3_one_32(0, h); // 0 passes
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->passes.size() == 0 && c->textures.size() == sizeof...(Args) && c->views == p_views && _compare_args(0, c->textures, args...)) {
+ return c->cache;
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+
+ Vector<RID> textures;
+ _create_args(textures, args...);
+
+ return _allocate_from_data(p_views, h, table_idx, textures, Vector<RD::FramebufferPass>());
+ }
+
+ RID get_cache_multipass(const Vector<RID> &p_textures, const Vector<RD::FramebufferPass> &p_passes, uint32_t p_views = 1) {
+ uint32_t h = hash_murmur3_one_32(p_views);
+ h = hash_murmur3_one_32(p_textures.size());
+ for (int i = 0; i < p_textures.size(); i++) {
+ h = hash_murmur3_one_64(p_textures[i].get_id(), h);
+ }
+ h = hash_murmur3_one_32(p_passes.size());
+ for (int i = 0; i < p_passes.size(); i++) {
+ h = _hash_pass(p_passes[i], h);
+ }
+
+ h = hash_fmix32(h);
+
+ uint32_t table_idx = h % HASH_TABLE_SIZE;
+ {
+ const Cache *c = hash_table[table_idx];
+
+ while (c) {
+ if (c->hash == h && c->views == p_views && c->textures.size() == (uint32_t)p_textures.size() && c->passes.size() == (uint32_t)p_passes.size()) {
+ bool all_ok = true;
+
+ for (int i = 0; i < p_textures.size(); i++) {
+ if (p_textures[i] != c->textures[i]) {
+ all_ok = false;
+ break;
+ }
+ }
+
+ if (all_ok) {
+ for (int i = 0; i < p_passes.size(); i++) {
+ if (!_compare_pass(p_passes[i], c->passes[i])) {
+ all_ok = false;
+ break;
+ }
+ }
+ }
+
+ if (all_ok) {
+ return c->cache;
+ }
+ }
+ c = c->next;
+ }
+ }
+
+ // Not in cache, create:
+ return _allocate_from_data(p_views, h, table_idx, p_textures, p_passes);
+ }
+
+ static FramebufferCacheRD *get_singleton() { return singleton; }
+
+ FramebufferCacheRD();
+ ~FramebufferCacheRD();
+};
+
+#endif // FRAMEBUFFER_CACHE_RD_H
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
index 9151c53823..7a2336970b 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "pipeline_cache_rd.h"
+
#include "core/os/memory.h"
RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id, bool p_wireframe, uint32_t p_render_pass, uint32_t p_bool_specializations) {
@@ -70,9 +71,7 @@ RID PipelineCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD
}
void PipelineCacheRD::_clear() {
-#ifndef _MSC_VER
-#warning Clear should probably recompile all the variants already compiled instead to avoid stalls? needs discussion
-#endif
+ // TODO: Clear should probably recompile all the variants already compiled instead to avoid stalls? Needs discussion.
if (versions) {
for (uint32_t i = 0; i < version_count; i++) {
//shader may be gone, so this may not be valid
diff --git a/servers/rendering/renderer_rd/pipeline_cache_rd.h b/servers/rendering/renderer_rd/pipeline_cache_rd.h
index ad83fc76b7..882e459bcd 100644
--- a/servers/rendering/renderer_rd/pipeline_cache_rd.h
+++ b/servers/rendering/renderer_rd/pipeline_cache_rd.h
@@ -97,4 +97,4 @@ public:
~PipelineCacheRD();
};
-#endif // RENDER_PIPELINE_CACHE_RD_H
+#endif // PIPELINE_CACHE_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
index 3c2f3f8a42..7e0070f8b7 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp
@@ -192,7 +192,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[1] = vd;
- buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_COLOR);
+ buffers.write[1] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_COLOR);
}
//uvs
@@ -220,7 +220,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[2] = vd;
- buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_TEX_UV);
+ buffers.write[2] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_TEX_UV);
}
//bones
@@ -253,7 +253,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[3] = vd;
- buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_BONES);
+ buffers.write[3] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_BONES);
}
//weights
@@ -286,7 +286,7 @@ RendererCanvasRender::PolygonID RendererCanvasRenderRD::request_polygon(const Ve
vd.stride = 0;
descriptions.write[4] = vd;
- buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::DEFAULT_RD_BUFFER_WEIGHTS);
+ buffers.write[4] = mesh_storage->mesh_get_default_rd_buffer(RendererRD::MeshStorage::DEFAULT_RD_BUFFER_WEIGHTS);
}
//check that everything is as it should be
@@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
//bind pipeline
- {
+ if (rect->flags & CANVAS_RECT_LCD) {
+ RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
+ RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
+ RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate);
+ } else {
RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format);
RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline);
}
@@ -528,7 +532,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
}
if (rect->flags & CANVAS_RECT_TRANSPOSE) {
- dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform
+ push_constant.flags |= FLAGS_TRANSPOSE_RECT;
}
if (rect->flags & CANVAS_RECT_CLIP_UV) {
@@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
push_constant.msdf[1] = rect->outline; // Outline size.
push_constant.msdf[2] = 0.f; // Reserved.
push_constant.msdf[3] = 0.f; // Reserved.
+ } else if (rect->flags & CANVAS_RECT_LCD) {
+ push_constant.flags |= FLAGS_USE_LCD;
}
push_constant.modulation[0] = rect->modulate.r * base_color.r;
@@ -700,7 +706,7 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend
//bind textures
- _bind_canvas_texture(p_draw_list, RID(), current_filter, current_repeat, last_texture, push_constant, texpixel_size);
+ _bind_canvas_texture(p_draw_list, primitive->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size);
RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3u, primitive->point_count) - 1]);
@@ -988,7 +994,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
} else {
screen = texture_storage->render_target_get_rd_backbuffer(p_to_render_target);
if (screen.is_null()) { //unallocated backbuffer
- screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ screen = RendererRD::TextureStorage::get_singleton()->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
}
u.append_id(screen);
@@ -1031,7 +1037,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 9;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
+ u.append_id(RendererRD::MaterialStorage::get_singleton()->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -1069,10 +1075,7 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
clear_colors.push_back(texture_storage->render_target_get_clear_request_color(p_to_render_target));
texture_storage->render_target_disable_clear_request(p_to_render_target);
}
-#ifndef _MSC_VER
-#warning TODO obtain from framebuffer format eventually when this is implemented
-#endif
-
+ // TODO: Obtain from framebuffer format eventually when this is implemented.
fb_uniform_set = texture_storage->render_target_get_framebuffer_uniform_set(p_to_render_target);
}
@@ -1108,14 +1111,26 @@ void RendererCanvasRenderRD::_render_items(RID p_to_render_target, int p_item_co
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
- if (material.is_null() && ci->canvas_group != nullptr) {
- material = default_canvas_group_material;
+ if (ci->canvas_group != nullptr) {
+ if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
+ if (!p_to_backbuffer) {
+ material = default_clip_children_material;
+ }
+ } else {
+ if (material.is_null()) {
+ if (ci->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_ONLY) {
+ material = default_clip_children_material;
+ } else {
+ material = default_canvas_group_material;
+ }
+ }
+ }
}
if (material != prev_material) {
CanvasMaterialData *material_data = nullptr;
if (material.is_valid()) {
- material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D));
+ material_data = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D));
}
if (material_data) {
@@ -1304,7 +1319,7 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
Size2i ssize = texture_storage->render_target_get_size(p_to_render_target);
Transform3D screen_transform;
- screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
+ screen_transform.translate_local(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f);
screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f));
_update_transform_to_mat4(screen_transform, state_buffer.screen_transform);
_update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform);
@@ -1356,11 +1371,15 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
default_repeat = p_default_repeat;
}
- //fill the list until rendering is possible.
- bool material_screen_texture_found = false;
Item *ci = p_item_list;
+
+ //fill the list until rendering is possible.
+ bool material_screen_texture_cached = false;
+ bool material_screen_texture_mipmaps_cached = false;
+
Rect2 back_buffer_rect;
bool backbuffer_copy = false;
+ bool backbuffer_gen_mipmaps = false;
Item *canvas_group_owner = nullptr;
@@ -1383,12 +1402,15 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
RID material = ci->material_owner == nullptr ? ci->material : ci->material_owner->material;
if (material.is_valid()) {
- CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::SHADER_TYPE_2D));
+ CanvasMaterialData *md = static_cast<CanvasMaterialData *>(material_storage->material_get_data(material, RendererRD::MaterialStorage::SHADER_TYPE_2D));
if (md && md->shader_data->valid) {
if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) {
- if (!material_screen_texture_found) {
+ if (!material_screen_texture_cached) {
backbuffer_copy = true;
back_buffer_rect = Rect2();
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
+ } else if (!material_screen_texture_mipmaps_cached) {
+ backbuffer_gen_mipmaps = md->shader_data->uses_screen_texture_mipmaps;
}
}
@@ -1427,10 +1449,12 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
-
- if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_OPAQUE) {
+ if (ci->canvas_group_owner->canvas_group->mode != RS::CANVAS_GROUP_MODE_TRANSPARENT) {
+ Rect2i group_rect = ci->canvas_group_owner->global_rect_cache;
texture_storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false);
+ if (ci->canvas_group_owner->canvas_group->mode == RS::CANVAS_GROUP_MODE_CLIP_AND_DRAW) {
+ items[item_count++] = ci->canvas_group_owner;
+ }
} else if (!backbuffer_cleared) {
texture_storage->render_target_clear_back_buffer(p_to_render_target, Rect2i(), Color(0, 0, 0, 0));
backbuffer_cleared = true;
@@ -1462,6 +1486,8 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
}
canvas_group_owner = nullptr;
+ // Backbuffer is dirty now and needs to be re-cleared if another CanvasGroup needs it.
+ backbuffer_cleared = false;
}
if (backbuffer_copy) {
@@ -1474,10 +1500,19 @@ void RendererCanvasRenderRD::canvas_render_items(RID p_to_render_target, Item *p
_render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list);
item_count = 0;
- texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true);
+ texture_storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, backbuffer_gen_mipmaps);
backbuffer_copy = false;
- material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies
+ backbuffer_gen_mipmaps = false;
+ material_screen_texture_cached = true; // After a backbuffer copy, screen texture makes no further copies.
+ material_screen_texture_mipmaps_cached = backbuffer_gen_mipmaps;
+ }
+
+ if (backbuffer_gen_mipmaps) {
+ texture_storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, back_buffer_rect);
+
+ backbuffer_gen_mipmaps = false;
+ material_screen_texture_mipmaps_cached = true;
}
items[item_count++] = ci;
@@ -1581,16 +1616,17 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
//light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1));
Rect2i rect((state.shadow_texture_size / 4) * i, p_shadow_index * 2, (state.shadow_texture_size / 4), 2);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
+ RD::InitialAction initial_action = i == 0 ? RD::INITIAL_ACTION_CLEAR_REGION : RD::INITIAL_ACTION_CLEAR_REGION_CONTINUE;
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, initial_action, i != 3 ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, initial_action, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
- CameraMatrix projection;
+ Projection projection;
{
real_t fov = 90;
real_t nearp = p_near;
real_t farp = p_far;
real_t aspect = 1.0;
- real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5));
+ real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5));
real_t ymin = -ymax;
real_t xmin = ymin * aspect;
real_t xmax = ymax * aspect;
@@ -1598,13 +1634,13 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index,
projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp);
}
- Vector3 cam_target = Basis(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
- projection = projection * CameraMatrix(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
+ Vector3 cam_target = Basis::from_euler(Vector3(0, 0, Math_TAU * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0));
+ projection = projection * Projection(Transform3D().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
- push_constant.projection[y * 4 + x] = projection.matrix[y][x];
+ push_constant.projection[y * 4 + x] = projection.columns[y][x];
}
}
static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) };
@@ -1670,16 +1706,16 @@ void RendererCanvasRenderRD::light_update_directional_shadow(RID p_rid, int p_sh
cc.push_back(Color(1, 1, 1, 1));
Rect2i rect(0, p_shadow_index * 2, state.shadow_texture_size, 2);
- RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
+ RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(state.shadow_fb, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR_REGION, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, rect);
- CameraMatrix projection;
+ Projection projection;
projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance);
- projection = projection * CameraMatrix(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
+ projection = projection * Projection(Transform3D().looking_at(Vector3(0, 1, 0), Vector3(0, 0, -1)).affine_inverse());
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
- push_constant.projection[y * 4 + x] = projection.matrix[y][x];
+ push_constant.projection[y * 4 + x] = projection.columns[y][x];
}
}
@@ -1742,12 +1778,12 @@ void RendererCanvasRenderRD::render_sdf(RID p_render_target, LightOccluderInstan
RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc);
- CameraMatrix projection;
+ Projection projection;
ShadowRenderPushConstant push_constant;
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
- push_constant.projection[y * 4 + x] = projection.matrix[y][x];
+ push_constant.projection[y * 4 + x] = projection.columns[y][x];
}
}
@@ -1878,11 +1914,12 @@ void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Ve
}
}
- //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush
+ //if same buffer len is being set, just use buffer_update to avoid a pipeline flush
if (oc->vertex_array.is_null()) {
//create from scratch
//vertices
+ // TODO: geometry is always of length lc * 6 * sizeof(float), so in doubles builds this will receive half the data it needs
oc->vertex_buffer = RD::get_singleton()->vertex_buffer_create(lc * 6 * sizeof(real_t), geometry);
Vector<RID> buffer;
@@ -1955,8 +1992,8 @@ void RendererCanvasRenderRD::occluder_polygon_set_shape(RID p_occluder, const Ve
} else {
//update existing
- RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, sizeof(real_t) * 2 * p_points.size(), p_points.ptr());
- RD::get_singleton()->buffer_update(oc->index_buffer, 0, sdf_indices.size() * sizeof(int32_t), sdf_indices.ptr());
+ RD::get_singleton()->buffer_update(oc->sdf_vertex_buffer, 0, sizeof(real_t) * 2 * p_points.size(), p_points.ptr());
+ RD::get_singleton()->buffer_update(oc->sdf_index_buffer, 0, sdf_indices.size() * sizeof(int32_t), sdf_indices.ptr());
}
}
}
@@ -1967,6 +2004,10 @@ void RendererCanvasRenderRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::
oc->cull_mode = p_mode;
}
+void RendererCanvasRenderRD::CanvasShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
+
void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
//compile
@@ -1975,6 +2016,7 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ubo_size = 0;
uniforms.clear();
uses_screen_texture = false;
+ uses_screen_texture_mipmaps = false;
uses_sdf = false;
uses_time = false;
@@ -1985,7 +2027,6 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
ShaderCompiler::GeneratedCode gen_code;
int blend_mode = BLEND_MODE_MIX;
- uses_screen_texture = false;
ShaderCompiler::IdentifierActions actions;
actions.entry_point_stages["vertex"] = ShaderCompiler::STAGE_VERTEX;
@@ -2010,6 +2051,8 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code);
ERR_FAIL_COND_MSG(err != OK, "Shader compilation failed.");
+ uses_screen_texture_mipmaps = gen_code.uses_screen_texture_mipmaps;
+
if (version.is_null()) {
version = canvas_singleton->shader.canvas_shader.version_create();
}
@@ -2020,12 +2063,16 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
for (int i = 0; i < gen_code.defines.size(); i++) {
print_line(gen_code.defines[i]);
}
+
+ HashMap<String, String>::Iterator el = gen_code.code.begin();
+ while (el) {
+ print_line("\n**code " + el->key + ":\n" + el->value);
+ ++el;
+ }
+
print_line("\n**uniforms:\n" + gen_code.uniforms);
- print_line("\n**vertex_globals:\n" + gen_code.vertex_global);
- print_line("\n**vertex_code:\n" + gen_code.vertex);
- print_line("\n**fragment_globals:\n" + gen_code.fragment_global);
- print_line("\n**fragment_code:\n" + gen_code.fragment);
- print_line("\n**light_code:\n" + gen_code.light);
+ print_line("\n**vertex_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX]);
+ print_line("\n**fragment_globals:\n" + gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT]);
#endif
canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_VERTEX], gen_code.stage_globals[ShaderCompiler::STAGE_FRAGMENT], gen_code.defines);
ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version));
@@ -2099,6 +2146,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::PipelineColorBlendState blend_state;
blend_state.attachments.push_back(attachment);
+ RD::PipelineColorBlendState::Attachment attachment_lcd;
+ attachment_lcd.enable_blend = true;
+ attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
+ attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ RD::PipelineColorBlendState blend_state_lcd;
+ blend_state_lcd.attachments.push_back(attachment_lcd);
+
//update pipelines
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
@@ -2114,10 +2173,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS,
+ RD::RENDER_PRIMITIVE_TRIANGLES,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- { //non lit
+ {
+ //non lit
SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE,
@@ -2127,8 +2188,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS },
- { //lit
+ SHADER_VARIANT_ATTRIBUTES_POINTS,
+ SHADER_VARIANT_QUAD,
+ },
+ {
+ //lit
SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
@@ -2138,18 +2202,24 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) {
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
+ SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
+ SHADER_VARIANT_QUAD_LIGHT,
+ },
};
RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]);
- pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
+ pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
+ } else {
+ pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
}
}
valid = true;
}
-void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -2166,11 +2236,15 @@ void RendererCanvasRenderRD::CanvasShaderData::set_default_texture_param(const S
}
}
-void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void RendererCanvasRenderRD::CanvasShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL) {
+ if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_LOCAL ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ // Don't expose any of these.
continue;
}
if (E.value.texture_order >= 0) {
@@ -2180,7 +2254,22 @@ void RendererCanvasRenderRD::CanvasShaderData::get_param_list(List<PropertyInfo>
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -2202,7 +2291,7 @@ void RendererCanvasRenderRD::CanvasShaderData::get_instance_param_list(List<Rend
}
}
-bool RendererCanvasRenderRD::CanvasShaderData::is_param_texture(const StringName &p_param) const {
+bool RendererCanvasRenderRD::CanvasShaderData::is_parameter_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -2241,7 +2330,7 @@ RendererCanvasRenderRD::CanvasShaderData::~CanvasShaderData() {
}
}
-RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
+RendererRD::MaterialStorage::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
CanvasShaderData *shader_data = memnew(CanvasShaderData);
return shader_data;
}
@@ -2249,14 +2338,14 @@ RendererRD::ShaderData *RendererCanvasRenderRD::_create_shader_func() {
bool RendererCanvasRenderRD::CanvasMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
RendererCanvasRenderRD *canvas_singleton = static_cast<RendererCanvasRenderRD *>(RendererCanvasRender::singleton);
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET);
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET, false);
}
RendererCanvasRenderRD::CanvasMaterialData::~CanvasMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-RendererRD::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
+RendererRD::MaterialStorage::MaterialData *RendererCanvasRenderRD::_create_material_func(CanvasShaderData *p_shader) {
CanvasMaterialData *material_data = memnew(CanvasMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
@@ -2270,10 +2359,9 @@ void RendererCanvasRenderRD::set_time(double p_time) {
void RendererCanvasRenderRD::update() {
}
-RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
+RendererCanvasRenderRD::RendererCanvasRenderRD() {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
- storage = p_storage;
{ //create default samplers
@@ -2331,6 +2419,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
blend_state.attachments.push_back(blend_attachment);
+ RD::PipelineColorBlendState::Attachment attachment_lcd;
+ attachment_lcd.enable_blend = true;
+ attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.color_blend_op = RD::BLEND_OP_ADD;
+ attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR;
+ attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
+ attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE;
+ attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+
+ RD::PipelineColorBlendState blend_state_lcd;
+ blend_state_lcd.attachments.push_back(attachment_lcd);
+
for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) {
for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) {
RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = {
@@ -2344,10 +2444,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
RD::RENDER_PRIMITIVE_LINES,
RD::RENDER_PRIMITIVE_LINESTRIPS,
RD::RENDER_PRIMITIVE_POINTS,
+ RD::RENDER_PRIMITIVE_TRIANGLES,
};
ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = {
- { //non lit
+ {
+ //non lit
SHADER_VARIANT_QUAD,
SHADER_VARIANT_NINEPATCH,
SHADER_VARIANT_PRIMITIVE,
@@ -2357,8 +2459,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
SHADER_VARIANT_ATTRIBUTES,
- SHADER_VARIANT_ATTRIBUTES_POINTS },
- { //lit
+ SHADER_VARIANT_ATTRIBUTES_POINTS,
+ SHADER_VARIANT_QUAD,
+ },
+ {
+ //lit
SHADER_VARIANT_QUAD_LIGHT,
SHADER_VARIANT_NINEPATCH_LIGHT,
SHADER_VARIANT_PRIMITIVE_LIGHT,
@@ -2368,11 +2473,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
SHADER_VARIANT_ATTRIBUTES_LIGHT,
- SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT },
+ SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT,
+ SHADER_VARIANT_QUAD_LIGHT,
+ },
};
RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]);
- shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) {
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS);
+ } else {
+ shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0);
+ }
}
}
}
@@ -2415,6 +2526,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.renames["VERTEX_ID"] = "gl_VertexIndex";
actions.renames["LIGHT_POSITION"] = "light_position";
+ actions.renames["LIGHT_DIRECTION"] = "light_direction";
+ actions.renames["LIGHT_IS_DIRECTIONAL"] = "is_directional";
actions.renames["LIGHT_COLOR"] = "light_color";
actions.renames["LIGHT_ENERGY"] = "light_energy";
actions.renames["LIGHT"] = "light";
@@ -2432,6 +2545,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n";
actions.usage_defines["NORMAL_MAP"] = "#define NORMAL_MAP_USED\n";
actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n";
+ actions.usage_defines["SPECULAR_SHININESS"] = "#define SPECULAR_SHININESS_USED\n";
actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n";
actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n";
@@ -2449,7 +2563,7 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
actions.base_varying_index = 4;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
shader.compiler.initialize(actions);
}
@@ -2609,8 +2723,8 @@ RendererCanvasRenderRD::RendererCanvasRenderRD(RendererStorageRD *p_storage) {
state.shadow_texture_size = GLOBAL_GET("rendering/2d/shadow_atlas/size");
//create functions for shader and material
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_2D, _create_material_funcs);
+ material_storage->shader_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_shader_funcs);
+ material_storage->material_set_data_request_function(RendererRD::MaterialStorage::SHADER_TYPE_2D, _create_material_funcs);
state.time = 0;
@@ -2639,6 +2753,26 @@ void fragment() {
material_storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader);
}
+ {
+ default_clip_children_shader = material_storage->shader_allocate();
+ material_storage->shader_initialize(default_clip_children_shader);
+
+ material_storage->shader_set_code(default_clip_children_shader, R"(
+// Default clip children shader.
+
+shader_type canvas_item;
+
+void fragment() {
+ vec4 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0);
+ COLOR.rgb = c.rgb;
+}
+)");
+ default_clip_children_material = material_storage->material_allocate();
+ material_storage->material_initialize(default_clip_children_material);
+
+ material_storage->material_set_shader(default_clip_children_material, default_clip_children_shader);
+ }
+
static_assert(sizeof(PushConstant) == 128);
}
@@ -2690,6 +2824,9 @@ RendererCanvasRenderRD::~RendererCanvasRenderRD() {
material_storage->material_free(default_canvas_group_material);
material_storage->shader_free(default_canvas_group_shader);
+ material_storage->material_free(default_clip_children_material);
+ material_storage->shader_free(default_clip_children_shader);
+
{
if (state.canvas_state_buffer.is_valid()) {
RD::get_singleton()->free(state.canvas_state_buffer);
diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
index 04881ce7e6..d1f3c9ec6a 100644
--- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h
@@ -28,21 +28,19 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_CANVAS_RENDER_RD_H
-#define RENDERING_SERVER_CANVAS_RENDER_RD_H
+#ifndef RENDERER_CANVAS_RENDER_RD_H
+#define RENDERER_CANVAS_RENDER_RD_H
#include "servers/rendering/renderer_canvas_render.h"
#include "servers/rendering/renderer_compositor.h"
#include "servers/rendering/renderer_rd/pipeline_cache_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/canvas.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/canvas_occlusion.glsl.gen.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/rendering_device.h"
#include "servers/rendering/shader_compiler.h"
class RendererCanvasRenderRD : public RendererCanvasRender {
- RendererStorageRD *storage = nullptr;
-
enum {
BASE_UNIFORM_SET = 0,
MATERIAL_UNIFORM_SET = 1,
@@ -87,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27),
FLAGS_USE_MSDF = (1 << 28),
+ FLAGS_USE_LCD = (1 << 29),
};
enum {
@@ -124,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
PIPELINE_VARIANT_ATTRIBUTE_LINES,
PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP,
PIPELINE_VARIANT_ATTRIBUTE_POINTS,
+ PIPELINE_VARIANT_QUAD_LCD_BLEND,
PIPELINE_VARIANT_MAX
};
enum PipelineLightMode {
@@ -151,7 +151,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
ShaderCompiler compiler;
} shader;
- struct CanvasShaderData : public RendererRD::ShaderData {
+ struct CanvasShaderData : public RendererRD::MaterialStorage::ShaderData {
enum BlendMode { //used internally
BLEND_MODE_MIX,
BLEND_MODE_ADD,
@@ -176,15 +176,17 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
HashMap<StringName, HashMap<int, RID>> default_texture_params;
bool uses_screen_texture = false;
+ bool uses_screen_texture_mipmaps = false;
bool uses_sdf = false;
bool uses_time = false;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void set_path_hint(const String &p_path);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_parameter_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
@@ -194,12 +196,12 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual ~CanvasShaderData();
};
- RendererRD::ShaderData *_create_shader_func();
- static RendererRD::ShaderData *_create_shader_funcs() {
+ RendererRD::MaterialStorage::ShaderData *_create_shader_func();
+ static RendererRD::MaterialStorage::ShaderData *_create_shader_funcs() {
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_shader_func();
}
- struct CanvasMaterialData : public RendererRD::MaterialData {
+ struct CanvasMaterialData : public RendererRD::MaterialStorage::MaterialData {
CanvasShaderData *shader_data = nullptr;
RID uniform_set;
@@ -209,8 +211,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
virtual ~CanvasMaterialData();
};
- RendererRD::MaterialData *_create_material_func(CanvasShaderData *p_shader);
- static RendererRD::MaterialData *_create_material_funcs(RendererRD::ShaderData *p_shader) {
+ RendererRD::MaterialStorage::MaterialData *_create_material_func(CanvasShaderData *p_shader);
+ static RendererRD::MaterialStorage::MaterialData *_create_material_funcs(RendererRD::MaterialStorage::ShaderData *p_shader) {
return static_cast<RendererCanvasRenderRD *>(singleton)->_create_material_func(static_cast<CanvasShaderData *>(p_shader));
}
@@ -419,6 +421,8 @@ class RendererCanvasRenderRD : public RendererCanvasRender {
RID default_canvas_group_shader;
RID default_canvas_group_material;
+ RID default_clip_children_material;
+ RID default_clip_children_shader;
RS::CanvasItemTextureFilter default_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
@@ -455,15 +459,13 @@ public:
void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_light_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used);
- void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {}
-
virtual void set_shadow_texture_size(int p_size);
void set_time(double p_time);
void update();
bool free(RID p_rid);
- RendererCanvasRenderRD(RendererStorageRD *p_storage);
+ RendererCanvasRenderRD();
~RendererCanvasRenderRD();
};
-#endif // RASTERIZER_CANVAS_RD_H
+#endif // RENDERER_CANVAS_RENDER_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
index 759b8690eb..3289bfb0ea 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.cpp
@@ -44,13 +44,9 @@ void RendererCompositorRD::blit_render_targets_to_screen(DisplayServer::WindowID
}
for (int i = 0; i < p_amount; i++) {
- RID texture = texture_storage->render_target_get_texture(p_render_targets[i].render_target);
- ERR_CONTINUE(texture.is_null());
- RID rd_texture = texture_storage->texture_get_rd_texture(texture);
+ RID rd_texture = texture_storage->render_target_get_rd_texture(p_render_targets[i].render_target);
ERR_CONTINUE(rd_texture.is_null());
- // TODO if keep_3d_linear was set when rendering to this render target we need to add a linear->sRGB conversion in.
-
if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) {
Vector<RD::Uniform> uniforms;
RD::Uniform u;
@@ -106,10 +102,8 @@ void RendererCompositorRD::begin_frame(double frame_step) {
}
void RendererCompositorRD::end_frame(bool p_swap_buffers) {
-#ifndef _MSC_VER
-#warning TODO: likely pass a bool to swap buffers to avoid display?
-#endif
- RD::get_singleton()->swap_buffers(); //probably should pass some bool to avoid display?
+ // TODO: Likely pass a bool to swap buffers to avoid display?
+ RD::get_singleton()->swap_buffers();
}
void RendererCompositorRD::initialize() {
@@ -154,12 +148,14 @@ uint64_t RendererCompositorRD::frame = 1;
void RendererCompositorRD::finalize() {
memdelete(scene);
memdelete(canvas);
- memdelete(storage);
+ memdelete(effects);
+ memdelete(fog);
memdelete(particles_storage);
memdelete(light_storage);
memdelete(mesh_storage);
memdelete(material_storage);
memdelete(texture_storage);
+ memdelete(utilities);
//only need to erase these, the rest are erased by cascade
blit.shader.version_free(blit.shader_version);
@@ -168,6 +164,10 @@ void RendererCompositorRD::finalize() {
}
void RendererCompositorRD::set_boot_image(const Ref<Image> &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {
+ if (p_image.is_null() || p_image->is_empty()) {
+ return;
+ }
+
RD::get_singleton()->prepare_screen_for_drawing();
RID texture = texture_storage->texture_allocate();
@@ -247,6 +247,7 @@ RendererCompositorRD *RendererCompositorRD::singleton = nullptr;
RendererCompositorRD::RendererCompositorRD() {
uniform_set_cache = memnew(UniformSetCacheRD);
+ framebuffer_cache = memnew(FramebufferCacheRD);
{
String shader_cache_dir = Engine::get_singleton()->get_shader_cache_path();
@@ -264,7 +265,7 @@ RendererCompositorRD::RendererCompositorRD() {
if (err != OK) {
ERR_PRINT("Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir);
} else {
- shader_cache_dir = shader_cache_dir.plus_file("shader_cache");
+ shader_cache_dir = shader_cache_dir.path_join("shader_cache");
bool shader_cache_enabled = GLOBAL_GET("rendering/shader_compiler/shader_cache/enabled");
if (!Engine::get_singleton()->is_editor_hint() && !shader_cache_enabled) {
@@ -287,31 +288,38 @@ RendererCompositorRD::RendererCompositorRD() {
singleton = this;
+ utilities = memnew(RendererRD::Utilities);
texture_storage = memnew(RendererRD::TextureStorage);
material_storage = memnew(RendererRD::MaterialStorage);
mesh_storage = memnew(RendererRD::MeshStorage);
light_storage = memnew(RendererRD::LightStorage);
particles_storage = memnew(RendererRD::ParticlesStorage);
- storage = memnew(RendererStorageRD);
- canvas = memnew(RendererCanvasRenderRD(storage));
+ fog = memnew(RendererRD::Fog);
+ canvas = memnew(RendererCanvasRenderRD());
- back_end = (bool)(int)GLOBAL_GET("rendering/vulkan/rendering/back_end");
+ String rendering_method = GLOBAL_GET("rendering/renderer/rendering_method");
uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
- if (back_end || textures_per_stage < 48) {
- scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile(storage));
- } else { // back_end == false
+ if (rendering_method == "mobile" || textures_per_stage < 48) {
+ scene = memnew(RendererSceneRenderImplementation::RenderForwardMobile());
+ if (rendering_method == "forward_plus") {
+ WARN_PRINT_ONCE("Platform supports less than 48 textures per stage which is less than required by the Clustered renderer. Defaulting to Mobile renderer.");
+ }
+ } else if (rendering_method == "forward_plus") {
// default to our high end renderer
- scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered(storage));
+ scene = memnew(RendererSceneRenderImplementation::RenderForwardClustered());
+ } else {
+ ERR_FAIL_MSG("Cannot instantiate RenderingDevice-based renderer with renderer type " + rendering_method);
}
scene->init();
// now we're ready to create our effects,
- storage->init_effects(!scene->_render_buffers_can_be_storage());
+ effects = memnew(EffectsRD(!scene->_render_buffers_can_be_storage()));
}
RendererCompositorRD::~RendererCompositorRD() {
memdelete(uniform_set_cache);
+ memdelete(framebuffer_cache);
ShaderRD::set_shader_cache_dir(String());
}
diff --git a/servers/rendering/renderer_rd/renderer_compositor_rd.h b/servers/rendering/renderer_rd/renderer_compositor_rd.h
index aefc189f68..a28335f800 100644
--- a/servers/rendering/renderer_rd/renderer_compositor_rd.h
+++ b/servers/rendering/renderer_rd/renderer_compositor_rd.h
@@ -28,34 +28,39 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_COMPOSITOR_RD_H
-#define RENDERING_SERVER_COMPOSITOR_RD_H
+#ifndef RENDERER_COMPOSITOR_RD_H
+#define RENDERER_COMPOSITOR_RD_H
#include "core/os/os.h"
-#include "core/templates/thread_work_pool.h"
#include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_rd/effects_rd.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
#include "servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h"
#include "servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h"
+#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
#include "servers/rendering/renderer_rd/renderer_canvas_render_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/shaders/blit.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/utilities.h"
#include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
class RendererCompositorRD : public RendererCompositor {
protected:
UniformSetCacheRD *uniform_set_cache = nullptr;
+ FramebufferCacheRD *framebuffer_cache = nullptr;
RendererCanvasRenderRD *canvas = nullptr;
+ RendererRD::Utilities *utilities = nullptr;
RendererRD::LightStorage *light_storage = nullptr;
RendererRD::MaterialStorage *material_storage = nullptr;
RendererRD::MeshStorage *mesh_storage = nullptr;
RendererRD::ParticlesStorage *particles_storage = nullptr;
RendererRD::TextureStorage *texture_storage = nullptr;
- RendererStorageRD *storage = nullptr;
+ RendererRD::Fog *fog = nullptr;
+ EffectsRD *effects = nullptr;
RendererSceneRenderRD *scene = nullptr;
enum BlitMode {
@@ -98,12 +103,18 @@ protected:
static uint64_t frame;
public:
- RendererLightStorage *get_light_storage() { return light_storage; };
- RendererMaterialStorage *get_material_storage() { return material_storage; };
- RendererMeshStorage *get_mesh_storage() { return mesh_storage; };
- RendererParticlesStorage *get_particles_storage() { return particles_storage; };
- RendererTextureStorage *get_texture_storage() { return texture_storage; };
- RendererStorage *get_storage() { return storage; }
+ RendererUtilities *get_utilities() { return utilities; };
+ RendererLightStorage *get_light_storage() { return light_storage; }
+ RendererMaterialStorage *get_material_storage() { return material_storage; }
+ RendererMeshStorage *get_mesh_storage() { return mesh_storage; }
+ RendererParticlesStorage *get_particles_storage() { return particles_storage; }
+ RendererTextureStorage *get_texture_storage() { return texture_storage; }
+ RendererGI *get_gi() {
+ ERR_FAIL_NULL_V(scene, nullptr);
+ return scene->get_gi();
+ }
+ RendererFog *get_fog() { return fog; }
+ EffectsRD *get_effects() { return effects; }
RendererCanvasRender *get_canvas() { return canvas; }
RendererSceneRender *get_scene() { return scene; }
@@ -138,4 +149,5 @@ public:
RendererCompositorRD();
~RendererCompositorRD();
};
-#endif // RASTERIZER_RD_H
+
+#endif // RENDERER_COMPOSITOR_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
deleted file mode 100644
index 0d9477d850..0000000000
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.cpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*************************************************************************/
-/* renderer_scene_environment_rd.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-
-uint64_t RendererSceneEnvironmentRD::auto_exposure_counter = 2;
-
-void RendererSceneEnvironmentRD::set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
- ambient_light = p_color;
- ambient_source = p_ambient;
- ambient_light_energy = p_energy;
- ambient_sky_contribution = p_sky_contribution;
- reflection_source = p_reflection_source;
-}
-
-void RendererSceneEnvironmentRD::set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
- exposure = p_exposure;
- tone_mapper = p_tone_mapper;
- if (!auto_exposure && p_auto_exposure) {
- auto_exposure_version = ++auto_exposure_counter;
- }
- auto_exposure = p_auto_exposure;
- white = p_white;
- min_luminance = p_min_luminance;
- max_luminance = p_max_luminance;
- auto_exp_speed = p_auto_exp_speed;
- auto_exp_scale = p_auto_exp_scale;
-}
-
-void RendererSceneEnvironmentRD::set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
- ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
- glow_enabled = p_enable;
- glow_levels = p_levels;
- glow_intensity = p_intensity;
- glow_strength = p_strength;
- glow_mix = p_mix;
- glow_bloom = p_bloom_threshold;
- glow_blend_mode = p_blend_mode;
- glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
- glow_hdr_bleed_scale = p_hdr_bleed_scale;
- glow_hdr_luminance_cap = p_hdr_luminance_cap;
- glow_map_strength = p_glow_map_strength;
- glow_map = p_glow_map;
-}
-
-void RendererSceneEnvironmentRD::set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
- sdfgi_enabled = p_enable;
- sdfgi_cascades = p_cascades;
- sdfgi_min_cell_size = p_min_cell_size;
- sdfgi_use_occlusion = p_use_occlusion;
- sdfgi_bounce_feedback = p_bounce_feedback;
- sdfgi_read_sky_light = p_read_sky;
- sdfgi_energy = p_energy;
- sdfgi_normal_bias = p_normal_bias;
- sdfgi_probe_bias = p_probe_bias;
- sdfgi_y_scale = p_y_scale;
-}
-
-void RendererSceneEnvironmentRD::set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
- fog_enabled = p_enable;
- fog_light_color = p_light_color;
- fog_light_energy = p_light_energy;
- fog_sun_scatter = p_sun_scatter;
- fog_density = p_density;
- fog_height = p_height;
- fog_height_density = p_height_density;
- fog_aerial_perspective = p_fog_aerial_perspective;
-}
-
-void RendererSceneEnvironmentRD::set_volumetric_fog(bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
- volumetric_fog_enabled = p_enable;
- volumetric_fog_density = p_density;
- volumetric_fog_scattering = p_albedo;
- volumetric_fog_emission = p_emission;
- volumetric_fog_emission_energy = p_emission_energy;
- volumetric_fog_anisotropy = p_anisotropy,
- volumetric_fog_length = p_length;
- volumetric_fog_detail_spread = p_detail_spread;
- volumetric_fog_gi_inject = p_gi_inject;
- volumetric_fog_temporal_reprojection = p_temporal_reprojection;
- volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
- volumetric_fog_ambient_inject = p_ambient_inject;
-}
-
-void RendererSceneEnvironmentRD::set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
- ssr_enabled = p_enable;
- ssr_max_steps = p_max_steps;
- ssr_fade_in = p_fade_int;
- ssr_fade_out = p_fade_out;
- ssr_depth_tolerance = p_depth_tolerance;
-}
-
-void RendererSceneEnvironmentRD::set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
- ssao_enabled = p_enable;
- ssao_radius = p_radius;
- ssao_intensity = p_intensity;
- ssao_power = p_power;
- ssao_detail = p_detail;
- ssao_horizon = p_horizon;
- ssao_sharpness = p_sharpness;
- ssao_direct_light_affect = p_light_affect;
- ssao_ao_channel_affect = p_ao_channel_affect;
-}
diff --git a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h b/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
deleted file mode 100644
index 4e170b8cfb..0000000000
--- a/servers/rendering/renderer_rd/renderer_scene_environment_rd.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/*************************************************************************/
-/* renderer_scene_environment_rd.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#ifndef RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H
-#define RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H
-
-#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering/rendering_device.h"
-
-class RendererSceneEnvironmentRD {
-private:
- static uint64_t auto_exposure_counter;
-
-public:
- // BG
- RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
- RID sky;
- float sky_custom_fov = 0.0;
- Basis sky_orientation;
- Color bg_color;
- float bg_energy = 1.0;
- int canvas_max_layer = 0;
- RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
- Color ambient_light;
- float ambient_light_energy = 1.0;
- float ambient_sky_contribution = 1.0;
- RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
-
- /// Tonemap
-
- RS::EnvironmentToneMapper tone_mapper;
- float exposure = 1.0;
- float white = 1.0;
- bool auto_exposure = false;
- float min_luminance = 0.2;
- float max_luminance = 8.0;
- float auto_exp_speed = 0.2;
- float auto_exp_scale = 0.5;
- uint64_t auto_exposure_version = 0;
-
- // Fog
- bool fog_enabled = false;
- Color fog_light_color = Color(0.5, 0.6, 0.7);
- float fog_light_energy = 1.0;
- float fog_sun_scatter = 0.0;
- float fog_density = 0.001;
- float fog_height = 0.0;
- float fog_height_density = 0.0; //can be negative to invert effect
- float fog_aerial_perspective = 0.0;
-
- /// Volumetric Fog
- ///
- bool volumetric_fog_enabled = false;
- float volumetric_fog_density = 0.01;
- Color volumetric_fog_scattering = Color(1, 1, 1);
- Color volumetric_fog_emission = Color(0, 0, 0);
- float volumetric_fog_emission_energy = 0.0;
- float volumetric_fog_anisotropy = 0.2;
- float volumetric_fog_length = 64.0;
- float volumetric_fog_detail_spread = 2.0;
- float volumetric_fog_gi_inject = 0.0;
- bool volumetric_fog_temporal_reprojection = true;
- float volumetric_fog_temporal_reprojection_amount = 0.9;
- float volumetric_fog_ambient_inject = 0.0;
-
- /// Glow
-
- bool glow_enabled = false;
- Vector<float> glow_levels;
- float glow_intensity = 0.8;
- float glow_strength = 1.0;
- float glow_bloom = 0.0;
- float glow_mix = 0.01;
- RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
- float glow_hdr_bleed_threshold = 1.0;
- float glow_hdr_luminance_cap = 12.0;
- float glow_hdr_bleed_scale = 2.0;
- float glow_map_strength = 0.0f;
- RID glow_map = RID();
-
- /// SSAO
-
- bool ssao_enabled = false;
- float ssao_radius = 1.0;
- float ssao_intensity = 2.0;
- float ssao_power = 1.5;
- float ssao_detail = 0.5;
- float ssao_horizon = 0.06;
- float ssao_sharpness = 0.98;
- float ssao_direct_light_affect = 0.0;
- float ssao_ao_channel_affect = 0.0;
-
- /// SSR
- ///
- bool ssr_enabled = false;
- int ssr_max_steps = 64;
- float ssr_fade_in = 0.15;
- float ssr_fade_out = 2.0;
- float ssr_depth_tolerance = 0.2;
-
- /// SSIL
- ///
- bool ssil_enabled = false;
- float ssil_radius = 5.0;
- float ssil_intensity = 1.0;
- float ssil_sharpness = 0.98;
- float ssil_normal_rejection = 1.0;
-
- /// SDFGI
- bool sdfgi_enabled = false;
- int sdfgi_cascades = 4;
- float sdfgi_min_cell_size = 0.2;
- bool sdfgi_use_occlusion = false;
- float sdfgi_bounce_feedback = 0.5;
- bool sdfgi_read_sky_light = true;
- float sdfgi_energy = 1.0;
- float sdfgi_normal_bias = 1.1;
- float sdfgi_probe_bias = 1.1;
- RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_75_PERCENT;
-
- /// Adjustments
-
- bool adjustments_enabled = false;
- float adjustments_brightness = 1.0f;
- float adjustments_contrast = 1.0f;
- float adjustments_saturation = 1.0f;
- bool use_1d_color_correction = false;
- RID color_correction = RID();
-
- void set_ambient_light(const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source);
- void set_tonemap(RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale);
- void set_glow(bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
- void set_sdfgi(bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
- void set_fog(bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective);
- void set_volumetric_fog(bool p_enable, float p_density, const Color &p_scatterin, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject);
- void set_ssr(bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
- void set_ssao(bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
-};
-
-#endif /* !RENDERING_SERVER_SCENE_ENVIRONMENT_RD_H */
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
index a1c6ff540d..75fe84f46b 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp
@@ -33,9 +33,11 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
#include "renderer_compositor_rd.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/rendering_server_default.h"
+#include "servers/rendering/storage/camera_attributes_storage.h"
void get_vogel_disk(float *r_kernel, int p_sample_count) {
const float golden_angle = 2.4;
@@ -49,17 +51,21 @@ void get_vogel_disk(float *r_kernel, int p_sample_count) {
}
}
-void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- bool needs_sdfgi = env && env->sdfgi_enabled;
+void RendererSceneRenderRD::sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) {
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND(rb.is_null());
+ Ref<RendererRD::GI::SDFGI> sdfgi;
+ if (rb->has_custom_data(RB_SCOPE_SDFGI)) {
+ sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ }
+
+ bool needs_sdfgi = p_environment.is_valid() && environment_get_sdfgi_enabled(p_environment);
if (!needs_sdfgi) {
- if (rb->sdfgi != nullptr) {
- //erase it
- rb->sdfgi->erase();
- memdelete(rb->sdfgi);
- rb->sdfgi = nullptr;
+ if (sdfgi.is_valid()) {
+ // delete it
+ sdfgi.unref();
+ rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
}
return;
}
@@ -67,37 +73,36 @@ void RendererSceneRenderRD::sdfgi_update(RID p_render_buffers, RID p_environment
static const uint32_t history_frames_to_converge[RS::ENV_SDFGI_CONVERGE_MAX] = { 5, 10, 15, 20, 25, 30 };
uint32_t requested_history_size = history_frames_to_converge[gi.sdfgi_frames_to_converge];
- if (rb->sdfgi && (rb->sdfgi->num_cascades != env->sdfgi_cascades || rb->sdfgi->min_cell_size != env->sdfgi_min_cell_size || requested_history_size != rb->sdfgi->history_size || rb->sdfgi->uses_occlusion != env->sdfgi_use_occlusion || rb->sdfgi->y_scale_mode != env->sdfgi_y_scale)) {
+ if (sdfgi.is_valid() && (sdfgi->num_cascades != environment_get_sdfgi_cascades(p_environment) || sdfgi->min_cell_size != environment_get_sdfgi_min_cell_size(p_environment) || requested_history_size != sdfgi->history_size || sdfgi->uses_occlusion != environment_get_sdfgi_use_occlusion(p_environment) || sdfgi->y_scale_mode != environment_get_sdfgi_y_scale(p_environment))) {
//configuration changed, erase
- rb->sdfgi->erase();
- memdelete(rb->sdfgi);
- rb->sdfgi = nullptr;
+ sdfgi.unref();
+ rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
}
- RendererSceneGIRD::SDFGI *sdfgi = rb->sdfgi;
- if (sdfgi == nullptr) {
+ if (sdfgi.is_null()) {
// re-create
- rb->sdfgi = gi.create_sdfgi(env, p_world_position, requested_history_size);
+ sdfgi = gi.create_sdfgi(p_environment, p_world_position, requested_history_size);
+ rb->set_custom_data(RB_SCOPE_SDFGI, sdfgi);
} else {
//check for updates
- rb->sdfgi->update(env, p_world_position);
+ sdfgi->update(p_environment, p_world_position);
}
}
-int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers) const {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
+int RendererSceneRenderRD::sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const {
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND_V(rb.is_null(), 0);
- ERR_FAIL_COND_V(rb == nullptr, 0);
-
- if (rb->sdfgi == nullptr) {
+ if (!rb->has_custom_data(RB_SCOPE_SDFGI)) {
return 0;
}
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
int dirty_count = 0;
- for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) {
- const RendererSceneGIRD::SDFGI::Cascade &c = rb->sdfgi->cascades[i];
+ for (uint32_t i = 0; i < sdfgi->cascades.size(); i++) {
+ const RendererRD::GI::SDFGI::Cascade &c = sdfgi->cascades[i];
- if (c.dirty_regions == RendererSceneGIRD::SDFGI::Cascade::DIRTY_ALL) {
+ if (c.dirty_regions == RendererRD::GI::SDFGI::Cascade::DIRTY_ALL) {
dirty_count++;
} else {
for (int j = 0; j < 3; j++) {
@@ -111,28 +116,32 @@ int RendererSceneRenderRD::sdfgi_get_pending_region_count(RID p_render_buffers)
return dirty_count;
}
-AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const {
+AABB RendererSceneRenderRD::sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const {
AABB bounds;
Vector3i from;
Vector3i size;
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(rb == nullptr, AABB());
- ERR_FAIL_COND_V(rb->sdfgi == nullptr, AABB());
- int c = rb->sdfgi->get_pending_region_data(p_region, from, size, bounds);
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND_V(rb.is_null(), AABB());
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ ERR_FAIL_COND_V(sdfgi.is_null(), AABB());
+
+ int c = sdfgi->get_pending_region_data(p_region, from, size, bounds);
ERR_FAIL_COND_V(c == -1, AABB());
return bounds;
}
-uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const {
+uint32_t RendererSceneRenderRD::sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const {
AABB bounds;
Vector3i from;
Vector3i size;
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(rb == nullptr, -1);
- ERR_FAIL_COND_V(rb->sdfgi == nullptr, -1);
- return rb->sdfgi->get_pending_region_data(p_region, from, size, bounds);
+ Ref<RenderSceneBuffersRD> rb = p_render_buffers;
+ ERR_FAIL_COND_V(rb.is_null(), -1);
+ Ref<RendererRD::GI::SDFGI> sdfgi = rb->get_custom_data(RB_SCOPE_SDFGI);
+ ERR_FAIL_COND_V(sdfgi.is_null(), -1);
+
+ return sdfgi->get_pending_region_data(p_region, from, size, bounds);
}
RID RendererSceneRenderRD::sky_allocate() {
@@ -158,145 +167,6 @@ Ref<Image> RendererSceneRenderRD::sky_bake_panorama(RID p_sky, float p_energy, b
return sky.sky_bake_panorama(p_sky, p_energy, p_bake_irradiance, p_size);
}
-RID RendererSceneRenderRD::environment_allocate() {
- return environment_owner.allocate_rid();
-}
-void RendererSceneRenderRD::environment_initialize(RID p_rid) {
- environment_owner.initialize_rid(p_rid, RendererSceneEnvironmentRD());
-}
-
-void RendererSceneRenderRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->background = p_bg;
-}
-
-void RendererSceneRenderRD::environment_set_sky(RID p_env, RID p_sky) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky = p_sky;
-}
-
-void RendererSceneRenderRD::environment_set_sky_custom_fov(RID p_env, float p_scale) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky_custom_fov = p_scale;
-}
-
-void RendererSceneRenderRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->sky_orientation = p_orientation;
-}
-
-void RendererSceneRenderRD::environment_set_bg_color(RID p_env, const Color &p_color) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->bg_color = p_color;
-}
-
-void RendererSceneRenderRD::environment_set_bg_energy(RID p_env, float p_energy) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->bg_energy = p_energy;
-}
-
-void RendererSceneRenderRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->canvas_max_layer = p_max_layer;
-}
-
-void RendererSceneRenderRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->set_ambient_light(p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source);
-}
-
-RS::EnvironmentBG RendererSceneRenderRD::environment_get_background(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX);
- return env->background;
-}
-
-RID RendererSceneRenderRD::environment_get_sky(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RID());
- return env->sky;
-}
-
-float RendererSceneRenderRD::environment_get_sky_custom_fov(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->sky_custom_fov;
-}
-
-Basis RendererSceneRenderRD::environment_get_sky_orientation(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Basis());
- return env->sky_orientation;
-}
-
-Color RendererSceneRenderRD::environment_get_bg_color(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Color());
- return env->bg_color;
-}
-
-float RendererSceneRenderRD::environment_get_bg_energy(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->bg_energy;
-}
-
-int RendererSceneRenderRD::environment_get_canvas_max_layer(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->canvas_max_layer;
-}
-
-Color RendererSceneRenderRD::environment_get_ambient_light_color(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Color());
- return env->ambient_light;
-}
-
-RS::EnvironmentAmbientSource RendererSceneRenderRD::environment_get_ambient_source(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG);
- return env->ambient_source;
-}
-
-float RendererSceneRenderRD::environment_get_ambient_light_energy(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->ambient_light_energy;
-}
-
-float RendererSceneRenderRD::environment_get_ambient_sky_contribution(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->ambient_sky_contribution;
-}
-
-RS::EnvironmentReflectionSource RendererSceneRenderRD::environment_get_reflection_source(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED);
- return env->reflection_source;
-}
-
-void RendererSceneRenderRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->set_tonemap(p_tone_mapper, p_exposure, p_white, p_auto_exposure, p_min_luminance, p_max_luminance, p_auto_exp_speed, p_auto_exp_scale);
-}
-
-void RendererSceneRenderRD::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
- env->set_glow(p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map);
-}
-
void RendererSceneRenderRD::environment_glow_set_use_bicubic_upscale(bool p_enable) {
glow_bicubic_upscale = p_enable;
}
@@ -305,79 +175,6 @@ void RendererSceneRenderRD::environment_glow_set_use_high_quality(bool p_enable)
glow_high_quality = p_enable;
}
-void RendererSceneRenderRD::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- if (!is_dynamic_gi_supported()) {
- return;
- }
-
- env->set_sdfgi(p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias);
-}
-
-void RendererSceneRenderRD::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->set_fog(p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_fog_aerial_perspective);
-}
-
-bool RendererSceneRenderRD::environment_is_fog_enabled(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
-
- return env->fog_enabled;
-}
-Color RendererSceneRenderRD::environment_get_fog_light_color(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Color());
- return env->fog_light_color;
-}
-float RendererSceneRenderRD::environment_get_fog_light_energy(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_light_energy;
-}
-float RendererSceneRenderRD::environment_get_fog_sun_scatter(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_sun_scatter;
-}
-float RendererSceneRenderRD::environment_get_fog_density(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_density;
-}
-float RendererSceneRenderRD::environment_get_fog_height(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
-
- return env->fog_height;
-}
-float RendererSceneRenderRD::environment_get_fog_height_density(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_height_density;
-}
-
-float RendererSceneRenderRD::environment_get_fog_aerial_perspective(RID p_env) const {
- const RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0);
- return env->fog_aerial_perspective;
-}
-
-void RendererSceneRenderRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- if (!is_volumetric_supported()) {
- return;
- }
-
- env->set_volumetric_fog(p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject);
-}
-
void RendererSceneRenderRD::environment_set_volumetric_fog_volume_size(int p_size, int p_depth) {
volumetric_fog_size = p_size;
volumetric_fog_depth = p_depth;
@@ -398,107 +195,16 @@ void RendererSceneRenderRD::environment_set_sdfgi_frames_to_update_light(RS::Env
gi.sdfgi_frames_to_update_light = p_update;
}
-void RendererSceneRenderRD::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->set_ssr(p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance);
-}
-
-void RendererSceneRenderRD::environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) {
- ssr_roughness_quality = p_quality;
-}
-
-RS::EnvironmentSSRRoughnessQuality RendererSceneRenderRD::environment_get_ssr_roughness_quality() const {
- return ssr_roughness_quality;
-}
-
-void RendererSceneRenderRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->set_ssao(p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect);
-}
-
-void RendererSceneRenderRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
- ssao_quality = p_quality;
- ssao_half_size = p_half_size;
- ssao_adaptive_target = p_adaptive_target;
- ssao_blur_passes = p_blur_passes;
- ssao_fadeout_from = p_fadeout_from;
- ssao_fadeout_to = p_fadeout_to;
-}
-
-void RendererSceneRenderRD::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->ssil_enabled = p_enable;
- env->ssil_radius = p_radius;
- env->ssil_intensity = p_intensity;
- env->ssil_sharpness = p_sharpness;
- env->ssil_normal_rejection = p_normal_rejection;
-}
-
-void RendererSceneRenderRD::environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) {
- ssil_quality = p_quality;
- ssil_half_size = p_half_size;
- ssil_adaptive_target = p_adaptive_target;
- ssil_blur_passes = p_blur_passes;
- ssil_fadeout_from = p_fadeout_from;
- ssil_fadeout_to = p_fadeout_to;
-}
-
-bool RendererSceneRenderRD::environment_is_ssao_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->ssao_enabled;
-}
-
-float RendererSceneRenderRD::environment_get_ssao_ao_affect(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0.0);
- return env->ssao_ao_channel_affect;
-}
-
-float RendererSceneRenderRD::environment_get_ssao_light_affect(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, 0.0);
- return env->ssao_direct_light_affect;
-}
-
-bool RendererSceneRenderRD::environment_is_ssil_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->ssil_enabled;
-}
-
-bool RendererSceneRenderRD::environment_is_ssr_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->ssr_enabled;
-}
-bool RendererSceneRenderRD::environment_is_sdfgi_enabled(RID p_env) const {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, false);
- return env->sdfgi_enabled;
-}
-
-bool RendererSceneRenderRD::is_environment(RID p_env) const {
- return environment_owner.owns(p_env);
-}
-
Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND_V(!env, Ref<Image>());
+ ERR_FAIL_COND_V(p_env.is_null(), Ref<Image>());
- RS::EnvironmentBG environment_background = env->background;
+ RS::EnvironmentBG environment_background = environment_get_background(p_env);
if (environment_background == RS::ENV_BG_CAMERA_FEED || environment_background == RS::ENV_BG_CANVAS || environment_background == RS::ENV_BG_KEEP) {
return Ref<Image>(); //nothing to bake
}
- RS::EnvironmentAmbientSource ambient_source = env->ambient_source;
+ RS::EnvironmentAmbientSource ambient_source = environment_get_ambient_source(p_env);
bool use_ambient_light = false;
bool use_cube_map = false;
@@ -508,14 +214,14 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
use_cube_map = (ambient_source == RS::ENV_AMBIENT_SOURCE_BG && environment_background == RS::ENV_BG_SKY) || ambient_source == RS::ENV_AMBIENT_SOURCE_SKY;
use_ambient_light = use_cube_map || ambient_source == RS::ENV_AMBIENT_SOURCE_COLOR;
}
- use_cube_map = use_cube_map || (environment_background == RS::ENV_BG_SKY && env->sky.is_valid());
+ use_cube_map = use_cube_map || (environment_background == RS::ENV_BG_SKY && environment_get_sky(p_env).is_valid());
Color ambient_color;
- float ambient_color_sky_mix;
+ float ambient_color_sky_mix = 0.0;
if (use_ambient_light) {
- ambient_color_sky_mix = env->ambient_sky_contribution;
- const float ambient_energy = env->ambient_light_energy;
- ambient_color = env->ambient_light;
+ ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_env);
+ const float ambient_energy = environment_get_ambient_light_energy(p_env);
+ ambient_color = environment_get_ambient_light(p_env);
ambient_color = ambient_color.srgb_to_linear();
ambient_color.r *= ambient_energy;
ambient_color.g *= ambient_energy;
@@ -523,7 +229,7 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
}
if (use_cube_map) {
- Ref<Image> panorama = sky_bake_panorama(env->sky, env->bg_energy, p_bake_irradiance, p_size);
+ Ref<Image> panorama = sky_bake_panorama(environment_get_sky(p_env), environment_get_bg_energy_multiplier(p_env), p_bake_irradiance, p_size);
if (use_ambient_light) {
for (int x = 0; x < p_size.width; x++) {
for (int y = 0; y < p_size.height; y++) {
@@ -533,279 +239,24 @@ Ref<Image> RendererSceneRenderRD::environment_bake_panorama(RID p_env, bool p_ba
}
return panorama;
} else {
- const float bg_energy = env->bg_energy;
- Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? storage->get_default_clear_color() : env->bg_color);
+ const float bg_energy_multiplier = environment_get_bg_energy_multiplier(p_env);
+ Color panorama_color = ((environment_background == RS::ENV_BG_CLEAR_COLOR) ? RSG::texture_storage->get_default_clear_color() : environment_get_bg_color(p_env));
panorama_color = panorama_color.srgb_to_linear();
- panorama_color.r *= bg_energy;
- panorama_color.g *= bg_energy;
- panorama_color.b *= bg_energy;
+ panorama_color.r *= bg_energy_multiplier;
+ panorama_color.g *= bg_energy_multiplier;
+ panorama_color.b *= bg_energy_multiplier;
if (use_ambient_light) {
panorama_color = ambient_color.lerp(panorama_color, ambient_color_sky_mix);
}
- Ref<Image> panorama;
- panorama.instantiate();
- panorama->create(p_size.width, p_size.height, false, Image::FORMAT_RGBAF);
+ Ref<Image> panorama = Image::create_empty(p_size.width, p_size.height, false, Image::FORMAT_RGBAF);
panorama->fill(panorama_color);
return panorama;
}
-
- return Ref<Image>();
-}
-
-////////////////////////////////////////////////////////////
-
-RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) {
- FogVolumeInstance fvi;
- fvi.volume = p_fog_volume;
- return fog_volume_instance_owner.make_rid(fvi);
-}
-void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
- ERR_FAIL_COND(!fvi);
- fvi->transform = p_transform;
-}
-void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
- ERR_FAIL_COND(!fvi);
- fvi->active = p_active;
-}
-
-RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
- ERR_FAIL_COND_V(!fvi, RID());
- return fvi->volume;
-}
-
-Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const {
- FogVolumeInstance *fvi = fog_volume_instance_owner.get_or_null(p_fog_volume_instance);
- ERR_FAIL_COND_V(!fvi, Vector3());
-
- return fvi->transform.get_origin();
-}
-
-////////////////////////////////////////////////////////////
-
-RID RendererSceneRenderRD::reflection_atlas_create() {
- ReflectionAtlas ra;
- ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count");
- ra.size = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_size");
-
- if (is_clustered_enabled()) {
- ra.cluster_builder = memnew(ClusterBuilderRD);
- ra.cluster_builder->set_shared(&cluster_builder_shared);
- ra.cluster_builder->setup(Size2i(ra.size, ra.size), max_cluster_elements, RID(), RID(), RID());
- } else {
- ra.cluster_builder = nullptr;
- }
-
- return reflection_atlas_owner.make_rid(ra);
-}
-
-void RendererSceneRenderRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
- ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);
- ERR_FAIL_COND(!ra);
-
- if (ra->size == p_reflection_size && ra->count == p_reflection_count) {
- return; //no changes
- }
-
- if (ra->cluster_builder) {
- // only if we're using our cluster
- ra->cluster_builder->setup(Size2i(ra->size, ra->size), max_cluster_elements, RID(), RID(), RID());
- }
-
- ra->size = p_reflection_size;
- ra->count = p_reflection_count;
-
- if (ra->reflection.is_valid()) {
- //clear and invalidate everything
- RD::get_singleton()->free(ra->reflection);
- ra->reflection = RID();
- RD::get_singleton()->free(ra->depth_buffer);
- ra->depth_buffer = RID();
- for (int i = 0; i < ra->reflections.size(); i++) {
- ra->reflections.write[i].data.clear_reflection_data();
- if (ra->reflections[i].owner.is_null()) {
- continue;
- }
- reflection_probe_release_atlas_index(ra->reflections[i].owner);
- //rp->atlasindex clear
- }
-
- ra->reflections.clear();
- }
-}
-
-int RendererSceneRenderRD::reflection_atlas_get_size(RID p_ref_atlas) const {
- ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);
- ERR_FAIL_COND_V(!ra, 0);
-
- return ra->size;
-}
-
-////////////////////////
-RID RendererSceneRenderRD::reflection_probe_instance_create(RID p_probe) {
- ReflectionProbeInstance rpi;
- rpi.probe = p_probe;
- rpi.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE);
-
- return reflection_probe_instance_owner.make_rid(rpi);
-}
-
-void RendererSceneRenderRD::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND(!rpi);
-
- rpi->transform = p_transform;
- rpi->dirty = true;
-}
-
-void RendererSceneRenderRD::reflection_probe_release_atlas_index(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND(!rpi);
-
- if (rpi->atlas.is_null()) {
- return; //nothing to release
- }
- ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
- ERR_FAIL_COND(!atlas);
- ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size());
- atlas->reflections.write[rpi->atlas_index].owner = RID();
- rpi->atlas_index = -1;
- rpi->atlas = RID();
}
-bool RendererSceneRenderRD::reflection_probe_instance_needs_redraw(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, false);
-
- if (rpi->rendering) {
- return false;
- }
-
- if (rpi->dirty) {
- return true;
- }
-
- if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
- return true;
- }
-
- return rpi->atlas_index == -1;
-}
-
-bool RendererSceneRenderRD::reflection_probe_instance_has_reflection(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, false);
-
- return rpi->atlas.is_valid();
-}
-
-bool RendererSceneRenderRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
- ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas);
-
- ERR_FAIL_COND_V(!atlas, false);
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, false);
-
- RD::get_singleton()->draw_command_begin_label("Reflection probe render");
-
- if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
- WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
- reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
- }
-
- if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
- // Invalidate reflection atlas, need to regenerate
- RD::get_singleton()->free(atlas->reflection);
- atlas->reflection = RID();
-
- for (int i = 0; i < atlas->reflections.size(); i++) {
- if (atlas->reflections[i].owner.is_null()) {
- continue;
- }
- reflection_probe_release_atlas_index(atlas->reflections[i].owner);
- }
-
- atlas->reflections.clear();
- }
-
- if (atlas->reflection.is_null()) {
- int mipmaps = MIN(sky.roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
- mipmaps = RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
- {
- //reflection atlas was unused, create:
- RD::TextureFormat tf;
- tf.array_layers = 6 * atlas->count;
- tf.format = _render_buffers_get_color_format();
- tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
- tf.mipmaps = mipmaps;
- tf.width = atlas->size;
- tf.height = atlas->size;
- tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
-
- atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
- tf.width = atlas->size;
- tf.height = atlas->size;
- tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
- atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
- atlas->reflections.resize(atlas->count);
- for (int i = 0; i < atlas->count; i++) {
- atlas->reflections.write[i].data.update_reflection_data(storage, atlas->size, mipmaps, false, atlas->reflection, i * 6, RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, sky.roughness_layers, _render_buffers_get_color_format());
- for (int j = 0; j < 6; j++) {
- atlas->reflections.write[i].fbs[j] = reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
- }
- }
-
- Vector<RID> fb;
- fb.push_back(atlas->depth_buffer);
- atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
- }
-
- if (rpi->atlas_index == -1) {
- for (int i = 0; i < atlas->reflections.size(); i++) {
- if (atlas->reflections[i].owner.is_null()) {
- rpi->atlas_index = i;
- break;
- }
- }
- //find the one used last
- if (rpi->atlas_index == -1) {
- //everything is in use, find the one least used via LRU
- uint64_t pass_min = 0;
-
- for (int i = 0; i < atlas->reflections.size(); i++) {
- ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.get_or_null(atlas->reflections[i].owner);
- if (rpi2->last_pass < pass_min) {
- pass_min = rpi2->last_pass;
- rpi->atlas_index = i;
- }
- }
- }
- }
-
- if (rpi->atlas_index != -1) { // should we fail if this is still -1 ?
- atlas->reflections.write[rpi->atlas_index].owner = p_instance;
- }
-
- rpi->atlas = p_reflection_atlas;
- rpi->rendering = true;
- rpi->dirty = false;
- rpi->processing_layer = 1;
- rpi->processing_side = 0;
-
- RD::get_singleton()->draw_command_end_label();
-
- return true;
-}
+/* REFLECTION PROBE */
RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID p_depth) {
Vector<RID> fb;
@@ -814,706 +265,39 @@ RID RendererSceneRenderRD::reflection_probe_create_framebuffer(RID p_color, RID
return RD::get_singleton()->framebuffer_create(fb);
}
-bool RendererSceneRenderRD::reflection_probe_instance_postprocess_step(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, false);
- ERR_FAIL_COND_V(!rpi->rendering, false);
- ERR_FAIL_COND_V(rpi->atlas.is_null(), false);
-
- ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
- if (!atlas || rpi->atlas_index == -1) {
- //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering)
- rpi->rendering = false;
- return false;
- }
-
- if (RSG::light_storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
- // Using real time reflections, all roughness is done in one step
- atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(storage, false);
- rpi->rendering = false;
- rpi->processing_side = 0;
- rpi->processing_layer = 1;
- return true;
- }
-
- if (rpi->processing_layer > 1) {
- atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, 10, rpi->processing_layer, sky.sky_ggx_samples_quality);
- rpi->processing_layer++;
- if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) {
- rpi->rendering = false;
- rpi->processing_side = 0;
- rpi->processing_layer = 1;
- return true;
- }
- return false;
-
- } else {
- atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(storage, false, rpi->processing_side, rpi->processing_layer, sky.sky_ggx_samples_quality);
- }
-
- rpi->processing_side++;
- if (rpi->processing_side == 6) {
- rpi->processing_side = 0;
- rpi->processing_layer++;
- }
-
- return false;
-}
-
-uint32_t RendererSceneRenderRD::reflection_probe_instance_get_resolution(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, 0);
-
- ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
- ERR_FAIL_COND_V(!atlas, 0);
- return atlas->size;
-}
-
-RID RendererSceneRenderRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, RID());
- ERR_FAIL_INDEX_V(p_index, 6, RID());
-
- ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
- ERR_FAIL_COND_V(!atlas, RID());
- return atlas->reflections[rpi->atlas_index].fbs[p_index];
-}
-
-RID RendererSceneRenderRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, RID());
- ERR_FAIL_INDEX_V(p_index, 6, RID());
-
- ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
- ERR_FAIL_COND_V(!atlas, RID());
- return atlas->depth_fb;
-}
-
-///////////////////////////////////////////////////////////
-
-RID RendererSceneRenderRD::shadow_atlas_create() {
- return shadow_atlas_owner.make_rid(ShadowAtlas());
-}
-
-void RendererSceneRenderRD::_update_shadow_atlas(ShadowAtlas *shadow_atlas) {
- if (shadow_atlas->size > 0 && shadow_atlas->depth.is_null()) {
- RD::TextureFormat tf;
- tf.format = shadow_atlas->use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT;
- tf.width = shadow_atlas->size;
- tf.height = shadow_atlas->size;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
-
- shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- Vector<RID> fb_tex;
- fb_tex.push_back(shadow_atlas->depth);
- shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb_tex);
- }
-}
-
-void RendererSceneRenderRD::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
- ERR_FAIL_COND(!shadow_atlas);
- ERR_FAIL_COND(p_size < 0);
- p_size = next_power_of_2(p_size);
-
- if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {
- return;
- }
-
- // erasing atlas
- if (shadow_atlas->depth.is_valid()) {
- RD::get_singleton()->free(shadow_atlas->depth);
- shadow_atlas->depth = RID();
- }
- for (int i = 0; i < 4; i++) {
- //clear subdivisions
- shadow_atlas->quadrants[i].shadows.clear();
- shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision);
- }
-
- //erase shadow atlas reference from lights
- for (const KeyValue<RID, uint32_t> &E : shadow_atlas->shadow_owners) {
- LightInstance *li = light_instance_owner.get_or_null(E.key);
- ERR_CONTINUE(!li);
- li->shadow_atlases.erase(p_atlas);
- }
-
- //clear owners
- shadow_atlas->shadow_owners.clear();
-
- shadow_atlas->size = p_size;
- shadow_atlas->use_16_bits = p_16_bits;
-}
-
-void RendererSceneRenderRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
- ERR_FAIL_COND(!shadow_atlas);
- ERR_FAIL_INDEX(p_quadrant, 4);
- ERR_FAIL_INDEX(p_subdivision, 16384);
-
- uint32_t subdiv = next_power_of_2(p_subdivision);
- if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer
- subdiv <<= 1;
- }
-
- subdiv = int(Math::sqrt((float)subdiv));
-
- //obtain the number that will be x*x
-
- if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) {
- return;
- }
-
- //erase all data from quadrant
- for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {
- if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {
- shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
- LightInstance *li = light_instance_owner.get_or_null(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
- ERR_CONTINUE(!li);
- li->shadow_atlases.erase(p_atlas);
- }
- }
-
- shadow_atlas->quadrants[p_quadrant].shadows.clear();
- shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv);
- shadow_atlas->quadrants[p_quadrant].subdivision = subdiv;
-
- //cache the smallest subdiv (for faster allocation in light update)
-
- shadow_atlas->smallest_subdiv = 1 << 30;
-
- for (int i = 0; i < 4; i++) {
- if (shadow_atlas->quadrants[i].subdivision) {
- shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision);
- }
- }
-
- if (shadow_atlas->smallest_subdiv == 1 << 30) {
- shadow_atlas->smallest_subdiv = 0;
- }
-
- //resort the size orders, simple bublesort for 4 elements..
-
- int swaps = 0;
- do {
- swaps = 0;
-
- for (int i = 0; i < 3; i++) {
- if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) {
- SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]);
- swaps++;
- }
- }
- } while (swaps > 0);
-}
-
-bool RendererSceneRenderRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) {
- for (int i = p_quadrant_count - 1; i >= 0; i--) {
- int qidx = p_in_quadrants[i];
-
- if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
- return false;
- }
-
- //look for an empty space
- int sc = shadow_atlas->quadrants[qidx].shadows.size();
- const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr();
-
- int found_free_idx = -1; //found a free one
- int found_used_idx = -1; //found existing one, must steal it
- uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion)
-
- for (int j = 0; j < sc; j++) {
- if (!sarr[j].owner.is_valid()) {
- found_free_idx = j;
- break;
- }
-
- LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
- ERR_CONTINUE(!sli);
-
- if (sli->last_scene_pass != scene_pass) {
- //was just allocated, don't kill it so soon, wait a bit..
- if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
- continue;
- }
-
- if (found_used_idx == -1 || sli->last_scene_pass < min_pass) {
- found_used_idx = j;
- min_pass = sli->last_scene_pass;
- }
- }
- }
-
- if (found_free_idx == -1 && found_used_idx == -1) {
- continue; //nothing found
- }
-
- if (found_free_idx == -1 && found_used_idx != -1) {
- found_free_idx = found_used_idx;
- }
-
- r_quadrant = qidx;
- r_shadow = found_free_idx;
-
- return true;
- }
-
- return false;
-}
-
-bool RendererSceneRenderRD::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) {
- for (int i = p_quadrant_count - 1; i >= 0; i--) {
- int qidx = p_in_quadrants[i];
-
- if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
- return false;
- }
-
- //look for an empty space
- int sc = shadow_atlas->quadrants[qidx].shadows.size();
- const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr();
-
- int found_idx = -1;
- uint64_t min_pass = 0; // sum of currently selected spots, try to get the least recently used pair
-
- for (int j = 0; j < sc - 1; j++) {
- uint64_t pass = 0;
-
- if (sarr[j].owner.is_valid()) {
- LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
- ERR_CONTINUE(!sli);
-
- if (sli->last_scene_pass == scene_pass) {
- continue;
- }
-
- //was just allocated, don't kill it so soon, wait a bit..
- if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
- continue;
- }
- pass += sli->last_scene_pass;
- }
-
- if (sarr[j + 1].owner.is_valid()) {
- LightInstance *sli = light_instance_owner.get_or_null(sarr[j + 1].owner);
- ERR_CONTINUE(!sli);
-
- if (sli->last_scene_pass == scene_pass) {
- continue;
- }
-
- //was just allocated, don't kill it so soon, wait a bit..
- if (p_tick - sarr[j + 1].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
- continue;
- }
- pass += sli->last_scene_pass;
- }
-
- if (found_idx == -1 || pass < min_pass) {
- found_idx = j;
- min_pass = pass;
-
- // we found two empty spots, no need to check the rest
- if (pass == 0) {
- break;
- }
- }
- }
-
- if (found_idx == -1) {
- continue; //nothing found
- }
-
- r_quadrant = qidx;
- r_shadow = found_idx;
-
- return true;
- }
-
- return false;
-}
-
-bool RendererSceneRenderRD::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
- ERR_FAIL_COND_V(!shadow_atlas, false);
-
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND_V(!li, false);
-
- if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {
- return false;
- }
-
- uint32_t quad_size = shadow_atlas->size >> 1;
- int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage));
-
- int valid_quadrants[4];
- int valid_quadrant_count = 0;
- int best_size = -1; //best size found
- int best_subdiv = -1; //subdiv for the best size
-
- //find the quadrants this fits into, and the best possible size it can fit into
- for (int i = 0; i < 4; i++) {
- int q = shadow_atlas->size_order[i];
- int sd = shadow_atlas->quadrants[q].subdivision;
- if (sd == 0) {
- continue; //unused
- }
-
- int max_fit = quad_size / sd;
-
- if (best_size != -1 && max_fit > best_size) {
- break; //too large
- }
-
- valid_quadrants[valid_quadrant_count++] = q;
- best_subdiv = sd;
-
- if (max_fit >= desired_fit) {
- best_size = max_fit;
- }
- }
-
- ERR_FAIL_COND_V(valid_quadrant_count == 0, false);
-
- uint64_t tick = OS::get_singleton()->get_ticks_msec();
-
- uint32_t old_key = ShadowAtlas::SHADOW_INVALID;
- uint32_t old_quadrant = ShadowAtlas::SHADOW_INVALID;
- uint32_t old_shadow = ShadowAtlas::SHADOW_INVALID;
- int old_subdivision = -1;
-
- bool should_realloc = false;
- bool should_redraw = false;
-
- if (shadow_atlas->shadow_owners.has(p_light_instance)) {
- old_key = shadow_atlas->shadow_owners[p_light_instance];
- old_quadrant = (old_key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- old_shadow = old_key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec);
- should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version;
-
- if (!should_realloc) {
- shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = p_light_version;
- //already existing, see if it should redraw or it's just OK
- return should_redraw;
- }
-
- old_subdivision = shadow_atlas->quadrants[old_quadrant].subdivision;
- }
-
- bool is_omni = li->light_type == RS::LIGHT_OMNI;
- bool found_shadow = false;
- int new_quadrant = -1;
- int new_shadow = -1;
-
- if (is_omni) {
- found_shadow = _shadow_atlas_find_omni_shadows(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow);
- } else {
- found_shadow = _shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow);
- }
-
- if (found_shadow) {
- if (old_quadrant != ShadowAtlas::SHADOW_INVALID) {
- shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = 0;
- shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].owner = RID();
-
- if (old_key & ShadowAtlas::OMNI_LIGHT_FLAG) {
- shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].version = 0;
- shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].owner = RID();
- }
- }
-
- uint32_t new_key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT;
- new_key |= new_shadow;
-
- ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
- _shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow);
-
- sh->owner = p_light_instance;
- sh->alloc_tick = tick;
- sh->version = p_light_version;
-
- if (is_omni) {
- new_key |= ShadowAtlas::OMNI_LIGHT_FLAG;
-
- int new_omni_shadow = new_shadow + 1;
- ShadowAtlas::Quadrant::Shadow *extra_sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_omni_shadow];
- _shadow_atlas_invalidate_shadow(extra_sh, p_atlas, shadow_atlas, new_quadrant, new_omni_shadow);
-
- extra_sh->owner = p_light_instance;
- extra_sh->alloc_tick = tick;
- extra_sh->version = p_light_version;
- }
-
- li->shadow_atlases.insert(p_atlas);
-
- //update it in map
- shadow_atlas->shadow_owners[p_light_instance] = new_key;
- //make it dirty, as it should redraw anyway
- return true;
- }
-
- return should_redraw;
-}
-
-void RendererSceneRenderRD::_shadow_atlas_invalidate_shadow(RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, RendererSceneRenderRD::ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx) {
- if (p_shadow->owner.is_valid()) {
- LightInstance *sli = light_instance_owner.get_or_null(p_shadow->owner);
- uint32_t old_key = p_shadow_atlas->shadow_owners[p_shadow->owner];
-
- if (old_key & ShadowAtlas::OMNI_LIGHT_FLAG) {
- uint32_t s = old_key & ShadowAtlas::SHADOW_INDEX_MASK;
- uint32_t omni_shadow_idx = p_shadow_idx + (s == (uint32_t)p_shadow_idx ? 1 : -1);
- RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *omni_shadow = &p_shadow_atlas->quadrants[p_quadrant].shadows.write[omni_shadow_idx];
- omni_shadow->version = 0;
- omni_shadow->owner = RID();
- }
-
- p_shadow_atlas->shadow_owners.erase(p_shadow->owner);
- p_shadow->version = 0;
- p_shadow->owner = RID();
- sli->shadow_atlases.erase(p_atlas);
- }
-}
-
-void RendererSceneRenderRD::_update_directional_shadow_atlas() {
- if (directional_shadow.depth.is_null() && directional_shadow.size > 0) {
- RD::TextureFormat tf;
- tf.format = directional_shadow.use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT;
- tf.width = directional_shadow.size;
- tf.height = directional_shadow.size;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
-
- directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- Vector<RID> fb_tex;
- fb_tex.push_back(directional_shadow.depth);
- directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb_tex);
- }
-}
-void RendererSceneRenderRD::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {
- p_size = nearest_power_of_2_templated(p_size);
-
- if (directional_shadow.size == p_size && directional_shadow.use_16_bits == p_16_bits) {
- return;
- }
-
- directional_shadow.size = p_size;
- directional_shadow.use_16_bits = p_16_bits;
-
- if (directional_shadow.depth.is_valid()) {
- RD::get_singleton()->free(directional_shadow.depth);
- directional_shadow.depth = RID();
- _base_uniforms_changed();
- }
-}
-
-void RendererSceneRenderRD::set_directional_shadow_count(int p_count) {
- directional_shadow.light_count = p_count;
- directional_shadow.current_light = 0;
-}
-
-static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) {
- int split_h = 1;
- int split_v = 1;
-
- while (split_h * split_v < p_shadow_count) {
- if (split_h == split_v) {
- split_h <<= 1;
- } else {
- split_v <<= 1;
- }
- }
-
- Rect2i rect(0, 0, p_size, p_size);
- rect.size.width /= split_h;
- rect.size.height /= split_v;
-
- rect.position.x = rect.size.width * (p_shadow_index % split_h);
- rect.position.y = rect.size.height * (p_shadow_index / split_h);
-
- return rect;
-}
-
-int RendererSceneRenderRD::get_directional_light_shadow_size(RID p_light_intance) {
- ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
-
- Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);
-
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance);
- ERR_FAIL_COND_V(!light_instance, 0);
-
- switch (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light)) {
- case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
- break; //none
- case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
- r.size.height /= 2;
- break;
- case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
- r.size /= 2;
- break;
- }
-
- return MAX(r.size.width, r.size.height);
-}
-
-//////////////////////////////////////////////////
-
-RID RendererSceneRenderRD::camera_effects_allocate() {
- return camera_effects_owner.allocate_rid();
-}
-void RendererSceneRenderRD::camera_effects_initialize(RID p_rid) {
- camera_effects_owner.initialize_rid(p_rid, CameraEffects());
-}
-
-void RendererSceneRenderRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
- dof_blur_quality = p_quality;
- dof_blur_use_jitter = p_use_jitter;
-}
-
-void RendererSceneRenderRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {
- dof_blur_bokeh_shape = p_shape;
-}
-
-void RendererSceneRenderRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) {
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
- ERR_FAIL_COND(!camfx);
-
- camfx->dof_blur_far_enabled = p_far_enable;
- camfx->dof_blur_far_distance = p_far_distance;
- camfx->dof_blur_far_transition = p_far_transition;
-
- camfx->dof_blur_near_enabled = p_near_enable;
- camfx->dof_blur_near_distance = p_near_distance;
- camfx->dof_blur_near_transition = p_near_transition;
-
- camfx->dof_blur_amount = p_amount;
-}
-
-void RendererSceneRenderRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
- ERR_FAIL_COND(!camfx);
-
- camfx->override_exposure_enabled = p_enable;
- camfx->override_exposure = p_exposure;
-}
-
-RID RendererSceneRenderRD::light_instance_create(RID p_light) {
- RID li = light_instance_owner.make_rid(LightInstance());
-
- LightInstance *light_instance = light_instance_owner.get_or_null(li);
-
- light_instance->self = li;
- light_instance->light = p_light;
- light_instance->light_type = RSG::light_storage->light_get_type(p_light);
- if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
- light_instance->forward_id = _allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT);
- }
-
- return li;
-}
-
-void RendererSceneRenderRD::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- light_instance->transform = p_transform;
-}
-
-void RendererSceneRenderRD::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- light_instance->aabb = p_aabb;
-}
-
-void RendererSceneRenderRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- ERR_FAIL_INDEX(p_pass, 6);
+/* FOG VOLUME INSTANCE */
- light_instance->shadow_transform[p_pass].camera = p_projection;
- light_instance->shadow_transform[p_pass].transform = p_transform;
- light_instance->shadow_transform[p_pass].farplane = p_far;
- light_instance->shadow_transform[p_pass].split = p_split;
- light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
- light_instance->shadow_transform[p_pass].range_begin = p_range_begin;
- light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size;
- light_instance->shadow_transform[p_pass].uv_scale = p_uv_scale;
-}
-
-void RendererSceneRenderRD::light_instance_mark_visible(RID p_light_instance) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND(!light_instance);
-
- light_instance->last_scene_pass = scene_pass;
+RID RendererSceneRenderRD::fog_volume_instance_create(RID p_fog_volume) {
+ return RendererRD::Fog::get_singleton()->fog_volume_instance_create(p_fog_volume);
}
-RendererSceneRenderRD::ShadowCubemap *RendererSceneRenderRD::_get_shadow_cubemap(int p_size) {
- if (!shadow_cubemaps.has(p_size)) {
- ShadowCubemap sc;
- {
- RD::TextureFormat tf;
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
- tf.width = p_size;
- tf.height = p_size;
- tf.texture_type = RD::TEXTURE_TYPE_CUBE;
- tf.array_layers = 6;
- tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
- sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- for (int i = 0; i < 6; i++) {
- RID side_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sc.cubemap, i, 0);
- Vector<RID> fbtex;
- fbtex.push_back(side_texture);
- sc.side_fb[i] = RD::get_singleton()->framebuffer_create(fbtex);
- }
-
- shadow_cubemaps[p_size] = sc;
- }
-
- return &shadow_cubemaps[p_size];
+void RendererSceneRenderRD::fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) {
+ RendererRD::Fog::get_singleton()->fog_volume_instance_set_transform(p_fog_volume_instance, p_transform);
}
-//////////////////////////
-
-RID RendererSceneRenderRD::decal_instance_create(RID p_decal) {
- DecalInstance di;
- di.decal = p_decal;
- di.forward_id = _allocate_forward_id(FORWARD_ID_TYPE_DECAL);
- return decal_instance_owner.make_rid(di);
+void RendererSceneRenderRD::fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) {
+ RendererRD::Fog::get_singleton()->fog_volume_instance_set_active(p_fog_volume_instance, p_active);
}
-void RendererSceneRenderRD::decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) {
- DecalInstance *di = decal_instance_owner.get_or_null(p_decal);
- ERR_FAIL_COND(!di);
- di->transform = p_transform;
+RID RendererSceneRenderRD::fog_volume_instance_get_volume(RID p_fog_volume_instance) const {
+ return RendererRD::Fog::get_singleton()->fog_volume_instance_get_volume(p_fog_volume_instance);
}
-/////////////////////////////////
-
-RID RendererSceneRenderRD::lightmap_instance_create(RID p_lightmap) {
- LightmapInstance li;
- li.lightmap = p_lightmap;
- return lightmap_instance_owner.make_rid(li);
-}
-void RendererSceneRenderRD::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
- LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap);
- ERR_FAIL_COND(!li);
- li->transform = p_transform;
+Vector3 RendererSceneRenderRD::fog_volume_instance_get_position(RID p_fog_volume_instance) const {
+ return RendererRD::Fog::get_singleton()->fog_volume_instance_get_position(p_fog_volume_instance);
}
-/////////////////////////////////
+/* VOXEL GI */
RID RendererSceneRenderRD::voxel_gi_instance_create(RID p_base) {
return gi.voxel_gi_instance_create(p_base);
}
void RendererSceneRenderRD::voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) {
+ if (!is_dynamic_gi_supported()) {
+ return;
+ }
+
gi.voxel_gi_instance_set_transform_to_data(p_probe, p_xform);
}
@@ -1525,199 +309,49 @@ bool RendererSceneRenderRD::voxel_gi_needs_update(RID p_probe) const {
return gi.voxel_gi_needs_update(p_probe);
}
-void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) {
+void RendererSceneRenderRD::voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) {
if (!is_dynamic_gi_supported()) {
return;
}
- gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects, this);
+ gi.voxel_gi_update(p_probe, p_update_light_instances, p_light_instances, p_dynamic_objects);
}
-void RendererSceneRenderRD::_debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
+void RendererSceneRenderRD::_debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, const uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth) {
+ ERR_FAIL_COND(p_render_buffers.is_null());
- if (!rb->sdfgi) {
+ if (!p_render_buffers->has_custom_data(RB_SCOPE_SDFGI)) {
return; //nothing to debug
}
- rb->sdfgi->debug_probes(p_draw_list, p_framebuffer, p_camera_with_transform);
-}
+ Ref<RendererRD::GI::SDFGI> sdfgi = p_render_buffers->get_custom_data(RB_SCOPE_SDFGI);
-////////////////////////////////
-RID RendererSceneRenderRD::render_buffers_create() {
- RenderBuffers rb;
- rb.data = _create_render_buffer_data();
- return render_buffers_owner.make_rid(rb);
+ sdfgi->debug_probes(p_framebuffer, p_view_count, p_camera_with_transforms, p_will_continue_color, p_will_continue_depth);
}
-void RendererSceneRenderRD::_allocate_blur_textures(RenderBuffers *rb) {
- ERR_FAIL_COND(!rb->blur[0].texture.is_null());
-
- uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH);
-
- RD::TextureFormat tf;
- tf.format = _render_buffers_get_color_format(); // RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- tf.texture_type = rb->view_count > 1 ? RD::TEXTURE_TYPE_2D_ARRAY : RD::TEXTURE_TYPE_2D;
- tf.array_layers = rb->view_count;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- if (_render_buffers_can_be_storage()) {
- tf.usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
- } else {
- tf.usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- }
- tf.mipmaps = mipmaps_required;
-
- rb->sss_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- //the second one is smaller (only used for separatable part of blur)
- tf.width >>= 1;
- tf.height >>= 1;
- tf.mipmaps--;
- rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- for (uint32_t l = 0; l < rb->view_count; l++) {
- RenderBuffers::Blur::Layer ll[2];
- int base_width = rb->internal_width;
- int base_height = rb->internal_height;
-
- for (uint32_t i = 0; i < mipmaps_required; i++) {
- RenderBuffers::Blur::Mipmap mm;
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, l, i);
-
- mm.width = base_width;
- mm.height = base_height;
-
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(mm.texture);
-
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
- }
-
- if (!_render_buffers_can_be_storage()) {
- // and half texture, this is an intermediate result so just allocate a texture, is this good enough?
- tf.width = MAX(1, base_width >> 1);
- tf.height = base_height;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.array_layers = 1;
- tf.mipmaps = 1;
-
- mm.half_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- Vector<RID> half_fb;
- half_fb.push_back(mm.half_texture);
- mm.half_fb = RD::get_singleton()->framebuffer_create(half_fb);
- }
-
- ll[0].mipmaps.push_back(mm);
-
- if (i > 0) {
- mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, l, i - 1);
-
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(mm.texture);
-
- mm.fb = RD::get_singleton()->framebuffer_create(fb);
-
- // We can re-use the half texture here as it is an intermediate result
- }
-
- ll[1].mipmaps.push_back(mm);
- }
-
- base_width = MAX(1, base_width >> 1);
- base_height = MAX(1, base_height >> 1);
- }
+////////////////////////////////
+Ref<RenderSceneBuffers> RendererSceneRenderRD::render_buffers_create() {
+ Ref<RenderSceneBuffersRD> rb;
+ rb.instantiate();
- rb->blur[0].layers.push_back(ll[0]);
- rb->blur[1].layers.push_back(ll[1]);
+ rb->set_can_be_storage(_render_buffers_can_be_storage());
+ rb->set_max_cluster_elements(max_cluster_elements);
+ rb->set_base_data_format(_render_buffers_get_color_format());
+ if (vrs) {
+ rb->set_vrs(vrs);
}
- if (!_render_buffers_can_be_storage()) {
- // create 4 weight textures, 2 full size, 2 half size
-
- tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.array_layers = 1; // Our DOF effect handles one eye per turn
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- tf.mipmaps = 1;
- for (uint32_t i = 0; i < 4; i++) {
- // associated blur texture
- RID texture;
- if (i == 1) {
- texture = rb->blur[0].layers[0].mipmaps[0].texture;
- } else if (i == 2) {
- texture = rb->blur[1].layers[0].mipmaps[0].texture;
- } else if (i == 3) {
- texture = rb->blur[0].layers[0].mipmaps[1].texture;
- }
-
- // create weight texture
- rb->weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ setup_render_buffer_data(rb);
- // create frame buffer
- Vector<RID> fb;
- if (i != 0) {
- fb.push_back(texture);
- }
- fb.push_back(rb->weight_buffers[i].weight);
- rb->weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
-
- if (i == 1) {
- // next 2 are half size
- tf.width = MAX(1u, tf.width >> 1);
- tf.height = MAX(1u, tf.height >> 1);
- }
- }
- }
+ return rb;
}
-void RendererSceneRenderRD::_allocate_depth_backbuffer_textures(RenderBuffers *rb) {
- ERR_FAIL_COND(!rb->depth_back_texture.is_null());
-
- {
- RD::TextureFormat tf;
- if (rb->view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- }
- // We're not using this as a depth stencil, just copying our data into this. May need to look into using a different format on mobile, maybe R16?
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
-
- tf.width = rb->width;
- tf.height = rb->height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
- tf.array_layers = rb->view_count; // create a layer for every view
-
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- tf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; // set this as color attachment because we're copying data into it, it's not actually used as a depth buffer
-
- rb->depth_back_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- if (!_render_buffers_can_be_storage()) {
- // create framebuffer so we can write into this...
-
- Vector<RID> fb;
- fb.push_back(rb->depth_back_texture);
-
- rb->depth_back_fb = RD::get_singleton()->framebuffer_create(fb, RD::INVALID_ID, rb->view_count);
- }
-}
-
-void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
+void RendererSceneRenderRD::_allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb) {
ERR_FAIL_COND(!rb->luminance.current.is_null());
- int w = rb->internal_width;
- int h = rb->internal_height;
+ Size2i internal_size = rb->get_internal_size();
+ int w = internal_size.x;
+ int h = internal_size.y;
while (true) {
w = MAX(w / 8, 1);
@@ -1763,638 +397,38 @@ void RendererSceneRenderRD::_allocate_luminance_textures(RenderBuffers *rb) {
}
}
-void RendererSceneRenderRD::_free_render_buffer_data(RenderBuffers *rb) {
- if (rb->views.size() > 1) { // if 1 these are copies ofs rb->internal_texture, rb->depth_texture and rb->texture_fb
- for (int i = 0; i < rb->views.size(); i++) {
- if (rb->views[i].view_fb.is_valid()) {
- RD::get_singleton()->free(rb->views[i].view_fb);
- }
- if (rb->views[i].view_texture.is_valid()) {
- RD::get_singleton()->free(rb->views[i].view_texture);
- }
- if (rb->views[i].view_depth.is_valid()) {
- RD::get_singleton()->free(rb->views[i].view_depth);
- }
- }
- }
- rb->views.clear();
-
- if (rb->texture_fb.is_valid()) {
- RD::get_singleton()->free(rb->texture_fb);
- rb->texture_fb = RID();
- }
-
- if (rb->internal_texture == rb->texture && rb->internal_texture.is_valid()) {
- RD::get_singleton()->free(rb->internal_texture);
- rb->texture = RID();
- rb->internal_texture = RID();
- rb->upscale_texture = RID();
- } else {
- if (rb->texture.is_valid()) {
- RD::get_singleton()->free(rb->texture);
- rb->texture = RID();
- }
-
- if (rb->internal_texture.is_valid()) {
- RD::get_singleton()->free(rb->internal_texture);
- rb->internal_texture = RID();
- }
-
- if (rb->upscale_texture.is_valid()) {
- RD::get_singleton()->free(rb->upscale_texture);
- rb->upscale_texture = RID();
- }
- }
-
- if (rb->depth_texture.is_valid()) {
- RD::get_singleton()->free(rb->depth_texture);
- rb->depth_texture = RID();
- }
-
- if (rb->depth_back_fb.is_valid()) {
- RD::get_singleton()->free(rb->depth_back_fb);
- rb->depth_back_fb = RID();
- }
-
- if (rb->depth_back_texture.is_valid()) {
- RD::get_singleton()->free(rb->depth_back_texture);
- rb->depth_back_texture = RID();
- }
-
- if (rb->sss_texture.is_valid()) {
- RD::get_singleton()->free(rb->sss_texture);
- rb->sss_texture = RID();
- }
-
- for (int i = 0; i < 2; i++) {
- for (int l = 0; l < rb->blur[i].layers.size(); l++) {
- for (int m = 0; m < rb->blur[i].layers[l].mipmaps.size(); m++) {
- // do we free the texture slice here? or is it enough to free the main texture?
-
- // do free the mobile extra stuff
- if (rb->blur[i].layers[l].mipmaps[m].fb.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].fb);
- }
- // texture and framebuffer in both blur mipmaps are shared, so only free from the first one
- if (i == 0) {
- if (rb->blur[i].layers[l].mipmaps[m].half_fb.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_fb);
- }
- if (rb->blur[i].layers[l].mipmaps[m].half_texture.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].layers[l].mipmaps[m].half_texture);
- }
- }
- }
- }
- rb->blur[i].layers.clear();
-
- if (rb->blur[i].texture.is_valid()) {
- RD::get_singleton()->free(rb->blur[i].texture);
- rb->blur[i].texture = RID();
- }
- }
-
- for (int i = 0; i < rb->luminance.fb.size(); i++) {
- RD::get_singleton()->free(rb->luminance.fb[i]);
- }
- rb->luminance.fb.clear();
-
- for (int i = 0; i < rb->luminance.reduce.size(); i++) {
- RD::get_singleton()->free(rb->luminance.reduce[i]);
- }
- rb->luminance.reduce.clear();
-
- if (rb->luminance.current_fb.is_valid()) {
- RD::get_singleton()->free(rb->luminance.current_fb);
- rb->luminance.current_fb = RID();
- }
-
- if (rb->luminance.current.is_valid()) {
- RD::get_singleton()->free(rb->luminance.current);
- rb->luminance.current = RID();
- }
-
- if (rb->ss_effects.linear_depth.is_valid()) {
- RD::get_singleton()->free(rb->ss_effects.linear_depth);
- rb->ss_effects.linear_depth = RID();
- rb->ss_effects.linear_depth_slices.clear();
- }
-
- if (rb->ss_effects.ssao.ao_final.is_valid()) {
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
-
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
-
- rb->ss_effects.ssao.ao_deinterleaved = RID();
- rb->ss_effects.ssao.ao_pong = RID();
- rb->ss_effects.ssao.ao_final = RID();
- rb->ss_effects.ssao.importance_map[0] = RID();
- rb->ss_effects.ssao.importance_map[1] = RID();
-
- rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
- rb->ss_effects.ssao.ao_pong_slices.clear();
- }
-
- if (rb->ss_effects.ssil.ssil_final.is_valid()) {
- RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
- RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssil.pong);
- RD::get_singleton()->free(rb->ss_effects.ssil.edges);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
-
- rb->ss_effects.ssil.ssil_final = RID();
- rb->ss_effects.ssil.deinterleaved = RID();
- rb->ss_effects.ssil.pong = RID();
- rb->ss_effects.ssil.edges = RID();
- rb->ss_effects.ssil.deinterleaved_slices.clear();
- rb->ss_effects.ssil.pong_slices.clear();
- rb->ss_effects.ssil.edges_slices.clear();
- rb->ss_effects.ssil.importance_map[0] = RID();
- rb->ss_effects.ssil.importance_map[1] = RID();
-
- RD::get_singleton()->free(rb->ss_effects.last_frame);
- rb->ss_effects.last_frame = RID();
- rb->ss_effects.last_frame_slices.clear();
- }
-
- if (rb->ssr.blur_radius[0].is_valid()) {
- RD::get_singleton()->free(rb->ssr.blur_radius[0]);
- RD::get_singleton()->free(rb->ssr.blur_radius[1]);
- rb->ssr.blur_radius[0] = RID();
- rb->ssr.blur_radius[1] = RID();
- }
-
- if (rb->ssr.depth_scaled.is_valid()) {
- RD::get_singleton()->free(rb->ssr.depth_scaled);
- rb->ssr.depth_scaled = RID();
- RD::get_singleton()->free(rb->ssr.normal_scaled);
- rb->ssr.normal_scaled = RID();
- }
-
- if (rb->taa.history.is_valid()) {
- RD::get_singleton()->free(rb->taa.history);
- rb->taa.history = RID();
- }
-
- if (rb->taa.temp.is_valid()) {
- RD::get_singleton()->free(rb->taa.temp);
- rb->taa.temp = RID();
- }
-
- if (rb->taa.prev_velocity.is_valid()) {
- RD::get_singleton()->free(rb->taa.prev_velocity);
- rb->taa.prev_velocity = RID();
- }
-
- if (rb->ambient_buffer.is_valid()) {
- RD::get_singleton()->free(rb->ambient_buffer);
- RD::get_singleton()->free(rb->reflection_buffer);
- rb->ambient_buffer = RID();
- rb->reflection_buffer = RID();
- }
-
- if (rb->gi.voxel_gi_buffer.is_valid()) {
- RD::get_singleton()->free(rb->gi.voxel_gi_buffer);
- rb->gi.voxel_gi_buffer = RID();
- }
-}
-
-void RendererSceneRenderRD::_process_sss(RID p_render_buffers, const CameraMatrix &p_camera) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
-
- bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
-
- if (!can_use_effects) {
- //just copy
- return;
- }
-
- if (rb->blur[0].texture.is_null()) {
- _allocate_blur_textures(rb);
- }
-
- storage->get_effects()->sub_surface_scattering(rb->internal_texture, rb->sss_texture, rb->depth_texture, p_camera, Size2i(rb->internal_width, rb->internal_height), sss_scale, sss_depth_scale, sss_quality);
-}
-
-void RendererSceneRenderRD::_process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
-
- bool can_use_effects = rb->internal_width >= 8 && rb->internal_height >= 8;
-
- if (!can_use_effects) {
- //just copy
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, RID());
- return;
- }
-
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
- ERR_FAIL_COND(!env);
-
- ERR_FAIL_COND(!env->ssr_enabled);
-
- if (rb->ssr.depth_scaled.is_null()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- tf.width = rb->internal_width / 2;
- tf.height = rb->internal_height / 2;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT;
-
- rb->ssr.depth_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
-
- rb->ssr.normal_scaled = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- if (ssr_roughness_quality != RS::ENV_SSR_ROUGHNESS_QUALITY_DISABLED && !rb->ssr.blur_radius[0].is_valid()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->internal_width / 2;
- tf.height = rb->internal_height / 2;
- tf.texture_type = RD::TEXTURE_TYPE_2D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rb->ssr.blur_radius[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->ssr.blur_radius[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- if (rb->blur[0].texture.is_null()) {
- _allocate_blur_textures(rb);
- }
-
- storage->get_effects()->screen_space_reflection(rb->internal_texture, p_normal_buffer, ssr_roughness_quality, rb->ssr.blur_radius[0], rb->ssr.blur_radius[1], p_metallic, p_metallic_mask, rb->depth_texture, rb->ssr.depth_scaled, rb->ssr.normal_scaled, rb->blur[0].layers[0].mipmaps[1].texture, rb->blur[1].layers[0].mipmaps[0].texture, Size2i(rb->internal_width / 2, rb->internal_height / 2), env->ssr_max_steps, env->ssr_fade_in, env->ssr_fade_out, env->ssr_depth_tolerance, p_projection);
- storage->get_effects()->merge_specular(p_dest_framebuffer, p_specular_buffer, p_use_additive ? RID() : rb->internal_texture, rb->blur[0].layers[0].mipmaps[1].texture);
-}
-
-void RendererSceneRenderRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
-
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
- ERR_FAIL_COND(!env);
-
- RENDER_TIMESTAMP("Process SSAO");
-
- if (rb->ss_effects.ssao.ao_final.is_valid() && ssao_using_half_size != ssao_half_size) {
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_pong);
- RD::get_singleton()->free(rb->ss_effects.ssao.ao_final);
-
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssao.importance_map[1]);
-
- rb->ss_effects.ssao.ao_deinterleaved = RID();
- rb->ss_effects.ssao.ao_pong = RID();
- rb->ss_effects.ssao.ao_final = RID();
- rb->ss_effects.ssao.importance_map[0] = RID();
- rb->ss_effects.ssao.importance_map[1] = RID();
- rb->ss_effects.ssao.ao_deinterleaved_slices.clear();
- rb->ss_effects.ssao.ao_pong_slices.clear();
- }
-
- int buffer_width;
- int buffer_height;
- int half_width;
- int half_height;
- if (ssao_half_size) {
- buffer_width = (rb->internal_width + 3) / 4;
- buffer_height = (rb->internal_height + 3) / 4;
- half_width = (rb->internal_width + 7) / 8;
- half_height = (rb->internal_height + 7) / 8;
- } else {
- buffer_width = (rb->internal_width + 1) / 2;
- buffer_height = (rb->internal_height + 1) / 2;
- half_width = (rb->internal_width + 3) / 4;
- half_height = (rb->internal_height + 3) / 4;
- }
- bool uniform_sets_are_invalid = false;
- if (rb->ss_effects.ssao.ao_deinterleaved.is_null()) {
- {
- rb->ss_effects.ssao.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssao_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_deinterleaved, "SSAO De-interleaved Array");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_deinterleaved, i, 0);
- rb->ss_effects.ssao.ao_deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8G8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_pong, "SSAO De-interleaved Array Pong");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssao.ao_pong, i, 0);
- rb->ss_effects.ssao.ao_pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSAO De-interleaved Array Layer " + itos(i) + " Pong");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = half_width;
- tf.height = half_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[0], "SSAO Importance Map");
- rb->ss_effects.ssao.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.importance_map[1], "SSAO Importance Map Pong");
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssao.ao_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssao.ao_final, "SSAO Final");
- }
- ssao_using_half_size = ssao_half_size;
- uniform_sets_are_invalid = true;
- }
-
- EffectsRD::SSAOSettings settings;
- settings.radius = env->ssao_radius;
- settings.intensity = env->ssao_intensity;
- settings.power = env->ssao_power;
- settings.detail = env->ssao_detail;
- settings.horizon = env->ssao_horizon;
- settings.sharpness = env->ssao_sharpness;
-
- settings.quality = ssao_quality;
- settings.half_size = ssao_half_size;
- settings.adaptive_target = ssao_adaptive_target;
- settings.blur_passes = ssao_blur_passes;
- settings.fadeout_from = ssao_fadeout_from;
- settings.fadeout_to = ssao_fadeout_to;
- settings.full_screen_size = Size2i(rb->internal_width, rb->internal_height);
- settings.half_screen_size = Size2i(buffer_width, buffer_height);
- settings.quarter_screen_size = Size2i(half_width, half_height);
-
- storage->get_effects()->generate_ssao(p_normal_buffer, rb->ss_effects.ssao.depth_texture_view, rb->ss_effects.ssao.ao_deinterleaved, rb->ss_effects.ssao.ao_deinterleaved_slices, rb->ss_effects.ssao.ao_pong, rb->ss_effects.ssao.ao_pong_slices, rb->ss_effects.ssao.ao_final, rb->ss_effects.ssao.importance_map[0], rb->ss_effects.ssao.importance_map[1], p_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssao.gather_uniform_set, rb->ss_effects.ssao.importance_map_uniform_set);
-}
-
-void RendererSceneRenderRD::_process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
-
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
- ERR_FAIL_COND(!env);
-
- RENDER_TIMESTAMP("Process SSIL");
-
- if (rb->ss_effects.ssil.ssil_final.is_valid() && ssil_using_half_size != ssil_half_size) {
- RD::get_singleton()->free(rb->ss_effects.ssil.ssil_final);
- RD::get_singleton()->free(rb->ss_effects.ssil.deinterleaved);
- RD::get_singleton()->free(rb->ss_effects.ssil.pong);
- RD::get_singleton()->free(rb->ss_effects.ssil.edges);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[0]);
- RD::get_singleton()->free(rb->ss_effects.ssil.importance_map[1]);
-
- rb->ss_effects.ssil.ssil_final = RID();
- rb->ss_effects.ssil.deinterleaved = RID();
- rb->ss_effects.ssil.pong = RID();
- rb->ss_effects.ssil.edges = RID();
- rb->ss_effects.ssil.deinterleaved_slices.clear();
- rb->ss_effects.ssil.pong_slices.clear();
- rb->ss_effects.ssil.edges_slices.clear();
- rb->ss_effects.ssil.importance_map[0] = RID();
- rb->ss_effects.ssil.importance_map[1] = RID();
- }
-
- int buffer_width;
- int buffer_height;
- int half_width;
- int half_height;
- if (ssil_half_size) {
- buffer_width = (rb->width + 3) / 4;
- buffer_height = (rb->height + 3) / 4;
- half_width = (rb->width + 7) / 8;
- half_height = (rb->height + 7) / 8;
- } else {
- buffer_width = (rb->width + 1) / 2;
- buffer_height = (rb->height + 1) / 2;
- half_width = (rb->width + 3) / 4;
- half_height = (rb->height + 3) / 4;
- }
- bool uniform_sets_are_invalid = false;
- if (rb->ss_effects.ssil.ssil_final.is_null()) {
- {
- rb->ss_effects.ssil.depth_texture_view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, ssil_half_size ? 1 : 0, 4, RD::TEXTURE_SLICE_2D_ARRAY);
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = rb->width;
- tf.height = rb->height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- rb->ss_effects.ssil.ssil_final = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.ssil_final, "SSIL texture");
- RD::get_singleton()->texture_clear(rb->ss_effects.ssil.ssil_final, Color(0, 0, 0, 0), 0, 1, 0, 1);
- if (rb->ss_effects.last_frame.is_null()) {
- tf.mipmaps = 6;
- rb->ss_effects.last_frame = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.last_frame, "Last Frame Radiance");
- RD::get_singleton()->texture_clear(rb->ss_effects.last_frame, Color(0, 0, 0, 0), 0, tf.mipmaps, 0, 1);
- for (uint32_t i = 0; i < 6; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.last_frame, 0, i);
- rb->ss_effects.last_frame_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "Last Frame Radiance Mip " + itos(i) + " ");
- }
- }
- }
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.deinterleaved = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.deinterleaved, "SSIL deinterleaved buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.deinterleaved, i, 0);
- rb->ss_effects.ssil.deinterleaved_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer array " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.pong = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.pong, "SSIL deinterleaved pong buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.pong, i, 0);
- rb->ss_effects.ssil.pong_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL deinterleaved buffer pong array " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = buffer_width;
- tf.height = buffer_height;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.edges = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.edges, "SSIL edges buffer");
- for (uint32_t i = 0; i < 4; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.ssil.edges, i, 0);
- rb->ss_effects.ssil.edges_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SSIL edges buffer slice " + itos(i) + " ");
- }
- }
-
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = half_width;
- tf.height = half_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.ssil.importance_map[0] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[0], "SSIL Importance Map");
- rb->ss_effects.ssil.importance_map[1] = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.ssil.importance_map[1], "SSIL Importance Map Pong");
- }
- uniform_sets_are_invalid = true;
- ssil_using_half_size = ssil_half_size;
- }
-
- EffectsRD::SSILSettings settings;
- settings.radius = env->ssil_radius;
- settings.intensity = env->ssil_intensity;
- settings.sharpness = env->ssil_sharpness;
- settings.normal_rejection = env->ssil_normal_rejection;
-
- settings.quality = ssil_quality;
- settings.half_size = ssil_half_size;
- settings.adaptive_target = ssil_adaptive_target;
- settings.blur_passes = ssil_blur_passes;
- settings.fadeout_from = ssil_fadeout_from;
- settings.fadeout_to = ssil_fadeout_to;
- settings.full_screen_size = Size2i(rb->width, rb->height);
- settings.half_screen_size = Size2i(buffer_width, buffer_height);
- settings.quarter_screen_size = Size2i(half_width, half_height);
-
- CameraMatrix correction;
- correction.set_depth_correction(true);
- CameraMatrix projection = correction * p_projection;
- Transform3D transform = p_transform;
- transform.set_origin(Vector3(0.0, 0.0, 0.0));
- CameraMatrix last_frame_projection = rb->ss_effects.last_frame_projection * CameraMatrix(rb->ss_effects.last_frame_transform.affine_inverse()) * CameraMatrix(transform) * projection.inverse();
-
- storage->get_effects()->screen_space_indirect_lighting(rb->ss_effects.last_frame, rb->ss_effects.ssil.ssil_final, p_normal_buffer, rb->ss_effects.ssil.depth_texture_view, rb->ss_effects.ssil.deinterleaved, rb->ss_effects.ssil.deinterleaved_slices, rb->ss_effects.ssil.pong, rb->ss_effects.ssil.pong_slices, rb->ss_effects.ssil.importance_map[0], rb->ss_effects.ssil.importance_map[1], rb->ss_effects.ssil.edges, rb->ss_effects.ssil.edges_slices, p_projection, last_frame_projection, settings, uniform_sets_are_invalid, rb->ss_effects.ssil.gather_uniform_set, rb->ss_effects.ssil.importance_map_uniform_set, rb->ss_effects.ssil.projection_uniform_set);
- rb->ss_effects.last_frame_projection = projection;
- rb->ss_effects.last_frame_transform = transform;
-}
-
-void RendererSceneRenderRD::_copy_framebuffer_to_ssil(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
-
- if (rb->ss_effects.last_frame.is_valid()) {
- copy_effects->copy_to_rect(rb->texture, rb->ss_effects.last_frame, Rect2i(0, 0, rb->width, rb->height));
-
- int width = rb->width;
- int height = rb->height;
- for (int i = 0; i < rb->ss_effects.last_frame_slices.size() - 1; i++) {
- width = MAX(1, width >> 1);
- height = MAX(1, height >> 1);
- copy_effects->make_mipmap(rb->ss_effects.last_frame_slices[i], rb->ss_effects.last_frame_slices[i + 1], Size2i(width, height));
- }
- }
-}
-
-void RendererSceneRenderRD::_process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
-
- bool just_allocated = false;
- if (rb->taa.history.is_null()) {
- RD::TextureFormat tf;
- if (rb->view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- }
- tf.format = _render_buffers_get_color_format();
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- tf.array_layers = rb->view_count; // create a layer for every view
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
-
- rb->taa.history = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->taa.temp = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- tf.format = RD::DATA_FORMAT_R16G16_SFLOAT;
- rb->taa.prev_velocity = RD::get_singleton()->texture_create(tf, RD::TextureView());
- just_allocated = true;
- }
-
- RD::get_singleton()->draw_command_begin_label("TAA");
- if (!just_allocated) {
- storage->get_effects()->taa_resolve(rb->internal_texture, rb->taa.temp, rb->depth_texture, p_velocity_buffer, rb->taa.prev_velocity, rb->taa.history, Size2(rb->internal_width, rb->internal_height), p_z_near, p_z_far);
- copy_effects->copy_to_rect(rb->taa.temp, rb->internal_texture, Rect2(0, 0, rb->internal_width, rb->internal_height));
- }
-
- copy_effects->copy_to_rect(rb->internal_texture, rb->taa.history, Rect2(0, 0, rb->internal_width, rb->internal_height));
- copy_effects->copy_to_rect(p_velocity_buffer, rb->taa.prev_velocity, Rect2(0, 0, rb->width, rb->height));
- RD::get_singleton()->draw_command_end_label();
-}
-
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(!rb);
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
RD::get_singleton()->draw_command_begin_label("Copy screen texture");
- if (rb->blur[0].texture.is_null()) {
- _allocate_blur_textures(rb);
- }
+ rb->allocate_blur_textures();
bool can_use_storage = _render_buffers_can_be_storage();
+ Size2i size = rb->get_internal_size();
+
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ RID texture = rb->get_internal_texture(v);
+ int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0).mipmaps);
+ RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, 0);
- for (uint32_t v = 0; v < rb->view_count; v++) {
if (can_use_storage) {
- copy_effects->copy_to_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].texture, Rect2i(0, 0, rb->width, rb->height));
- for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) {
- copy_effects->make_mipmap(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].texture, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height));
- }
+ copy_effects->copy_to_rect(texture, dest, Rect2i(0, 0, size.x, size.y));
} else {
- copy_effects->copy_to_fb_rect(rb->views[v].view_texture, rb->blur[0].layers[v].mipmaps[0].fb, Rect2i(0, 0, rb->width, rb->height));
- for (int i = 1; i < rb->blur[0].layers[v].mipmaps.size(); i++) {
- copy_effects->make_mipmap_raster(rb->blur[0].layers[v].mipmaps[i - 1].texture, rb->blur[0].layers[v].mipmaps[i].fb, Size2i(rb->blur[0].layers[v].mipmaps[i].width, rb->blur[0].layers[v].mipmaps[i].height));
+ RID fb = FramebufferCacheRD::get_singleton()->get_cache(dest);
+ copy_effects->copy_to_fb_rect(texture, fb, Rect2i(0, 0, size.x, size.y));
+ }
+
+ for (int i = 1; i < mipmaps; i++) {
+ RID source = dest;
+ dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
+ Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, v, i);
+
+ if (can_use_storage) {
+ copy_effects->make_mipmap(source, dest, msize);
+ } else {
+ copy_effects->make_mipmap_raster(source, dest, msize);
}
}
}
@@ -2403,23 +437,30 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
}
void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(!rb);
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
- if (rb->depth_back_texture.is_null()) {
- _allocate_depth_backbuffer_textures(rb);
- }
+ // note, this only creates our back depth texture if we haven't already created it.
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+ usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; // set this as color attachment because we're copying data into it, it's not actually used as a depth buffer
- // @TODO IMPLEMENT MULTIVIEW, all effects need to support stereo buffers or effects are only applied to the left eye
+ rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, RD::DATA_FORMAT_R32_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1);
bool can_use_storage = _render_buffers_can_be_storage();
+ Size2i size = rb->get_internal_size();
+ for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) {
+ RID depth_texture = rb->get_depth_texture(v);
+ RID depth_back_texture = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, v, 0);
- if (can_use_storage) {
- copy_effects->copy_to_rect(rb->depth_texture, rb->depth_back_texture, Rect2i(0, 0, rb->width, rb->height));
- } else {
- copy_effects->copy_to_fb_rect(rb->depth_texture, rb->depth_back_fb, Rect2i(0, 0, rb->width, rb->height));
+ if (can_use_storage) {
+ copy_effects->copy_to_rect(depth_texture, depth_back_texture, Rect2i(0, 0, size.x, size.y));
+ } else {
+ RID depth_back_fb = FramebufferCacheRD::get_singleton()->get_cache(depth_back_texture);
+ copy_effects->copy_to_fb_rect(depth_texture, depth_back_fb, Rect2i(0, 0, size.x, size.y));
+ }
}
RD::get_singleton()->draw_command_end_label();
@@ -2427,41 +468,44 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
- // Glow and override exposure (if enabled).
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
+
+ // Glow, auto exposure and DoF (if enabled).
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ Size2i internal_size = rb->get_internal_size();
+ Size2i target_size = rb->get_target_size();
+
+ bool can_use_effects = target_size.x >= 8 && target_size.y >= 8; // FIXME I think this should check internal size, we do all our post processing at this size...
bool can_use_storage = _render_buffers_can_be_storage();
- if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) {
+ RID render_target = rb->get_render_target();
+ RID internal_texture = rb->get_internal_texture();
+
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Depth of Field");
RD::get_singleton()->draw_command_begin_label("DOF");
- if (rb->blur[0].texture.is_null()) {
- _allocate_blur_textures(rb);
- }
+
+ rb->allocate_blur_textures();
RendererRD::BokehDOF::BokehBuffers buffers;
// Textures we use
- buffers.base_texture_size = Size2i(rb->internal_width, rb->internal_height);
- buffers.secondary_texture = rb->blur[0].layers[0].mipmaps[0].texture;
- buffers.half_texture[0] = rb->blur[1].layers[0].mipmaps[0].texture;
- buffers.half_texture[1] = rb->blur[0].layers[0].mipmaps[1].texture;
+ buffers.base_texture_size = rb->get_internal_size();
+ buffers.secondary_texture = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0);
+ buffers.half_texture[0] = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
+ buffers.half_texture[1] = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1);
- float bokeh_size = camfx->dof_blur_amount * 64.0;
if (can_use_storage) {
- for (uint32_t i = 0; i < rb->view_count; i++) {
- buffers.base_texture = rb->views[i].view_texture;
- buffers.depth_texture = rb->views[i].view_depth;
+ for (uint32_t i = 0; i < rb->get_view_count(); i++) {
+ buffers.base_texture = rb->get_internal_texture(i);
+ buffers.depth_texture = rb->get_depth_texture(i);
// In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
- float z_near = p_render_data->view_projection[i].get_z_near();
- float z_far = p_render_data->view_projection[i].get_z_far();
- bokeh_dof->bokeh_dof_compute(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, z_near, z_far, p_render_data->cam_orthogonal);
+ float z_near = p_render_data->scene_data->view_projection[i].get_z_near();
+ float z_far = p_render_data->scene_data->view_projection[i].get_z_far();
+ bokeh_dof->bokeh_dof_compute(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->scene_data->cam_orthogonal);
};
} else {
// Set framebuffers.
@@ -2476,35 +520,40 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
// Set weight buffers.
buffers.base_weight_fb = rb->weight_buffers[0].fb;
- for (uint32_t i = 0; i < rb->view_count; i++) {
- buffers.base_texture = rb->views[i].view_texture;
- buffers.depth_texture = rb->views[i].view_depth;
- buffers.base_fb = rb->views[i].view_fb;
+ for (uint32_t i = 0; i < rb->get_view_count(); i++) {
+ buffers.base_texture = rb->get_internal_texture(i);
+ buffers.depth_texture = rb->get_depth_texture(i);
+ buffers.base_fb = FramebufferCacheRD::get_singleton()->get_cache(buffers.base_texture); // TODO move this into bokeh_dof_raster, we can do this internally
// In stereo p_render_data->z_near and p_render_data->z_far can be offset for our combined frustrum
- float z_near = p_render_data->view_projection[i].get_z_near();
- float z_far = p_render_data->view_projection[i].get_z_far();
- bokeh_dof->bokeh_dof_raster(buffers, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, z_near, z_far, p_render_data->cam_orthogonal);
+ float z_near = p_render_data->scene_data->view_projection[i].get_z_near();
+ float z_far = p_render_data->scene_data->view_projection[i].get_z_far();
+ bokeh_dof->bokeh_dof_raster(buffers, p_render_data->camera_attributes, z_near, z_far, p_render_data->scene_data->cam_orthogonal);
}
}
RD::get_singleton()->draw_command_end_label();
}
- if (can_use_effects && env && env->auto_exposure) {
+ float auto_exposure_scale = 1.0;
+
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
RENDER_TIMESTAMP("Auto exposure");
+
RD::get_singleton()->draw_command_begin_label("Auto exposure");
if (rb->luminance.current.is_null()) {
_allocate_luminance_textures(rb);
}
+ uint64_t auto_exposure_version = RSG::camera_attributes->camera_attributes_get_auto_exposure_version(p_render_data->camera_attributes);
+ bool set_immediate = auto_exposure_version != rb->get_auto_exposure_version();
+ rb->set_auto_exposure_version(auto_exposure_version);
- bool set_immediate = env->auto_exposure_version != rb->auto_exposure_version;
- rb->auto_exposure_version = env->auto_exposure_version;
-
- double step = env->auto_exp_speed * time_step;
+ double step = RSG::camera_attributes->camera_attributes_get_auto_exposure_adjust_speed(p_render_data->camera_attributes) * time_step;
+ float auto_exposure_min_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_min_sensitivity(p_render_data->camera_attributes);
+ float auto_exposure_max_sensitivity = RSG::camera_attributes->camera_attributes_get_auto_exposure_max_sensitivity(p_render_data->camera_attributes);
if (can_use_storage) {
- storage->get_effects()->luminance_reduction(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ RendererCompositorRD::singleton->get_effects()->luminance_reduction(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
} else {
- storage->get_effects()->luminance_reduction_raster(rb->internal_texture, Size2i(rb->internal_width, rb->internal_height), rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate);
+ RendererCompositorRD::singleton->get_effects()->luminance_reduction_raster(internal_texture, internal_size, rb->luminance.reduce, rb->luminance.fb, rb->luminance.current, auto_exposure_min_sensitivity, auto_exposure_max_sensitivity, step, set_immediate);
}
// Swap final reduce with prev luminance.
SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]);
@@ -2512,26 +561,25 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
SWAP(rb->luminance.current_fb, rb->luminance.fb.write[rb->luminance.fb.size() - 1]);
}
+ auto_exposure_scale = RSG::camera_attributes->camera_attributes_get_auto_exposure_scale(p_render_data->camera_attributes);
+
RenderingServerDefault::redraw_request(); // Redraw all the time if auto exposure rendering is on.
RD::get_singleton()->draw_command_end_label();
}
int max_glow_level = -1;
- if (can_use_effects && env && env->glow_enabled) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
RENDER_TIMESTAMP("Glow");
RD::get_singleton()->draw_command_begin_label("Gaussian Glow");
- /* see that blur textures are allocated */
-
- if (rb->blur[1].texture.is_null()) {
- _allocate_blur_textures(rb);
- }
+ rb->allocate_blur_textures();
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
- if (env->glow_levels[i] > 0.0) {
- if (i >= rb->blur[1].layers[0].mipmaps.size()) {
- max_glow_level = rb->blur[1].layers[0].mipmaps.size() - 1;
+ if (environment_get_glow_levels(p_render_data->environment)[i] > 0.0) {
+ int mipmaps = int(rb->get_texture_format(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1).mipmaps);
+ if (i >= mipmaps) {
+ max_glow_level = mipmaps - 1;
} else {
max_glow_level = i;
}
@@ -2539,26 +587,32 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
}
float luminance_multiplier = _render_buffers_get_luminance_multiplier();
- for (uint32_t l = 0; l < rb->view_count; l++) {
+ for (uint32_t l = 0; l < rb->get_view_count(); l++) {
for (int i = 0; i < (max_glow_level + 1); i++) {
- int vp_w = rb->blur[1].layers[l].mipmaps[i].width;
- int vp_h = rb->blur[1].layers[l].mipmaps[i].height;
+ Size2i vp_size = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
if (i == 0) {
RID luminance_texture;
- if (env->auto_exposure && rb->luminance.current.is_valid()) {
+ if (RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
luminance_texture = rb->luminance.current;
}
+ RID source = rb->get_internal_texture(l);
+ RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
if (can_use_storage) {
- copy_effects->gaussian_glow(rb->views[l].view_texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
} else {
- copy_effects->gaussian_glow_raster(rb->views[l].view_texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale);
+ RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view
+ copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality, true, environment_get_glow_hdr_luminance_cap(p_render_data->environment), environment_get_exposure(p_render_data->environment), environment_get_glow_bloom(p_render_data->environment), environment_get_glow_hdr_bleed_threshold(p_render_data->environment), environment_get_glow_hdr_bleed_scale(p_render_data->environment), luminance_texture, auto_exposure_scale);
}
} else {
+ RID source = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i - 1);
+ RID dest = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, l, i);
+
if (can_use_storage) {
- copy_effects->gaussian_glow(rb->blur[1].layers[l].mipmaps[i - 1].texture, rb->blur[1].layers[l].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ copy_effects->gaussian_glow(source, dest, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality);
} else {
- copy_effects->gaussian_glow_raster(rb->blur[1].layers[l].mipmaps[i - 1].texture, luminance_multiplier, rb->blur[1].layers[l].mipmaps[i].half_fb, rb->blur[1].layers[l].mipmaps[i].half_texture, rb->blur[1].layers[l].mipmaps[i].fb, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality);
+ RID half = rb->get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, 0, i); // we can reuse this for each view
+ copy_effects->gaussian_glow_raster(source, half, dest, luminance_multiplier, vp_size, environment_get_glow_strength(p_render_data->environment), glow_high_quality);
}
}
}
@@ -2573,154 +627,169 @@ void RendererSceneRenderRD::_render_buffers_post_process_and_tonemap(const Rende
RendererRD::ToneMapper::TonemapSettings tonemap;
- if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) {
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes) && rb->luminance.current.is_valid()) {
tonemap.use_auto_exposure = true;
tonemap.exposure_texture = rb->luminance.current;
- tonemap.auto_exposure_grey = env->auto_exp_scale;
+ tonemap.auto_exposure_scale = auto_exposure_scale;
} else {
- tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
- if (can_use_effects && env && env->glow_enabled) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
tonemap.use_glow = true;
- tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(env->glow_blend_mode);
- tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity;
+ tonemap.glow_mode = RendererRD::ToneMapper::TonemapSettings::GlowMode(environment_get_glow_blend_mode(p_render_data->environment));
+ tonemap.glow_intensity = environment_get_glow_blend_mode(p_render_data->environment) == RS::ENV_GLOW_BLEND_MODE_MIX ? environment_get_glow_mix(p_render_data->environment) : environment_get_glow_intensity(p_render_data->environment);
for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) {
- tonemap.glow_levels[i] = env->glow_levels[i];
+ tonemap.glow_levels[i] = environment_get_glow_levels(p_render_data->environment)[i];
}
- tonemap.glow_texture_size.x = rb->blur[1].layers[0].mipmaps[0].width;
- tonemap.glow_texture_size.y = rb->blur[1].layers[0].mipmaps[0].height;
+
+ Size2i msize = rb->get_texture_slice_size(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
+ tonemap.glow_texture_size.x = msize.width;
+ tonemap.glow_texture_size.y = msize.height;
tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale;
- tonemap.glow_texture = rb->blur[1].texture;
- if (env->glow_map.is_valid()) {
- tonemap.glow_map_strength = env->glow_map_strength;
- tonemap.glow_map = texture_storage->texture_get_rd_texture(env->glow_map);
+ tonemap.glow_texture = rb->get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1);
+ if (environment_get_glow_map(p_render_data->environment).is_valid()) {
+ tonemap.glow_map_strength = environment_get_glow_map_strength(p_render_data->environment);
+ tonemap.glow_map = texture_storage->texture_get_rd_texture(environment_get_glow_map(p_render_data->environment));
} else {
tonemap.glow_map_strength = 0.0f;
- tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
} else {
- tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
- if (rb->screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
+ if (rb->get_screen_space_aa() == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
tonemap.use_fxaa = true;
}
- tonemap.use_debanding = rb->use_debanding;
- tonemap.texture_size = Vector2i(rb->internal_width, rb->internal_height);
+ tonemap.use_debanding = rb->get_use_debanding();
+ tonemap.texture_size = Vector2i(rb->get_internal_size().x, rb->get_internal_size().y);
- if (env) {
- tonemap.tonemap_mode = env->tone_mapper;
- tonemap.white = env->white;
- tonemap.exposure = env->exposure;
- }
-
- if (camfx && camfx->override_exposure_enabled) {
- tonemap.exposure = camfx->override_exposure;
+ if (p_render_data->environment.is_valid()) {
+ tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment);
+ tonemap.white = environment_get_white(p_render_data->environment);
+ tonemap.exposure = environment_get_exposure(p_render_data->environment);
}
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
- tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
-
- if (can_use_effects && env) {
- tonemap.use_bcs = env->adjustments_enabled;
- tonemap.brightness = env->adjustments_brightness;
- tonemap.contrast = env->adjustments_contrast;
- tonemap.saturation = env->adjustments_saturation;
- if (env->adjustments_enabled && env->color_correction.is_valid()) {
+ tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
+
+ if (can_use_effects && p_render_data->environment.is_valid()) {
+ tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment);
+ tonemap.brightness = environment_get_adjustments_brightness(p_render_data->environment);
+ tonemap.contrast = environment_get_adjustments_contrast(p_render_data->environment);
+ tonemap.saturation = environment_get_adjustments_saturation(p_render_data->environment);
+ if (environment_get_adjustments_enabled(p_render_data->environment) && environment_get_color_correction(p_render_data->environment).is_valid()) {
tonemap.use_color_correction = true;
- tonemap.use_1d_color_correction = env->use_1d_color_correction;
- tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
+ tonemap.use_1d_color_correction = environment_get_use_1d_color_correction(p_render_data->environment);
+ tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(environment_get_color_correction(p_render_data->environment));
}
}
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
- tonemap.view_count = p_render_data->view_count;
+ tonemap.view_count = rb->get_view_count();
+
+ RID dest_fb;
+ if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) {
+ // If we use FSR to upscale we need to write our result into an intermediate buffer.
+ // Note that this is cached so we only create the texture the first time.
+ RID dest_texture = rb->create_texture(SNAME("Tonemapper"), SNAME("destination"), _render_buffers_get_color_format(), RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT);
+ dest_fb = FramebufferCacheRD::get_singleton()->get_cache(dest_texture);
+ } else {
+ // If we do a bilinear upscale we just render into our render target and our shader will upscale automatically.
+ // Target size in this case is lying as we never get our real target size communicated.
+ // Bit nasty but...
+ dest_fb = texture_storage->render_target_get_rd_framebuffer(render_target);
+ }
- tone_mapper->tonemapper(rb->internal_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), tonemap);
+ tone_mapper->tonemapper(internal_texture, dest_fb, tonemap);
RD::get_singleton()->draw_command_end_label();
}
- if (can_use_effects && can_use_storage && (rb->internal_width != rb->width || rb->internal_height != rb->height)) {
+ if (fsr && can_use_effects && (internal_size.x != target_size.x || internal_size.y != target_size.y)) {
+ // TODO Investigate? Does this work? We never write into our render target and we've already done so up above in our tonemapper.
+ // I think FSR should either work before our tonemapper or as an alternative of our tonemapper.
+
RD::get_singleton()->draw_command_begin_label("FSR 1.0 Upscale");
- storage->get_effects()->fsr_upscale(rb->internal_texture, rb->upscale_texture, rb->texture, Size2i(rb->internal_width, rb->internal_height), Size2i(rb->width, rb->height), rb->fsr_sharpness);
+ for (uint32_t v = 0; v < rb->get_view_count(); v++) {
+ RID source_texture = rb->get_texture_slice(SNAME("Tonemapper"), SNAME("destination"), v, 0);
+ RID dest_texture = texture_storage->render_target_get_rd_texture_slice(render_target, v);
+
+ fsr->fsr_upscale(rb, source_texture, dest_texture);
+ }
RD::get_singleton()->draw_command_end_label();
}
- texture_storage->render_target_disable_clear_request(rb->render_target);
+ texture_storage->render_target_disable_clear_request(render_target);
}
void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
RD::get_singleton()->draw_command_begin_label("Post Process Subpass");
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(!rb);
-
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
- // Override exposure (if enabled).
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_render_data->camera_effects);
+ Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
+ ERR_FAIL_COND(rb.is_null());
- bool can_use_effects = rb->width >= 8 && rb->height >= 8;
+ // FIXME: Our input it our internal_texture, shouldn't this be using internal_size ??
+ // Seeing we don't support FSR in our mobile renderer right now target_size = internal_size...
+ Size2i target_size = rb->get_target_size();
+ bool can_use_effects = target_size.x >= 8 && target_size.y >= 8;
RD::DrawListID draw_list = RD::get_singleton()->draw_list_switch_to_next_pass();
RendererRD::ToneMapper::TonemapSettings tonemap;
- if (env) {
- tonemap.tonemap_mode = env->tone_mapper;
- tonemap.exposure = env->exposure;
- tonemap.white = env->white;
- }
-
- if (camfx && camfx->override_exposure_enabled) {
- tonemap.exposure = camfx->override_exposure;
+ if (p_render_data->environment.is_valid()) {
+ tonemap.tonemap_mode = environment_get_tone_mapper(p_render_data->environment);
+ tonemap.exposure = environment_get_exposure(p_render_data->environment);
+ tonemap.white = environment_get_white(p_render_data->environment);
}
// We don't support glow or auto exposure here, if they are needed, don't use subpasses!
// The problem is that we need to use the result so far and process them before we can
// apply this to our results.
- if (can_use_effects && env && env->glow_enabled) {
+ if (can_use_effects && p_render_data->environment.is_valid() && environment_get_glow_enabled(p_render_data->environment)) {
ERR_FAIL_MSG("Glow is not supported when using subpasses.");
}
- if (can_use_effects && env && env->auto_exposure) {
- ERR_FAIL_MSG("Glow is not supported when using subpasses.");
+
+ if (can_use_effects && RSG::camera_attributes->camera_attributes_uses_auto_exposure(p_render_data->camera_attributes)) {
+ ERR_FAIL_MSG("Auto Exposure is not supported when using subpasses.");
}
tonemap.use_glow = false;
- tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
- tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.glow_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ tonemap.glow_map = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
tonemap.use_auto_exposure = false;
- tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_WHITE);
+ tonemap.exposure_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
tonemap.use_color_correction = false;
tonemap.use_1d_color_correction = false;
- tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_3D_WHITE);
-
- if (can_use_effects && env) {
- tonemap.use_bcs = env->adjustments_enabled;
- tonemap.brightness = env->adjustments_brightness;
- tonemap.contrast = env->adjustments_contrast;
- tonemap.saturation = env->adjustments_saturation;
- if (env->adjustments_enabled && env->color_correction.is_valid()) {
+ tonemap.color_correction_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
+
+ if (can_use_effects && p_render_data->environment.is_valid()) {
+ tonemap.use_bcs = environment_get_adjustments_enabled(p_render_data->environment);
+ tonemap.brightness = environment_get_adjustments_brightness(p_render_data->environment);
+ tonemap.contrast = environment_get_adjustments_contrast(p_render_data->environment);
+ tonemap.saturation = environment_get_adjustments_saturation(p_render_data->environment);
+ if (environment_get_adjustments_enabled(p_render_data->environment) && environment_get_color_correction(p_render_data->environment).is_valid()) {
tonemap.use_color_correction = true;
- tonemap.use_1d_color_correction = env->use_1d_color_correction;
- tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(env->color_correction);
+ tonemap.use_1d_color_correction = environment_get_use_1d_color_correction(p_render_data->environment);
+ tonemap.color_correction_texture = texture_storage->texture_get_rd_texture(environment_get_color_correction(p_render_data->environment));
}
}
- tonemap.use_debanding = rb->use_debanding;
- tonemap.texture_size = Vector2i(rb->width, rb->height);
+ tonemap.use_debanding = rb->get_use_debanding();
+ tonemap.texture_size = Vector2i(target_size.x, target_size.y);
tonemap.luminance_multiplier = _render_buffers_get_luminance_multiplier();
- tonemap.view_count = p_render_data->view_count;
+ tonemap.view_count = rb->get_view_count();
tone_mapper->tonemapper(draw_list, p_source_texture, RD::get_singleton()->framebuffer_get_format(p_framebuffer), tonemap);
@@ -2728,38 +797,38 @@ void RendererSceneRenderRD::_post_process_subpass(RID p_source_texture, RID p_fr
}
void RendererSceneRenderRD::_disable_clear_request(const RenderDataRD *p_render_data) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(!rb);
+ ERR_FAIL_COND(p_render_data->render_buffers.is_null());
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- texture_storage->render_target_disable_clear_request(rb->render_target);
+ texture_storage->render_target_disable_clear_request(p_render_data->render_buffers->get_render_target());
}
-void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
+void RendererSceneRenderRD::_render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer) {
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
+ ERR_FAIL_COND(p_render_buffers.is_null());
+
+ RID render_target = p_render_buffers->get_render_target();
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) {
if (p_shadow_atlas.is_valid()) {
- RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas);
+ RID shadow_atlas_texture = RendererRD::LightStorage::get_singleton()->shadow_atlas_get_texture(p_shadow_atlas);
if (shadow_atlas_texture.is_null()) {
- shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK);
+ shadow_atlas_texture = texture_storage->texture_rd_get_default(RendererRD::TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
}
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) {
- if (directional_shadow_get_texture().is_valid()) {
- RID shadow_atlas_texture = directional_shadow_get_texture();
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ if (RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture().is_valid()) {
+ RID shadow_atlas_texture = RendererRD::LightStorage::get_singleton()->directional_shadow_get_texture();
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
- copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, true);
+ copy_effects->copy_to_fb_rect(shadow_atlas_texture, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, true);
}
}
@@ -2767,258 +836,42 @@ void RendererSceneRenderRD::_render_buffers_debug_draw(RID p_render_buffers, RID
RID decal_atlas = RendererRD::TextureStorage::get_singleton()->decal_atlas_get_texture();
if (decal_atlas.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
- copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
+ copy_effects->copy_to_fb_rect(decal_atlas, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize / 2), false, false, true);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) {
- if (rb->luminance.current.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
+ if (p_render_buffers->luminance.current.is_valid()) {
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
- copy_effects->copy_to_fb_rect(rb->luminance.current, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true);
+ copy_effects->copy_to_fb_rect(p_render_buffers->luminance.current, texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize / 8), false, true);
}
}
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ss_effects.ssao.ao_final.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- copy_effects->copy_to_fb_rect(rb->ss_effects.ssao.ao_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true);
- }
-
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSIL && rb->ss_effects.ssil.ssil_final.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- copy_effects->copy_to_fb_rect(rb->ss_effects.ssil.ssil_final, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
- }
-
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
- }
-
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_GI_BUFFER && rb->ambient_buffer.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- RID ambient_texture = rb->ambient_buffer;
- RID reflection_texture = rb->reflection_buffer;
- copy_effects->copy_to_fb_rect(ambient_texture, texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false, false, true, reflection_texture);
+ Size2 rtsize = texture_storage->render_target_get_size(render_target);
+ copy_effects->copy_to_fb_rect(_render_buffers_get_normal_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_OCCLUDERS) {
if (p_occlusion_buffer.is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2i(Vector2(), rtsize), true, false);
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
+ copy_effects->copy_to_fb_rect(texture_storage->texture_get_rd_texture(p_occlusion_buffer), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2i(Vector2(), rtsize), true, false);
}
}
if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_MOTION_VECTORS && _render_buffers_get_velocity_texture(p_render_buffers).is_valid()) {
- Size2 rtsize = texture_storage->render_target_get_size(rb->render_target);
- copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, false);
- }
-}
-
-void RendererSceneRenderRD::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_env);
- ERR_FAIL_COND(!env);
-
- env->adjustments_enabled = p_enable;
- env->adjustments_brightness = p_brightness;
- env->adjustments_contrast = p_contrast;
- env->adjustments_saturation = p_saturation;
- env->use_1d_color_correction = p_use_1d_color_correction;
- env->color_correction = p_color_correction;
-}
-
-RID RendererSceneRenderRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
- if (!rb->blur[0].texture.is_valid()) {
- return RID(); //not valid at the moment
- }
- return rb->blur[0].texture;
-}
-
-RID RendererSceneRenderRD::render_buffers_get_back_depth_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
- if (!rb->depth_back_texture.is_valid()) {
- return RID(); //not valid at the moment
+ Size2i rtsize = texture_storage->render_target_get_size(render_target);
+ copy_effects->copy_to_fb_rect(_render_buffers_get_velocity_texture(p_render_buffers), texture_storage->render_target_get_rd_framebuffer(render_target), Rect2(Vector2(), rtsize), false, false);
}
- return rb->depth_back_texture;
-}
-
-RID RendererSceneRenderRD::render_buffers_get_depth_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
-
- return rb->depth_texture;
-}
-
-RID RendererSceneRenderRD::render_buffers_get_ao_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
-
- return rb->ss_effects.ssao.ao_final;
-}
-RID RendererSceneRenderRD::render_buffers_get_ssil_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
-
- return rb->ss_effects.ssil.ssil_final;
-}
-
-RID RendererSceneRenderRD::render_buffers_get_voxel_gi_buffer(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
- if (rb->gi.voxel_gi_buffer.is_null()) {
- rb->gi.voxel_gi_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(RendererSceneGIRD::VoxelGIData) * RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES);
- }
- return rb->gi.voxel_gi_buffer;
}
RID RendererSceneRenderRD::render_buffers_get_default_voxel_gi_buffer() {
return gi.default_voxel_gi_buffer;
}
-RID RendererSceneRenderRD::render_buffers_get_gi_ambient_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
- return rb->ambient_buffer;
-}
-RID RendererSceneRenderRD::render_buffers_get_gi_reflection_texture(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
- return rb->reflection_buffer;
-}
-
-uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, 0);
- ERR_FAIL_COND_V(!rb->sdfgi, 0);
-
- return rb->sdfgi->cascades.size();
-}
-bool RendererSceneRenderRD::render_buffers_is_sdfgi_enabled(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, false);
-
- return rb->sdfgi != nullptr;
-}
-RID RendererSceneRenderRD::render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
- ERR_FAIL_COND_V(!rb->sdfgi, RID());
-
- return rb->sdfgi->lightprobe_texture;
-}
-
-Vector3 RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, Vector3());
- ERR_FAIL_COND_V(!rb->sdfgi, Vector3());
- ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3());
-
- return Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + rb->sdfgi->cascades[p_cascade].position)) * rb->sdfgi->cascades[p_cascade].cell_size;
-}
-
-Vector3i RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, Vector3i());
- ERR_FAIL_COND_V(!rb->sdfgi, Vector3i());
- ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), Vector3i());
- int32_t probe_divisor = rb->sdfgi->cascade_size / RendererSceneGIRD::SDFGI::PROBE_DIVISOR;
-
- return rb->sdfgi->cascades[p_cascade].position / probe_divisor;
-}
-
-float RendererSceneRenderRD::render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, 0);
- ERR_FAIL_COND_V(!rb->sdfgi, 0);
-
- return rb->sdfgi->normal_bias;
-}
-float RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, 0);
- ERR_FAIL_COND_V(!rb->sdfgi, 0);
- ERR_FAIL_UNSIGNED_INDEX_V(p_cascade, rb->sdfgi->cascades.size(), 0);
-
- return float(rb->sdfgi->cascade_size) * rb->sdfgi->cascades[p_cascade].cell_size / float(rb->sdfgi->probe_axis_count - 1);
-}
-uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, 0);
- ERR_FAIL_COND_V(!rb->sdfgi, 0);
-
- return rb->sdfgi->probe_axis_count;
-}
-
-uint32_t RendererSceneRenderRD::render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, 0);
- ERR_FAIL_COND_V(!rb->sdfgi, 0);
-
- return rb->sdfgi->cascade_size;
-}
-
-bool RendererSceneRenderRD::render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, false);
- ERR_FAIL_COND_V(!rb->sdfgi, false);
-
- return rb->sdfgi->uses_occlusion;
-}
-
-float RendererSceneRenderRD::render_buffers_get_sdfgi_energy(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, 0.0);
- ERR_FAIL_COND_V(!rb->sdfgi, 0.0);
-
- return rb->sdfgi->energy;
-}
-RID RendererSceneRenderRD::render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
- ERR_FAIL_COND_V(!rb->sdfgi, RID());
-
- return rb->sdfgi->occlusion_texture;
-}
-
-bool RendererSceneRenderRD::render_buffers_has_volumetric_fog(RID p_render_buffers) const {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, false);
-
- return rb->volumetric_fog != nullptr;
-}
-RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_texture(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, RID());
-
- return rb->volumetric_fog->fog_map;
-}
-
-RID RendererSceneRenderRD::render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, RID());
-
- if (!rb->volumetric_fog) {
- return RID();
- }
-
- return rb->volumetric_fog->sky_uniform_set;
-}
-
-float RendererSceneRenderRD::render_buffers_get_volumetric_fog_end(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0);
- return rb->volumetric_fog->length;
-}
-float RendererSceneRenderRD::render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers) {
- const RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb || !rb->volumetric_fog, 0);
- return rb->volumetric_fog->spread;
-}
-
float RendererSceneRenderRD::_render_buffers_get_luminance_multiplier() {
return 1.0;
}
@@ -3031,160 +884,11 @@ bool RendererSceneRenderRD::_render_buffers_can_be_storage() {
return true;
}
-void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
- ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
-
- if (!_render_buffers_can_be_storage()) {
- p_internal_height = p_height;
- p_internal_width = p_width;
- }
-
- if (p_width != p_internal_width) {
- float fsr_mipmap_bias = -log2f(p_width / p_internal_width) + p_fsr_mipmap_bias;
- material_storage->sampler_rd_configure_custom(fsr_mipmap_bias);
- update_uniform_sets();
- }
-
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
-
- // Should we add an overrule per viewport?
- rb->internal_width = p_internal_width;
- rb->internal_height = p_internal_height;
- rb->width = p_width;
- rb->height = p_height;
- rb->fsr_sharpness = p_fsr_sharpness;
- rb->render_target = p_render_target;
- rb->msaa = p_msaa;
- rb->screen_space_aa = p_screen_space_aa;
- rb->use_taa = p_use_taa;
- rb->use_debanding = p_use_debanding;
- rb->view_count = p_view_count;
-
- if (is_clustered_enabled()) {
- if (rb->cluster_builder == nullptr) {
- rb->cluster_builder = memnew(ClusterBuilderRD);
- }
- rb->cluster_builder->set_shared(&cluster_builder_shared);
- }
-
- _free_render_buffer_data(rb);
-
- {
- RD::TextureFormat tf;
- if (rb->view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- }
- tf.format = _render_buffers_get_color_format();
- tf.width = rb->internal_width; // If set to rb->width, msaa won't crash
- tf.height = rb->internal_height; // If set to rb->width, msaa won't crash
- tf.array_layers = rb->view_count; // create a layer for every view
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
- if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- }
- tf.usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
-
- rb->internal_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
-
- if ((p_internal_width != p_width || p_internal_height != p_height)) {
- tf.width = rb->width;
- tf.height = rb->height;
- rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- rb->upscale_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- } else {
- rb->texture = rb->internal_texture;
- rb->upscale_texture = rb->internal_texture;
- }
- }
-
- {
- RD::TextureFormat tf;
- if (rb->view_count > 1) {
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- }
- if (rb->msaa == RS::VIEWPORT_MSAA_DISABLED) {
- tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
- } else {
- tf.format = RD::DATA_FORMAT_R32_SFLOAT;
- }
-
- tf.width = rb->internal_width;
- tf.height = rb->internal_height;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
- tf.array_layers = rb->view_count; // create a layer for every view
-
- if (rb->msaa != RS::VIEWPORT_MSAA_DISABLED) {
- tf.usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- } else {
- tf.usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
- }
-
- rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
-
- {
- if (!_render_buffers_can_be_storage()) {
- // ONLY USED ON MOBILE RENDERER, ONLY USED FOR POST EFFECTS!
- Vector<RID> fb;
- fb.push_back(rb->internal_texture);
-
- rb->texture_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, rb->view_count);
- }
-
- rb->views.clear(); // JIC
- if (rb->view_count == 1) {
- // copy as a convenience
- RenderBuffers::View view;
- view.view_texture = rb->internal_texture;
- view.view_depth = rb->depth_texture;
- view.view_fb = rb->texture_fb;
- rb->views.push_back(view);
- } else {
- for (uint32_t i = 0; i < rb->view_count; i++) {
- RenderBuffers::View view;
- view.view_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->internal_texture, i, 0);
- view.view_depth = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->depth_texture, i, 0);
-
- if (!_render_buffers_can_be_storage()) {
- Vector<RID> fb;
- fb.push_back(view.view_texture);
- view.view_fb = RD::get_singleton()->framebuffer_create(fb, RenderingDevice::INVALID_ID, 1);
- }
-
- rb->views.push_back(view);
- }
- }
- }
-
- RID target_texture = texture_storage->render_target_get_rd_texture(rb->render_target);
- rb->data->configure(rb->internal_texture, rb->depth_texture, target_texture, p_internal_width, p_internal_height, p_msaa, p_use_taa, p_view_count);
-
- if (is_clustered_enabled()) {
- rb->cluster_builder->setup(Size2i(p_internal_width, p_internal_height), max_cluster_elements, rb->depth_texture, RendererRD::MaterialStorage::get_singleton()->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED), rb->internal_texture);
- }
-}
-
void RendererSceneRenderRD::gi_set_use_half_resolution(bool p_enable) {
gi.half_resolution = p_enable;
}
-void RendererSceneRenderRD::sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) {
- sss_quality = p_quality;
-}
-
-RS::SubSurfaceScatteringQuality RendererSceneRenderRD::sub_surface_scattering_get_quality() const {
- return sss_quality;
-}
-
-void RendererSceneRenderRD::sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) {
- sss_scale = p_scale;
- sss_depth_scale = p_depth_scale;
-}
-
-void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
+void RendererSceneRenderRD::positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
if (shadows_quality != p_quality) {
@@ -3231,7 +935,7 @@ void RendererSceneRenderRD::shadows_quality_set(RS::ShadowQuality p_quality) {
_update_shader_quality_settings();
}
-void RendererSceneRenderRD::directional_shadow_quality_set(RS::ShadowQuality p_quality) {
+void RendererSceneRenderRD::directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) {
ERR_FAIL_INDEX_MSG(p_quality, RS::SHADOW_QUALITY_MAX, "Shadow quality too high, please see RenderingServer's ShadowQuality enum");
if (directional_shadow_quality != p_quality) {
@@ -3301,1600 +1005,36 @@ bool RendererSceneRenderRD::is_using_radiance_cubemap_array() const {
return sky.sky_use_cubemap_array;
}
-RendererSceneRenderRD::RenderBufferData *RendererSceneRenderRD::render_buffers_get_data(RID p_render_buffers) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND_V(!rb, nullptr);
- return rb->data;
-}
-
-void RendererSceneRenderRD::_setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
- RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
- cluster.reflection_count = 0;
-
- for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
- if (cluster.reflection_count == cluster.max_reflections) {
- break;
- }
-
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_reflections[i]);
- if (!rpi) {
- continue;
- }
-
- cluster.reflection_sort[cluster.reflection_count].instance = rpi;
- cluster.reflection_sort[cluster.reflection_count].depth = -p_camera_inverse_transform.xform(rpi->transform.origin).z;
- cluster.reflection_count++;
- }
-
- if (cluster.reflection_count > 0) {
- SortArray<Cluster::InstanceSort<ReflectionProbeInstance>> sort_array;
- sort_array.sort(cluster.reflection_sort, cluster.reflection_count);
- }
-
- bool using_forward_ids = _uses_forward_ids();
- for (uint32_t i = 0; i < cluster.reflection_count; i++) {
- ReflectionProbeInstance *rpi = cluster.reflection_sort[i].instance;
-
- if (using_forward_ids) {
- _map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i);
- }
-
- RID base_probe = rpi->probe;
-
- Cluster::ReflectionData &reflection_ubo = cluster.reflections[i];
-
- Vector3 extents = light_storage->reflection_probe_get_extents(base_probe);
-
- rpi->cull_mask = light_storage->reflection_probe_get_cull_mask(base_probe);
-
- reflection_ubo.box_extents[0] = extents.x;
- reflection_ubo.box_extents[1] = extents.y;
- reflection_ubo.box_extents[2] = extents.z;
- reflection_ubo.index = rpi->atlas_index;
-
- Vector3 origin_offset = light_storage->reflection_probe_get_origin_offset(base_probe);
-
- reflection_ubo.box_offset[0] = origin_offset.x;
- reflection_ubo.box_offset[1] = origin_offset.y;
- reflection_ubo.box_offset[2] = origin_offset.z;
- reflection_ubo.mask = light_storage->reflection_probe_get_cull_mask(base_probe);
-
- reflection_ubo.intensity = light_storage->reflection_probe_get_intensity(base_probe);
- reflection_ubo.ambient_mode = light_storage->reflection_probe_get_ambient_mode(base_probe);
-
- reflection_ubo.exterior = !light_storage->reflection_probe_is_interior(base_probe);
- reflection_ubo.box_project = light_storage->reflection_probe_is_box_projection(base_probe);
-
- Color ambient_linear = light_storage->reflection_probe_get_ambient_color(base_probe).srgb_to_linear();
- float interior_ambient_energy = light_storage->reflection_probe_get_ambient_color_energy(base_probe);
- reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
- reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
- reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
-
- Transform3D transform = rpi->transform;
- Transform3D proj = (p_camera_inverse_transform * transform).inverse();
- RendererStorageRD::store_transform(proj, reflection_ubo.local_matrix);
-
- if (current_cluster_builder != nullptr) {
- current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_REFLECTION_PROBE, transform, extents);
- }
-
- rpi->last_pass = RSG::rasterizer->get_frame_number();
- }
-
- if (cluster.reflection_count) {
- RD::get_singleton()->buffer_update(cluster.reflection_buffer, 0, cluster.reflection_count * sizeof(Cluster::ReflectionData), cluster.reflections, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
- }
-}
-
-void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
-
- Transform3D inverse_transform = p_camera_transform.affine_inverse();
-
- r_directional_light_count = 0;
- r_positional_light_count = 0;
-
- Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
-
- cluster.omni_light_count = 0;
- cluster.spot_light_count = 0;
-
- r_directional_light_soft_shadows = false;
-
- for (int i = 0; i < (int)p_lights.size(); i++) {
- LightInstance *li = light_instance_owner.get_or_null(p_lights[i]);
- if (!li) {
- continue;
- }
- RID base = li->light;
-
- ERR_CONTINUE(base.is_null());
-
- RS::LightType type = light_storage->light_get_type(base);
- switch (type) {
- case RS::LIGHT_DIRECTIONAL: {
- if (r_directional_light_count >= cluster.max_directional_lights || light_storage->light_directional_get_sky_mode(base) == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
- continue;
- }
-
- Cluster::DirectionalLightData &light_data = cluster.directional_lights[r_directional_light_count];
-
- Transform3D light_transform = li->transform;
-
- Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
-
- light_data.direction[0] = direction.x;
- light_data.direction[1] = direction.y;
- light_data.direction[2] = direction.z;
-
- float sign = light_storage->light_is_negative(base) ? -1 : 1;
-
- light_data.energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI;
-
- Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
- light_data.color[0] = linear_col.r;
- light_data.color[1] = linear_col.g;
- light_data.color[2] = linear_col.b;
-
- light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR);
- light_data.mask = light_storage->light_get_cull_mask(base);
-
- float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
-
- light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset
-
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
- WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
- }
-
- light_data.shadow_enabled = p_using_shadows && light_storage->light_has_shadow(base);
-
- float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
- if (angular_diameter > 0.0) {
- // I know tan(0) is 0, but let's not risk it with numerical precision.
- // technically this will keep expanding until reaching the sun, but all we care
- // is expand until we reach the radius of the near plane (there can't be more occluders than that)
- angular_diameter = Math::tan(Math::deg2rad(angular_diameter));
- if (light_storage->light_has_shadow(base)) {
- r_directional_light_soft_shadows = true;
- }
- } else {
- angular_diameter = 0.0;
- }
-
- if (light_data.shadow_enabled) {
- RS::LightDirectionalShadowMode smode = light_storage->light_directional_get_shadow_mode(base);
-
- int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
- light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light_storage->light_directional_get_blend_splits(base);
- for (int j = 0; j < 4; j++) {
- Rect2 atlas_rect = li->shadow_transform[j].atlas_rect;
- CameraMatrix matrix = li->shadow_transform[j].camera;
- float split = li->shadow_transform[MIN(limit, j)].split;
-
- CameraMatrix bias;
- bias.set_light_bias();
- CameraMatrix rectm;
- rectm.set_light_atlas_rect(atlas_rect);
-
- Transform3D modelview = (inverse_transform * li->shadow_transform[j].transform).inverse();
-
- CameraMatrix shadow_mtx = rectm * bias * matrix * modelview;
- light_data.shadow_split_offsets[j] = split;
- float bias_scale = li->shadow_transform[j].bias_scale;
- light_data.shadow_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0 * bias_scale;
- light_data.shadow_normal_bias[j] = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * li->shadow_transform[j].shadow_texel_size;
- light_data.shadow_transmittance_bias[j] = light_storage->light_get_transmittance_bias(base) * bias_scale;
- light_data.shadow_z_range[j] = li->shadow_transform[j].farplane;
- light_data.shadow_range_begin[j] = li->shadow_transform[j].range_begin;
- RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
-
- Vector2 uv_scale = li->shadow_transform[j].uv_scale;
- uv_scale *= atlas_rect.size; //adapt to atlas size
- switch (j) {
- case 0: {
- light_data.uv_scale1[0] = uv_scale.x;
- light_data.uv_scale1[1] = uv_scale.y;
- } break;
- case 1: {
- light_data.uv_scale2[0] = uv_scale.x;
- light_data.uv_scale2[1] = uv_scale.y;
- } break;
- case 2: {
- light_data.uv_scale3[0] = uv_scale.x;
- light_data.uv_scale3[1] = uv_scale.y;
- } break;
- case 3: {
- light_data.uv_scale4[0] = uv_scale.x;
- light_data.uv_scale4[1] = uv_scale.y;
- } break;
- }
- }
-
- float fade_start = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START);
- light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
- light_data.fade_to = -light_data.shadow_split_offsets[3];
- light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
-
- light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
- light_data.softshadow_angle = angular_diameter;
- light_data.bake_mode = light_storage->light_get_bake_mode(base);
-
- if (angular_diameter <= 0.0) {
- light_data.soft_shadow_scale *= directional_shadow_quality_radius_get(); // Only use quality radius for PCF
- }
- }
-
- r_directional_light_count++;
- } break;
- case RS::LIGHT_OMNI: {
- if (cluster.omni_light_count >= cluster.max_lights) {
- continue;
- }
-
- const real_t distance = camera_plane.distance_to(li->transform.origin);
-
- if (light_storage->light_is_distance_fade_enabled(li->light)) {
- const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
- const float fade_length = light_storage->light_get_distance_fade_length(li->light);
-
- if (distance > fade_begin) {
- if (distance > fade_begin + fade_length) {
- // Out of range, don't draw this light to improve performance.
- continue;
- }
- }
- }
-
- cluster.omni_light_sort[cluster.omni_light_count].instance = li;
- cluster.omni_light_sort[cluster.omni_light_count].depth = distance;
- cluster.omni_light_count++;
- } break;
- case RS::LIGHT_SPOT: {
- if (cluster.spot_light_count >= cluster.max_lights) {
- continue;
- }
-
- const real_t distance = camera_plane.distance_to(li->transform.origin);
-
- if (light_storage->light_is_distance_fade_enabled(li->light)) {
- const float fade_begin = light_storage->light_get_distance_fade_begin(li->light);
- const float fade_length = light_storage->light_get_distance_fade_length(li->light);
-
- if (distance > fade_begin) {
- if (distance > fade_begin + fade_length) {
- // Out of range, don't draw this light to improve performance.
- continue;
- }
- }
- }
-
- cluster.spot_light_sort[cluster.spot_light_count].instance = li;
- cluster.spot_light_sort[cluster.spot_light_count].depth = distance;
- cluster.spot_light_count++;
- } break;
- }
-
- li->last_pass = RSG::rasterizer->get_frame_number();
- }
-
- if (cluster.omni_light_count) {
- SortArray<Cluster::InstanceSort<LightInstance>> sorter;
- sorter.sort(cluster.omni_light_sort, cluster.omni_light_count);
- }
-
- if (cluster.spot_light_count) {
- SortArray<Cluster::InstanceSort<LightInstance>> sorter;
- sorter.sort(cluster.spot_light_sort, cluster.spot_light_count);
- }
-
- ShadowAtlas *shadow_atlas = nullptr;
-
- if (p_shadow_atlas.is_valid() && p_using_shadows) {
- shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
- }
-
- bool using_forward_ids = _uses_forward_ids();
-
- for (uint32_t i = 0; i < (cluster.omni_light_count + cluster.spot_light_count); i++) {
- uint32_t index = (i < cluster.omni_light_count) ? i : i - (cluster.omni_light_count);
- Cluster::LightData &light_data = (i < cluster.omni_light_count) ? cluster.omni_lights[index] : cluster.spot_lights[index];
- RS::LightType type = (i < cluster.omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
- LightInstance *li = (i < cluster.omni_light_count) ? cluster.omni_light_sort[index].instance : cluster.spot_light_sort[index].instance;
- RID base = li->light;
-
- if (using_forward_ids) {
- _map_forward_id(type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, li->forward_id, index);
- }
-
- Transform3D light_transform = li->transform;
-
- float sign = light_storage->light_is_negative(base) ? -1 : 1;
- Color linear_col = light_storage->light_get_color(base).srgb_to_linear();
-
- light_data.attenuation = light_storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION);
-
- // Reuse fade begin, fade length and distance for shadow LOD determination later.
- float fade_begin = 0.0;
- float fade_length = 0.0;
- real_t distance = 0.0;
-
- float fade = 1.0;
- if (light_storage->light_is_distance_fade_enabled(li->light)) {
- fade_begin = light_storage->light_get_distance_fade_begin(li->light);
- fade_length = light_storage->light_get_distance_fade_length(li->light);
- distance = camera_plane.distance_to(li->transform.origin);
-
- if (distance > fade_begin) {
- // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
- fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
- }
- }
-
- float energy = sign * light_storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI * fade;
-
- light_data.color[0] = linear_col.r * energy;
- light_data.color[1] = linear_col.g * energy;
- light_data.color[2] = linear_col.b * energy;
- light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0;
- light_data.bake_mode = light_storage->light_get_bake_mode(base);
-
- float radius = MAX(0.001, light_storage->light_get_param(base, RS::LIGHT_PARAM_RANGE));
- light_data.inv_radius = 1.0 / radius;
-
- Vector3 pos = inverse_transform.xform(light_transform.origin);
-
- light_data.position[0] = pos.x;
- light_data.position[1] = pos.y;
- light_data.position[2] = pos.z;
-
- Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized();
-
- light_data.direction[0] = direction.x;
- light_data.direction[1] = direction.y;
- light_data.direction[2] = direction.z;
-
- float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE);
-
- light_data.size = size;
-
- light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION);
- float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE);
- light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle));
-
- light_data.mask = light_storage->light_get_cull_mask(base);
-
- light_data.atlas_rect[0] = 0;
- light_data.atlas_rect[1] = 0;
- light_data.atlas_rect[2] = 0;
- light_data.atlas_rect[3] = 0;
-
- RID projector = light_storage->light_get_projector(base);
-
- if (projector.is_valid()) {
- Rect2 rect = texture_storage->decal_atlas_get_texture_rect(projector);
-
- if (type == RS::LIGHT_SPOT) {
- light_data.projector_rect[0] = rect.position.x;
- light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped
- light_data.projector_rect[2] = rect.size.width;
- light_data.projector_rect[3] = -rect.size.height;
- } else {
- light_data.projector_rect[0] = rect.position.x;
- light_data.projector_rect[1] = rect.position.y;
- light_data.projector_rect[2] = rect.size.width;
- light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half
- }
- } else {
- light_data.projector_rect[0] = 0;
- light_data.projector_rect[1] = 0;
- light_data.projector_rect[2] = 0;
- light_data.projector_rect[3] = 0;
- }
-
- const bool needs_shadow = shadow_atlas && shadow_atlas->shadow_owners.has(li->self);
-
- bool in_shadow_range = true;
- if (needs_shadow && light_storage->light_is_distance_fade_enabled(li->light)) {
- if (distance > light_storage->light_get_distance_fade_shadow(li->light)) {
- // Out of range, don't draw shadows to improve performance.
- in_shadow_range = false;
- }
- }
-
- if (needs_shadow && in_shadow_range) {
- // fill in the shadow information
-
- light_data.shadow_enabled = true;
-
- float shadow_texel_size = light_instance_get_shadow_texel_size(li->self, p_shadow_atlas);
- light_data.shadow_normal_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * shadow_texel_size * 10.0;
-
- if (type == RS::LIGHT_SPOT) {
- light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS) / 100.0;
- } else { //omni
- light_data.shadow_bias = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BIAS);
- }
-
- light_data.transmittance_bias = light_storage->light_get_transmittance_bias(base);
-
- Vector2i omni_offset;
- Rect2 rect = light_instance_get_shadow_atlas_rect(li->self, p_shadow_atlas, omni_offset);
-
- light_data.atlas_rect[0] = rect.position.x;
- light_data.atlas_rect[1] = rect.position.y;
- light_data.atlas_rect[2] = rect.size.width;
- light_data.atlas_rect[3] = rect.size.height;
-
- light_data.soft_shadow_scale = light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR);
- light_data.shadow_volumetric_fog_fade = 1.0 / light_storage->light_get_shadow_volumetric_fog_fade(base);
-
- if (type == RS::LIGHT_OMNI) {
- Transform3D proj = (inverse_transform * light_transform).inverse();
-
- RendererStorageRD::store_transform(proj, light_data.shadow_matrix);
-
- if (size > 0.0) {
- light_data.soft_shadow_size = size;
- } else {
- light_data.soft_shadow_size = 0.0;
- light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
- }
-
- light_data.direction[0] = omni_offset.x * float(rect.size.width);
- light_data.direction[1] = omni_offset.y * float(rect.size.height);
- } else if (type == RS::LIGHT_SPOT) {
- Transform3D modelview = (inverse_transform * light_transform).inverse();
- CameraMatrix bias;
- bias.set_light_bias();
-
- CameraMatrix shadow_mtx = bias * li->shadow_transform[0].camera * modelview;
- RendererStorageRD::store_camera(shadow_mtx, light_data.shadow_matrix);
-
- if (size > 0.0) {
- CameraMatrix cm = li->shadow_transform[0].camera;
- float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle));
- light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
- } else {
- light_data.soft_shadow_size = 0.0;
- light_data.soft_shadow_scale *= shadows_quality_radius_get(); // Only use quality radius for PCF
- }
- }
- } else {
- light_data.shadow_enabled = false;
- }
-
- li->cull_mask = light_storage->light_get_cull_mask(base);
-
- if (current_cluster_builder != nullptr) {
- current_cluster_builder->add_light(type == RS::LIGHT_SPOT ? ClusterBuilderRD::LIGHT_TYPE_SPOT : ClusterBuilderRD::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle);
- }
-
- r_positional_light_count++;
- }
-
- //update without barriers
- if (cluster.omni_light_count) {
- RD::get_singleton()->buffer_update(cluster.omni_light_buffer, 0, sizeof(Cluster::LightData) * cluster.omni_light_count, cluster.omni_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
- }
-
- if (cluster.spot_light_count) {
- RD::get_singleton()->buffer_update(cluster.spot_light_buffer, 0, sizeof(Cluster::LightData) * cluster.spot_light_count, cluster.spot_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
- }
-
- if (r_directional_light_count) {
- RD::get_singleton()->buffer_update(cluster.directional_light_buffer, 0, sizeof(Cluster::DirectionalLightData) * r_directional_light_count, cluster.directional_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
- }
-}
-
-void RendererSceneRenderRD::_setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
-
- Transform3D uv_xform;
- uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
- uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
-
- uint32_t decal_count = p_decals.size();
-
- cluster.decal_count = 0;
-
- for (uint32_t i = 0; i < decal_count; i++) {
- if (cluster.decal_count == cluster.max_decals) {
- break;
- }
-
- DecalInstance *di = decal_instance_owner.get_or_null(p_decals[i]);
- if (!di) {
- continue;
- }
- RID decal = di->decal;
-
- Transform3D xform = di->transform;
-
- real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
-
- if (texture_storage->decal_is_distance_fade_enabled(decal)) {
- float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
- float fade_length = texture_storage->decal_get_distance_fade_length(decal);
-
- if (distance > fade_begin) {
- if (distance > fade_begin + fade_length) {
- continue; // do not use this decal, its invisible
- }
- }
- }
-
- cluster.decal_sort[cluster.decal_count].instance = di;
- cluster.decal_sort[cluster.decal_count].depth = distance;
- cluster.decal_count++;
- }
-
- if (cluster.decal_count > 0) {
- SortArray<Cluster::InstanceSort<DecalInstance>> sort_array;
- sort_array.sort(cluster.decal_sort, cluster.decal_count);
- }
-
- bool using_forward_ids = _uses_forward_ids();
- for (uint32_t i = 0; i < cluster.decal_count; i++) {
- DecalInstance *di = cluster.decal_sort[i].instance;
- RID decal = di->decal;
-
- if (using_forward_ids) {
- _map_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id, i);
- }
-
- di->cull_mask = texture_storage->decal_get_cull_mask(decal);
-
- Transform3D xform = di->transform;
- float fade = 1.0;
-
- if (texture_storage->decal_is_distance_fade_enabled(decal)) {
- const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
- const float fade_begin = texture_storage->decal_get_distance_fade_begin(decal);
- const float fade_length = texture_storage->decal_get_distance_fade_length(decal);
-
- if (distance > fade_begin) {
- // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
- fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
- }
- }
-
- Cluster::DecalData &dd = cluster.decals[i];
-
- Vector3 decal_extents = texture_storage->decal_get_extents(decal);
-
- Transform3D scale_xform;
- scale_xform.basis.scale(decal_extents);
- Transform3D to_decal_xform = (p_camera_inverse_xform * di->transform * scale_xform * uv_xform).affine_inverse();
- RendererStorageRD::store_transform(to_decal_xform, dd.xform);
-
- Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized();
- normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
-
- dd.normal[0] = normal.x;
- dd.normal[1] = normal.y;
- dd.normal[2] = normal.z;
- dd.normal_fade = texture_storage->decal_get_normal_fade(decal);
-
- RID albedo_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ALBEDO);
- RID emission_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_EMISSION);
- if (albedo_tex.is_valid()) {
- Rect2 rect = texture_storage->decal_atlas_get_texture_rect(albedo_tex);
- dd.albedo_rect[0] = rect.position.x;
- dd.albedo_rect[1] = rect.position.y;
- dd.albedo_rect[2] = rect.size.x;
- dd.albedo_rect[3] = rect.size.y;
- } else {
- if (!emission_tex.is_valid()) {
- continue; //no albedo, no emission, no decal.
- }
- dd.albedo_rect[0] = 0;
- dd.albedo_rect[1] = 0;
- dd.albedo_rect[2] = 0;
- dd.albedo_rect[3] = 0;
- }
-
- RID normal_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_NORMAL);
-
- if (normal_tex.is_valid()) {
- Rect2 rect = texture_storage->decal_atlas_get_texture_rect(normal_tex);
- dd.normal_rect[0] = rect.position.x;
- dd.normal_rect[1] = rect.position.y;
- dd.normal_rect[2] = rect.size.x;
- dd.normal_rect[3] = rect.size.y;
-
- Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
- RendererStorageRD::store_basis_3x4(normal_xform, dd.normal_xform);
- } else {
- dd.normal_rect[0] = 0;
- dd.normal_rect[1] = 0;
- dd.normal_rect[2] = 0;
- dd.normal_rect[3] = 0;
- }
-
- RID orm_tex = texture_storage->decal_get_texture(decal, RS::DECAL_TEXTURE_ORM);
- if (orm_tex.is_valid()) {
- Rect2 rect = texture_storage->decal_atlas_get_texture_rect(orm_tex);
- dd.orm_rect[0] = rect.position.x;
- dd.orm_rect[1] = rect.position.y;
- dd.orm_rect[2] = rect.size.x;
- dd.orm_rect[3] = rect.size.y;
- } else {
- dd.orm_rect[0] = 0;
- dd.orm_rect[1] = 0;
- dd.orm_rect[2] = 0;
- dd.orm_rect[3] = 0;
- }
-
- if (emission_tex.is_valid()) {
- Rect2 rect = texture_storage->decal_atlas_get_texture_rect(emission_tex);
- dd.emission_rect[0] = rect.position.x;
- dd.emission_rect[1] = rect.position.y;
- dd.emission_rect[2] = rect.size.x;
- dd.emission_rect[3] = rect.size.y;
- } else {
- dd.emission_rect[0] = 0;
- dd.emission_rect[1] = 0;
- dd.emission_rect[2] = 0;
- dd.emission_rect[3] = 0;
- }
-
- Color modulate = texture_storage->decal_get_modulate(decal);
- dd.modulate[0] = modulate.r;
- dd.modulate[1] = modulate.g;
- dd.modulate[2] = modulate.b;
- dd.modulate[3] = modulate.a * fade;
- dd.emission_energy = texture_storage->decal_get_emission_energy(decal) * fade;
- dd.albedo_mix = texture_storage->decal_get_albedo_mix(decal);
- dd.mask = texture_storage->decal_get_cull_mask(decal);
- dd.upper_fade = texture_storage->decal_get_upper_fade(decal);
- dd.lower_fade = texture_storage->decal_get_lower_fade(decal);
-
- if (current_cluster_builder != nullptr) {
- current_cluster_builder->add_box(ClusterBuilderRD::BOX_TYPE_DECAL, xform, decal_extents);
- }
- }
-
- if (cluster.decal_count > 0) {
- RD::get_singleton()->buffer_update(cluster.decal_buffer, 0, sizeof(Cluster::DecalData) * cluster.decal_count, cluster.decals, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// FOG SHADER
-
-void RendererSceneRenderRD::FogShaderData::set_code(const String &p_code) {
- //compile
-
- code = p_code;
- valid = false;
- ubo_size = 0;
- uniforms.clear();
-
- if (code.is_empty()) {
- return; //just invalid, but no error
- }
-
- ShaderCompiler::GeneratedCode gen_code;
- ShaderCompiler::IdentifierActions actions;
- actions.entry_point_stages["fog"] = ShaderCompiler::STAGE_COMPUTE;
-
- uses_time = false;
-
- actions.usage_flag_pointers["TIME"] = &uses_time;
-
- actions.uniforms = &uniforms;
-
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- Error err = scene_singleton->volumetric_fog.compiler.compile(RS::SHADER_FOG, code, &actions, path, gen_code);
- ERR_FAIL_COND_MSG(err != OK, "Fog shader compilation failed.");
-
- if (version.is_null()) {
- version = scene_singleton->volumetric_fog.shader.version_create();
- }
-
- scene_singleton->volumetric_fog.shader.version_set_compute_code(version, gen_code.code, gen_code.uniforms, gen_code.stage_globals[ShaderCompiler::STAGE_COMPUTE], gen_code.defines);
- ERR_FAIL_COND(!scene_singleton->volumetric_fog.shader.version_is_valid(version));
-
- ubo_size = gen_code.uniform_total_size;
- ubo_offsets = gen_code.uniform_offsets;
- texture_uniforms = gen_code.texture_uniforms;
-
- pipeline = RD::get_singleton()->compute_pipeline_create(scene_singleton->volumetric_fog.shader.version_get_shader(version, 0));
-
- valid = true;
-}
-
-void RendererSceneRenderRD::FogShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
- if (!p_texture.is_valid()) {
- if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
- default_texture_params[p_name].erase(p_index);
-
- if (default_texture_params[p_name].is_empty()) {
- default_texture_params.erase(p_name);
- }
- }
- } else {
- if (!default_texture_params.has(p_name)) {
- default_texture_params[p_name] = HashMap<int, RID>();
- }
- default_texture_params[p_name][p_index] = p_texture;
- }
-}
-
-void RendererSceneRenderRD::FogShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
- RBMap<int, StringName> order;
-
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL || E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- if (E.value.texture_order >= 0) {
- order[E.value.texture_order + 100000] = E.key;
- } else {
- order[E.value.order] = E.key;
- }
- }
-
- for (const KeyValue<int, StringName> &E : order) {
- PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
- pi.name = E.value;
- p_param_list->push_back(pi);
- }
-}
-
-void RendererSceneRenderRD::FogShaderData::get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const {
- for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
- if (E.value.scope != ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
- continue;
- }
-
- RendererMaterialStorage::InstanceShaderParam p;
- p.info = ShaderLanguage::uniform_to_property_info(E.value);
- p.info.name = E.key; //supply name
- p.index = E.value.instance_index;
- p.default_value = ShaderLanguage::constant_value_to_variant(E.value.default_value, E.value.type, E.value.array_size, E.value.hint);
- p_param_list->push_back(p);
- }
-}
-
-bool RendererSceneRenderRD::FogShaderData::is_param_texture(const StringName &p_param) const {
- if (!uniforms.has(p_param)) {
- return false;
- }
-
- return uniforms[p_param].texture_order >= 0;
-}
-
-bool RendererSceneRenderRD::FogShaderData::is_animated() const {
- return false;
-}
-
-bool RendererSceneRenderRD::FogShaderData::casts_shadows() const {
- return false;
-}
-
-Variant RendererSceneRenderRD::FogShaderData::get_default_parameter(const StringName &p_parameter) const {
- if (uniforms.has(p_parameter)) {
- ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter];
- Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value;
- return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.array_size, uniform.hint);
- }
- return Variant();
-}
-
-RS::ShaderNativeSourceCode RendererSceneRenderRD::FogShaderData::get_native_source_code() const {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- return scene_singleton->volumetric_fog.shader.version_get_native_source_code(version);
-}
-
-RendererSceneRenderRD::FogShaderData::~FogShaderData() {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
- ERR_FAIL_COND(!scene_singleton);
- //pipeline variants will clear themselves if shader is gone
- if (version.is_valid()) {
- scene_singleton->volumetric_fog.shader.version_free(version);
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Fog material
-
-bool RendererSceneRenderRD::FogMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- RendererSceneRenderRD *scene_singleton = static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton);
-
- uniform_set_updated = true;
-
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, scene_singleton->volumetric_fog.shader.version_get_shader(shader_data->version, 0), VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
-}
-
-RendererSceneRenderRD::FogMaterialData::~FogMaterialData() {
- free_parameters_uniform_set(uniform_set);
-}
-
-RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_func() {
- FogShaderData *shader_data = memnew(FogShaderData);
- return shader_data;
-}
-
-RendererRD::ShaderData *RendererSceneRenderRD::_create_fog_shader_funcs() {
- return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_shader_func();
-};
-
-RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_func(FogShaderData *p_shader) {
- FogMaterialData *material_data = memnew(FogMaterialData);
- material_data->shader_data = p_shader;
- //update will happen later anyway so do nothing.
- return material_data;
-}
-
-RendererRD::MaterialData *RendererSceneRenderRD::_create_fog_material_funcs(RendererRD::ShaderData *p_shader) {
- return static_cast<RendererSceneRenderRD *>(RendererSceneRenderRD::singleton)->_create_fog_material_func(static_cast<FogShaderData *>(p_shader));
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Volumetric Fog
-
-void RendererSceneRenderRD::_volumetric_fog_erase(RenderBuffers *rb) {
- ERR_FAIL_COND(!rb->volumetric_fog);
-
- RD::get_singleton()->free(rb->volumetric_fog->prev_light_density_map);
- RD::get_singleton()->free(rb->volumetric_fog->light_density_map);
- RD::get_singleton()->free(rb->volumetric_fog->fog_map);
- RD::get_singleton()->free(rb->volumetric_fog->density_map);
- RD::get_singleton()->free(rb->volumetric_fog->light_map);
- RD::get_singleton()->free(rb->volumetric_fog->emissive_map);
-
- if (rb->volumetric_fog->fog_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->fog_uniform_set);
- }
- if (rb->volumetric_fog->process_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set);
- }
- if (rb->volumetric_fog->process_uniform_set2.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set2)) {
- RD::get_singleton()->free(rb->volumetric_fog->process_uniform_set2);
- }
- if (rb->volumetric_fog->sdfgi_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->sdfgi_uniform_set);
- }
- if (rb->volumetric_fog->sky_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sky_uniform_set)) {
- RD::get_singleton()->free(rb->volumetric_fog->sky_uniform_set);
- }
-
- memdelete(rb->volumetric_fog);
-
- rb->volumetric_fog = nullptr;
-}
-
-Vector3i RendererSceneRenderRD::_point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform) {
- Vector3 view_position = p_cam_transform.affine_inverse().xform(p_point);
- view_position.z = MIN(view_position.z, -0.01); // Clamp to the front of camera
- Vector3 fog_position = Vector3(0, 0, 0);
-
- view_position.y = -view_position.y;
- fog_position.z = -view_position.z / fog_end;
- fog_position.x = (view_position.x / (2 * (fog_near_size.x * (1.0 - fog_position.z) + fog_far_size.x * fog_position.z))) + 0.5;
- fog_position.y = (view_position.y / (2 * (fog_near_size.y * (1.0 - fog_position.z) + fog_far_size.y * fog_position.z))) + 0.5;
- fog_position.z = Math::pow(float(fog_position.z), float(1.0 / volumetric_fog_detail_spread));
- fog_position = fog_position * fog_size - Vector3(0.5, 0.5, 0.5);
-
- fog_position.x = CLAMP(fog_position.x, 0.0, fog_size.x);
- fog_position.y = CLAMP(fog_position.y, 0.0, fog_size.y);
- fog_position.z = CLAMP(fog_position.z, 0.0, fog_size.z);
-
- return Vector3i(fog_position);
-}
-
-void RendererSceneRenderRD::_update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
- ERR_FAIL_COND(!is_clustered_enabled()); // can't use volumetric fog without clustered
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_environment);
-
- float ratio = float(rb->width) / float((rb->width + rb->height) / 2);
- uint32_t target_width = uint32_t(float(volumetric_fog_size) * ratio);
- uint32_t target_height = uint32_t(float(volumetric_fog_size) / ratio);
-
- if (rb->volumetric_fog) {
- //validate
- if (!env || !env->volumetric_fog_enabled || rb->volumetric_fog->width != target_width || rb->volumetric_fog->height != target_height || rb->volumetric_fog->depth != volumetric_fog_depth) {
- _volumetric_fog_erase(rb);
- }
- }
-
- if (!env || !env->volumetric_fog_enabled) {
- //no reason to enable or update, bye
- return;
- }
-
- RENDER_TIMESTAMP("> Volumetric Fog");
- RD::get_singleton()->draw_command_begin_label("Volumetric Fog");
+void RendererSceneRenderRD::_update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers) {
+ if (p_render_buffers.is_valid() && vrs) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- if (env && env->volumetric_fog_enabled && !rb->volumetric_fog) {
- //required volumetric fog but not existing, create
- rb->volumetric_fog = memnew(VolumetricFog);
- rb->volumetric_fog->width = target_width;
- rb->volumetric_fog->height = target_height;
- rb->volumetric_fog->depth = volumetric_fog_depth;
+ RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_buffers->get_render_target());
+ if (vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ RID vrs_texture = p_render_buffers->get_texture(RB_SCOPE_VRS, RB_TEXTURE);
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
- tf.width = target_width;
- tf.height = target_height;
- tf.depth = volumetric_fog_depth;
- tf.texture_type = RD::TEXTURE_TYPE_3D;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
-
- rb->volumetric_fog->light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_density_map, "Fog light-density map");
-
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
-
- rb->volumetric_fog->prev_light_density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->prev_light_density_map, "Fog previous light-density map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->prev_light_density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
-
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
-
- rb->volumetric_fog->fog_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->fog_map, "Fog map");
-
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- Vector<uint8_t> dm;
- dm.resize(target_width * target_height * volumetric_fog_depth * 4);
- dm.fill(0);
-
- rb->volumetric_fog->density_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
- rb->volumetric_fog->light_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
- rb->volumetric_fog->emissive_map = RD::get_singleton()->storage_buffer_create(dm.size(), dm);
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
-#else
- tf.format = RD::DATA_FORMAT_R32_UINT;
- tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- rb->volumetric_fog->density_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->density_map, "Fog density map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->density_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
- rb->volumetric_fog->light_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->light_map, "Fog light map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->light_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
- rb->volumetric_fog->emissive_map = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->volumetric_fog->emissive_map, "Fog emissive map");
- RD::get_singleton()->texture_clear(rb->volumetric_fog->emissive_map, Color(0, 0, 0, 0), 0, 1, 0, 1);
-#endif
-
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.binding = 0;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.append_id(rb->volumetric_fog->fog_map);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->sky_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky.sky_shader.default_shader_rd, RendererSceneSkyRD::SKY_SET_FOG);
- }
-
- if (p_fog_volumes.size() > 0) {
- RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog Volumes");
-
- RENDER_TIMESTAMP("Render FogVolumes");
-
- VolumetricFogShader::VolumeUBO params;
-
- Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
- Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
- float z_near = p_cam_projection.get_z_near();
- float z_far = p_cam_projection.get_z_far();
- float fog_end = env->volumetric_fog_length;
-
- Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
- Vector2 fog_near_size;
- if (p_cam_projection.is_orthogonal()) {
- fog_near_size = fog_far_size;
- } else {
- fog_near_size = Vector2();
- }
-
- params.fog_frustum_size_begin[0] = fog_near_size.x;
- params.fog_frustum_size_begin[1] = fog_near_size.y;
-
- params.fog_frustum_size_end[0] = fog_far_size.x;
- params.fog_frustum_size_end[1] = fog_far_size.y;
-
- params.fog_frustum_end = fog_end;
- params.z_near = z_near;
- params.z_far = z_far;
- params.time = time;
-
- params.fog_volume_size[0] = rb->volumetric_fog->width;
- params.fog_volume_size[1] = rb->volumetric_fog->height;
- params.fog_volume_size[2] = rb->volumetric_fog->depth;
-
- params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
- params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
- params.detail_spread = env->volumetric_fog_detail_spread;
- params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
-
- Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
- storage->store_transform(to_prev_cam_view, params.to_prev_view);
- storage->store_transform(p_cam_transform, params.transform);
-
- RD::get_singleton()->buffer_update(volumetric_fog.volume_ubo, 0, sizeof(VolumetricFogShader::VolumeUBO), &params, RD::BARRIER_MASK_COMPUTE);
-
- if (rb->volumetric_fog->fog_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->fog_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 1;
- u.append_id(rb->volumetric_fog->emissive_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 2;
- u.append_id(volumetric_fog.volume_ubo);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 3;
- u.append_id(rb->volumetric_fog->density_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 4;
- u.append_id(rb->volumetric_fog->light_map);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->fog_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
- }
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- bool any_uses_time = false;
-
- for (int i = 0; i < (int)p_fog_volumes.size(); i++) {
- FogVolumeInstance *fog_volume_instance = fog_volume_instance_owner.get_or_null(p_fog_volumes[i]);
- ERR_FAIL_COND(!fog_volume_instance);
- RID fog_volume = fog_volume_instance->volume;
-
- RID fog_material = storage->fog_volume_get_material(fog_volume);
+ // We use get_cache_multipass instead of get_cache_multiview because the default behavior is for
+ // our vrs_texture to be used as the VRS attachment. In this particular case we're writing to it
+ // so it needs to be set as our color attachment
- FogMaterialData *material = nullptr;
+ Vector<RID> textures;
+ textures.push_back(vrs_texture);
- if (fog_material.is_valid()) {
- material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
- if (!material || !material->shader_data->valid) {
- material = nullptr;
- }
- }
-
- if (!material) {
- fog_material = volumetric_fog.default_material;
- material = static_cast<FogMaterialData *>(material_storage->material_get_data(fog_material, RendererRD::SHADER_TYPE_FOG));
- }
-
- ERR_FAIL_COND(!material);
-
- FogShaderData *shader_data = material->shader_data;
-
- ERR_FAIL_COND(!shader_data);
+ Vector<RD::FramebufferPass> passes;
+ RD::FramebufferPass pass;
+ pass.color_attachments.push_back(0);
+ passes.push_back(pass);
- any_uses_time |= shader_data->uses_time;
-
- Vector3i min = Vector3i();
- Vector3i max = Vector3i();
- Vector3i kernel_size = Vector3i();
-
- Vector3 position = fog_volume_instance->transform.get_origin();
- RS::FogVolumeShape volume_type = storage->fog_volume_get_shape(fog_volume);
- Vector3 extents = storage->fog_volume_get_extents(fog_volume);
-
- if (volume_type != RS::FOG_VOLUME_SHAPE_WORLD) {
- // Local fog volume.
- Vector3i points[8];
- points[0] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[1] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[2] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[3] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[4] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[5] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[6] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
- points[7] = _point_get_position_in_froxel_volume(fog_volume_instance->transform.xform(Vector3(-extents.x, -extents.y, -extents.z)), fog_end, fog_near_size, fog_far_size, env->volumetric_fog_detail_spread, Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth), p_cam_transform);
-
- min = Vector3i(int32_t(rb->volumetric_fog->width) - 1, int32_t(rb->volumetric_fog->height) - 1, int32_t(rb->volumetric_fog->depth) - 1);
- max = Vector3i(1, 1, 1);
-
- for (int j = 0; j < 8; j++) {
- min = Vector3i(MIN(min.x, points[j].x), MIN(min.y, points[j].y), MIN(min.z, points[j].z));
- max = Vector3i(MAX(max.x, points[j].x), MAX(max.y, points[j].y), MAX(max.z, points[j].z));
- }
+ RID vrs_fb = FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, p_render_buffers->get_view_count());
- kernel_size = max - min;
- } else {
- // Volume type global runs on all cells
- extents = Vector3(rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- min = Vector3i(0, 0, 0);
- kernel_size = Vector3i(int32_t(rb->volumetric_fog->width), int32_t(rb->volumetric_fog->height), int32_t(rb->volumetric_fog->depth));
- }
-
- if (kernel_size.x == 0 || kernel_size.y == 0 || kernel_size.z == 0) {
- continue;
- }
-
- volumetric_fog.push_constant.position[0] = position.x;
- volumetric_fog.push_constant.position[1] = position.y;
- volumetric_fog.push_constant.position[2] = position.z;
- volumetric_fog.push_constant.extents[0] = extents.x;
- volumetric_fog.push_constant.extents[1] = extents.y;
- volumetric_fog.push_constant.extents[2] = extents.z;
- volumetric_fog.push_constant.corner[0] = min.x;
- volumetric_fog.push_constant.corner[1] = min.y;
- volumetric_fog.push_constant.corner[2] = min.z;
- volumetric_fog.push_constant.shape = uint32_t(storage->fog_volume_get_shape(fog_volume));
- storage->store_transform(fog_volume_instance->transform.affine_inverse(), volumetric_fog.push_constant.transform);
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, shader_data->pipeline);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->fog_uniform_set, VolumetricFogShader::FogSet::FOG_SET_UNIFORMS);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, &volumetric_fog.push_constant, sizeof(VolumetricFogShader::FogPushConstant));
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, volumetric_fog.base_uniform_set, VolumetricFogShader::FogSet::FOG_SET_BASE);
- if (material->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(material->uniform_set)) { // Material may not have a uniform set.
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, material->uniform_set, VolumetricFogShader::FogSet::FOG_SET_MATERIAL);
- }
-
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, kernel_size.x, kernel_size.y, kernel_size.z);
- }
- if (any_uses_time || env->volumetric_fog_temporal_reprojection) {
- RenderingServerDefault::redraw_request();
+ vrs->update_vrs_texture(vrs_fb, p_render_buffers->get_render_target());
}
-
- RD::get_singleton()->draw_command_end_label();
-
- RD::get_singleton()->compute_list_end();
}
-
- if (rb->volumetric_fog->process_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->process_uniform_set)) {
- //re create uniform set if needed
- Vector<RD::Uniform> uniforms;
- Vector<RD::Uniform> copy_uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
- if (shadow_atlas == nullptr || shadow_atlas->depth.is_null()) {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
- } else {
- u.append_id(shadow_atlas->depth);
- }
-
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- if (directional_shadow.depth.is_valid()) {
- u.append_id(directional_shadow.depth);
- } else {
- u.append_id(texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_BLACK));
- }
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 3;
- u.append_id(get_omni_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 4;
- u.append_id(get_spot_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 5;
- u.append_id(get_directional_light_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 6;
- u.append_id(rb->cluster_builder->get_cluster_buffer());
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 7;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 8;
- u.append_id(rb->volumetric_fog->light_density_map);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.append_id(rb->volumetric_fog->fog_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 9;
- u.append_id(rb->volumetric_fog->prev_light_density_map);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 10;
- u.append_id(shadow_sampler);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 11;
- u.append_id(render_buffers_get_voxel_gi_buffer(p_render_buffers));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 12;
- for (int i = 0; i < RendererSceneGIRD::MAX_VOXEL_GI_INSTANCES; i++) {
- u.append_id(rb->gi.voxel_gi_textures[i]);
- }
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;
- u.binding = 13;
- u.append_id(material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED));
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 14;
- u.append_id(volumetric_fog.params_ubo);
- uniforms.push_back(u);
- copy_uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 15;
- u.append_id(rb->volumetric_fog->prev_light_density_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 16;
- u.append_id(rb->volumetric_fog->density_map);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 17;
- u.append_id(rb->volumetric_fog->light_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
-#else
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
-#endif
- u.binding = 18;
- u.append_id(rb->volumetric_fog->emissive_map);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 19;
- RID radiance_texture = texture_storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RendererRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
- RID sky_texture = env->sky.is_valid() ? sky.sky_get_radiance_texture_rd(env->sky) : RID();
- u.append_id(sky_texture.is_valid() ? sky_texture : radiance_texture);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->copy_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY), 0);
-
- rb->volumetric_fog->process_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY), 0);
-
- RID aux7 = uniforms.write[7].get_id(0);
- RID aux8 = uniforms.write[8].get_id(0);
-
- uniforms.write[7].set_id(0, aux8);
- uniforms.write[8].set_id(0, aux7);
-
- rb->volumetric_fog->process_uniform_set2 = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, 0), 0);
- }
-
- bool using_sdfgi = env->volumetric_fog_gi_inject > 0.0001 && env->sdfgi_enabled && (rb->sdfgi != nullptr);
-
- if (using_sdfgi) {
- if (rb->volumetric_fog->sdfgi_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->volumetric_fog->sdfgi_uniform_set)) {
- Vector<RD::Uniform> uniforms;
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;
- u.binding = 0;
- u.append_id(gi.sdfgi_ubo);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 1;
- u.append_id(rb->sdfgi->ambient_texture);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;
- u.binding = 2;
- u.append_id(rb->sdfgi->occlusion_texture);
- uniforms.push_back(u);
- }
-
- rb->volumetric_fog->sdfgi_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI), 1);
- }
- }
-
- rb->volumetric_fog->length = env->volumetric_fog_length;
- rb->volumetric_fog->spread = env->volumetric_fog_detail_spread;
-
- VolumetricFogShader::ParamsUBO params;
-
- Vector2 frustum_near_size = p_cam_projection.get_viewport_half_extents();
- Vector2 frustum_far_size = p_cam_projection.get_far_plane_half_extents();
- float z_near = p_cam_projection.get_z_near();
- float z_far = p_cam_projection.get_z_far();
- float fog_end = env->volumetric_fog_length;
-
- Vector2 fog_far_size = frustum_near_size.lerp(frustum_far_size, (fog_end - z_near) / (z_far - z_near));
- Vector2 fog_near_size;
- if (p_cam_projection.is_orthogonal()) {
- fog_near_size = fog_far_size;
- } else {
- fog_near_size = Vector2();
- }
-
- params.fog_frustum_size_begin[0] = fog_near_size.x;
- params.fog_frustum_size_begin[1] = fog_near_size.y;
-
- params.fog_frustum_size_end[0] = fog_far_size.x;
- params.fog_frustum_size_end[1] = fog_far_size.y;
-
- params.ambient_inject = env->volumetric_fog_ambient_inject * env->ambient_light_energy;
- params.z_far = z_far;
-
- params.fog_frustum_end = fog_end;
-
- Color ambient_color = env->ambient_light.srgb_to_linear();
- params.ambient_color[0] = ambient_color.r;
- params.ambient_color[1] = ambient_color.g;
- params.ambient_color[2] = ambient_color.b;
- params.sky_contribution = env->ambient_sky_contribution;
-
- params.fog_volume_size[0] = rb->volumetric_fog->width;
- params.fog_volume_size[1] = rb->volumetric_fog->height;
- params.fog_volume_size[2] = rb->volumetric_fog->depth;
-
- params.directional_light_count = p_directional_light_count;
-
- Color emission = env->volumetric_fog_emission.srgb_to_linear();
- params.base_emission[0] = emission.r * env->volumetric_fog_emission_energy;
- params.base_emission[1] = emission.g * env->volumetric_fog_emission_energy;
- params.base_emission[2] = emission.b * env->volumetric_fog_emission_energy;
- params.base_density = env->volumetric_fog_density;
-
- Color base_scattering = env->volumetric_fog_scattering.srgb_to_linear();
- params.base_scattering[0] = base_scattering.r;
- params.base_scattering[1] = base_scattering.g;
- params.base_scattering[2] = base_scattering.b;
- params.phase_g = env->volumetric_fog_anisotropy;
-
- params.detail_spread = env->volumetric_fog_detail_spread;
- params.gi_inject = env->volumetric_fog_gi_inject;
-
- params.cam_rotation[0] = p_cam_transform.basis[0][0];
- params.cam_rotation[1] = p_cam_transform.basis[1][0];
- params.cam_rotation[2] = p_cam_transform.basis[2][0];
- params.cam_rotation[3] = 0;
- params.cam_rotation[4] = p_cam_transform.basis[0][1];
- params.cam_rotation[5] = p_cam_transform.basis[1][1];
- params.cam_rotation[6] = p_cam_transform.basis[2][1];
- params.cam_rotation[7] = 0;
- params.cam_rotation[8] = p_cam_transform.basis[0][2];
- params.cam_rotation[9] = p_cam_transform.basis[1][2];
- params.cam_rotation[10] = p_cam_transform.basis[2][2];
- params.cam_rotation[11] = 0;
- params.filter_axis = 0;
- params.max_voxel_gi_instances = env->volumetric_fog_gi_inject > 0.001 ? p_voxel_gi_count : 0;
- params.temporal_frame = RSG::rasterizer->get_frame_number() % VolumetricFog::MAX_TEMPORAL_FRAMES;
-
- Transform3D to_prev_cam_view = p_prev_cam_inv_transform * p_cam_transform;
- storage->store_transform(to_prev_cam_view, params.to_prev_view);
-
- params.use_temporal_reprojection = env->volumetric_fog_temporal_reprojection;
- params.temporal_blend = env->volumetric_fog_temporal_reprojection_amount;
-
- {
- uint32_t cluster_size = rb->cluster_builder->get_cluster_size();
- params.cluster_shift = get_shift_from_power_of_2(cluster_size);
-
- uint32_t cluster_screen_width = (rb->width - 1) / cluster_size + 1;
- uint32_t cluster_screen_height = (rb->height - 1) / cluster_size + 1;
- params.max_cluster_element_count_div_32 = max_cluster_elements / 32;
- params.cluster_type_size = cluster_screen_width * cluster_screen_height * (params.max_cluster_element_count_div_32 + 32);
- params.cluster_width = cluster_screen_width;
-
- params.screen_size[0] = rb->width;
- params.screen_size[1] = rb->height;
- }
-
- Basis sky_transform = env->sky_orientation;
- sky_transform = sky_transform.inverse() * p_cam_transform.basis;
- RendererStorageRD::store_transform_3x3(sky_transform, params.radiance_inverse_xform);
-
- RD::get_singleton()->draw_command_begin_label("Render Volumetric Fog");
-
- RENDER_TIMESTAMP("Render Fog");
- RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params, RD::BARRIER_MASK_COMPUTE);
-
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[using_sdfgi ? VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI : VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY]);
-
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
-
- if (using_sdfgi) {
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->sdfgi_uniform_set, 1);
- }
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
-
- // Copy fog to history buffer
- if (env->volumetric_fog_temporal_reprojection) {
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_COPY]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->copy_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- }
- RD::get_singleton()->draw_command_end_label();
-
- if (volumetric_fog_filter_active) {
- RD::get_singleton()->draw_command_begin_label("Filter Fog");
-
- RENDER_TIMESTAMP("Filter Fog");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
-
- RD::get_singleton()->compute_list_end();
- //need restart for buffer update
-
- params.filter_axis = 1;
- RD::get_singleton()->buffer_update(volumetric_fog.params_ubo, 0, sizeof(VolumetricFogShader::ParamsUBO), &params);
-
- compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FILTER]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set2, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, rb->volumetric_fog->depth);
-
- RD::get_singleton()->compute_list_add_barrier(compute_list);
- RD::get_singleton()->draw_command_end_label();
- }
-
- RENDER_TIMESTAMP("Integrate Fog");
- RD::get_singleton()->draw_command_begin_label("Integrate Fog");
-
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, volumetric_fog.process_pipelines[VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_FOG]);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->volumetric_fog->process_uniform_set, 0);
- RD::get_singleton()->compute_list_dispatch_threads(compute_list, rb->volumetric_fog->width, rb->volumetric_fog->height, 1);
-
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_RASTER);
-
- RENDER_TIMESTAMP("< Volumetric Fog");
- RD::get_singleton()->draw_command_end_label();
- RD::get_singleton()->draw_command_end_label();
}
bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) {
if (p_render_data->render_buffers.is_valid()) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- if (rb->sdfgi != nullptr) {
+ if (p_render_data->render_buffers->has_custom_data(RB_SCOPE_SDFGI)) {
return true;
}
}
@@ -4902,17 +1042,13 @@ bool RendererSceneRenderRD::_needs_post_prepass_render(RenderDataRD *p_render_da
}
void RendererSceneRenderRD::_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi) {
- if (p_render_data->render_buffers.is_valid()) {
- if (p_use_gi) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(rb == nullptr);
- if (rb->sdfgi == nullptr) {
- return;
- }
-
- RendererSceneEnvironmentRD *env = environment_owner.get_or_null(p_render_data->environment);
- rb->sdfgi->update_probes(env, sky.sky_owner.get_or_null(env->sky));
+ if (p_render_data->render_buffers.is_valid() && p_use_gi) {
+ if (!p_render_data->render_buffers->has_custom_data(RB_SCOPE_SDFGI)) {
+ return;
}
+
+ Ref<RendererRD::GI::SDFGI> sdfgi = p_render_data->render_buffers->get_custom_data(RB_SCOPE_SDFGI);
+ sdfgi->update_probes(p_render_data->environment, sky.sky_owner.get_or_null(environment_get_sky(p_render_data->environment)));
}
}
@@ -4924,210 +1060,72 @@ void RendererSceneRenderRD::_pre_resolve_render(RenderDataRD *p_render_data, boo
}
}
-void RendererSceneRenderRD::_pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer) {
- // Render shadows while GI is rendering, due to how barriers are handled, this should happen at the same time
+void RendererSceneRenderRD::render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RenderingMethod::RenderInfo *r_render_info) {
RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
- if (p_render_data->render_buffers.is_valid() && p_use_gi) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(rb == nullptr);
- if (rb->sdfgi != nullptr) {
- rb->sdfgi->store_probes();
- }
+ // getting this here now so we can direct call a bunch of things more easily
+ Ref<RenderSceneBuffersRD> rb;
+ if (p_render_buffers.is_valid()) {
+ rb = p_render_buffers; // cast it...
+ ERR_FAIL_COND(rb.is_null());
}
- render_state.cube_shadows.clear();
- render_state.shadows.clear();
- render_state.directional_shadows.clear();
-
- Plane camera_plane(-p_render_data->cam_transform.basis.get_column(Vector3::AXIS_Z), p_render_data->cam_transform.origin);
- float lod_distance_multiplier = p_render_data->cam_projection.get_lod_multiplier();
+ // setup scene data
+ RenderSceneDataRD scene_data;
{
- for (int i = 0; i < render_state.render_shadow_count; i++) {
- LightInstance *li = light_instance_owner.get_or_null(render_state.render_shadows[i].light);
-
- if (light_storage->light_get_type(li->light) == RS::LIGHT_DIRECTIONAL) {
- render_state.directional_shadows.push_back(i);
- } else if (light_storage->light_get_type(li->light) == RS::LIGHT_OMNI && light_storage->light_omni_get_shadow_mode(li->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
- render_state.cube_shadows.push_back(i);
- } else {
- render_state.shadows.push_back(i);
- }
- }
-
- //cube shadows are rendered in their own way
- for (uint32_t i = 0; i < render_state.cube_shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.cube_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.cube_shadows[i]].pass, render_state.render_shadows[render_state.cube_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, true, true, true, p_render_data->render_info);
- }
-
- if (render_state.directional_shadows.size()) {
- //open the pass for directional shadows
- _update_directional_shadow_atlas();
- RD::get_singleton()->draw_list_begin(directional_shadow.fb, RD::INITIAL_ACTION_DROP, RD::FINAL_ACTION_DISCARD, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE);
- RD::get_singleton()->draw_list_end();
- }
- }
-
- // Render GI
-
- bool render_shadows = render_state.directional_shadows.size() || render_state.shadows.size();
- bool render_gi = p_render_data->render_buffers.is_valid() && p_use_gi;
-
- if (render_shadows && render_gi) {
- RENDER_TIMESTAMP("Render GI + Render Shadows (Parallel)");
- } else if (render_shadows) {
- RENDER_TIMESTAMP("Render Shadows");
- } else if (render_gi) {
- RENDER_TIMESTAMP("Render GI");
- }
-
- //prepare shadow rendering
- if (render_shadows) {
- _render_shadow_begin();
-
- //render directional shadows
- for (uint32_t i = 0; i < render_state.directional_shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.directional_shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.directional_shadows[i]].pass, render_state.render_shadows[render_state.directional_shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, false, i == render_state.directional_shadows.size() - 1, false, p_render_data->render_info);
- }
- //render positional shadows
- for (uint32_t i = 0; i < render_state.shadows.size(); i++) {
- _render_shadow_pass(render_state.render_shadows[render_state.shadows[i]].light, p_render_data->shadow_atlas, render_state.render_shadows[render_state.shadows[i]].pass, render_state.render_shadows[render_state.shadows[i]].instances, camera_plane, lod_distance_multiplier, p_render_data->screen_mesh_lod_threshold, i == 0, i == render_state.shadows.size() - 1, true, p_render_data->render_info);
- }
-
- _render_shadow_process();
- }
-
- //start GI
- if (render_gi) {
- gi.process_gi(p_render_data->render_buffers, p_normal_roughness_buffer, p_voxel_gi_buffer, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, *p_render_data->voxel_gi_instances, this);
- }
-
- //Do shadow rendering (in parallel with GI)
- if (render_shadows) {
- _render_shadow_end(RD::BARRIER_MASK_NO_BARRIER);
- }
-
- if (render_gi) {
- RD::get_singleton()->compute_list_end(RD::BARRIER_MASK_NO_BARRIER); //use a later barrier
- }
-
- if (p_render_data->render_buffers.is_valid()) {
- if (p_use_ssao || p_use_ssil) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_render_data->render_buffers);
- ERR_FAIL_COND(!rb);
-
- bool invalidate_uniform_set = false;
- if (rb->ss_effects.linear_depth.is_null()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R16_SFLOAT;
- tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
- tf.width = (rb->width + 1) / 2;
- tf.height = (rb->height + 1) / 2;
- tf.mipmaps = 5;
- tf.array_layers = 4;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
- rb->ss_effects.linear_depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
- RD::get_singleton()->set_resource_name(rb->ss_effects.linear_depth, "SS Effects Depth");
- for (uint32_t i = 0; i < tf.mipmaps; i++) {
- RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ss_effects.linear_depth, 0, i, 1, RD::TEXTURE_SLICE_2D_ARRAY);
- rb->ss_effects.linear_depth_slices.push_back(slice);
- RD::get_singleton()->set_resource_name(slice, "SS Effects Depth Mip " + itos(i) + " ");
- }
- invalidate_uniform_set = true;
- }
+ // Our first camera is used by default
+ scene_data.cam_transform = p_camera_data->main_transform;
+ scene_data.cam_projection = p_camera_data->main_projection;
+ scene_data.cam_orthogonal = p_camera_data->is_orthogonal;
+ scene_data.taa_jitter = p_camera_data->taa_jitter;
- storage->get_effects()->downsample_depth(rb->depth_texture, rb->ss_effects.linear_depth_slices, ssao_quality, ssil_quality, invalidate_uniform_set, ssao_half_size, ssil_half_size, Size2i(rb->width, rb->height), p_render_data->cam_projection);
+ scene_data.view_count = p_camera_data->view_count;
+ for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
+ scene_data.view_eye_offset[v] = p_camera_data->view_offset[v].origin;
+ scene_data.view_projection[v] = p_camera_data->view_projection[v];
}
- if (p_use_ssao) {
- _process_ssao(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_buffer, p_render_data->cam_projection);
- }
+ scene_data.prev_cam_transform = p_prev_camera_data->main_transform;
+ scene_data.prev_cam_projection = p_prev_camera_data->main_projection;
+ scene_data.prev_taa_jitter = p_prev_camera_data->taa_jitter;
- if (p_use_ssil) {
- _process_ssil(p_render_data->render_buffers, p_render_data->environment, p_normal_roughness_buffer, p_render_data->cam_projection, p_render_data->cam_transform);
+ for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
+ scene_data.prev_view_projection[v] = p_prev_camera_data->view_projection[v];
}
- }
- //full barrier here, we need raster, transfer and compute and it depends from the previous work
- RD::get_singleton()->barrier(RD::BARRIER_MASK_ALL, RD::BARRIER_MASK_ALL);
+ scene_data.z_near = p_camera_data->main_projection.get_z_near();
+ scene_data.z_far = p_camera_data->main_projection.get_z_far();
- if (current_cluster_builder) {
- current_cluster_builder->begin(p_render_data->cam_transform, p_render_data->cam_projection, !p_render_data->reflection_probe.is_valid());
- }
-
- bool using_shadows = true;
+ // this should be the same for all cameras..
+ scene_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
- if (p_render_data->reflection_probe.is_valid()) {
- if (!RSG::light_storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_render_data->reflection_probe))) {
- using_shadows = false;
+ if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
+ scene_data.screen_mesh_lod_threshold = 0.0;
+ } else {
+ scene_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
}
- } else {
- //do not render reflections when rendering a reflection probe
- _setup_reflections(*p_render_data->reflection_probes, p_render_data->cam_transform.affine_inverse(), p_render_data->environment);
- }
-
- uint32_t directional_light_count = 0;
- uint32_t positional_light_count = 0;
- _setup_lights(*p_render_data->lights, p_render_data->cam_transform, p_render_data->shadow_atlas, using_shadows, directional_light_count, positional_light_count, p_render_data->directional_light_soft_shadows);
- _setup_decals(*p_render_data->decals, p_render_data->cam_transform.affine_inverse());
-
- p_render_data->directional_light_count = directional_light_count;
- if (current_cluster_builder) {
- current_cluster_builder->bake_cluster();
- }
-
- if (p_render_data->render_buffers.is_valid()) {
- bool directional_shadows = false;
- for (uint32_t i = 0; i < directional_light_count; i++) {
- if (cluster.directional_lights[i].shadow_enabled) {
- directional_shadows = true;
- break;
- }
+ if (p_shadow_atlas.is_valid()) {
+ int shadow_atlas_size = light_storage->shadow_atlas_get_size(p_shadow_atlas);
+ scene_data.shadow_atlas_pixel_size.x = 1.0 / shadow_atlas_size;
+ scene_data.shadow_atlas_pixel_size.y = 1.0 / shadow_atlas_size;
}
- if (is_volumetric_supported()) {
- _update_volumetric_fog(p_render_data->render_buffers, p_render_data->environment, p_render_data->cam_projection, p_render_data->cam_transform, p_render_data->prev_cam_transform.affine_inverse(), p_render_data->shadow_atlas, directional_light_count, directional_shadows, positional_light_count, render_state.voxel_gi_count, *p_render_data->fog_volumes);
+ {
+ int directional_shadow_size = light_storage->directional_shadow_get_size();
+ scene_data.directional_shadow_pixel_size.x = 1.0 / directional_shadow_size;
+ scene_data.directional_shadow_pixel_size.y = 1.0 / directional_shadow_size;
}
- }
-}
-void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data, RendererScene::RenderInfo *r_render_info) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
-
- // getting this here now so we can direct call a bunch of things more easily
- RenderBuffers *rb = nullptr;
- if (p_render_buffers.is_valid()) {
- rb = render_buffers_owner.get_or_null(p_render_buffers);
- ERR_FAIL_COND(!rb);
+ scene_data.time = time;
+ scene_data.time_step = time_step;
}
//assign render data
RenderDataRD render_data;
{
- render_data.render_buffers = p_render_buffers;
-
- // Our first camera is used by default
- render_data.cam_transform = p_camera_data->main_transform;
- render_data.cam_projection = p_camera_data->main_projection;
- render_data.view_projection[0] = p_camera_data->main_projection;
- render_data.cam_orthogonal = p_camera_data->is_orthogonal;
- render_data.taa_jitter = p_camera_data->taa_jitter;
-
- render_data.view_count = p_camera_data->view_count;
- for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
- render_data.view_projection[v] = p_camera_data->view_projection[v];
- }
-
- render_data.prev_cam_transform = p_prev_camera_data->main_transform;
- render_data.prev_cam_projection = p_prev_camera_data->main_projection;
- render_data.prev_taa_jitter = p_prev_camera_data->taa_jitter;
-
- for (uint32_t v = 0; v < p_camera_data->view_count; v++) {
- render_data.prev_view_projection[v] = p_prev_camera_data->view_projection[v];
- }
-
- render_data.z_near = p_camera_data->main_projection.get_z_near();
- render_data.z_far = p_camera_data->main_projection.get_z_far();
+ render_data.render_buffers = rb;
+ render_data.scene_data = &scene_data;
render_data.instances = &p_instances;
render_data.lights = &p_lights;
@@ -5137,27 +1135,19 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.lightmaps = &p_lightmaps;
render_data.fog_volumes = &p_fog_volumes;
render_data.environment = p_environment;
- render_data.camera_effects = p_camera_effects;
+ render_data.camera_attributes = p_camera_attributes;
render_data.shadow_atlas = p_shadow_atlas;
+ render_data.occluder_debug_tex = p_occluder_debug_tex;
render_data.reflection_atlas = p_reflection_atlas;
render_data.reflection_probe = p_reflection_probe;
render_data.reflection_probe_pass = p_reflection_probe_pass;
- // this should be the same for all cameras..
- render_data.lod_distance_multiplier = p_camera_data->main_projection.get_lod_multiplier();
- render_data.lod_camera_plane = Plane(-p_camera_data->main_transform.basis.get_column(Vector3::AXIS_Z), p_camera_data->main_transform.get_origin());
-
- if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) {
- render_data.screen_mesh_lod_threshold = 0.0;
- } else {
- render_data.screen_mesh_lod_threshold = p_screen_mesh_lod_threshold;
- }
+ render_data.render_shadows = p_render_shadows;
+ render_data.render_shadow_count = p_render_shadow_count;
+ render_data.render_sdfgi_regions = p_render_sdfgi_regions;
+ render_data.render_sdfgi_region_count = p_render_sdfgi_region_count;
+ render_data.sdfgi_update_data = p_sdfgi_update_data;
- render_state.render_shadows = p_render_shadows;
- render_state.render_shadow_count = p_render_shadow_count;
- render_state.render_sdfgi_regions = p_render_sdfgi_regions;
- render_state.render_sdfgi_region_count = p_render_sdfgi_region_count;
- render_state.sdfgi_update_data = p_sdfgi_update_data;
render_data.render_info = r_render_info;
}
@@ -5169,294 +1159,27 @@ void RendererSceneRenderRD::render_scene(RID p_render_buffers, const CameraData
render_data.voxel_gi_instances = &empty;
}
- //sdfgi first
- if (rb != nullptr && rb->sdfgi != nullptr) {
- for (int i = 0; i < render_state.render_sdfgi_region_count; i++) {
- rb->sdfgi->render_region(p_render_buffers, render_state.render_sdfgi_regions[i].region, render_state.render_sdfgi_regions[i].instances, this);
- }
- if (render_state.sdfgi_update_data->update_static) {
- rb->sdfgi->render_static_lights(p_render_buffers, render_state.sdfgi_update_data->static_cascade_count, p_sdfgi_update_data->static_cascade_indices, render_state.sdfgi_update_data->static_positional_lights, this);
- }
- }
-
Color clear_color;
if (p_render_buffers.is_valid()) {
- clear_color = texture_storage->render_target_get_clear_request_color(rb->render_target);
+ clear_color = texture_storage->render_target_get_clear_request_color(rb->get_render_target());
} else {
- clear_color = storage->get_default_clear_color();
+ clear_color = RSG::texture_storage->get_default_clear_color();
}
- //assign render indices to voxel_gi_instances
- if (is_dynamic_gi_supported()) {
- for (uint32_t i = 0; i < (uint32_t)p_voxel_gi_instances.size(); i++) {
- RendererSceneGIRD::VoxelGIInstance *voxel_gi_inst = gi.voxel_gi_instance_owner.get_or_null(p_voxel_gi_instances[i]);
- if (voxel_gi_inst) {
- voxel_gi_inst->render_index = i;
- }
- }
- }
-
- if (render_buffers_owner.owns(render_data.render_buffers)) {
- // render_data.render_buffers == p_render_buffers so we can use our already retrieved rb
- current_cluster_builder = rb->cluster_builder;
- } else if (reflection_probe_instance_owner.owns(render_data.reflection_probe)) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(render_data.reflection_probe);
- ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(rpi->atlas);
- if (!ra) {
- ERR_PRINT("reflection probe has no reflection atlas! Bug?");
- current_cluster_builder = nullptr;
- } else {
- current_cluster_builder = ra->cluster_builder;
- }
- } else {
- ERR_PRINT("No render buffer nor reflection atlas, bug"); //should never happen, will crash
- current_cluster_builder = nullptr;
- }
-
- render_state.voxel_gi_count = 0;
-
- if (rb != nullptr && is_dynamic_gi_supported()) {
- if (rb->sdfgi) {
- rb->sdfgi->update_cascades();
- rb->sdfgi->pre_process_gi(render_data.cam_transform, &render_data, this);
- rb->sdfgi->update_light();
- }
-
- gi.setup_voxel_gi_instances(render_data.render_buffers, render_data.cam_transform, *render_data.voxel_gi_instances, render_state.voxel_gi_count, this);
- }
-
- render_state.depth_prepass_used = false;
//calls _pre_opaque_render between depth pre-pass and opaque pass
- if (current_cluster_builder != nullptr) {
- render_data.cluster_buffer = current_cluster_builder->get_cluster_buffer();
- render_data.cluster_size = current_cluster_builder->get_cluster_size();
- render_data.cluster_max_elements = current_cluster_builder->get_max_cluster_elements();
- }
-
_render_scene(&render_data, clear_color);
-
- if (p_render_buffers.is_valid()) {
- /*
- _debug_draw_cluster(p_render_buffers);
- _render_buffers_post_process_and_tonemap(&render_data);
- */
-
- _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas, p_occluder_debug_tex);
- if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SDFGI && rb != nullptr && rb->sdfgi != nullptr) {
- rb->sdfgi->debug_draw(render_data.cam_projection, render_data.cam_transform, rb->width, rb->height, rb->render_target, rb->texture);
- }
- }
}
-void RendererSceneRenderRD::_debug_draw_cluster(RID p_render_buffers) {
- if (p_render_buffers.is_valid() && current_cluster_builder != nullptr) {
- RS::ViewportDebugDraw dd = get_debug_draw_mode();
-
- if (dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS || dd == RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES) {
- ClusterBuilderRD::ElementType elem_type = ClusterBuilderRD::ELEMENT_TYPE_MAX;
- switch (dd) {
- case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_OMNI_LIGHTS:
- elem_type = ClusterBuilderRD::ELEMENT_TYPE_OMNI_LIGHT;
- break;
- case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_SPOT_LIGHTS:
- elem_type = ClusterBuilderRD::ELEMENT_TYPE_SPOT_LIGHT;
- break;
- case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_DECALS:
- elem_type = ClusterBuilderRD::ELEMENT_TYPE_DECAL;
- break;
- case RS::VIEWPORT_DEBUG_DRAW_CLUSTER_REFLECTION_PROBES:
- elem_type = ClusterBuilderRD::ELEMENT_TYPE_REFLECTION_PROBE;
- break;
- default: {
- }
- }
- current_cluster_builder->debug(elem_type);
- }
- }
+void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
+ _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region, 1.0);
}
-void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, bool p_open_pass, bool p_close_pass, bool p_clear_region, RendererScene::RenderInfo *p_render_info) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_light);
- ERR_FAIL_COND(!light_instance);
-
- Rect2i atlas_rect;
- uint32_t atlas_size;
- RID atlas_fb;
-
- bool using_dual_paraboloid = false;
- bool using_dual_paraboloid_flip = false;
- Vector2i dual_paraboloid_offset;
- RID render_fb;
- RID render_texture;
- float zfar;
-
- bool use_pancake = false;
- bool render_cubemap = false;
- bool finalize_cubemap = false;
-
- bool flip_y = false;
-
- CameraMatrix light_projection;
- Transform3D light_transform;
-
- if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) {
- //set pssm stuff
- if (light_instance->last_scene_shadow_pass != scene_pass) {
- light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
- directional_shadow.current_light++;
- light_instance->last_scene_shadow_pass = scene_pass;
- }
-
- use_pancake = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE) > 0;
- light_projection = light_instance->shadow_transform[p_pass].camera;
- light_transform = light_instance->shadow_transform[p_pass].transform;
-
- atlas_rect = light_instance->directional_rect;
-
- if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) {
- atlas_rect.size.width /= 2;
- atlas_rect.size.height /= 2;
-
- if (p_pass == 1) {
- atlas_rect.position.x += atlas_rect.size.width;
- } else if (p_pass == 2) {
- atlas_rect.position.y += atlas_rect.size.height;
- } else if (p_pass == 3) {
- atlas_rect.position += atlas_rect.size;
- }
- } else if (RSG::light_storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
- atlas_rect.size.height /= 2;
-
- if (p_pass == 0) {
- } else {
- atlas_rect.position.y += atlas_rect.size.height;
- }
- }
-
- light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect;
-
- light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size;
- light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size;
-
- zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
-
- render_fb = directional_shadow.fb;
- render_texture = RID();
- flip_y = true;
-
- } else {
- //set from shadow atlas
-
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
- ERR_FAIL_COND(!shadow_atlas);
- ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light));
-
- _update_shadow_atlas(shadow_atlas);
-
- uint32_t key = shadow_atlas->shadow_owners[p_light];
-
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- ERR_FAIL_INDEX((int)shadow, shadow_atlas->quadrants[quadrant].shadows.size());
-
- uint32_t quadrant_size = shadow_atlas->size >> 1;
-
- atlas_rect.position.x = (quadrant & 1) * quadrant_size;
- atlas_rect.position.y = (quadrant >> 1) * quadrant_size;
-
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- atlas_rect.position.x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- atlas_rect.position.y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
-
- atlas_rect.size.width = shadow_size;
- atlas_rect.size.height = shadow_size;
-
- zfar = RSG::light_storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE);
-
- if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) {
- bool wrap = (shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision == 0;
- dual_paraboloid_offset = wrap ? Vector2i(1 - shadow_atlas->quadrants[quadrant].subdivision, 1) : Vector2i(1, 0);
-
- if (RSG::light_storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) {
- ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2);
-
- render_fb = cubemap->side_fb[p_pass];
- render_texture = cubemap->cubemap;
-
- light_projection = light_instance->shadow_transform[p_pass].camera;
- light_transform = light_instance->shadow_transform[p_pass].transform;
- render_cubemap = true;
- finalize_cubemap = p_pass == 5;
- atlas_fb = shadow_atlas->fb;
-
- atlas_size = shadow_atlas->size;
-
- if (p_pass == 0) {
- _render_shadow_begin();
- }
-
- } else {
- atlas_rect.position.x += 1;
- atlas_rect.position.y += 1;
- atlas_rect.size.x -= 2;
- atlas_rect.size.y -= 2;
-
- atlas_rect.position += p_pass * atlas_rect.size * dual_paraboloid_offset;
-
- light_projection = light_instance->shadow_transform[0].camera;
- light_transform = light_instance->shadow_transform[0].transform;
-
- using_dual_paraboloid = true;
- using_dual_paraboloid_flip = p_pass == 1;
- render_fb = shadow_atlas->fb;
- flip_y = true;
- }
-
- } else if (RSG::light_storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) {
- light_projection = light_instance->shadow_transform[0].camera;
- light_transform = light_instance->shadow_transform[0].transform;
-
- render_fb = shadow_atlas->fb;
-
- flip_y = true;
- }
- }
-
- if (render_cubemap) {
- //rendering to cubemap
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, false, false, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, Rect2(), false, true, true, true, p_render_info);
- if (finalize_cubemap) {
- _render_shadow_process();
- _render_shadow_end();
- //reblit
- Rect2 atlas_rect_norm = atlas_rect;
- atlas_rect_norm.position /= float(atlas_size);
- atlas_rect_norm.size /= float(atlas_size);
- storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), false);
- atlas_rect_norm.position += Vector2(dual_paraboloid_offset) * atlas_rect_norm.size;
- storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect_norm, atlas_rect.size, light_projection.get_z_near(), light_projection.get_z_far(), true);
-
- //restore transform so it can be properly used
- light_instance_set_shadow_transform(p_light, CameraMatrix(), light_instance->transform, zfar, 0, 0, 0);
- }
-
- } else {
- //render shadow
- _render_shadow_append(render_fb, p_instances, light_projection, light_transform, zfar, 0, 0, using_dual_paraboloid, using_dual_paraboloid_flip, use_pancake, p_camera_plane, p_lod_distance_multiplier, p_screen_mesh_lod_threshold, atlas_rect, flip_y, p_clear_region, p_open_pass, p_close_pass, p_render_info);
- }
-}
-
-void RendererSceneRenderRD::render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) {
- _render_material(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_instances, p_framebuffer, p_region);
-}
-
-void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) {
+void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) {
RendererRD::ParticlesStorage *particles_storage = RendererRD::ParticlesStorage::get_singleton();
ERR_FAIL_COND(!particles_storage->particles_collision_is_heightfield(p_collider));
Vector3 extents = particles_storage->particles_collision_get_extents(p_collider) * p_transform.basis.get_scale();
- CameraMatrix cm;
+ Projection cm;
cm.set_orthogonal(-extents.x, extents.x, -extents.z, extents.z, 0, extents.y * 2.0);
Vector3 cam_pos = p_transform.origin;
@@ -5471,93 +1194,17 @@ void RendererSceneRenderRD::render_particle_collider_heightfield(RID p_collider,
}
bool RendererSceneRenderRD::free(RID p_rid) {
- if (render_buffers_owner.owns(p_rid)) {
- RenderBuffers *rb = render_buffers_owner.get_or_null(p_rid);
- _free_render_buffer_data(rb);
- memdelete(rb->data);
- if (rb->sdfgi) {
- rb->sdfgi->erase();
- memdelete(rb->sdfgi);
- rb->sdfgi = nullptr;
- }
- if (rb->volumetric_fog) {
- _volumetric_fog_erase(rb);
- }
- if (rb->cluster_builder) {
- memdelete(rb->cluster_builder);
- }
- render_buffers_owner.free(p_rid);
- } else if (environment_owner.owns(p_rid)) {
- //not much to delete, just free it
- environment_owner.free(p_rid);
- } else if (camera_effects_owner.owns(p_rid)) {
- //not much to delete, just free it
- camera_effects_owner.free(p_rid);
- } else if (reflection_atlas_owner.owns(p_rid)) {
- reflection_atlas_set_size(p_rid, 0, 0);
- ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_rid);
- if (ra->cluster_builder) {
- memdelete(ra->cluster_builder);
- }
- reflection_atlas_owner.free(p_rid);
- } else if (reflection_probe_instance_owner.owns(p_rid)) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_rid);
- _free_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id);
- reflection_probe_release_atlas_index(p_rid);
- reflection_probe_instance_owner.free(p_rid);
- } else if (decal_instance_owner.owns(p_rid)) {
- DecalInstance *di = decal_instance_owner.get_or_null(p_rid);
- _free_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id);
- decal_instance_owner.free(p_rid);
- } else if (lightmap_instance_owner.owns(p_rid)) {
- lightmap_instance_owner.free(p_rid);
- } else if (gi.voxel_gi_instance_owner.owns(p_rid)) {
- RendererSceneGIRD::VoxelGIInstance *voxel_gi = gi.voxel_gi_instance_owner.get_or_null(p_rid);
- if (voxel_gi->texture.is_valid()) {
- RD::get_singleton()->free(voxel_gi->texture);
- RD::get_singleton()->free(voxel_gi->write_buffer);
- }
-
- for (int i = 0; i < voxel_gi->dynamic_maps.size(); i++) {
- RD::get_singleton()->free(voxel_gi->dynamic_maps[i].texture);
- RD::get_singleton()->free(voxel_gi->dynamic_maps[i].depth);
- }
-
- gi.voxel_gi_instance_owner.free(p_rid);
+ if (is_environment(p_rid)) {
+ environment_free(p_rid);
+ } else if (RSG::camera_attributes->owns_camera_attributes(p_rid)) {
+ RSG::camera_attributes->camera_attributes_free(p_rid);
+ } else if (gi.voxel_gi_instance_owns(p_rid)) {
+ gi.voxel_gi_instance_free(p_rid);
} else if (sky.sky_owner.owns(p_rid)) {
sky.update_dirty_skys();
sky.free_sky(p_rid);
- } else if (light_instance_owner.owns(p_rid)) {
- LightInstance *light_instance = light_instance_owner.get_or_null(p_rid);
-
- //remove from shadow atlases..
- for (const RID &E : light_instance->shadow_atlases) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E);
- ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid));
- uint32_t key = shadow_atlas->shadow_owners[p_rid];
- uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
-
- if (key & ShadowAtlas::OMNI_LIGHT_FLAG) {
- // Omni lights use two atlas spots, make sure to clear the other as well
- shadow_atlas->quadrants[q].shadows.write[s + 1].owner = RID();
- }
-
- shadow_atlas->shadow_owners.erase(p_rid);
- }
-
- if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
- _free_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id);
- }
- light_instance_owner.free(p_rid);
-
- } else if (shadow_atlas_owner.owns(p_rid)) {
- shadow_atlas_set_size(p_rid, 0);
- shadow_atlas_owner.free(p_rid);
- } else if (fog_volume_instance_owner.owns(p_rid)) {
- fog_volume_instance_owner.free(p_rid);
+ } else if (RendererRD::Fog::get_singleton()->owns_fog_volume_instance(p_rid)) {
+ RendererRD::Fog::get_singleton()->fog_instance_free(p_rid);
} else {
return false;
}
@@ -5596,7 +1243,7 @@ float RendererSceneRenderRD::screen_space_roughness_limiter_get_limit() const {
return screen_space_roughness_limiter_limit;
}
-TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) {
+TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) {
RD::TextureFormat tf;
tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
tf.width = p_image_size.width; // Always 64x64
@@ -5629,7 +1276,8 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
//RID sampled_light;
- GeometryInstance *gi = geometry_instance_create(p_base);
+ RenderGeometryInstance *gi_inst = geometry_instance_create(p_base);
+ ERR_FAIL_NULL_V(gi_inst, TypedArray<Image>());
uint32_t sc = RSG::mesh_storage->mesh_get_surface_count(p_base);
Vector<RID> materials;
@@ -5641,50 +1289,42 @@ TypedArray<Image> RendererSceneRenderRD::bake_render_uv2(RID p_base, const Vecto
}
}
- geometry_instance_set_surface_materials(gi, materials);
+ gi_inst->set_surface_materials(materials);
if (cull_argument.size() == 0) {
cull_argument.push_back(nullptr);
}
- cull_argument[0] = gi;
+ cull_argument[0] = gi_inst;
_render_uv2(cull_argument, fb, Rect2i(0, 0, p_image_size.width, p_image_size.height));
- geometry_instance_free(gi);
+ geometry_instance_free(gi_inst);
TypedArray<Image> ret;
{
PackedByteArray data = RD::get_singleton()->texture_get_data(albedo_alpha_tex, 0);
- Ref<Image> img;
- img.instantiate();
- img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
+ Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
RD::get_singleton()->free(albedo_alpha_tex);
ret.push_back(img);
}
{
PackedByteArray data = RD::get_singleton()->texture_get_data(normal_tex, 0);
- Ref<Image> img;
- img.instantiate();
- img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
+ Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
RD::get_singleton()->free(normal_tex);
ret.push_back(img);
}
{
PackedByteArray data = RD::get_singleton()->texture_get_data(orm_tex, 0);
- Ref<Image> img;
- img.instantiate();
- img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
+ Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBA8, data);
RD::get_singleton()->free(orm_tex);
ret.push_back(img);
}
{
PackedByteArray data = RD::get_singleton()->texture_get_data(emission_tex, 0);
- Ref<Image> img;
- img.instantiate();
- img->create(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBAH, data);
+ Ref<Image> img = Image::create_from_data(p_image_size.width, p_image_size.height, false, Image::FORMAT_RGBAH, data);
RD::get_singleton()->free(emission_tex);
ret.push_back(img);
}
@@ -5702,25 +1342,8 @@ void RendererSceneRenderRD::sdfgi_set_debug_probe_select(const Vector3 &p_positi
RendererSceneRenderRD *RendererSceneRenderRD::singleton = nullptr;
-RID RendererSceneRenderRD::get_reflection_probe_buffer() {
- return cluster.reflection_buffer;
-}
-RID RendererSceneRenderRD::get_omni_light_buffer() {
- return cluster.omni_light_buffer;
-}
-
-RID RendererSceneRenderRD::get_spot_light_buffer() {
- return cluster.spot_light_buffer;
-}
-
-RID RendererSceneRenderRD::get_directional_light_buffer() {
- return cluster.directional_light_buffer;
-}
-RID RendererSceneRenderRD::get_decal_buffer() {
- return cluster.decal_buffer;
-}
-int RendererSceneRenderRD::get_max_directional_lights() const {
- return cluster.max_directional_lights;
+bool RendererSceneRenderRD::is_vrs_supported() const {
+ return RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS);
}
bool RendererSceneRenderRD::is_dynamic_gi_supported() const {
@@ -5728,11 +1351,6 @@ bool RendererSceneRenderRD::is_dynamic_gi_supported() const {
return true;
}
-bool RendererSceneRenderRD::is_clustered_enabled() const {
- // used by default.
- return true;
-}
-
bool RendererSceneRenderRD::is_volumetric_supported() const {
// usable by default (unless low end = true)
return true;
@@ -5742,214 +1360,54 @@ uint32_t RendererSceneRenderRD::get_max_elements() const {
return GLOBAL_GET("rendering/limits/cluster_builder/max_clustered_elements");
}
-RendererSceneRenderRD::RendererSceneRenderRD(RendererStorageRD *p_storage) {
- storage = p_storage;
+RendererSceneRenderRD::RendererSceneRenderRD() {
singleton = this;
}
void RendererSceneRenderRD::init() {
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
-
max_cluster_elements = get_max_elements();
+ RendererRD::LightStorage::get_singleton()->set_max_cluster_elements(max_cluster_elements);
- directional_shadow.size = GLOBAL_GET("rendering/shadows/directional_shadow/size");
- directional_shadow.use_16_bits = GLOBAL_GET("rendering/shadows/directional_shadow/16_bits");
+ /* Forward ID */
+ forward_id_storage = create_forward_id_storage();
/* SKY SHADER */
- sky.init(storage);
+ sky.init();
/* GI */
if (is_dynamic_gi_supported()) {
- gi.init(storage, &sky);
+ gi.init(&sky);
}
{ //decals
- cluster.max_decals = max_cluster_elements;
- uint32_t decal_buffer_size = cluster.max_decals * sizeof(Cluster::DecalData);
- cluster.decals = memnew_arr(Cluster::DecalData, cluster.max_decals);
- cluster.decal_sort = memnew_arr(Cluster::InstanceSort<DecalInstance>, cluster.max_decals);
- cluster.decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
- }
-
- { //reflections
-
- cluster.max_reflections = max_cluster_elements;
- cluster.reflections = memnew_arr(Cluster::ReflectionData, cluster.max_reflections);
- cluster.reflection_sort = memnew_arr(Cluster::InstanceSort<ReflectionProbeInstance>, cluster.max_reflections);
- cluster.reflection_buffer = RD::get_singleton()->storage_buffer_create(sizeof(Cluster::ReflectionData) * cluster.max_reflections);
+ RendererRD::TextureStorage::get_singleton()->set_max_decals(max_cluster_elements);
}
{ //lights
- cluster.max_lights = max_cluster_elements;
-
- uint32_t light_buffer_size = cluster.max_lights * sizeof(Cluster::LightData);
- cluster.omni_lights = memnew_arr(Cluster::LightData, cluster.max_lights);
- cluster.omni_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
- cluster.omni_light_sort = memnew_arr(Cluster::InstanceSort<LightInstance>, cluster.max_lights);
- cluster.spot_lights = memnew_arr(Cluster::LightData, cluster.max_lights);
- cluster.spot_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
- cluster.spot_light_sort = memnew_arr(Cluster::InstanceSort<LightInstance>, cluster.max_lights);
- //defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(cluster.max_lights) + "\n";
-
- cluster.max_directional_lights = MAX_DIRECTIONAL_LIGHTS;
- uint32_t directional_light_buffer_size = cluster.max_directional_lights * sizeof(Cluster::DirectionalLightData);
- cluster.directional_lights = memnew_arr(Cluster::DirectionalLightData, cluster.max_directional_lights);
- cluster.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
}
if (is_volumetric_supported()) {
- {
- // Initialize local fog shader
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("");
- volumetric_fog.shader.initialize(volumetric_fog_modes);
-
- material_storage->shader_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_shader_funcs);
- material_storage->material_set_data_request_function(RendererRD::SHADER_TYPE_FOG, _create_fog_material_funcs);
- volumetric_fog.volume_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::VolumeUBO));
- }
-
- {
- ShaderCompiler::DefaultIdentifierActions actions;
-
- actions.renames["TIME"] = "scene_params.time";
- actions.renames["PI"] = _MKSTR(Math_PI);
- actions.renames["TAU"] = _MKSTR(Math_TAU);
- actions.renames["E"] = _MKSTR(Math_E);
- actions.renames["WORLD_POSITION"] = "world.xyz";
- actions.renames["OBJECT_POSITION"] = "params.position";
- actions.renames["UVW"] = "uvw";
- actions.renames["EXTENTS"] = "params.extents";
- actions.renames["ALBEDO"] = "albedo";
- actions.renames["DENSITY"] = "density";
- actions.renames["EMISSION"] = "emission";
- actions.renames["SDF"] = "sdf";
-
- actions.usage_defines["SDF"] = "#define SDF_USED\n";
- actions.usage_defines["DENSITY"] = "#define DENSITY_USED\n";
- actions.usage_defines["ALBEDO"] = "#define ALBEDO_USED\n";
- actions.usage_defines["EMISSION"] = "#define EMISSION_USED\n";
-
- actions.sampler_array_name = "material_samplers";
- actions.base_texture_binding_index = 1;
- actions.texture_layout_set = VolumetricFogShader::FogSet::FOG_SET_MATERIAL;
- actions.base_uniform_string = "material.";
-
- actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
- actions.default_repeat = ShaderLanguage::REPEAT_DISABLE;
- actions.global_buffer_array_variable = "global_variables.data";
-
- volumetric_fog.compiler.initialize(actions);
- }
-
- {
- // default material and shader for fog shader
- volumetric_fog.default_shader = material_storage->shader_allocate();
- material_storage->shader_initialize(volumetric_fog.default_shader);
- material_storage->shader_set_code(volumetric_fog.default_shader, R"(
-// Default fog shader.
-
-shader_type fog;
-
-void fog() {
- DENSITY = 1.0;
- ALBEDO = vec3(1.0);
-}
-)");
- volumetric_fog.default_material = material_storage->material_allocate();
- material_storage->material_initialize(volumetric_fog.default_material);
- material_storage->material_set_shader(volumetric_fog.default_material, volumetric_fog.default_shader);
-
- FogMaterialData *md = static_cast<FogMaterialData *>(material_storage->material_get_data(volumetric_fog.default_material, RendererRD::SHADER_TYPE_FOG));
- volumetric_fog.default_shader_rd = volumetric_fog.shader.version_get_shader(md->shader_data->version, 0);
-
- Vector<RD::Uniform> uniforms;
-
- {
- Vector<RID> ids;
- ids.resize(12);
- RID *ids_ptr = ids.ptrw();
- ids_ptr[0] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[1] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[2] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[3] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[4] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[5] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED);
- ids_ptr[6] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[7] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[8] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[9] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[10] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
- ids_ptr[11] = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED);
-
- RD::Uniform u(RD::UNIFORM_TYPE_SAMPLER, 1, ids);
- uniforms.push_back(u);
- }
-
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(RendererRD::MaterialStorage::get_singleton()->global_variables_get_storage_buffer());
- uniforms.push_back(u);
- }
-
- volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE);
- }
- {
- String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(cluster.max_directional_lights) + "\n";
- defines += "\n#define MAX_SKY_LOD " + itos(get_roughness_layers() - 1) + ".0\n";
- if (is_using_radiance_cubemap_array()) {
- defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n";
- }
- Vector<String> volumetric_fog_modes;
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n");
- volumetric_fog_modes.push_back("\n#define MODE_DENSITY\n#define ENABLE_SDFGI\n");
- volumetric_fog_modes.push_back("\n#define MODE_FILTER\n");
- volumetric_fog_modes.push_back("\n#define MODE_FOG\n");
- volumetric_fog_modes.push_back("\n#define MODE_COPY\n");
-
- volumetric_fog.process_shader.initialize(volumetric_fog_modes, defines);
- volumetric_fog.process_shader_version = volumetric_fog.process_shader.version_create();
- for (int i = 0; i < VolumetricFogShader::VOLUMETRIC_FOG_PROCESS_SHADER_MAX; i++) {
- volumetric_fog.process_pipelines[i] = RD::get_singleton()->compute_pipeline_create(volumetric_fog.process_shader.version_get_shader(volumetric_fog.process_shader_version, i));
- }
- volumetric_fog.params_ubo = RD::get_singleton()->uniform_buffer_create(sizeof(VolumetricFogShader::ParamsUBO));
- }
+ RendererRD::Fog::get_singleton()->init_fog_shader(RendererRD::LightStorage::get_singleton()->get_max_directional_lights(), get_roughness_layers(), is_using_radiance_cubemap_array());
}
- {
- RD::SamplerState sampler;
- sampler.mag_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.min_filter = RD::SAMPLER_FILTER_NEAREST;
- sampler.enable_compare = true;
- sampler.compare_op = RD::COMPARE_OP_LESS;
- shadow_sampler = RD::get_singleton()->sampler_create(sampler);
- }
+ RSG::camera_attributes->camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))));
+ RSG::camera_attributes->camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"));
+ use_physical_light_units = GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units");
- camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_shape"))));
- camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/camera/depth_of_field/depth_of_field_use_jitter"));
- environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/environment/ssao/quality"))), GLOBAL_GET("rendering/environment/ssao/half_size"), GLOBAL_GET("rendering/environment/ssao/adaptive_target"), GLOBAL_GET("rendering/environment/ssao/blur_passes"), GLOBAL_GET("rendering/environment/ssao/fadeout_from"), GLOBAL_GET("rendering/environment/ssao/fadeout_to"));
screen_space_roughness_limiter = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/enabled");
screen_space_roughness_limiter_amount = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/amount");
screen_space_roughness_limiter_limit = GLOBAL_GET("rendering/anti_aliasing/screen_space_roughness_limiter/limit");
glow_bicubic_upscale = int(GLOBAL_GET("rendering/environment/glow/upscale_mode")) > 0;
glow_high_quality = GLOBAL_GET("rendering/environment/glow/use_high_quality");
- ssr_roughness_quality = RS::EnvironmentSSRRoughnessQuality(int(GLOBAL_GET("rendering/environment/screen_space_reflection/roughness_quality")));
- sss_quality = RS::SubSurfaceScatteringQuality(int(GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_quality")));
- sss_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_scale");
- sss_depth_scale = GLOBAL_GET("rendering/environment/subsurface_scattering/subsurface_scattering_depth_scale");
-
- environment_set_ssil_quality(RS::EnvironmentSSILQuality(int(GLOBAL_GET("rendering/environment/ssil/quality"))), GLOBAL_GET("rendering/environment/ssil/half_size"), GLOBAL_GET("rendering/environment/ssil/adaptive_target"), GLOBAL_GET("rendering/environment/ssil/blur_passes"), GLOBAL_GET("rendering/environment/ssil/fadeout_from"), GLOBAL_GET("rendering/environment/ssil/fadeout_to"));
directional_penumbra_shadow_kernel = memnew_arr(float, 128);
directional_soft_shadow_kernel = memnew_arr(float, 128);
penumbra_shadow_kernel = memnew_arr(float, 128);
soft_shadow_kernel = memnew_arr(float, 128);
- shadows_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/shadows/soft_shadow_quality"))));
- directional_shadow_quality_set(RS::ShadowQuality(int(GLOBAL_GET("rendering/shadows/directional_shadow/soft_shadow_quality"))));
+ positional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality"))));
+ directional_soft_shadow_filter_set_quality(RS::ShadowQuality(int(GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality"))));
environment_set_volumetric_fog_volume_size(GLOBAL_GET("rendering/environment/volumetric_fog/volume_size"), GLOBAL_GET("rendering/environment/volumetric_fog/volume_depth"));
environment_set_volumetric_fog_filter_active(GLOBAL_GET("rendering/environment/volumetric_fog/use_filter"));
@@ -5963,10 +1421,16 @@ void fog() {
bokeh_dof = memnew(RendererRD::BokehDOF(!can_use_storage));
copy_effects = memnew(RendererRD::CopyEffects(!can_use_storage));
tone_mapper = memnew(RendererRD::ToneMapper);
+ vrs = memnew(RendererRD::VRS);
+ if (can_use_storage) {
+ fsr = memnew(RendererRD::FSR);
+ }
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
- RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ if (forward_id_storage) {
+ memdelete(forward_id_storage);
+ }
if (bokeh_dof) {
memdelete(bokeh_dof);
@@ -5977,9 +1441,11 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
if (tone_mapper) {
memdelete(tone_mapper);
}
-
- for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
- RD::get_singleton()->free(E.value.cubemap);
+ if (vrs) {
+ memdelete(vrs);
+ }
+ if (fsr) {
+ memdelete(fsr);
}
if (sky.sky_scene_state.uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky.sky_scene_state.uniform_set)) {
@@ -5991,11 +1457,7 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
}
if (is_volumetric_supported()) {
- volumetric_fog.process_shader.version_free(volumetric_fog.process_shader_version);
- RD::get_singleton()->free(volumetric_fog.volume_ubo);
- RD::get_singleton()->free(volumetric_fog.params_ubo);
- material_storage->shader_free(volumetric_fog.default_shader);
- material_storage->material_free(volumetric_fog.default_material);
+ RendererRD::Fog::get_singleton()->free_fog_shader();
}
memdelete_arr(directional_penumbra_shadow_kernel);
@@ -6003,25 +1465,6 @@ RendererSceneRenderRD::~RendererSceneRenderRD() {
memdelete_arr(penumbra_shadow_kernel);
memdelete_arr(soft_shadow_kernel);
- {
- RD::get_singleton()->free(cluster.directional_light_buffer);
- RD::get_singleton()->free(cluster.omni_light_buffer);
- RD::get_singleton()->free(cluster.spot_light_buffer);
- RD::get_singleton()->free(cluster.reflection_buffer);
- RD::get_singleton()->free(cluster.decal_buffer);
- memdelete_arr(cluster.directional_lights);
- memdelete_arr(cluster.omni_lights);
- memdelete_arr(cluster.spot_lights);
- memdelete_arr(cluster.omni_light_sort);
- memdelete_arr(cluster.spot_light_sort);
- memdelete_arr(cluster.reflections);
- memdelete_arr(cluster.reflection_sort);
- memdelete_arr(cluster.decals);
- memdelete_arr(cluster.decal_sort);
- }
-
- RD::get_singleton()->free(shadow_sampler);
-
- directional_shadow_atlas_set_size(0);
+ RSG::light_storage->directional_shadow_atlas_set_size(0);
cull_argument.reset(); //avoid exit error
}
diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
index 1b1df6469e..2312603829 100644
--- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h
+++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_RENDER_RD_H
-#define RENDERING_SERVER_SCENE_RENDER_RD_H
+#ifndef RENDERER_SCENE_RENDER_RD_H
+#define RENDERER_SCENE_RENDER_RD_H
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
@@ -37,38 +37,27 @@
#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
#include "servers/rendering/renderer_rd/effects/bokeh_dof.h"
#include "servers/rendering/renderer_rd/effects/copy_effects.h"
+#include "servers/rendering/renderer_rd/effects/fsr.h"
#include "servers/rendering/renderer_rd/effects/tone_mapper.h"
-#include "servers/rendering/renderer_rd/renderer_scene_environment_rd.h"
-#include "servers/rendering/renderer_rd/renderer_scene_gi_rd.h"
-#include "servers/rendering/renderer_rd/renderer_scene_sky_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
-#include "servers/rendering/renderer_rd/shaders/volumetric_fog.glsl.gen.h"
-#include "servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl.gen.h"
-#include "servers/rendering/renderer_scene.h"
+#include "servers/rendering/renderer_rd/effects/vrs.h"
+#include "servers/rendering/renderer_rd/environment/fog.h"
+#include "servers/rendering/renderer_rd/environment/gi.h"
+#include "servers/rendering/renderer_rd/environment/sky.h"
+#include "servers/rendering/renderer_rd/framebuffer_cache_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h"
#include "servers/rendering/renderer_scene_render.h"
#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/rendering_method.h"
-struct RenderDataRD {
- RID render_buffers;
-
- Transform3D cam_transform;
- CameraMatrix cam_projection;
- Vector2 taa_jitter;
- bool cam_orthogonal = false;
-
- // For stereo rendering
- uint32_t view_count = 1;
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
-
- Transform3D prev_cam_transform;
- CameraMatrix prev_cam_projection;
- Vector2 prev_taa_jitter;
- CameraMatrix prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+// For RenderDataRD, possibly inherited from RefCounted and add proper getters for our implementation classes
- float z_near = 0.0;
- float z_far = 0.0;
+struct RenderDataRD {
+ Ref<RenderSceneBuffersRD> render_buffers;
+ RenderSceneDataRD *scene_data;
- const PagedArray<RendererSceneRender::GeometryInstance *> *instances = nullptr;
+ const PagedArray<RenderGeometryInstance *> *instances = nullptr;
const PagedArray<RID> *lights = nullptr;
const PagedArray<RID> *reflection_probes = nullptr;
const PagedArray<RID> *voxel_gi_instances = nullptr;
@@ -76,16 +65,13 @@ struct RenderDataRD {
const PagedArray<RID> *lightmaps = nullptr;
const PagedArray<RID> *fog_volumes = nullptr;
RID environment;
- RID camera_effects;
+ RID camera_attributes;
RID shadow_atlas;
+ RID occluder_debug_tex;
RID reflection_atlas;
RID reflection_probe;
int reflection_probe_pass = 0;
- float lod_distance_multiplier = 0.0;
- Plane lod_camera_plane;
- float screen_mesh_lod_threshold = 0.0;
-
RID cluster_buffer;
uint32_t cluster_size = 0;
uint32_t cluster_max_elements = 0;
@@ -93,65 +79,70 @@ struct RenderDataRD {
uint32_t directional_light_count = 0;
bool directional_light_soft_shadows = false;
- RendererScene::RenderInfo *render_info = nullptr;
+ RenderingMethod::RenderInfo *render_info = nullptr;
+
+ /* Shadow data */
+ const RendererSceneRender::RenderShadowData *render_shadows = nullptr;
+ int render_shadow_count = 0;
+
+ LocalVector<int> cube_shadows;
+ LocalVector<int> shadows;
+ LocalVector<int> directional_shadows;
+
+ /* GI info */
+ const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr;
+ int render_sdfgi_region_count = 0;
+ const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr;
+
+ uint32_t voxel_gi_count = 0;
};
class RendererSceneRenderRD : public RendererSceneRender {
- friend RendererSceneSkyRD;
- friend RendererSceneGIRD;
+ friend RendererRD::SkyRD;
+ friend RendererRD::GI;
protected:
- RendererStorageRD *storage = nullptr;
+ RendererRD::ForwardIDStorage *forward_id_storage = nullptr;
RendererRD::BokehDOF *bokeh_dof = nullptr;
RendererRD::CopyEffects *copy_effects = nullptr;
RendererRD::ToneMapper *tone_mapper = nullptr;
+ RendererRD::FSR *fsr = nullptr;
+ RendererRD::VRS *vrs = nullptr;
double time = 0.0;
double time_step = 0.0;
- struct RenderBufferData {
- virtual void configure(RID p_color_buffer, RID p_depth_buffer, RID p_target_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa, bool p_use_taa, uint32_t p_view_count) = 0;
- virtual ~RenderBufferData() {}
- };
- virtual RenderBufferData *_create_render_buffer_data() = 0;
+ /* ENVIRONMENT */
+
+ bool glow_bicubic_upscale = false;
+ bool glow_high_quality = false;
- void _setup_lights(const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
- void _setup_decals(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
- void _setup_reflections(const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
+ bool use_physical_light_units = false;
- virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
+ ////////////////////////////////
- virtual void _render_shadow_begin() = 0;
- virtual void _render_shadow_append(RID p_framebuffer, const PagedArray<GeometryInstance *> &p_instances, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0.0, float p_screen_mesh_lod_threshold = 0.0, const Rect2i &p_rect = Rect2i(), bool p_flip_y = false, bool p_clear_region = true, bool p_begin = true, bool p_end = true, RendererScene::RenderInfo *p_render_info = nullptr) = 0;
- virtual void _render_shadow_process() = 0;
- virtual void _render_shadow_end(uint32_t p_barrier = RD::BARRIER_MASK_ALL) = 0;
+ virtual RendererRD::ForwardIDStorage *create_forward_id_storage() { return memnew(RendererRD::ForwardIDStorage); };
- virtual void _render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_uv2(const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void _render_sdfgi(RID p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<GeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture) = 0;
- virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ void _update_vrs(Ref<RenderSceneBuffersRD> p_render_buffers);
- void _debug_sdfgi_probes(RID p_render_buffers, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform);
- void _debug_draw_cluster(RID p_render_buffers);
+ virtual void setup_render_buffer_data(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
- RenderBufferData *render_buffers_get_data(RID p_render_buffers);
+ virtual void _render_scene(RenderDataRD *p_render_data, const Color &p_default_color) = 0;
+ virtual void _render_buffers_debug_draw(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
- virtual void _base_uniforms_changed() = 0;
- virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0;
- virtual RID _render_buffers_get_velocity_texture(RID p_render_buffers) = 0;
+ virtual void _render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region, float p_exposure_normalization) = 0;
+ virtual void _render_uv2(const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void _render_sdfgi(Ref<RenderSceneBuffersRD> p_render_buffers, const Vector3i &p_from, const Vector3i &p_size, const AABB &p_bounds, const PagedArray<RenderGeometryInstance *> &p_instances, const RID &p_albedo_texture, const RID &p_emission_texture, const RID &p_emission_aniso_texture, const RID &p_geom_facing_texture, float p_exposure_normalization) = 0;
+ virtual void _render_particle_collider_heightfield(RID p_fb, const Transform3D &p_cam_transform, const Projection &p_cam_projection, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
- void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection);
- void _process_ssr(RID p_render_buffers, RID p_dest_framebuffer, RID p_normal_buffer, RID p_specular_buffer, RID p_metallic, const Color &p_metallic_mask, RID p_environment, const CameraMatrix &p_projection, bool p_use_additive);
- void _process_sss(RID p_render_buffers, const CameraMatrix &p_camera);
- void _process_ssil(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection, const Transform3D &p_transform);
- void _copy_framebuffer_to_ssil(RID p_render_buffers);
- void _process_taa(RID p_render_buffers, RID p_velocity_buffer, float p_z_near, float p_z_far);
+ void _debug_sdfgi_probes(Ref<RenderSceneBuffersRD> p_render_buffers, RID p_framebuffer, uint32_t p_view_count, const Projection *p_camera_with_transforms, bool p_will_continue_color, bool p_will_continue_depth);
+
+ virtual RID _render_buffers_get_normal_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
+ virtual RID _render_buffers_get_velocity_texture(Ref<RenderSceneBuffersRD> p_render_buffers) = 0;
bool _needs_post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _post_prepass_render(RenderDataRD *p_render_data, bool p_use_gi);
void _pre_resolve_render(RenderDataRD *p_render_data, bool p_use_gi);
- void _pre_opaque_render(RenderDataRD *p_render_data, bool p_use_ssao, bool p_use_ssil, bool p_use_gi, RID p_normal_roughness_buffer, RID p_voxel_gi_buffer);
-
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data);
@@ -159,36 +150,11 @@ protected:
void _disable_clear_request(const RenderDataRD *p_render_data);
// needed for a single argument calls (material and uv2)
- PagedArrayPool<GeometryInstance *> cull_argument_pool;
- PagedArray<GeometryInstance *> cull_argument; //need this to exist
-
- RendererSceneGIRD gi;
- RendererSceneSkyRD sky;
-
- RendererSceneEnvironmentRD *get_environment(RID p_environment) {
- if (p_environment.is_valid()) {
- return environment_owner.get_or_null(p_environment);
- } else {
- return nullptr;
- }
- };
+ PagedArrayPool<RenderGeometryInstance *> cull_argument_pool;
+ PagedArray<RenderGeometryInstance *> cull_argument; //need this to exist
- //used for mobile renderer mostly
-
- typedef int32_t ForwardID;
-
- enum ForwardIDType {
- FORWARD_ID_TYPE_OMNI_LIGHT,
- FORWARD_ID_TYPE_SPOT_LIGHT,
- FORWARD_ID_TYPE_REFLECTION_PROBE,
- FORWARD_ID_TYPE_DECAL,
- FORWARD_ID_MAX,
- };
-
- virtual ForwardID _allocate_forward_id(ForwardIDType p_type) { return -1; }
- virtual void _free_forward_id(ForwardIDType p_type, ForwardID p_id) {}
- virtual void _map_forward_id(ForwardIDType p_type, ForwardID p_id, uint32_t p_index) {}
- virtual bool _uses_forward_ids() const { return false; }
+ RendererRD::SkyRD sky;
+ RendererRD::GI gi;
virtual void _update_shader_quality_settings() {}
@@ -196,125 +162,7 @@ private:
RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
static RendererSceneRenderRD *singleton;
- /* REFLECTION ATLAS */
-
- struct ReflectionAtlas {
- int count = 0;
- int size = 0;
-
- RID reflection;
- RID depth_buffer;
- RID depth_fb;
-
- struct Reflection {
- RID owner;
- RendererSceneSkyRD::ReflectionData data;
- RID fbs[6];
- };
-
- Vector<Reflection> reflections;
-
- ClusterBuilderRD *cluster_builder = nullptr;
- };
-
- mutable RID_Owner<ReflectionAtlas> reflection_atlas_owner;
-
- /* REFLECTION PROBE INSTANCE */
-
- struct ReflectionProbeInstance {
- RID probe;
- int atlas_index = -1;
- RID atlas;
-
- bool dirty = true;
- bool rendering = false;
- int processing_layer = 1;
- int processing_side = 0;
-
- uint32_t render_step = 0;
- uint64_t last_pass = 0;
- uint32_t cull_mask = 0;
-
- ForwardID forward_id = -1;
-
- Transform3D transform;
- };
-
- mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
-
- /* DECAL INSTANCE */
-
- struct DecalInstance {
- RID decal;
- Transform3D transform;
- uint32_t cull_mask = 0;
- ForwardID forward_id = -1;
- };
-
- mutable RID_Owner<DecalInstance> decal_instance_owner;
-
- /* LIGHTMAP INSTANCE */
-
- struct LightmapInstance {
- RID lightmap;
- Transform3D transform;
- };
-
- mutable RID_Owner<LightmapInstance> lightmap_instance_owner;
-
- /* SHADOW ATLAS */
-
- struct ShadowShrinkStage {
- RID texture;
- RID filter_texture;
- uint32_t size = 0;
- };
-
- struct ShadowAtlas {
- enum {
- QUADRANT_SHIFT = 27,
- OMNI_LIGHT_FLAG = 1 << 26,
- SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1,
- SHADOW_INVALID = 0xFFFFFFFF
- };
-
- struct Quadrant {
- uint32_t subdivision = 0;
-
- struct Shadow {
- RID owner;
- uint64_t version = 0;
- uint64_t fog_version = 0; // used for fog
- uint64_t alloc_tick = 0;
-
- Shadow() {}
- };
-
- Vector<Shadow> shadows;
-
- Quadrant() {}
- } quadrants[4];
-
- int size_order[4] = { 0, 1, 2, 3 };
- uint32_t smallest_subdiv = 0;
-
- int size = 0;
- bool use_16_bits = true;
-
- RID depth;
- RID fb; //for copying
-
- HashMap<RID, uint32_t> shadow_owners;
- };
-
- RID_Owner<ShadowAtlas> shadow_atlas_owner;
-
- void _update_shadow_atlas(ShadowAtlas *shadow_atlas);
-
- void _shadow_atlas_invalidate_shadow(RendererSceneRenderRD::ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, RendererSceneRenderRD::ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx);
- bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
- bool _shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
-
+ /* Shadow atlas */
RS::ShadowQuality shadows_quality = RS::SHADOW_QUALITY_MAX; //So it always updates when first set
RS::ShadowQuality directional_shadow_quality = RS::SHADOW_QUALITY_MAX;
float shadows_quality_radius = 1.0;
@@ -331,713 +179,51 @@ private:
RS::DecalFilter decals_filter = RS::DECAL_FILTER_LINEAR_MIPMAPS;
RS::LightProjectorFilter light_projectors_filter = RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS;
- /* DIRECTIONAL SHADOW */
-
- struct DirectionalShadow {
- RID depth;
- RID fb; //when renderign direct
-
- int light_count = 0;
- int size = 0;
- bool use_16_bits = true;
- int current_light = 0;
- } directional_shadow;
-
- void _update_directional_shadow_atlas();
-
- /* SHADOW CUBEMAPS */
-
- struct ShadowCubemap {
- RID cubemap;
- RID side_fb[6];
- };
-
- HashMap<int, ShadowCubemap> shadow_cubemaps;
- ShadowCubemap *_get_shadow_cubemap(int p_size);
-
- void _create_shadow_cubemaps();
-
- /* LIGHT INSTANCE */
-
- struct LightInstance {
- struct ShadowTransform {
- CameraMatrix camera;
- Transform3D transform;
- float farplane;
- float split;
- float bias_scale;
- float shadow_texel_size;
- float range_begin;
- Rect2 atlas_rect;
- Vector2 uv_scale;
- };
-
- RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
-
- ShadowTransform shadow_transform[6];
-
- AABB aabb;
- RID self;
- RID light;
- Transform3D transform;
-
- Vector3 light_vector;
- Vector3 spot_vector;
- float linear_att = 0.0;
-
- uint64_t shadow_pass = 0;
- uint64_t last_scene_pass = 0;
- uint64_t last_scene_shadow_pass = 0;
- uint64_t last_pass = 0;
- uint32_t cull_mask = 0;
- uint32_t light_directional_index = 0;
-
- Rect2 directional_rect;
-
- HashSet<RID> shadow_atlases; //shadow atlases where this light is registered
-
- ForwardID forward_id = -1;
-
- LightInstance() {}
- };
-
- mutable RID_Owner<LightInstance> light_instance_owner;
-
- /* FOG VOLUMES */
-
- struct FogVolumeInstance {
- RID volume;
- Transform3D transform;
- bool active = false;
- };
-
- mutable RID_Owner<FogVolumeInstance> fog_volume_instance_owner;
-
- /* ENVIRONMENT */
-
- RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM;
- bool ssao_half_size = false;
- bool ssao_using_half_size = false;
- float ssao_adaptive_target = 0.5;
- int ssao_blur_passes = 2;
- float ssao_fadeout_from = 50.0;
- float ssao_fadeout_to = 300.0;
-
- RS::EnvironmentSSILQuality ssil_quality = RS::ENV_SSIL_QUALITY_MEDIUM;
- bool ssil_half_size = false;
- bool ssil_using_half_size = false;
- float ssil_adaptive_target = 0.5;
- int ssil_blur_passes = 4;
- float ssil_fadeout_from = 50.0;
- float ssil_fadeout_to = 300.0;
-
- bool glow_bicubic_upscale = false;
- bool glow_high_quality = false;
- RS::EnvironmentSSRRoughnessQuality ssr_roughness_quality = RS::ENV_SSR_ROUGHNESS_QUALITY_LOW;
-
- mutable RID_Owner<RendererSceneEnvironmentRD, true> environment_owner;
-
- /* CAMERA EFFECTS */
-
- struct CameraEffects {
- bool dof_blur_far_enabled = false;
- float dof_blur_far_distance = 10;
- float dof_blur_far_transition = 5;
-
- bool dof_blur_near_enabled = false;
- float dof_blur_near_distance = 2;
- float dof_blur_near_transition = 1;
-
- float dof_blur_amount = 0.1;
-
- bool override_exposure_enabled = false;
- float override_exposure = 1;
- };
-
- RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM;
- RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON;
- bool dof_blur_use_jitter = false;
- RS::SubSurfaceScatteringQuality sss_quality = RS::SUB_SURFACE_SCATTERING_QUALITY_MEDIUM;
- float sss_scale = 0.05;
- float sss_depth_scale = 0.01;
-
- mutable RID_Owner<CameraEffects, true> camera_effects_owner;
-
/* RENDER BUFFERS */
- ClusterBuilderSharedDataRD cluster_builder_shared;
- ClusterBuilderRD *current_cluster_builder = nullptr;
-
- struct VolumetricFog;
-
- struct RenderBuffers {
- RenderBufferData *data = nullptr;
- int internal_width = 0;
- int internal_height = 0;
- int width = 0;
- int height = 0;
- float fsr_sharpness = 0.2f;
- RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
- RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
- bool use_taa = false;
- bool use_debanding = false;
- uint32_t view_count = 1;
-
- RID render_target;
-
- uint64_t auto_exposure_version = 1;
-
- RID sss_texture; //texture for sss. This needs to be a different resolution than blur[0]
- RID internal_texture; //main texture for rendering to, must be filled after done rendering
- RID texture; //upscaled version of main texture (This uses the same resource as internal_texture if there is no upscaling)
- RID depth_texture; //main depth texture
- RID texture_fb; // framebuffer for the main texture, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
- RID upscale_texture; //used when upscaling internal_texture (This uses the same resource as internal_texture if there is no upscaling)
-
- // Access to the layers for each of our views (specifically needed for applying post effects on stereoscopic images)
- struct View {
- RID view_texture; // texture slice for this view/layer
- RID view_depth; // depth slice for this view/layer
- RID view_fb; // framebuffer for this view/layer, ONLY USED FOR MOBILE RENDERER POST EFFECTS, DO NOT USE FOR RENDERING 3D!!!
- };
- Vector<View> views;
-
- RendererSceneGIRD::SDFGI *sdfgi = nullptr;
- VolumetricFog *volumetric_fog = nullptr;
- RendererSceneGIRD::RenderBuffersGI gi;
-
- ClusterBuilderRD *cluster_builder = nullptr;
-
- //built-in textures used for ping pong image processing and blurring
- struct Blur {
- RID texture;
-
- struct Mipmap {
- RID texture;
- int width;
- int height;
-
- // only used on mobile renderer
- RID fb;
- RID half_texture;
- RID half_fb;
- };
-
- struct Layer {
- Vector<Mipmap> mipmaps;
- };
-
- Vector<Layer> layers;
- };
-
- Blur blur[2]; //the second one starts from the first mipmap
-
- struct WeightBuffers {
- RID weight;
- RID fb; // FB with both texture and weight writing into one level lower
- };
-
- // 2 full size, 2 half size
- WeightBuffers weight_buffers[4]; // Only used in raster
-
- RID depth_back_texture;
- RID depth_back_fb; // only used on mobile
-
- struct Luminance {
- Vector<RID> reduce;
- RID current;
-
- // used only on mobile renderer
- Vector<RID> fb;
- RID current_fb;
- } luminance;
-
- struct SSEffects {
- RID linear_depth;
- Vector<RID> linear_depth_slices;
-
- RID downsample_uniform_set;
-
- RID last_frame;
- Vector<RID> last_frame_slices;
-
- CameraMatrix last_frame_projection;
- Transform3D last_frame_transform;
-
- struct SSAO {
- RID ao_deinterleaved;
- Vector<RID> ao_deinterleaved_slices;
- RID ao_pong;
- Vector<RID> ao_pong_slices;
- RID ao_final;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- } ssao;
-
- struct SSIL {
- RID ssil_final;
- RID deinterleaved;
- Vector<RID> deinterleaved_slices;
- RID pong;
- Vector<RID> pong_slices;
- RID edges;
- Vector<RID> edges_slices;
- RID importance_map[2];
- RID depth_texture_view;
-
- RID gather_uniform_set;
- RID importance_map_uniform_set;
- RID projection_uniform_set;
- } ssil;
- } ss_effects;
-
- struct SSR {
- RID normal_scaled;
- RID depth_scaled;
- RID blur_radius[2];
- } ssr;
-
- struct TAA {
- RID history;
- RID temp;
- RID prev_velocity; // Last frame velocity buffer
- } taa;
-
- RID ambient_buffer;
- RID reflection_buffer;
- };
+ // TODO move into effects/luminance.h/cpp
+ void _allocate_luminance_textures(Ref<RenderSceneBuffersRD> rb);
/* GI */
bool screen_space_roughness_limiter = false;
float screen_space_roughness_limiter_amount = 0.25;
float screen_space_roughness_limiter_limit = 0.18;
- mutable RID_Owner<RenderBuffers> render_buffers_owner;
-
- void _free_render_buffer_data(RenderBuffers *rb);
- void _allocate_blur_textures(RenderBuffers *rb);
- void _allocate_depth_backbuffer_textures(RenderBuffers *rb);
- void _allocate_luminance_textures(RenderBuffers *rb);
-
- void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas, RID p_occlusion_buffer);
-
- /* Cluster */
-
- struct Cluster {
- /* Scene State UBO */
-
- // !BAS! Most data here is not just used by our clustering logic but also by other lighting implementations. Maybe rename this struct to something more appropriate
-
- enum {
- REFLECTION_AMBIENT_DISABLED = 0,
- REFLECTION_AMBIENT_ENVIRONMENT = 1,
- REFLECTION_AMBIENT_COLOR = 2,
- };
-
- struct ReflectionData {
- float box_extents[3];
- float index;
- float box_offset[3];
- uint32_t mask;
- float ambient[3]; // ambient color,
- float intensity;
- uint32_t exterior;
- uint32_t box_project;
- uint32_t ambient_mode;
- uint32_t pad;
- float local_matrix[16]; // up to here for spot and omni, rest is for directional
- };
-
- struct LightData {
- float position[3];
- float inv_radius;
- float direction[3]; // in omni, x and y are used for dual paraboloid offset
- float size;
-
- float color[3];
- float attenuation;
-
- float inv_spot_attenuation;
- float cos_spot_angle;
- float specular_amount;
- uint32_t shadow_enabled;
-
- float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
- float shadow_matrix[16];
- float shadow_bias;
- float shadow_normal_bias;
- float transmittance_bias;
- float soft_shadow_size;
- float soft_shadow_scale;
- uint32_t mask;
- float shadow_volumetric_fog_fade;
- uint32_t bake_mode;
- float projector_rect[4];
- };
-
- struct DirectionalLightData {
- float direction[3];
- float energy;
- float color[3];
- float size;
- float specular;
- uint32_t mask;
- float softshadow_angle;
- float soft_shadow_scale;
- uint32_t blend_splits;
- uint32_t shadow_enabled;
- float fade_from;
- float fade_to;
- uint32_t pad[2];
- uint32_t bake_mode;
- float shadow_volumetric_fog_fade;
- float shadow_bias[4];
- float shadow_normal_bias[4];
- float shadow_transmittance_bias[4];
- float shadow_z_range[4];
- float shadow_range_begin[4];
- float shadow_split_offsets[4];
- float shadow_matrices[4][16];
- float uv_scale1[2];
- float uv_scale2[2];
- float uv_scale3[2];
- float uv_scale4[2];
- };
-
- struct DecalData {
- float xform[16];
- float inv_extents[3];
- float albedo_mix;
- float albedo_rect[4];
- float normal_rect[4];
- float orm_rect[4];
- float emission_rect[4];
- float modulate[4];
- float emission_energy;
- uint32_t mask;
- float upper_fade;
- float lower_fade;
- float normal_xform[12];
- float normal[3];
- float normal_fade;
- };
-
- template <class T>
- struct InstanceSort {
- float depth;
- T *instance = nullptr;
- bool operator<(const InstanceSort &p_sort) const {
- return depth < p_sort.depth;
- }
- };
-
- ReflectionData *reflections = nullptr;
- InstanceSort<ReflectionProbeInstance> *reflection_sort;
- uint32_t max_reflections;
- RID reflection_buffer;
- uint32_t max_reflection_probes_per_instance;
- uint32_t reflection_count = 0;
-
- DecalData *decals = nullptr;
- InstanceSort<DecalInstance> *decal_sort;
- uint32_t max_decals;
- RID decal_buffer;
- uint32_t decal_count;
-
- LightData *omni_lights = nullptr;
- LightData *spot_lights = nullptr;
-
- InstanceSort<LightInstance> *omni_light_sort;
- InstanceSort<LightInstance> *spot_light_sort;
- uint32_t max_lights;
- RID omni_light_buffer;
- RID spot_light_buffer;
- uint32_t omni_light_count = 0;
- uint32_t spot_light_count = 0;
-
- DirectionalLightData *directional_lights = nullptr;
- uint32_t max_directional_lights;
- RID directional_light_buffer;
-
- } cluster;
-
- struct RenderState {
- const RendererSceneRender::RenderShadowData *render_shadows = nullptr;
- int render_shadow_count = 0;
- const RendererSceneRender::RenderSDFGIData *render_sdfgi_regions = nullptr;
- int render_sdfgi_region_count = 0;
- const RendererSceneRender::RenderSDFGIUpdateData *sdfgi_update_data = nullptr;
-
- uint32_t voxel_gi_count = 0;
-
- LocalVector<int> cube_shadows;
- LocalVector<int> shadows;
- LocalVector<int> directional_shadows;
-
- bool depth_prepass_used; // this does not seem used anywhere...
- } render_state;
-
- struct VolumetricFog {
- enum {
- MAX_TEMPORAL_FRAMES = 16
- };
-
- uint32_t width = 0;
- uint32_t height = 0;
- uint32_t depth = 0;
-
- float length;
- float spread;
-
- RID light_density_map;
- RID prev_light_density_map;
- RID fog_map;
- RID density_map;
- RID light_map;
- RID emissive_map;
-
- RID fog_uniform_set;
- RID copy_uniform_set;
- RID process_uniform_set;
- RID process_uniform_set2;
- RID sdfgi_uniform_set;
- RID sky_uniform_set;
-
- int last_shadow_filter = -1;
- };
-
- struct VolumetricFogShader {
- enum FogSet {
- FOG_SET_BASE,
- FOG_SET_UNIFORMS,
- FOG_SET_MATERIAL,
- FOG_SET_MAX,
- };
-
- struct FogPushConstant {
- float position[3];
- float pad;
-
- float extents[3];
- float pad2;
-
- int32_t corner[3];
- uint32_t shape;
-
- float transform[16];
- };
-
- struct VolumeUBO {
- float fog_frustum_size_begin[2];
- float fog_frustum_size_end[2];
-
- float fog_frustum_end;
- float z_near;
- float z_far;
- float time;
-
- int32_t fog_volume_size[3];
- uint32_t directional_light_count;
-
- uint32_t use_temporal_reprojection;
- uint32_t temporal_frame;
- float detail_spread;
- float temporal_blend;
-
- float to_prev_view[16];
- float transform[16];
- };
-
- ShaderCompiler compiler;
- VolumetricFogShaderRD shader;
- FogPushConstant push_constant;
- RID volume_ubo;
-
- RID default_shader;
- RID default_material;
- RID default_shader_rd;
-
- RID base_uniform_set;
-
- RID params_ubo;
-
- enum {
- VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY,
- VOLUMETRIC_FOG_PROCESS_SHADER_DENSITY_WITH_SDFGI,
- VOLUMETRIC_FOG_PROCESS_SHADER_FILTER,
- VOLUMETRIC_FOG_PROCESS_SHADER_FOG,
- VOLUMETRIC_FOG_PROCESS_SHADER_COPY,
- VOLUMETRIC_FOG_PROCESS_SHADER_MAX,
- };
-
- struct ParamsUBO {
- float fog_frustum_size_begin[2];
- float fog_frustum_size_end[2];
-
- float fog_frustum_end;
- float ambient_inject;
- float z_far;
- uint32_t filter_axis;
-
- float ambient_color[3];
- float sky_contribution;
-
- int32_t fog_volume_size[3];
- uint32_t directional_light_count;
-
- float base_emission[3];
- float base_density;
-
- float base_scattering[3];
- float phase_g;
-
- float detail_spread;
- float gi_inject;
- uint32_t max_voxel_gi_instances;
- uint32_t cluster_type_size;
+ /* Light data */
- float screen_size[2];
- uint32_t cluster_shift;
- uint32_t cluster_width;
-
- uint32_t max_cluster_element_count_div_32;
- uint32_t use_temporal_reprojection;
- uint32_t temporal_frame;
- float temporal_blend;
-
- float cam_rotation[12];
- float to_prev_view[16];
- float radiance_inverse_xform[12];
- };
-
- VolumetricFogProcessShaderRD process_shader;
+ uint64_t scene_pass = 0;
- RID process_shader_version;
- RID process_pipelines[VOLUMETRIC_FOG_PROCESS_SHADER_MAX];
+ uint32_t max_cluster_elements = 512;
- } volumetric_fog;
+ /* Volumetric Fog */
- uint32_t volumetric_fog_depth = 128;
uint32_t volumetric_fog_size = 128;
+ uint32_t volumetric_fog_depth = 128;
bool volumetric_fog_filter_active = true;
- Vector3i _point_get_position_in_froxel_volume(const Vector3 &p_point, float fog_end, const Vector2 &fog_near_size, const Vector2 &fog_far_size, float volumetric_fog_detail_spread, const Vector3 &fog_size, const Transform3D &p_cam_transform);
- void _volumetric_fog_erase(RenderBuffers *rb);
- void _update_volumetric_fog(RID p_render_buffers, RID p_environment, const CameraMatrix &p_cam_projection, const Transform3D &p_cam_transform, const Transform3D &p_prev_cam_inv_transform, RID p_shadow_atlas, int p_directional_light_count, bool p_use_directional_shadows, int p_positional_light_count, int p_voxel_gi_count, const PagedArray<RID> &p_fog_volumes);
-
- struct FogShaderData : public RendererRD::ShaderData {
- bool valid = false;
- RID version;
-
- RID pipeline;
- HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> uniforms;
- Vector<ShaderCompiler::GeneratedCode::Texture> texture_uniforms;
-
- Vector<uint32_t> ubo_offsets;
- uint32_t ubo_size = 0;
-
- String path;
- String code;
- HashMap<StringName, HashMap<int, RID>> default_texture_params;
-
- bool uses_time = false;
-
- virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
- virtual bool is_animated() const;
- virtual bool casts_shadows() const;
- virtual Variant get_default_parameter(const StringName &p_parameter) const;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const;
-
- FogShaderData() {}
- virtual ~FogShaderData();
- };
-
- struct FogMaterialData : public RendererRD::MaterialData {
- FogShaderData *shader_data = nullptr;
- RID uniform_set;
- bool uniform_set_updated;
-
- virtual void set_render_priority(int p_priority) {}
- virtual void set_next_pass(RID p_pass) {}
- virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~FogMaterialData();
- };
-
- RendererRD::ShaderData *_create_fog_shader_func();
- static RendererRD::ShaderData *_create_fog_shader_funcs();
-
- RendererRD::MaterialData *_create_fog_material_func(FogShaderData *p_shader);
- static RendererRD::MaterialData *_create_fog_material_funcs(RendererRD::ShaderData *p_shader);
-
- RID shadow_sampler;
-
- uint64_t scene_pass = 0;
- uint64_t shadow_atlas_realloc_tolerance_msec = 500;
-
- /* !BAS! is this used anywhere?
- struct SDFGICosineNeighbour {
- uint32_t neighbour;
- float weight;
- };
- */
-
- uint32_t max_cluster_elements = 512;
-
- void _render_shadow_pass(RID p_light, RID p_shadow_atlas, int p_pass, const PagedArray<GeometryInstance *> &p_instances, const Plane &p_camera_plane = Plane(), float p_lod_distance_multiplier = 0, float p_screen_mesh_lod_threshold = 0.0, bool p_open_pass = true, bool p_close_pass = true, bool p_clear_region = true, RendererScene::RenderInfo *p_render_info = nullptr);
-
public:
- virtual Transform3D geometry_instance_get_transform(GeometryInstance *p_instance) = 0;
- virtual AABB geometry_instance_get_aabb(GeometryInstance *p_instance) = 0;
-
- /* SHADOW ATLAS API */
-
- virtual RID shadow_atlas_create() override;
- virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
- virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
- virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override;
- _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
- ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
- ERR_FAIL_COND_V(!atlas, false);
- return atlas->shadow_owners.has(p_light_intance);
- }
+ static RendererSceneRenderRD *get_singleton() { return singleton; }
- _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) {
- ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
- ERR_FAIL_COND_V(!atlas, RID());
- return atlas->depth;
- }
+ /* LIGHTING */
- _FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) {
- ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
- ERR_FAIL_COND_V(!atlas, Size2i());
- return Size2(atlas->size, atlas->size);
- }
+ virtual void setup_added_reflection_probe(const Transform3D &p_transform, const Vector3 &p_half_extents){};
+ virtual void setup_added_light(const RS::LightType p_type, const Transform3D &p_transform, float p_radius, float p_spot_aperture){};
+ virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_extents){};
- virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override;
- virtual int get_directional_light_shadow_size(RID p_light_intance) override;
- virtual void set_directional_shadow_count(int p_count) override;
+ /* GI */
- _FORCE_INLINE_ RID directional_shadow_get_texture() {
- return directional_shadow.depth;
- }
+ RendererRD::GI *get_gi() { return &gi; }
- _FORCE_INLINE_ Size2i directional_shadow_get_size() {
- return Size2i(directional_shadow.size, directional_shadow.size);
- }
+ /* SKY */
+
+ RendererRD::SkyRD *get_sky() { return &sky; }
/* SDFGI UPDATE */
- virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
- virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const override;
- virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const override;
- virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const override;
+ virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) override;
+ virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const override;
+ virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
+ virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const override;
RID sdfgi_get_ubo() const { return gi.sdfgi_ubo; }
/* SKY API */
@@ -1052,343 +238,44 @@ public:
/* ENVIRONMENT API */
- virtual RID environment_allocate() override;
- virtual void environment_initialize(RID p_rid) override;
-
- virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) override;
- virtual void environment_set_sky(RID p_env, RID p_sky) override;
- virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) override;
- virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) override;
- virtual void environment_set_bg_color(RID p_env, const Color &p_color) override;
- virtual void environment_set_bg_energy(RID p_env, float p_energy) override;
- virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) override;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) override;
-
- virtual RS::EnvironmentBG environment_get_background(RID p_env) const override;
- RID environment_get_sky(RID p_env) const;
- float environment_get_sky_custom_fov(RID p_env) const;
- Basis environment_get_sky_orientation(RID p_env) const;
- Color environment_get_bg_color(RID p_env) const;
- float environment_get_bg_energy(RID p_env) const;
- virtual int environment_get_canvas_max_layer(RID p_env) const override;
- Color environment_get_ambient_light_color(RID p_env) const;
- RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
- float environment_get_ambient_light_energy(RID p_env) const;
- float environment_get_ambient_sky_contribution(RID p_env) const;
- RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
-
- virtual bool is_environment(RID p_env) const override;
-
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) override;
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) override;
virtual void environment_glow_set_use_high_quality(bool p_enable) override;
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) override;
- bool environment_is_fog_enabled(RID p_env) const;
- Color environment_get_fog_light_color(RID p_env) const;
- float environment_get_fog_light_energy(RID p_env) const;
- float environment_get_fog_sun_scatter(RID p_env) const;
- float environment_get_fog_density(RID p_env) const;
- float environment_get_fog_height(RID p_env) const;
- float environment_get_fog_height_density(RID p_env) const;
- float environment_get_fog_aerial_perspective(RID p_env) const;
-
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) override;
-
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) override;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) override;
- virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) override;
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) override;
- virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
- virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) override;
- virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) override;
- bool environment_is_ssao_enabled(RID p_env) const;
- float environment_get_ssao_ao_affect(RID p_env) const;
- float environment_get_ssao_light_affect(RID p_env) const;
- bool environment_is_ssil_enabled(RID p_env) const;
- bool environment_is_ssr_enabled(RID p_env) const;
- bool environment_is_sdfgi_enabled(RID p_env) const;
-
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) override;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) override;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) override;
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) override;
- virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) override;
- RS::EnvironmentSSRRoughnessQuality environment_get_ssr_roughness_quality() const;
-
- virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) override;
- virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) override;
-
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) override;
- /* CAMERA EFFECTS */
-
- virtual RID camera_effects_allocate() override;
- virtual void camera_effects_initialize(RID p_rid) override;
-
- virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) override;
- virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) override;
-
- virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) override;
- virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) override;
-
- bool camera_effects_uses_dof(RID p_camera_effects) {
- CameraEffects *camfx = camera_effects_owner.get_or_null(p_camera_effects);
-
- return camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0;
- }
-
- /* LIGHT INSTANCE API */
-
- virtual RID light_instance_create(RID p_light) override;
- virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
- virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
- virtual void light_instance_mark_visible(RID p_light_instance) override;
-
- _FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->light;
+ _FORCE_INLINE_ bool is_using_physical_light_units() {
+ return use_physical_light_units;
}
- _FORCE_INLINE_ Transform3D light_instance_get_base_transform(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->transform;
- }
-
- _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas, Vector2i &r_omni_offset) {
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- uint32_t key = shadow_atlas->shadow_owners[li->self];
-
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
- uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK;
-
- ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2());
-
- uint32_t atlas_size = shadow_atlas->size;
- uint32_t quadrant_size = atlas_size >> 1;
-
- uint32_t x = (quadrant & 1) * quadrant_size;
- uint32_t y = (quadrant >> 1) * quadrant_size;
-
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
- x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
- y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
-
- if (key & ShadowAtlas::OMNI_LIGHT_FLAG) {
- if (((shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision) == 0) {
- r_omni_offset.x = 1 - int(shadow_atlas->quadrants[quadrant].subdivision);
- r_omni_offset.y = 1;
- } else {
- r_omni_offset.x = 1;
- r_omni_offset.y = 0;
- }
- }
-
- uint32_t width = shadow_size;
- uint32_t height = shadow_size;
-
- return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size));
- }
-
- _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].camera;
- }
-
- _FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) {
-#ifdef DEBUG_ENABLED
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0);
-#endif
- ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
- ERR_FAIL_COND_V(!shadow_atlas, 0);
-#ifdef DEBUG_ENABLED
- ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0);
-#endif
- uint32_t key = shadow_atlas->shadow_owners[p_light_instance];
-
- uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3;
-
- uint32_t quadrant_size = shadow_atlas->size >> 1;
+ /* REFLECTION PROBE */
- uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
-
- return float(1.0) / shadow_size;
- }
-
- _FORCE_INLINE_ Transform3D
- light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].transform;
- }
- _FORCE_INLINE_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].bias_scale;
- }
- _FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].farplane;
- }
- _FORCE_INLINE_ float light_instance_get_shadow_range_begin(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].range_begin;
- }
-
- _FORCE_INLINE_ Vector2 light_instance_get_shadow_uv_scale(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].uv_scale;
- }
-
- _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].atlas_rect;
- }
-
- _FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].split;
- }
-
- _FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->shadow_transform[p_index].shadow_texel_size;
- }
-
- _FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- li->last_pass = p_pass;
- }
-
- _FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->last_pass;
- }
-
- _FORCE_INLINE_ ForwardID light_instance_get_forward_id(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->forward_id;
- }
-
- _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
- LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
- return li->light_type;
- }
+ virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth);
/* FOG VOLUMES */
+ uint32_t get_volumetric_fog_size() const { return volumetric_fog_size; }
+ uint32_t get_volumetric_fog_depth() const { return volumetric_fog_depth; }
+ bool get_volumetric_fog_filter_active() const { return volumetric_fog_filter_active; }
+
virtual RID fog_volume_instance_create(RID p_fog_volume) override;
virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) override;
virtual void fog_volume_instance_set_active(RID p_fog_volume_instance, bool p_active) override;
virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const override;
virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const override;
- virtual RID reflection_atlas_create() override;
- virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
- virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
-
- _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
- ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_ref_atlas);
- ERR_FAIL_COND_V(!atlas, RID());
- return atlas->reflection;
- }
-
- virtual RID reflection_probe_instance_create(RID p_probe) override;
- virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
- virtual void reflection_probe_release_atlas_index(RID p_instance) override;
- virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
- virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
- virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
- virtual RID reflection_probe_create_framebuffer(RID p_color, RID p_depth);
- virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
-
- uint32_t reflection_probe_instance_get_resolution(RID p_instance);
- RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
- RID reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index);
-
- _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, RID());
-
- return rpi->probe;
- }
-
- _FORCE_INLINE_ ForwardID reflection_probe_instance_get_forward_id(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, 0);
-
- return rpi->forward_id;
- }
-
- _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND(!rpi);
- rpi->last_pass = p_render_pass;
- }
-
- _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, 0);
-
- return rpi->last_pass;
- }
-
- _FORCE_INLINE_ Transform3D reflection_probe_instance_get_transform(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, Transform3D());
-
- return rpi->transform;
- }
-
- _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) {
- ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
- ERR_FAIL_COND_V(!rpi, -1);
-
- return rpi->atlas_index;
- }
-
- virtual RID decal_instance_create(RID p_decal) override;
- virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) override;
-
- _FORCE_INLINE_ RID decal_instance_get_base(RID p_decal) const {
- DecalInstance *decal = decal_instance_owner.get_or_null(p_decal);
- return decal->decal;
- }
-
- _FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal) const {
- DecalInstance *decal = decal_instance_owner.get_or_null(p_decal);
- return decal->forward_id;
- }
-
- _FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal) const {
- DecalInstance *decal = decal_instance_owner.get_or_null(p_decal);
- return decal->transform;
- }
-
- virtual RID lightmap_instance_create(RID p_lightmap) override;
- virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
- _FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
- return lightmap_instance_owner.get_or_null(p_lightmap_instance) != nullptr;
- }
-
- _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
- LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance);
- return li->lightmap;
- }
- _FORCE_INLINE_ Transform3D lightmap_instance_get_transform(RID p_lightmap_instance) {
- LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance);
- return li->transform;
- }
-
/* gi light probes */
virtual RID voxel_gi_instance_create(RID p_base) override;
virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) override;
virtual bool voxel_gi_needs_update(RID p_probe) const override;
- virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RendererSceneRender::GeometryInstance *> &p_dynamic_objects) override;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) override;
virtual void voxel_gi_set_quality(RS::VoxelGIQuality p_quality) override { gi.voxel_gi_quality = p_quality; }
/* render buffers */
@@ -1396,46 +283,19 @@ public:
virtual float _render_buffers_get_luminance_multiplier();
virtual RD::DataFormat _render_buffers_get_color_format();
virtual bool _render_buffers_can_be_storage();
- virtual RID render_buffers_create() override;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual Ref<RenderSceneBuffers> render_buffers_create() override;
virtual void gi_set_use_half_resolution(bool p_enable) override;
- RID render_buffers_get_depth_texture(RID p_render_buffers);
- RID render_buffers_get_ao_texture(RID p_render_buffers);
- RID render_buffers_get_ssil_texture(RID p_render_buffers);
- RID render_buffers_get_back_buffer_texture(RID p_render_buffers);
- RID render_buffers_get_back_depth_texture(RID p_render_buffers);
- RID render_buffers_get_voxel_gi_buffer(RID p_render_buffers);
RID render_buffers_get_default_voxel_gi_buffer();
- RID render_buffers_get_gi_ambient_texture(RID p_render_buffers);
- RID render_buffers_get_gi_reflection_texture(RID p_render_buffers);
-
- uint32_t render_buffers_get_sdfgi_cascade_count(RID p_render_buffers) const;
- bool render_buffers_is_sdfgi_enabled(RID p_render_buffers) const;
- RID render_buffers_get_sdfgi_irradiance_probes(RID p_render_buffers) const;
- Vector3 render_buffers_get_sdfgi_cascade_offset(RID p_render_buffers, uint32_t p_cascade) const;
- Vector3i render_buffers_get_sdfgi_cascade_probe_offset(RID p_render_buffers, uint32_t p_cascade) const;
- float render_buffers_get_sdfgi_cascade_probe_size(RID p_render_buffers, uint32_t p_cascade) const;
- float render_buffers_get_sdfgi_normal_bias(RID p_render_buffers) const;
- uint32_t render_buffers_get_sdfgi_cascade_probe_count(RID p_render_buffers) const;
- uint32_t render_buffers_get_sdfgi_cascade_size(RID p_render_buffers) const;
- bool render_buffers_is_sdfgi_using_occlusion(RID p_render_buffers) const;
- float render_buffers_get_sdfgi_energy(RID p_render_buffers) const;
- RID render_buffers_get_sdfgi_occlusion_texture(RID p_render_buffers) const;
-
- bool render_buffers_has_volumetric_fog(RID p_render_buffers) const;
- RID render_buffers_get_volumetric_fog_texture(RID p_render_buffers);
- RID render_buffers_get_volumetric_fog_sky_uniform_set(RID p_render_buffers);
- float render_buffers_get_volumetric_fog_end(RID p_render_buffers);
- float render_buffers_get_volumetric_fog_detail_spread(RID p_render_buffers);
+ virtual void base_uniforms_changed() = 0;
virtual void update_uniform_sets(){};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) override;
+ virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RenderingMethod::RenderInfo *r_render_info = nullptr) override;
- virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
+ virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) override;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) override;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) override;
virtual void set_scene_pass(uint64_t p_pass) override {
scene_pass = p_pass;
@@ -1449,38 +309,62 @@ public:
virtual float screen_space_roughness_limiter_get_amount() const;
virtual float screen_space_roughness_limiter_get_limit() const;
- virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) override;
- RS::SubSurfaceScatteringQuality sub_surface_scattering_get_quality() const;
- virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) override;
-
- virtual void shadows_quality_set(RS::ShadowQuality p_quality) override;
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) override;
+ virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
+ virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) override;
virtual void decals_set_filter(RS::DecalFilter p_filter) override;
virtual void light_projectors_set_filter(RS::LightProjectorFilter p_filter) override;
- _FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const { return shadows_quality; }
- _FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const { return directional_shadow_quality; }
- _FORCE_INLINE_ float shadows_quality_radius_get() const { return shadows_quality_radius; }
- _FORCE_INLINE_ float directional_shadow_quality_radius_get() const { return directional_shadow_quality_radius; }
+ _FORCE_INLINE_ RS::ShadowQuality shadows_quality_get() const {
+ return shadows_quality;
+ }
+ _FORCE_INLINE_ RS::ShadowQuality directional_shadow_quality_get() const {
+ return directional_shadow_quality;
+ }
+ _FORCE_INLINE_ float shadows_quality_radius_get() const {
+ return shadows_quality_radius;
+ }
+ _FORCE_INLINE_ float directional_shadow_quality_radius_get() const {
+ return directional_shadow_quality_radius;
+ }
- _FORCE_INLINE_ float *directional_penumbra_shadow_kernel_get() { return directional_penumbra_shadow_kernel; }
- _FORCE_INLINE_ float *directional_soft_shadow_kernel_get() { return directional_soft_shadow_kernel; }
- _FORCE_INLINE_ float *penumbra_shadow_kernel_get() { return penumbra_shadow_kernel; }
- _FORCE_INLINE_ float *soft_shadow_kernel_get() { return soft_shadow_kernel; }
+ _FORCE_INLINE_ float *directional_penumbra_shadow_kernel_get() {
+ return directional_penumbra_shadow_kernel;
+ }
+ _FORCE_INLINE_ float *directional_soft_shadow_kernel_get() {
+ return directional_soft_shadow_kernel;
+ }
+ _FORCE_INLINE_ float *penumbra_shadow_kernel_get() {
+ return penumbra_shadow_kernel;
+ }
+ _FORCE_INLINE_ float *soft_shadow_kernel_get() {
+ return soft_shadow_kernel;
+ }
- _FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const { return directional_penumbra_shadow_samples; }
- _FORCE_INLINE_ int directional_soft_shadow_samples_get() const { return directional_soft_shadow_samples; }
- _FORCE_INLINE_ int penumbra_shadow_samples_get() const { return penumbra_shadow_samples; }
- _FORCE_INLINE_ int soft_shadow_samples_get() const { return soft_shadow_samples; }
+ _FORCE_INLINE_ int directional_penumbra_shadow_samples_get() const {
+ return directional_penumbra_shadow_samples;
+ }
+ _FORCE_INLINE_ int directional_soft_shadow_samples_get() const {
+ return directional_soft_shadow_samples;
+ }
+ _FORCE_INLINE_ int penumbra_shadow_samples_get() const {
+ return penumbra_shadow_samples;
+ }
+ _FORCE_INLINE_ int soft_shadow_samples_get() const {
+ return soft_shadow_samples;
+ }
- _FORCE_INLINE_ RS::LightProjectorFilter light_projectors_get_filter() const { return light_projectors_filter; }
- _FORCE_INLINE_ RS::DecalFilter decals_get_filter() const { return decals_filter; }
+ _FORCE_INLINE_ RS::LightProjectorFilter light_projectors_get_filter() const {
+ return light_projectors_filter;
+ }
+ _FORCE_INLINE_ RS::DecalFilter decals_get_filter() const {
+ return decals_filter;
+ }
int get_roughness_layers() const;
bool is_using_radiance_cubemap_array() const;
- virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) override;
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) override;
virtual bool free(RID p_rid) override;
@@ -1493,24 +377,17 @@ public:
virtual void set_time(double p_time, double p_step) override;
- RID get_reflection_probe_buffer();
- RID get_omni_light_buffer();
- RID get_spot_light_buffer();
- RID get_directional_light_buffer();
- RID get_decal_buffer();
- int get_max_directional_lights() const;
-
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) override;
+ virtual bool is_vrs_supported() const;
virtual bool is_dynamic_gi_supported() const;
- virtual bool is_clustered_enabled() const;
virtual bool is_volumetric_supported() const;
virtual uint32_t get_max_elements() const;
void init();
- RendererSceneRenderRD(RendererStorageRD *p_storage);
+ RendererSceneRenderRD();
~RendererSceneRenderRD();
};
-#endif // RASTERIZER_SCENE_RD_H
+#endif // RENDERER_SCENE_RENDER_RD_H
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.cpp b/servers/rendering/renderer_rd/renderer_storage_rd.cpp
deleted file mode 100644
index d5166c6905..0000000000
--- a/servers/rendering/renderer_rd/renderer_storage_rd.cpp
+++ /dev/null
@@ -1,751 +0,0 @@
-/*************************************************************************/
-/* renderer_storage_rd.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#include "renderer_storage_rd.h"
-
-#include "core/config/engine.h"
-#include "core/config/project_settings.h"
-#include "core/io/resource_loader.h"
-#include "core/math/math_defs.h"
-#include "renderer_compositor_rd.h"
-#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/mesh_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/particles_storage.h"
-#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
-#include "servers/rendering/rendering_server_globals.h"
-#include "servers/rendering/shader_language.h"
-
-/* FOG VOLUMES */
-
-RID RendererStorageRD::fog_volume_allocate() {
- return fog_volume_owner.allocate_rid();
-}
-void RendererStorageRD::fog_volume_initialize(RID p_rid) {
- fog_volume_owner.initialize_rid(p_rid, FogVolume());
-}
-
-void RendererStorageRD::fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND(!fog_volume);
-
- if (p_shape == fog_volume->shape) {
- return;
- }
-
- fog_volume->shape = p_shape;
- fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND(!fog_volume);
-
- fog_volume->extents = p_extents;
- fog_volume->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-void RendererStorageRD::fog_volume_set_material(RID p_fog_volume, RID p_material) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND(!fog_volume);
- fog_volume->material = p_material;
-}
-
-RID RendererStorageRD::fog_volume_get_material(RID p_fog_volume) const {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, RID());
-
- return fog_volume->material;
-}
-
-RS::FogVolumeShape RendererStorageRD::fog_volume_get_shape(RID p_fog_volume) const {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, RS::FOG_VOLUME_SHAPE_BOX);
-
- return fog_volume->shape;
-}
-
-AABB RendererStorageRD::fog_volume_get_aabb(RID p_fog_volume) const {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, AABB());
-
- switch (fog_volume->shape) {
- case RS::FOG_VOLUME_SHAPE_ELLIPSOID:
- case RS::FOG_VOLUME_SHAPE_CONE:
- case RS::FOG_VOLUME_SHAPE_CYLINDER:
- case RS::FOG_VOLUME_SHAPE_BOX: {
- AABB aabb;
- aabb.position = -fog_volume->extents;
- aabb.size = fog_volume->extents * 2;
- return aabb;
- }
- default: {
- // Need some size otherwise will get culled
- return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2));
- }
- }
-
- return AABB();
-}
-
-Vector3 RendererStorageRD::fog_volume_get_extents(RID p_fog_volume) const {
- const FogVolume *fog_volume = fog_volume_owner.get_or_null(p_fog_volume);
- ERR_FAIL_COND_V(!fog_volume, Vector3());
- return fog_volume->extents;
-}
-
-/* VISIBILITY NOTIFIER */
-
-RID RendererStorageRD::visibility_notifier_allocate() {
- return visibility_notifier_owner.allocate_rid();
-}
-void RendererStorageRD::visibility_notifier_initialize(RID p_notifier) {
- visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
-}
-void RendererStorageRD::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND(!vn);
- vn->aabb = p_aabb;
- vn->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-void RendererStorageRD::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND(!vn);
- vn->enter_callback = p_enter_callbable;
- vn->exit_callback = p_exit_callable;
-}
-
-AABB RendererStorageRD::visibility_notifier_get_aabb(RID p_notifier) const {
- const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND_V(!vn, AABB());
- return vn->aabb;
-}
-void RendererStorageRD::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
- ERR_FAIL_COND(!vn);
-
- if (p_enter) {
- if (!vn->enter_callback.is_null()) {
- if (p_deferred) {
- vn->enter_callback.call_deferred(nullptr, 0);
- } else {
- Variant r;
- Callable::CallError ce;
- vn->enter_callback.call(nullptr, 0, r, ce);
- }
- }
- } else {
- if (!vn->exit_callback.is_null()) {
- if (p_deferred) {
- vn->exit_callback.call_deferred(nullptr, 0);
- } else {
- Variant r;
- Callable::CallError ce;
- vn->exit_callback.call(nullptr, 0, r, ce);
- }
- }
- }
-}
-
-/* VOXEL GI */
-
-RID RendererStorageRD::voxel_gi_allocate() {
- return voxel_gi_owner.allocate_rid();
-}
-void RendererStorageRD::voxel_gi_initialize(RID p_voxel_gi) {
- voxel_gi_owner.initialize_rid(p_voxel_gi, VoxelGI());
-}
-
-void RendererStorageRD::voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- if (voxel_gi->octree_buffer.is_valid()) {
- RD::get_singleton()->free(voxel_gi->octree_buffer);
- RD::get_singleton()->free(voxel_gi->data_buffer);
- if (voxel_gi->sdf_texture.is_valid()) {
- RD::get_singleton()->free(voxel_gi->sdf_texture);
- }
-
- voxel_gi->sdf_texture = RID();
- voxel_gi->octree_buffer = RID();
- voxel_gi->data_buffer = RID();
- voxel_gi->octree_buffer_size = 0;
- voxel_gi->data_buffer_size = 0;
- voxel_gi->cell_count = 0;
- }
-
- voxel_gi->to_cell_xform = p_to_cell_xform;
- voxel_gi->bounds = p_aabb;
- voxel_gi->octree_size = p_octree_size;
- voxel_gi->level_counts = p_level_counts;
-
- if (p_octree_cells.size()) {
- ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32
-
- uint32_t cell_count = p_octree_cells.size() / 32;
-
- ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches
-
- voxel_gi->cell_count = cell_count;
- voxel_gi->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells);
- voxel_gi->octree_buffer_size = p_octree_cells.size();
- voxel_gi->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells);
- voxel_gi->data_buffer_size = p_data_cells.size();
-
- if (p_distance_field.size()) {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = voxel_gi->octree_size.x;
- tf.height = voxel_gi->octree_size.y;
- tf.depth = voxel_gi->octree_size.z;
- tf.texture_type = RD::TEXTURE_TYPE_3D;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
- Vector<Vector<uint8_t>> s;
- s.push_back(p_distance_field);
- voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s);
- }
-#if 0
- {
- RD::TextureFormat tf;
- tf.format = RD::DATA_FORMAT_R8_UNORM;
- tf.width = voxel_gi->octree_size.x;
- tf.height = voxel_gi->octree_size.y;
- tf.depth = voxel_gi->octree_size.z;
- tf.type = RD::TEXTURE_TYPE_3D;
- tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
- tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM);
- tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT);
- voxel_gi->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView());
- }
- RID shared_tex;
- {
- RD::TextureView tv;
- tv.format_override = RD::DATA_FORMAT_R8_UINT;
- shared_tex = RD::get_singleton()->texture_create_shared(tv, voxel_gi->sdf_texture);
- }
- //update SDF texture
- Vector<RD::Uniform> uniforms;
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 1;
- u.append_id(voxel_gi->octree_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.binding = 2;
- u.append_id(voxel_gi->data_buffer);
- uniforms.push_back(u);
- }
- {
- RD::Uniform u;
- u.uniform_type = RD::UNIFORM_TYPE_IMAGE;
- u.binding = 3;
- u.append_id(shared_tex);
- uniforms.push_back(u);
- }
-
- RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, voxel_gi_sdf_shader_version_shader, 0);
-
- {
- uint32_t push_constant[4] = { 0, 0, 0, 0 };
-
- for (int i = 0; i < voxel_gi->level_counts.size() - 1; i++) {
- push_constant[0] += voxel_gi->level_counts[i];
- }
- push_constant[1] = push_constant[0] + voxel_gi->level_counts[voxel_gi->level_counts.size() - 1];
-
- print_line("offset: " + itos(push_constant[0]));
- print_line("size: " + itos(push_constant[1]));
- //create SDF
- RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
- RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, voxel_gi_sdf_shader_pipeline);
- RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0);
- RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4);
- RD::get_singleton()->compute_list_dispatch(compute_list, voxel_gi->octree_size.x / 4, voxel_gi->octree_size.y / 4, voxel_gi->octree_size.z / 4);
- RD::get_singleton()->compute_list_end();
- }
-
- RD::get_singleton()->free(uniform_set);
- RD::get_singleton()->free(shared_tex);
- }
-#endif
- }
-
- voxel_gi->version++;
- voxel_gi->data_version++;
-
- voxel_gi->dependency.changed_notify(DEPENDENCY_CHANGED_AABB);
-}
-
-AABB RendererStorageRD::voxel_gi_get_bounds(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, AABB());
-
- return voxel_gi->bounds;
-}
-
-Vector3i RendererStorageRD::voxel_gi_get_octree_size(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, Vector3i());
- return voxel_gi->octree_size;
-}
-
-Vector<uint8_t> RendererStorageRD::voxel_gi_get_octree_cells(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
-
- if (voxel_gi->octree_buffer.is_valid()) {
- return RD::get_singleton()->buffer_get_data(voxel_gi->octree_buffer);
- }
- return Vector<uint8_t>();
-}
-
-Vector<uint8_t> RendererStorageRD::voxel_gi_get_data_cells(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
-
- if (voxel_gi->data_buffer.is_valid()) {
- return RD::get_singleton()->buffer_get_data(voxel_gi->data_buffer);
- }
- return Vector<uint8_t>();
-}
-
-Vector<uint8_t> RendererStorageRD::voxel_gi_get_distance_field(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, Vector<uint8_t>());
-
- if (voxel_gi->data_buffer.is_valid()) {
- return RD::get_singleton()->texture_get_data(voxel_gi->sdf_texture, 0);
- }
- return Vector<uint8_t>();
-}
-
-Vector<int> RendererStorageRD::voxel_gi_get_level_counts(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, Vector<int>());
-
- return voxel_gi->level_counts;
-}
-
-Transform3D RendererStorageRD::voxel_gi_get_to_cell_xform(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, Transform3D());
-
- return voxel_gi->to_cell_xform;
-}
-
-void RendererStorageRD::voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->dynamic_range = p_range;
- voxel_gi->version++;
-}
-
-float RendererStorageRD::voxel_gi_get_dynamic_range(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
-
- return voxel_gi->dynamic_range;
-}
-
-void RendererStorageRD::voxel_gi_set_propagation(RID p_voxel_gi, float p_range) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->propagation = p_range;
- voxel_gi->version++;
-}
-
-float RendererStorageRD::voxel_gi_get_propagation(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->propagation;
-}
-
-void RendererStorageRD::voxel_gi_set_energy(RID p_voxel_gi, float p_energy) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->energy = p_energy;
-}
-
-float RendererStorageRD::voxel_gi_get_energy(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->energy;
-}
-
-void RendererStorageRD::voxel_gi_set_bias(RID p_voxel_gi, float p_bias) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->bias = p_bias;
-}
-
-float RendererStorageRD::voxel_gi_get_bias(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->bias;
-}
-
-void RendererStorageRD::voxel_gi_set_normal_bias(RID p_voxel_gi, float p_normal_bias) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->normal_bias = p_normal_bias;
-}
-
-float RendererStorageRD::voxel_gi_get_normal_bias(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->normal_bias;
-}
-
-void RendererStorageRD::voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->anisotropy_strength = p_strength;
-}
-
-float RendererStorageRD::voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->anisotropy_strength;
-}
-
-void RendererStorageRD::voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->interior = p_enable;
-}
-
-void RendererStorageRD::voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND(!voxel_gi);
-
- voxel_gi->use_two_bounces = p_enable;
- voxel_gi->version++;
-}
-
-bool RendererStorageRD::voxel_gi_is_using_two_bounces(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, false);
- return voxel_gi->use_two_bounces;
-}
-
-bool RendererStorageRD::voxel_gi_is_interior(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->interior;
-}
-
-uint32_t RendererStorageRD::voxel_gi_get_version(RID p_voxel_gi) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->version;
-}
-
-uint32_t RendererStorageRD::voxel_gi_get_data_version(RID p_voxel_gi) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, 0);
- return voxel_gi->data_version;
-}
-
-RID RendererStorageRD::voxel_gi_get_octree_buffer(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, RID());
- return voxel_gi->octree_buffer;
-}
-
-RID RendererStorageRD::voxel_gi_get_data_buffer(RID p_voxel_gi) const {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, RID());
- return voxel_gi->data_buffer;
-}
-
-RID RendererStorageRD::voxel_gi_get_sdf_texture(RID p_voxel_gi) {
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_voxel_gi);
- ERR_FAIL_COND_V(!voxel_gi, RID());
-
- return voxel_gi->sdf_texture;
-}
-
-/* misc */
-
-void RendererStorageRD::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
- if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_base)) {
- RendererRD::Mesh *mesh = RendererRD::MeshStorage::get_singleton()->get_mesh(p_base);
- p_instance->update_dependency(&mesh->dependency);
- } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_base)) {
- RendererRD::MultiMesh *multimesh = RendererRD::MeshStorage::get_singleton()->get_multimesh(p_base);
- p_instance->update_dependency(&multimesh->dependency);
- if (multimesh->mesh.is_valid()) {
- base_update_dependency(multimesh->mesh, p_instance);
- }
- } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
- RendererRD::ReflectionProbe *rp = RendererRD::LightStorage::get_singleton()->get_reflection_probe(p_base);
- p_instance->update_dependency(&rp->dependency);
- } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_base)) {
- RendererRD::Decal *decal = RendererRD::TextureStorage::get_singleton()->get_decal(p_base);
- p_instance->update_dependency(&decal->dependency);
- } else if (voxel_gi_owner.owns(p_base)) {
- VoxelGI *gip = voxel_gi_owner.get_or_null(p_base);
- p_instance->update_dependency(&gip->dependency);
- } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_base)) {
- RendererRD::Lightmap *lm = RendererRD::LightStorage::get_singleton()->get_lightmap(p_base);
- p_instance->update_dependency(&lm->dependency);
- } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_base)) {
- RendererRD::Light *l = RendererRD::LightStorage::get_singleton()->get_light(p_base);
- p_instance->update_dependency(&l->dependency);
- } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_base)) {
- RendererRD::Particles *p = RendererRD::ParticlesStorage::get_singleton()->get_particles(p_base);
- p_instance->update_dependency(&p->dependency);
- } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
- RendererRD::ParticlesCollision *pc = RendererRD::ParticlesStorage::get_singleton()->get_particles_collision(p_base);
- p_instance->update_dependency(&pc->dependency);
- } else if (fog_volume_owner.owns(p_base)) {
- FogVolume *fv = fog_volume_owner.get_or_null(p_base);
- p_instance->update_dependency(&fv->dependency);
- } else if (visibility_notifier_owner.owns(p_base)) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_base);
- p_instance->update_dependency(&vn->dependency);
- }
-}
-
-RS::InstanceType RendererStorageRD::get_base_type(RID p_rid) const {
- if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
- return RS::INSTANCE_MESH;
- }
- if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
- return RS::INSTANCE_MULTIMESH;
- }
- if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
- return RS::INSTANCE_REFLECTION_PROBE;
- }
- if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
- return RS::INSTANCE_DECAL;
- }
- if (voxel_gi_owner.owns(p_rid)) {
- return RS::INSTANCE_VOXEL_GI;
- }
- if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
- return RS::INSTANCE_LIGHT;
- }
- if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
- return RS::INSTANCE_LIGHTMAP;
- }
- if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
- return RS::INSTANCE_PARTICLES;
- }
- if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
- return RS::INSTANCE_PARTICLES_COLLISION;
- }
- if (fog_volume_owner.owns(p_rid)) {
- return RS::INSTANCE_FOG_VOLUME;
- }
- if (visibility_notifier_owner.owns(p_rid)) {
- return RS::INSTANCE_VISIBLITY_NOTIFIER;
- }
-
- return RS::INSTANCE_NONE;
-}
-
-void RendererStorageRD::update_dirty_resources() {
- RendererRD::MaterialStorage::get_singleton()->_update_global_variables(); //must do before materials, so it can queue them for update
- RendererRD::MaterialStorage::get_singleton()->_update_queued_materials();
- RendererRD::MeshStorage::get_singleton()->_update_dirty_multimeshes();
- RendererRD::MeshStorage::get_singleton()->_update_dirty_skeletons();
- RendererRD::TextureStorage::get_singleton()->update_decal_atlas();
-}
-
-bool RendererStorageRD::has_os_feature(const String &p_feature) const {
- if (!RD::get_singleton()) {
- return false;
- }
-
- if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
- return true;
- }
-
- return false;
-}
-
-bool RendererStorageRD::free(RID p_rid) {
- if (RendererRD::TextureStorage::get_singleton()->owns_texture(p_rid)) {
- RendererRD::TextureStorage::get_singleton()->texture_free(p_rid);
- } else if (RendererRD::TextureStorage::get_singleton()->owns_canvas_texture(p_rid)) {
- RendererRD::TextureStorage::get_singleton()->canvas_texture_free(p_rid);
- } else if (RendererRD::MaterialStorage::get_singleton()->owns_shader(p_rid)) {
- RendererRD::MaterialStorage::get_singleton()->shader_free(p_rid);
- } else if (RendererRD::MaterialStorage::get_singleton()->owns_material(p_rid)) {
- RendererRD::MaterialStorage::get_singleton()->material_free(p_rid);
- } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
- RendererRD::MeshStorage::get_singleton()->mesh_free(p_rid);
- } else if (RendererRD::MeshStorage::get_singleton()->owns_mesh_instance(p_rid)) {
- RendererRD::MeshStorage::get_singleton()->mesh_instance_free(p_rid);
- } else if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
- RendererRD::MeshStorage::get_singleton()->multimesh_free(p_rid);
- } else if (RendererRD::MeshStorage::get_singleton()->owns_skeleton(p_rid)) {
- RendererRD::MeshStorage::get_singleton()->skeleton_free(p_rid);
- } else if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
- RendererRD::LightStorage::get_singleton()->reflection_probe_free(p_rid);
- } else if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
- RendererRD::TextureStorage::get_singleton()->decal_free(p_rid);
- } else if (voxel_gi_owner.owns(p_rid)) {
- voxel_gi_allocate_data(p_rid, Transform3D(), AABB(), Vector3i(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<uint8_t>(), Vector<int>()); //deallocate
- VoxelGI *voxel_gi = voxel_gi_owner.get_or_null(p_rid);
- voxel_gi->dependency.deleted_notify(p_rid);
- voxel_gi_owner.free(p_rid);
- } else if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
- RendererRD::LightStorage::get_singleton()->lightmap_free(p_rid);
- } else if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
- RendererRD::LightStorage::get_singleton()->light_free(p_rid);
- } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
- RendererRD::ParticlesStorage::get_singleton()->particles_free(p_rid);
- } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
- RendererRD::ParticlesStorage::get_singleton()->particles_collision_free(p_rid);
- } else if (visibility_notifier_owner.owns(p_rid)) {
- VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_rid);
- vn->dependency.deleted_notify(p_rid);
- visibility_notifier_owner.free(p_rid);
- } else if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision_instance(p_rid)) {
- RendererRD::ParticlesStorage::get_singleton()->particles_collision_instance_free(p_rid);
- } else if (fog_volume_owner.owns(p_rid)) {
- FogVolume *fog_volume = fog_volume_owner.get_or_null(p_rid);
- fog_volume->dependency.deleted_notify(p_rid);
- fog_volume_owner.free(p_rid);
- } else if (RendererRD::TextureStorage::get_singleton()->owns_render_target(p_rid)) {
- RendererRD::TextureStorage::get_singleton()->render_target_free(p_rid);
- } else {
- return false;
- }
-
- return true;
-}
-
-void RendererStorageRD::init_effects(bool p_prefer_raster_effects) {
- effects = memnew(EffectsRD(p_prefer_raster_effects));
-}
-
-EffectsRD *RendererStorageRD::get_effects() {
- ERR_FAIL_NULL_V_MSG(effects, nullptr, "Effects haven't been initialised yet.");
- return effects;
-}
-
-void RendererStorageRD::capture_timestamps_begin() {
- RD::get_singleton()->capture_timestamp("Frame Begin");
-}
-
-void RendererStorageRD::capture_timestamp(const String &p_name) {
- RD::get_singleton()->capture_timestamp(p_name);
-}
-
-uint32_t RendererStorageRD::get_captured_timestamps_count() const {
- return RD::get_singleton()->get_captured_timestamps_count();
-}
-
-uint64_t RendererStorageRD::get_captured_timestamps_frame() const {
- return RD::get_singleton()->get_captured_timestamps_frame();
-}
-
-uint64_t RendererStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const {
- return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index);
-}
-
-uint64_t RendererStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const {
- return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index);
-}
-
-String RendererStorageRD::get_captured_timestamp_name(uint32_t p_index) const {
- return RD::get_singleton()->get_captured_timestamp_name(p_index);
-}
-
-void RendererStorageRD::update_memory_info() {
- texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES);
- buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS);
- total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL);
-}
-uint64_t RendererStorageRD::get_rendering_info(RS::RenderingInfo p_info) {
- if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) {
- return texture_mem_cache;
- } else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) {
- return buffer_mem_cache;
- } else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) {
- return total_mem_cache;
- }
- return 0;
-}
-
-String RendererStorageRD::get_video_adapter_name() const {
- return RenderingDevice::get_singleton()->get_device_name();
-}
-
-String RendererStorageRD::get_video_adapter_vendor() const {
- return RenderingDevice::get_singleton()->get_device_vendor_name();
-}
-
-RenderingDevice::DeviceType RendererStorageRD::get_video_adapter_type() const {
- return RenderingDevice::get_singleton()->get_device_type();
-}
-
-String RendererStorageRD::get_video_adapter_api_version() const {
- return RenderingDevice::get_singleton()->get_device_api_version();
-}
-
-RendererStorageRD *RendererStorageRD::base_singleton = nullptr;
-
-RendererStorageRD::RendererStorageRD() {
- base_singleton = this;
-}
-
-RendererStorageRD::~RendererStorageRD() {
- if (effects) {
- memdelete(effects);
- effects = nullptr;
- }
-}
diff --git a/servers/rendering/renderer_rd/renderer_storage_rd.h b/servers/rendering/renderer_rd/renderer_storage_rd.h
deleted file mode 100644
index 07fae45a26..0000000000
--- a/servers/rendering/renderer_rd/renderer_storage_rd.h
+++ /dev/null
@@ -1,306 +0,0 @@
-/*************************************************************************/
-/* renderer_storage_rd.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#ifndef RENDERING_SERVER_STORAGE_RD_H
-#define RENDERING_SERVER_STORAGE_RD_H
-
-#include "core/templates/list.h"
-#include "core/templates/local_vector.h"
-#include "core/templates/rid_owner.h"
-#include "servers/rendering/renderer_compositor.h"
-#include "servers/rendering/renderer_rd/effects_rd.h"
-#include "servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
-#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering/rendering_device.h"
-#include "servers/rendering/shader_compiler.h"
-
-class RendererStorageRD : public RendererStorage {
-public:
- static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.rows[0][0];
- p_array[1] = p_mtx.basis.rows[1][0];
- p_array[2] = p_mtx.basis.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.basis.rows[0][1];
- p_array[5] = p_mtx.basis.rows[1][1];
- p_array[6] = p_mtx.basis.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.basis.rows[0][2];
- p_array[9] = p_mtx.basis.rows[1][2];
- p_array[10] = p_mtx.basis.rows[2][2];
- p_array[11] = 0;
- p_array[12] = p_mtx.origin.x;
- p_array[13] = p_mtx.origin.y;
- p_array[14] = p_mtx.origin.z;
- p_array[15] = 1;
- }
-
- static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.rows[0][0];
- p_array[1] = p_mtx.rows[1][0];
- p_array[2] = p_mtx.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.rows[0][1];
- p_array[5] = p_mtx.rows[1][1];
- p_array[6] = p_mtx.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.rows[0][2];
- p_array[9] = p_mtx.rows[1][2];
- p_array[10] = p_mtx.rows[2][2];
- p_array[11] = 0;
- }
-
- static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
- p_array[0] = p_mtx.rows[0][0];
- p_array[1] = p_mtx.rows[1][0];
- p_array[2] = p_mtx.rows[2][0];
- p_array[3] = 0;
- p_array[4] = p_mtx.rows[0][1];
- p_array[5] = p_mtx.rows[1][1];
- p_array[6] = p_mtx.rows[2][1];
- p_array[7] = 0;
- p_array[8] = p_mtx.rows[0][2];
- p_array[9] = p_mtx.rows[1][2];
- p_array[10] = p_mtx.rows[2][2];
- p_array[11] = 0;
- }
-
- static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
- p_array[0] = p_mtx.basis.rows[0][0];
- p_array[1] = p_mtx.basis.rows[0][1];
- p_array[2] = p_mtx.basis.rows[0][2];
- p_array[3] = p_mtx.origin.x;
- p_array[4] = p_mtx.basis.rows[1][0];
- p_array[5] = p_mtx.basis.rows[1][1];
- p_array[6] = p_mtx.basis.rows[1][2];
- p_array[7] = p_mtx.origin.y;
- p_array[8] = p_mtx.basis.rows[2][0];
- p_array[9] = p_mtx.basis.rows[2][1];
- p_array[10] = p_mtx.basis.rows[2][2];
- p_array[11] = p_mtx.origin.z;
- }
-
- static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) {
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- p_array[i * 4 + j] = p_mtx.matrix[i][j];
- }
- }
- }
-
- static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
- for (int i = 0; i < 128; i++) {
- p_array[i] = p_kernel[i];
- }
- }
-
-private:
- /* FOG VOLUMES */
-
- struct FogVolume {
- RID material;
- Vector3 extents = Vector3(1, 1, 1);
-
- RS::FogVolumeShape shape = RS::FOG_VOLUME_SHAPE_BOX;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<FogVolume, true> fog_volume_owner;
-
- /* visibility_notifier */
-
- struct VisibilityNotifier {
- AABB aabb;
- Callable enter_callback;
- Callable exit_callback;
- Dependency dependency;
- };
-
- mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
-
- /* VOXEL GI */
-
- struct VoxelGI {
- RID octree_buffer;
- RID data_buffer;
- RID sdf_texture;
-
- uint32_t octree_buffer_size = 0;
- uint32_t data_buffer_size = 0;
-
- Vector<int> level_counts;
-
- int cell_count = 0;
-
- Transform3D to_cell_xform;
- AABB bounds;
- Vector3i octree_size;
-
- float dynamic_range = 2.0;
- float energy = 1.0;
- float bias = 1.4;
- float normal_bias = 0.0;
- float propagation = 0.7;
- bool interior = false;
- bool use_two_bounces = false;
-
- float anisotropy_strength = 0.5;
-
- uint32_t version = 1;
- uint32_t data_version = 1;
-
- Dependency dependency;
- };
-
- mutable RID_Owner<VoxelGI, true> voxel_gi_owner;
-
- /* EFFECTS */
-
- EffectsRD *effects = nullptr;
-
-public:
- //internal usage
-
- void base_update_dependency(RID p_base, DependencyTracker *p_instance);
-
- /* VOXEL GI API */
-
- RID voxel_gi_allocate();
- void voxel_gi_initialize(RID p_voxel_gi);
-
- void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts);
-
- AABB voxel_gi_get_bounds(RID p_voxel_gi) const;
- Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const;
- Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const;
- Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const;
- Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const;
-
- Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const;
- Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const;
-
- void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range);
- float voxel_gi_get_dynamic_range(RID p_voxel_gi) const;
-
- void voxel_gi_set_propagation(RID p_voxel_gi, float p_range);
- float voxel_gi_get_propagation(RID p_voxel_gi) const;
-
- void voxel_gi_set_energy(RID p_voxel_gi, float p_energy);
- float voxel_gi_get_energy(RID p_voxel_gi) const;
-
- void voxel_gi_set_bias(RID p_voxel_gi, float p_bias);
- float voxel_gi_get_bias(RID p_voxel_gi) const;
-
- void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range);
- float voxel_gi_get_normal_bias(RID p_voxel_gi) const;
-
- void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable);
- bool voxel_gi_is_interior(RID p_voxel_gi) const;
-
- void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable);
- bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const;
-
- void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength);
- float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const;
-
- uint32_t voxel_gi_get_version(RID p_probe);
- uint32_t voxel_gi_get_data_version(RID p_probe);
-
- RID voxel_gi_get_octree_buffer(RID p_voxel_gi) const;
- RID voxel_gi_get_data_buffer(RID p_voxel_gi) const;
-
- RID voxel_gi_get_sdf_texture(RID p_voxel_gi);
-
- /* FOG VOLUMES */
-
- virtual RID fog_volume_allocate();
- virtual void fog_volume_initialize(RID p_rid);
-
- virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape);
- virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents);
- virtual void fog_volume_set_material(RID p_fog_volume, RID p_material);
- virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const;
- virtual RID fog_volume_get_material(RID p_fog_volume) const;
- virtual AABB fog_volume_get_aabb(RID p_fog_volume) const;
- virtual Vector3 fog_volume_get_extents(RID p_fog_volume) const;
-
- /* VISIBILITY NOTIFIER */
-
- virtual RID visibility_notifier_allocate();
- virtual void visibility_notifier_initialize(RID p_notifier);
- virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb);
- virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable);
-
- virtual AABB visibility_notifier_get_aabb(RID p_notifier) const;
- virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred);
-
- RS::InstanceType get_base_type(RID p_rid) const;
-
- bool free(RID p_rid);
-
- bool has_os_feature(const String &p_feature) const;
-
- void update_dirty_resources();
-
- void set_debug_generate_wireframes(bool p_generate) {}
-
- //keep cached since it can be called form any thread
- uint64_t texture_mem_cache = 0;
- uint64_t buffer_mem_cache = 0;
- uint64_t total_mem_cache = 0;
-
- virtual void update_memory_info();
- virtual uint64_t get_rendering_info(RS::RenderingInfo p_info);
-
- String get_video_adapter_name() const;
- String get_video_adapter_vendor() const;
- RenderingDevice::DeviceType get_video_adapter_type() const;
- String get_video_adapter_api_version() const;
-
- virtual void capture_timestamps_begin();
- virtual void capture_timestamp(const String &p_name);
- virtual uint32_t get_captured_timestamps_count() const;
- virtual uint64_t get_captured_timestamps_frame() const;
- virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const;
- virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const;
- virtual String get_captured_timestamp_name(uint32_t p_index) const;
-
- static RendererStorageRD *base_singleton;
-
- void init_effects(bool p_prefer_raster_effects);
- EffectsRD *get_effects();
-
- RendererStorageRD();
- ~RendererStorageRD();
-};
-
-#endif // RASTERIZER_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/shader_rd.cpp b/servers/rendering/renderer_rd/shader_rd.cpp
index 04e05380f1..5e9eadadd9 100644
--- a/servers/rendering/renderer_rd/shader_rd.cpp
+++ b/servers/rendering/renderer_rd/shader_rd.cpp
@@ -177,9 +177,10 @@ void ShaderRD::_build_variant_code(StringBuilder &builder, uint32_t p_variant, c
for (const KeyValue<StringName, CharString> &E : p_version->code_sections) {
builder.append(String("#define ") + String(E.key) + "_CODE_USED\n");
}
-#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED)
+#if defined(MACOS_ENABLED) || defined(IOS_ENABLED)
builder.append("#define MOLTENVK_USED\n");
#endif
+ builder.append(String("#define RENDER_DRIVER_") + OS::get_singleton()->get_current_rendering_driver_name().to_upper() + "\n");
} break;
case StageTemplate::Chunk::TYPE_MATERIAL_UNIFORMS: {
builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment)
@@ -380,7 +381,7 @@ static const uint32_t cache_file_version = 2;
bool ShaderRD::_load_from_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
- String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
+ String path = shader_cache_dir.path_join(name).path_join(base_sha256).path_join(sha1) + ".cache";
Ref<FileAccess> f = FileAccess::open(path, FileAccess::READ);
if (f.is_null()) {
@@ -443,7 +444,7 @@ bool ShaderRD::_load_from_cache(Version *p_version) {
void ShaderRD::_save_to_cache(Version *p_version) {
String sha1 = _version_get_sha1(p_version);
- String path = shader_cache_dir.plus_file(name).plus_file(base_sha256).plus_file(sha1) + ".cache";
+ String path = shader_cache_dir.path_join(name).path_join(base_sha256).path_join(sha1) + ".cache";
Ref<FileAccess> f = FileAccess::open(path, FileAccess::WRITE);
ERR_FAIL_COND(f.is_null());
@@ -476,7 +477,9 @@ void ShaderRD::_compile_version(Version *p_version) {
#if 1
- RendererThreadPool::singleton->thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &ShaderRD::_compile_variant, p_version, variant_defines.size(), -1, true, SNAME("ShaderCompilation"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
+
#else
for (int i = 0; i < variant_defines.size(); i++) {
_compile_variant(i, p_version);
diff --git a/servers/rendering/renderer_rd/shaders/SCsub b/servers/rendering/renderer_rd/shaders/SCsub
index acb843bfb6..5405985741 100644
--- a/servers/rendering/renderer_rd/shaders/SCsub
+++ b/servers/rendering/renderer_rd/shaders/SCsub
@@ -10,10 +10,13 @@ if "RD_GLSL" in env["BUILDERS"]:
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
# make sure we recompile shaders if include files change
- env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
# compile shaders
for glsl_file in glsl_files:
env.RD_GLSL(glsl_file)
SConscript("effects/SCsub")
+SConscript("environment/SCsub")
+SConscript("forward_clustered/SCsub")
+SConscript("forward_mobile/SCsub")
diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl
index f8e9020f9f..8593e6b265 100644
--- a/servers/rendering/renderer_rd/shaders/canvas.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas.glsl
@@ -313,6 +313,14 @@ vec4 light_compute(
vec2 uv,
vec4 color, bool is_directional) {
vec4 light = vec4(0.0);
+ vec3 light_direction = vec3(0.0);
+
+ if (is_directional) {
+ light_direction = normalize(mix(vec3(light_position.xy, 0.0), vec3(0, 0, 1), light_position.z));
+ light_position = vec3(0.0);
+ } else {
+ light_direction = normalize(light_position - light_vertex);
+ }
#CODE : LIGHT
@@ -509,7 +517,13 @@ void main() {
float a = clamp(d * px_size + 0.5, 0.0, 1.0);
color.a = a * color.a;
}
-
+ } else if (bool(draw_data.flags & FLAGS_USE_LCD)) {
+ vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv);
+ if (lcd_sample.a == 1.0) {
+ color.rgb = lcd_sample.rgb * color.a;
+ } else {
+ color = vec4(0.0, 0.0, 0.0, 0.0);
+ }
} else {
#else
{
@@ -584,14 +598,14 @@ void main() {
normal = normalize((canvas_data.canvas_normal_transform * vec4(normal, 0.0)).xyz);
}
- vec3 base_color = color.rgb;
+ vec4 base_color = color;
if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) {
color = vec4(0.0); //invisible by default due to using light mask
}
#ifdef MODE_LIGHT_ONLY
color = vec4(0.0);
-#else
+#elif !defined(MODE_UNSHADED)
color *= canvas_data.canvas_modulation;
#endif
@@ -608,12 +622,14 @@ void main() {
#ifdef LIGHT_CODE_USED
vec4 shadow_modulate = vec4(1.0);
- light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, true);
+ light_color = light_compute(light_vertex, vec3(direction, light_array.data[light_base].height), normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, true);
#else
if (normal_used) {
vec3 light_vec = normalize(mix(vec3(direction, 0.0), vec3(0, 0, 1), light_array.data[light_base].height));
- light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used);
+ light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
+ } else {
+ light_color.rgb *= base_color.rgb;
}
#endif
@@ -639,20 +655,7 @@ void main() {
if (i >= light_count) {
break;
}
- uint light_base;
- if (i < 8) {
- if (i < 4) {
- light_base = draw_data.lights[0];
- } else {
- light_base = draw_data.lights[1];
- }
- } else {
- if (i < 12) {
- light_base = draw_data.lights[2];
- } else {
- light_base = draw_data.lights[3];
- }
- }
+ uint light_base = draw_data.lights[i >> 2];
light_base >>= (i & 3) * 8;
light_base &= 0xFF;
@@ -667,7 +670,7 @@ void main() {
vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
light_color.rgb *= light_base_color.rgb;
- light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, color, false);
+ light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, uv, base_color, false);
#else
light_color.rgb *= light_base_color.rgb * light_base_color.a;
@@ -676,9 +679,10 @@ void main() {
vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height);
vec3 pos = light_vertex;
vec3 light_vec = normalize(light_pos - pos);
- float cNdotL = max(0.0, dot(normal, light_vec));
- light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used);
+ light_color.rgb = light_normal_compute(light_vec, normal, base_color.rgb, light_color.rgb, specular_shininess, specular_shininess_used);
+ } else {
+ light_color.rgb *= base_color.rgb;
}
#endif
if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) {
diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
index 12f57b0178..1b627a3e81 100644
--- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl
@@ -25,6 +25,7 @@
#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27)
#define FLAGS_USE_MSDF (1 << 28)
+#define FLAGS_USE_LCD (1 << 29)
#define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1
@@ -138,10 +139,10 @@ layout(set = 0, binding = 7) uniform texture2D sdf_texture;
layout(set = 0, binding = 8) uniform sampler material_samplers[12];
-layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 9, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* SET1: Is reserved for the material */
diff --git a/servers/rendering/renderer_rd/shaders/cluster_render.glsl b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
index 2fe230f0bf..8c26a67926 100644
--- a/servers/rendering/renderer_rd/shaders/cluster_render.glsl
+++ b/servers/rendering/renderer_rd/shaders/cluster_render.glsl
@@ -64,7 +64,7 @@ void main() {
#version 450
#VERSION_DEFINES
-
+#ifndef MOLTENVK_USED // Metal will corrupt GPU state otherwise
#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic) && defined(has_GL_KHR_shader_subgroup_vote)
#extension GL_KHR_shader_subgroup_ballot : enable
@@ -73,6 +73,7 @@ void main() {
#define USE_SUBGROUPS
#endif
+#endif
layout(location = 0) in float depth_interp;
layout(location = 1) in flat uint element_index;
@@ -141,7 +142,11 @@ void main() {
}
}
#else
- if (!gl_HelperInvocation) {
+// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs
+#ifndef MOLTENVK_USED
+ if (!gl_HelperInvocation)
+#endif
+ {
atomicOr(cluster_render.data[usage_write_offset], usage_write_bit);
}
#endif
@@ -161,7 +166,11 @@ void main() {
}
}
#else
- if (!gl_HelperInvocation) {
+// MoltenVK/Metal fails to compile shaders using gl_HelperInvocation for some GPUs
+#ifndef MOLTENVK_USED
+ if (!gl_HelperInvocation)
+#endif
+ {
atomicOr(cluster_render.data[z_write_offset], z_write_bit);
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/effects/SCsub b/servers/rendering/renderer_rd/shaders/effects/SCsub
index fc513d3fb9..f06a2d86e2 100644
--- a/servers/rendering/renderer_rd/shaders/effects/SCsub
+++ b/servers/rendering/renderer_rd/shaders/effects/SCsub
@@ -4,13 +4,13 @@ Import("env")
if "RD_GLSL" in env["BUILDERS"]:
# find all include files
- gl_include_files = [str(f) for f in Glob("*_inc.glsl")]
+ gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")]
# find all shader code(all glsl files excluding our include files)
glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
# make sure we recompile shaders if include files change
- env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files)
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
# compile shaders
for glsl_file in glsl_files:
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
index 96f5c3e9f2..cb06250cf2 100644
--- a/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster.glsl
@@ -129,7 +129,7 @@ void main() {
#ifdef GLOW_USE_AUTO_EXPOSURE
- frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey;
+ frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_scale;
#endif
frag_color *= blur.glow_exposure;
diff --git a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
index 730504571a..06ca198f37 100644
--- a/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/blur_raster_inc.glsl
@@ -16,7 +16,7 @@ layout(push_constant, std430) uniform Blur {
float glow_exposure; // 04 - 36
float glow_white; // 04 - 40
float glow_luminance_cap; // 04 - 44
- float glow_auto_exposure_grey; // 04 - 48
+ float glow_auto_exposure_scale; // 04 - 48
float luminance_multiplier; // 04 - 52
float res1; // 04 - 56
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
index 0438671dd2..fe770ac065 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof.glsl
@@ -30,7 +30,7 @@ layout(set = 1, binding = 0) uniform sampler2D source_bokeh;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
@@ -41,11 +41,25 @@ float get_depth_at_pos(vec2 uv) {
float get_blur_size(float depth) {
if (params.blur_near_active && depth < params.blur_near_begin) {
- return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
+ if (params.use_physical_near) {
+ // Physically-based.
+ float d = abs(params.blur_near_begin - depth);
+ return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative.
+ } else {
+ // Non-physically-based.
+ return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative.
+ }
}
if (params.blur_far_active && depth > params.blur_far_begin) {
- return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ if (params.use_physical_far) {
+ // Physically-based.
+ float d = abs(params.blur_far_begin - depth);
+ return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP;
+ } else {
+ // Non-physically-based.
+ return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ }
}
return 0.0;
@@ -172,6 +186,7 @@ void main() {
uv += pixel_size * 0.5; //half pixel to read centers
vec4 color = texture(color_texture, uv);
+ float initial_blur = color.a;
float accum = 1.0;
float radius = params.blur_scale;
@@ -179,8 +194,8 @@ void main() {
vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius;
vec4 sample_color = texture(color_texture, suv);
float sample_size = abs(sample_color.a);
- if (sample_color.a > color.a) {
- sample_size = clamp(sample_size, 0.0, abs(color.a) * 2.0);
+ if (sample_color.a > initial_blur) {
+ sample_size = clamp(sample_size, 0.0, abs(initial_blur) * 2.0);
}
float m = smoothstep(radius - 0.5, radius + 0.5, sample_size);
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
index b90a527554..4a2b0edc18 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_inc.glsl
@@ -20,6 +20,11 @@ layout(push_constant, std430) uniform Params {
bool use_jitter;
float jitter_seed;
+ bool use_physical_near;
+ bool use_physical_far;
+
+ float blur_size_near;
+ float blur_size_far;
uint pad[2];
}
params;
diff --git a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
index a3b3938ee9..1b487835d2 100644
--- a/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/bokeh_dof_raster.glsl
@@ -52,7 +52,7 @@ layout(set = 2, binding = 0) uniform sampler2D original_weight;
#ifdef MODE_GEN_BLUR_SIZE
float get_depth_at_pos(vec2 uv) {
- float depth = textureLod(source_depth, uv, 0.0).x;
+ float depth = textureLod(source_depth, uv, 0.0).x * 2.0 - 1.0;
if (params.orthogonal) {
depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
} else {
@@ -63,11 +63,25 @@ float get_depth_at_pos(vec2 uv) {
float get_blur_size(float depth) {
if (params.blur_near_active && depth < params.blur_near_begin) {
- return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative
+ if (params.use_physical_near) {
+ // Physically-based.
+ float d = abs(params.blur_near_begin - depth);
+ return -(d / (params.blur_near_begin - d)) * params.blur_size_near - DEPTH_GAP; // Near blur is negative.
+ } else {
+ // Non-physically-based.
+ return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; // Near blur is negative.
+ }
}
if (params.blur_far_active && depth > params.blur_far_begin) {
- return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ if (params.use_physical_far) {
+ // Physically-based.
+ float d = abs(params.blur_far_begin - depth);
+ return (d / (params.blur_far_begin + d)) * params.blur_size_far + DEPTH_GAP;
+ } else {
+ // Non-physically-based.
+ return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP;
+ }
}
return 0.0;
@@ -207,12 +221,9 @@ void main() {
vec4 sample_color = texture(source_color, uv_adj);
sample_color.a = texture(source_weight, uv_adj).r;
- float limit;
-
- if (sample_color.a < color.a) {
- limit = abs(sample_color.a);
- } else {
- limit = abs(color.a);
+ float limit = abs(sample_color.a);
+ if (sample_color.a > color.a) {
+ limit = clamp(limit, 0.0, abs(color.a) * 2.0);
}
limit -= DEPTH_GAP;
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy.glsl b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
index 3a4ef86ef0..bfe329b8ec 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy.glsl
@@ -31,7 +31,7 @@ layout(push_constant, std430) uniform Params {
float glow_exposure;
float glow_white;
float glow_luminance_cap;
- float glow_auto_exposure_grey;
+ float glow_auto_exposure_scale;
// DOF.
float camera_z_far;
float camera_z_near;
@@ -185,7 +185,7 @@ void main() {
if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) {
#ifdef GLOW_USE_AUTO_EXPOSURE
- color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_grey;
+ color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.glow_auto_exposure_scale;
#endif
color *= params.glow_exposure;
diff --git a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
index 9787c9879d..1c17eabb56 100644
--- a/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/copy_to_fb.glsl
@@ -88,7 +88,7 @@ layout(set = 0, binding = 0) uniform sampler2DArray source_color;
layout(set = 1, binding = 0) uniform sampler2DArray source_depth;
layout(location = 1) out float depth;
#endif /* MODE_TWO_SOURCES */
-#else
+#else /* MULTIVIEW */
layout(set = 0, binding = 0) uniform sampler2D source_color;
#ifdef MODE_TWO_SOURCES
layout(set = 1, binding = 0) uniform sampler2D source_color2;
@@ -139,7 +139,7 @@ void main() {
//uv.y = 1.0 - uv.y;
uv = 1.0 - uv;
}
-#endif
+#endif /* MODE_PANORAMA_TO_DP */
#ifdef MULTIVIEW
vec4 color = textureLod(source_color, uv, 0.0);
@@ -148,12 +148,13 @@ void main() {
depth = textureLod(source_depth, uv, 0.0).r;
#endif /* MODE_TWO_SOURCES */
-#else
+#else /* MULTIVIEW */
vec4 color = textureLod(source_color, uv, 0.0);
#ifdef MODE_TWO_SOURCES
color += textureLod(source_color2, uv, 0.0);
#endif /* MODE_TWO_SOURCES */
#endif /* MULTIVIEW */
+
if (params.force_luminance) {
color.rgb = vec3(max(max(color.r, color.g), color.b));
}
@@ -163,5 +164,6 @@ void main() {
if (params.srgb) {
color.rgb = linear_to_srgb(color.rgb);
}
+
frag_color = color;
}
diff --git a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
index e77d0de719..e77d0de719 100644
--- a/servers/rendering/renderer_rd/shaders/cube_to_dp.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cube_to_dp.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler.glsl
index 63f0ce690e..63f0ce690e 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_inc.glsl
index 641e0906f5..641e0906f5 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_inc.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
index 0828ffd921..0828ffd921 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_downsampler_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_downsampler_raster.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter.glsl
index 2a774b0eb4..2a774b0eb4 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_filter.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl
index 0990dc7c2f..0990dc7c2f 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_filter_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_filter_raster.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl
index 1d46f59408..1d46f59408 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_roughness.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl
index 1bee428a6f..1bee428a6f 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_inc.glsl
diff --git a/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl
index c29accd8a7..c29accd8a7 100644
--- a/servers/rendering/renderer_rd/shaders/cubemap_roughness_raster.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/cubemap_roughness_raster.glsl
diff --git a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl b/servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl
index c8eb78a2f0..c8eb78a2f0 100644
--- a/servers/rendering/renderer_rd/shaders/fsr_upscale.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/fsr_upscale.glsl
diff --git a/servers/rendering/renderer_rd/shaders/resolve.glsl b/servers/rendering/renderer_rd/shaders/effects/resolve.glsl
index 0e086331c0..0e086331c0 100644
--- a/servers/rendering/renderer_rd/shaders/resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/resolve.glsl
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
index a416891ff2..9d8294a7da 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection.glsl
@@ -30,14 +30,14 @@ layout(push_constant, std430) uniform Params {
bool orthogonal;
float filter_mipmap_levels;
bool use_half_res;
- uint metallic_mask;
-
- mat4 projection;
+ uint view_index;
}
params;
+#include "screen_space_reflection_inc.glsl"
+
vec2 view_to_screen(vec3 view_pos, out float w) {
- vec4 projected = params.projection * vec4(view_pos, 1.0);
+ vec4 projected = scene_data.projection[params.view_index] * vec4(view_pos, 1.0);
projected.xyz /= projected.w;
projected.xy = projected.xy * 0.5 + 0.5;
w = projected.w;
@@ -46,24 +46,16 @@ vec2 view_to_screen(vec3 view_pos, out float w) {
#define M_PI 3.14159265359
-vec3 reconstructCSPosition(vec2 S, float z) {
- if (params.orthogonal) {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
- } else {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
- }
-}
-
void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
vec2 pixel_size = 1.0 / vec2(params.screen_size);
- vec2 uv = vec2(ssC) * pixel_size;
+ vec2 uv = vec2(ssC.xy) * pixel_size;
uv += pixel_size * 0.5;
@@ -77,7 +69,12 @@ void main() {
normal = normalize(normal);
normal.y = -normal.y; //because this code reads flipped
- vec3 view_dir = normalize(vertex);
+ vec3 view_dir;
+ if (sc_multiview) {
+ view_dir = normalize(vertex + scene_data.eye_offset[params.view_index].xyz);
+ } else {
+ view_dir = normalize(vertex);
+ }
vec3 ray_dir = normalize(reflect(view_dir, normal));
if (dot(ray_dir, normal) < 0.001) {
@@ -124,7 +121,7 @@ void main() {
// clip z and w advance to line advance
vec2 line_advance = normalize(line_dir); // down to pixel
- float step_size = length(line_advance) / length(line_dir);
+ float step_size = 1.0 / length(line_dir);
float z_advance = z_dir * step_size; // adapt z advance to line advance
float w_advance = w_dir * step_size; // adapt w advance to line advance
@@ -142,6 +139,14 @@ void main() {
float depth;
vec2 prev_pos = pos;
+ if (ivec2(pos + line_advance - 0.5) == ssC) {
+ // It is possible for rounding to cause our first pixel to check to be the pixel we're reflecting.
+ // Make sure we skip it
+ pos += line_advance;
+ z += z_advance;
+ w += w_advance;
+ }
+
bool found = false;
float steps_taken = 0.0;
@@ -152,20 +157,33 @@ void main() {
w += w_advance;
// convert to linear depth
-
- depth = imageLoad(source_depth, ivec2(pos - 0.5)).r;
+ ivec2 test_pos = ivec2(pos - 0.5);
+ depth = imageLoad(source_depth, test_pos).r;
+ if (sc_multiview) {
+ depth = depth * 2.0 - 1.0;
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ depth = -depth;
+ }
z_from = z_to;
z_to = z / w;
if (depth > z_to) {
- // if depth was surpassed
- if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far) {
- // check the depth tolerance and far clip
- // check that normal is valid
- found = true;
+ // Test if our ray is hitting the "right" side of the surface, if not we're likely self reflecting and should skip.
+ vec4 test_normal_roughness = imageLoad(source_normal_roughness, test_pos);
+ vec3 test_normal = test_normal_roughness.xyz * 2.0 - 1.0;
+ test_normal = normalize(test_normal);
+ test_normal.y = -test_normal.y; //because this code reads flipped
+
+ if (dot(ray_dir, test_normal) < 0.001) {
+ // if depth was surpassed
+ if (depth <= max(z_to, z_from) + params.depth_tolerance && -depth < params.camera_z_far * 0.95) {
+ // check the depth tolerance and far clip
+ // check that normal is valid
+ found = true;
+ }
+ break;
}
- break;
}
steps_taken += 1.0;
@@ -175,17 +193,18 @@ void main() {
if (found) {
float margin_blend = 1.0;
- vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.5 * 0.05); // make a uniform margin
- if (any(bvec4(lessThan(pos, -margin), greaterThan(pos, params.screen_size + margin)))) {
- // clip outside screen + margin
+ vec2 margin = vec2((params.screen_size.x + params.screen_size.y) * 0.05); // make a uniform margin
+ if (any(bvec4(lessThan(pos, vec2(0.0, 0.0)), greaterThan(pos, params.screen_size)))) {
+ // clip at the screen edges
imageStore(ssr_image, ssC, vec4(0.0));
return;
}
{
- //blend fading out towards external margin
- vec2 margin_grad = mix(pos - params.screen_size, -pos, lessThan(pos, vec2(0.0)));
- margin_blend = 1.0 - smoothstep(0.0, margin.x, max(margin_grad.x, margin_grad.y));
+ //blend fading out towards inner margin
+ // 0.5 = midpoint of reflection
+ vec2 margin_grad = mix(params.screen_size - pos, pos, lessThan(pos, params.screen_size * 0.5));
+ margin_blend = smoothstep(0.0, margin.x * margin.y, margin_grad.x * margin_grad.y);
//margin_blend = 1.0;
}
@@ -222,16 +241,21 @@ void main() {
blur_radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
}
}
- final_color = imageLoad(source_diffuse, ivec2((final_pos - 0.5) * pixel_size));
imageStore(blur_radius_image, ssC, vec4(blur_radius / 255.0)); //stored in r8
-#endif
+#endif // MODE_ROUGH
final_color = vec4(imageLoad(source_diffuse, ivec2(final_pos - 0.5)).rgb, fade * margin_blend);
- //change blend by metallic
- vec4 metallic_mask = unpackUnorm4x8(params.metallic_mask);
- final_color.a *= dot(metallic_mask, texelFetch(source_metallic, ssC << 1, 0));
+
+ // Schlick term.
+ float metallic = texelFetch(source_metallic, ssC << 1, 0).w;
+ float f0 = mix(0.04, 1.0, metallic); // Assume a "specular" amount of 0.5
+ normal.y = -normal.y;
+ float m = clamp(1.0 - dot(normalize(normal), -view_dir), 0.0, 1.0);
+ float m2 = m * m;
+ m = m2 * m2 * m; // pow(m,5)
+ final_color.a *= f0 + (1.0 - f0) * m; // Fresnel Schlick term.
imageStore(ssr_image, ssC, final_color);
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl
index 20e1712496..a63d60e0b2 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_filter.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_filter.glsl
@@ -22,7 +22,7 @@ layout(push_constant, std430) uniform Params {
bool orthogonal;
float edge_tolerance;
int increment;
- uint pad;
+ uint view_index;
ivec2 screen_size;
bool vertical;
@@ -30,6 +30,8 @@ layout(push_constant, std430) uniform Params {
}
params;
+#include "screen_space_reflection_inc.glsl"
+
#define GAUSS_TABLE_SIZE 15
const float gauss_table[GAUSS_TABLE_SIZE + 1] = float[](
@@ -64,14 +66,6 @@ float gauss_weight(float p_val) {
#define M_PI 3.14159265359
-vec3 reconstructCSPosition(vec2 S, float z) {
- if (params.orthogonal) {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z);
- } else {
- return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
- }
-}
-
void do_filter(inout vec4 accum, inout float accum_radius, inout float divisor, ivec2 texcoord, ivec2 increment, vec3 p_pos, vec3 normal, float p_limit_radius) {
for (int i = 1; i < params.steps; i++) {
float d = float(i * params.increment);
@@ -110,7 +104,7 @@ void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
@@ -130,13 +124,13 @@ void main() {
ivec2 direction = ivec2(params.increment, 0);
#endif
float depth = imageLoad(source_depth, ssC).r;
- vec3 pos = reconstructCSPosition(vec2(ssC) + 0.5, depth);
+ vec3 pos = reconstructCSPosition(vec2(ssC.xy) + 0.5, depth);
vec3 normal = imageLoad(source_normal, ssC).xyz * 2.0 - 1.0;
normal = normalize(normal);
normal.y = -normal.y;
- do_filter(accum, accum_radius, divisor, ssC, direction, pos, normal, radius);
- do_filter(accum, accum_radius, divisor, ssC, -direction, pos, normal, radius);
+ do_filter(accum, accum_radius, divisor, ssC.xy, direction, pos, normal, radius);
+ do_filter(accum, accum_radius, divisor, ssC.xy, -direction, pos, normal, radius);
if (divisor > 0.0) {
accum /= divisor;
diff --git a/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl
new file mode 100644
index 0000000000..26405ab040
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_inc.glsl
@@ -0,0 +1,28 @@
+layout(constant_id = 0) const bool sc_multiview = false;
+
+layout(set = 4, binding = 0, std140) uniform SceneData {
+ mat4x4 projection[2];
+ mat4x4 inv_projection[2];
+ vec4 eye_offset[2];
+}
+scene_data;
+
+vec3 reconstructCSPosition(vec2 screen_pos, float z) {
+ if (sc_multiview) {
+ vec4 pos;
+ pos.xy = (2.0 * vec2(screen_pos) / vec2(params.screen_size)) - 1.0;
+ pos.z = z * 2.0 - 1.0;
+ pos.w = 1.0;
+
+ pos = scene_data.inv_projection[params.view_index] * pos;
+ pos.xyz /= pos.w;
+
+ return pos.xyz;
+ } else {
+ if (params.orthogonal) {
+ return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw), z);
+ } else {
+ return vec3((screen_pos.xy * params.proj_info.xy + params.proj_info.zw) * z, z);
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
index 3f537e273a..a7da0812df 100644
--- a/servers/rendering/renderer_rd/shaders/screen_space_reflection_scale.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/screen_space_reflection_scale.glsl
@@ -6,6 +6,11 @@
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
+/* Specialization Constants (Toggles) */
+
+layout(constant_id = 0) const bool sc_multiview = false;
+
+/* inputs */
layout(set = 0, binding = 0) uniform sampler2D source_ssr;
layout(set = 1, binding = 0) uniform sampler2D source_depth;
layout(set = 1, binding = 1) uniform sampler2D source_normal;
@@ -28,7 +33,7 @@ void main() {
// Pixel being shaded
ivec2 ssC = ivec2(gl_GlobalInvocationID.xy);
- if (any(greaterThanEqual(ssC, params.screen_size))) { //too large, do nothing
+ if (any(greaterThanEqual(ssC.xy, params.screen_size))) { //too large, do nothing
return;
}
//do not filter, SSR will generate arctifacts if this is done
@@ -57,13 +62,19 @@ void main() {
normal.xyz += nr.xyz * 2.0 - 1.0;
normal.w += nr.w;
- d = d * 2.0 - 1.0;
- if (params.orthogonal) {
- d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ if (sc_multiview) {
+ // we're doing a full unproject so we need the value as is.
+ depth += d;
} else {
- d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near));
+ // unproject our Z value so we can use it directly.
+ d = d * 2.0 - 1.0;
+ if (params.orthogonal) {
+ d = ((d + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ d = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - d * (params.camera_z_far - params.camera_z_near));
+ }
+ depth += -d;
}
- depth += -d;
}
color /= 4.0;
@@ -71,17 +82,22 @@ void main() {
normal.xyz = normalize(normal.xyz / 4.0) * 0.5 + 0.5;
normal.w /= 4.0;
} else {
- color = texelFetch(source_ssr, ssC << 1, 0);
- depth = texelFetch(source_depth, ssC << 1, 0).r;
- normal = texelFetch(source_normal, ssC << 1, 0);
-
- depth = depth * 2.0 - 1.0;
- if (params.orthogonal) {
- depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
- } else {
- depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ ivec2 ofs = ssC << 1;
+
+ color = texelFetch(source_ssr, ofs, 0);
+ depth = texelFetch(source_depth, ofs, 0).r;
+ normal = texelFetch(source_normal, ofs, 0);
+
+ if (!sc_multiview) {
+ // unproject our Z value so we can use it directly.
+ depth = depth * 2.0 - 1.0;
+ if (params.orthogonal) {
+ depth = ((depth + (params.camera_z_far + params.camera_z_near) / (params.camera_z_far - params.camera_z_near)) * (params.camera_z_far - params.camera_z_near)) / 2.0;
+ } else {
+ depth = 2.0 * params.camera_z_near * params.camera_z_far / (params.camera_z_far + params.camera_z_near - depth * (params.camera_z_far - params.camera_z_near));
+ }
+ depth = -depth;
}
- depth = -depth;
}
imageStore(dest_ssr, ssC, color);
diff --git a/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
new file mode 100644
index 0000000000..c62144fdaf
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/specular_merge.glsl
@@ -0,0 +1,112 @@
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(location = 0) out vec3 uv_interp;
+#else // USE_MULTIVIEW
+layout(location = 0) out vec2 uv_interp;
+#endif //USE_MULTIVIEW
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+
+#ifdef USE_MULTIVIEW
+ uv_interp = vec3(base_arr[gl_VertexIndex], ViewIndex);
+
+ gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
+#else
+ uv_interp = base_arr[gl_VertexIndex];
+
+ gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
+#endif
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(location = 0) in vec3 uv_interp;
+#else // USE_MULTIVIEW
+layout(location = 0) in vec2 uv_interp;
+#endif //USE_MULTIVIEW
+
+#ifdef USE_MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2DArray specular;
+#else // USE_MULTIVIEW
+layout(set = 0, binding = 0) uniform sampler2D specular;
+#endif //USE_MULTIVIEW
+
+#ifdef MODE_SSR
+
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 0) uniform sampler2DArray ssr;
+#else // USE_MULTIVIEW
+layout(set = 1, binding = 0) uniform sampler2D ssr;
+#endif //USE_MULTIVIEW
+
+#endif
+
+#ifdef MODE_MERGE
+
+#ifdef USE_MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2DArray diffuse;
+#else // USE_MULTIVIEW
+layout(set = 2, binding = 0) uniform sampler2D diffuse;
+#endif //USE_MULTIVIEW
+
+#endif
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+ frag_color.rgb = texture(specular, uv_interp).rgb;
+ frag_color.a = 0.0;
+#ifdef MODE_SSR
+
+ vec4 ssr_color = texture(ssr, uv_interp);
+ frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
+#endif
+
+#ifdef MODE_MERGE
+ frag_color += texture(diffuse, uv_interp);
+#endif
+ //added using additive blend
+}
diff --git a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
index 134aae5ce7..134aae5ce7 100644
--- a/servers/rendering/renderer_rd/shaders/ss_effects_downsample.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ss_effects_downsample.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
index 2a87e273bc..2a87e273bc 100644
--- a/servers/rendering/renderer_rd/shaders/ssao.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
index f42734c46d..f42734c46d 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_blur.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
index 04f98964e8..04f98964e8 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_importance_map.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
index f6a9a92fac..f6a9a92fac 100644
--- a/servers/rendering/renderer_rd/shaders/ssao_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssao_interleave.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
index 513791dfbf..513791dfbf 100644
--- a/servers/rendering/renderer_rd/shaders/ssil.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
index 47c56571f6..47c56571f6 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_blur.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_blur.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
index 6b6b02739d..6b6b02739d 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_importance_map.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_importance_map.glsl
diff --git a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
index 9e86ac0cf0..9e86ac0cf0 100644
--- a/servers/rendering/renderer_rd/shaders/ssil_interleave.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/ssil_interleave.glsl
diff --git a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl b/servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl
index fb35d3cde6..fb35d3cde6 100644
--- a/servers/rendering/renderer_rd/shaders/subsurface_scattering.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/subsurface_scattering.glsl
diff --git a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl
index a1a77b95aa..02566d8e35 100644
--- a/servers/rendering/renderer_rd/shaders/taa_resolve.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/taa_resolve.glsl
@@ -29,9 +29,12 @@
#VERSION_DEFINES
-// Based on Spartan Engine's TAA implementation https://github.com/PanosK92/SpartanEngine/blob/master/Data/shaders/temporal_antialiasing.hlsl
+// Based on Spartan Engine's TAA implementation (without TAA upscale).
+// <https://github.com/PanosK92/SpartanEngine/blob/a8338d0609b85dc32f3732a5c27fb4463816a3b9/Data/shaders/temporal_antialiasing.hlsl>
+#ifndef MOLTENVK_USED
#define USE_SUBGROUPS
+#endif // MOLTENVK_USED
#define GROUP_SIZE 8
#define FLT_MIN 0.00000001
@@ -188,7 +191,7 @@ vec3 sample_catmull_rom_9(sampler2D stex, vec2 uv, vec2 resolution) {
// Source: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
// License: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae
- // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
+ // We're going to sample a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
// down the sample location to get the exact center of our "starting" texel. The starting texel will be at
// location [1, 1] in the grid, where [0, 0] is the top left corner.
vec2 sample_pos = uv * resolution;
diff --git a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
index a8ccdea60b..52aee8b648 100644
--- a/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
+++ b/servers/rendering/renderer_rd/shaders/effects/tonemap.glsl
@@ -75,7 +75,7 @@ layout(push_constant, std430) uniform Params {
float exposure;
float white;
- float auto_exposure_grey;
+ float auto_exposure_scale;
float luminance_multiplier;
vec2 pixel_size;
@@ -360,15 +360,15 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) {
const float FXAA_SPAN_MAX = 8.0;
#ifdef MULTIVIEW
- vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
- vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(1.0, -1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
- vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
- vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(1.0, 1.0) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNW = textureLod(source_color, vec3(uv_interp + vec2(-0.5, -0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNE = textureLod(source_color, vec3(uv_interp + vec2(0.5, -0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSW = textureLod(source_color, vec3(uv_interp + vec2(-0.5, 0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSE = textureLod(source_color, vec3(uv_interp + vec2(0.5, 0.5) * params.pixel_size, ViewIndex), 0.0).xyz * exposure * params.luminance_multiplier;
#else
- vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
- vec3 rgbNE = textureLod(source_color, uv_interp + vec2(1.0, -1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
- vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
- vec3 rgbSE = textureLod(source_color, uv_interp + vec2(1.0, 1.0) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNW = textureLod(source_color, uv_interp + vec2(-0.5, -0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbNE = textureLod(source_color, uv_interp + vec2(0.5, -0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSW = textureLod(source_color, uv_interp + vec2(-0.5, 0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
+ vec3 rgbSE = textureLod(source_color, uv_interp + vec2(0.5, 0.5) * params.pixel_size, 0.0).xyz * exposure * params.luminance_multiplier;
#endif
vec3 rgbM = color;
vec3 luma = vec3(0.299, 0.587, 0.114);
@@ -440,7 +440,7 @@ void main() {
#ifndef SUBPASS
if (params.use_auto_exposure) {
- exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_grey);
+ exposure *= 1.0 / (texelFetch(source_auto_exposure, ivec2(0, 0), 0).r * params.luminance_multiplier / params.auto_exposure_scale);
}
#endif
@@ -448,6 +448,11 @@ void main() {
// Early Tonemap & SRGB Conversion
#ifndef SUBPASS
+ if (params.use_fxaa) {
+ // FXAA must be performed before glow to preserve the "bleed" effect of glow.
+ color.rgb = do_fxaa(color.rgb, exposure, uv_interp);
+ }
+
if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) {
vec3 glow = gather_glow(source_glow, uv_interp) * params.luminance_multiplier;
if (params.glow_map_strength > 0.001) {
@@ -455,18 +460,8 @@ void main() {
}
color.rgb = mix(color.rgb, glow, params.glow_intensity);
}
-
- if (params.use_fxaa) {
- color.rgb = do_fxaa(color.rgb, exposure, uv_interp);
- }
#endif
- if (params.use_debanding) {
- // For best results, debanding should be done before tonemapping.
- // Otherwise, we're adding noise to an already-quantized image.
- color.rgb += screen_space_dither(gl_FragCoord.xy);
- }
-
color.rgb = apply_tonemapping(color.rgb, params.white);
color.rgb = linear_to_srgb(color.rgb); // regular linear -> SRGB conversion
@@ -497,5 +492,11 @@ void main() {
color.rgb = apply_color_correction(color.rgb);
}
+ if (params.use_debanding) {
+ // Debanding should be done at the end of tonemapping, but before writing to the LDR buffer.
+ // Otherwise, we're adding noise to an already-quantized image.
+ color.rgb += screen_space_dither(gl_FragCoord.xy);
+ }
+
frag_color = color;
}
diff --git a/servers/rendering/renderer_rd/shaders/effects/vrs.glsl b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
new file mode 100644
index 0000000000..5ef83c0b44
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/effects/vrs.glsl
@@ -0,0 +1,72 @@
+#[vertex]
+
+#version 450
+
+#VERSION_DEFINES
+
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#endif //MULTIVIEW
+
+#ifdef MULTIVIEW
+layout(location = 0) out vec3 uv_interp;
+#else
+layout(location = 0) out vec2 uv_interp;
+#endif
+
+void main() {
+ vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
+ uv_interp.xy = base_arr[gl_VertexIndex];
+#ifdef MULTIVIEW
+ uv_interp.z = ViewIndex;
+#endif
+
+ gl_Position = vec4(uv_interp.xy * 2.0 - 1.0, 0.0, 1.0);
+}
+
+#[fragment]
+
+#version 450
+
+#VERSION_DEFINES
+
+#ifdef MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#extension GL_EXT_multiview : enable
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#endif //MULTIVIEW
+
+#ifdef MULTIVIEW
+layout(location = 0) in vec3 uv_interp;
+layout(set = 0, binding = 0) uniform sampler2DArray source_color;
+#else /* MULTIVIEW */
+layout(location = 0) in vec2 uv_interp;
+layout(set = 0, binding = 0) uniform sampler2D source_color;
+#endif /* MULTIVIEW */
+
+layout(location = 0) out uint frag_color;
+
+void main() {
+#ifdef MULTIVIEW
+ vec3 uv = uv_interp;
+#else
+ vec2 uv = uv_interp;
+#endif
+
+#ifdef MULTIVIEW
+ vec4 color = textureLod(source_color, uv, 0.0);
+#else /* MULTIVIEW */
+ vec4 color = textureLod(source_color, uv, 0.0);
+#endif /* MULTIVIEW */
+
+ // See if we can change the sampler to one that returns int...
+ frag_color = uint(color.r * 256.0);
+}
diff --git a/servers/rendering/renderer_rd/shaders/environment/SCsub b/servers/rendering/renderer_rd/shaders/environment/SCsub
new file mode 100644
index 0000000000..f06a2d86e2
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/environment/SCsub
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+Import("env")
+
+if "RD_GLSL" in env["BUILDERS"]:
+ # find all include files
+ gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")]
+
+ # find all shader code(all glsl files excluding our include files)
+ glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
+
+ # make sure we recompile shaders if include files change
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
+
+ # compile shaders
+ for glsl_file in glsl_files:
+ env.RD_GLSL(glsl_file)
diff --git a/servers/rendering/renderer_rd/shaders/gi.glsl b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
index 0c7f08813b..ab927df678 100644
--- a/servers/rendering/renderer_rd/shaders/gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/gi.glsl
@@ -8,6 +8,12 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#define M_PI 3.141592
+/* Specialization Constants (Toggles) */
+
+layout(constant_id = 0) const bool sc_half_res = false;
+layout(constant_id = 1) const bool sc_use_full_projection_matrix = false;
+layout(constant_id = 2) const bool sc_use_vrs = false;
+
#define SDFGI_MAX_CASCADES 8
//set 0 for SDFGI and render buffers
@@ -26,6 +32,8 @@ struct ProbeCascadeData {
float to_probe;
ivec3 probe_world_offset;
float to_cell; // 1/bounds * grid_size
+ vec3 pad;
+ float exposure_normalization;
};
layout(rgba16f, set = 0, binding = 9) uniform restrict writeonly image2D ambient_buffer;
@@ -77,6 +85,9 @@ struct VoxelGIData {
float normal_bias; // 4 - 88
bool blend_ambient; // 4 - 92
uint mipmaps; // 4 - 96
+
+ vec3 pad; // 12 - 108
+ float exposure_normalization; // 4 - 112
};
layout(set = 0, binding = 16, std140) uniform VoxelGIs {
@@ -86,19 +97,31 @@ voxel_gi_instances;
layout(set = 0, binding = 17) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
-layout(push_constant, std430) uniform Params {
+layout(set = 0, binding = 18, std140) uniform SceneData {
+ mat4x4 inv_projection[2];
+ mat4x4 cam_transform;
+ vec4 eye_offset[2];
+
ivec2 screen_size;
- float z_near;
- float z_far;
+ float pad1;
+ float pad2;
+}
+scene_data;
- vec4 proj_info;
+layout(r8ui, set = 0, binding = 19) uniform restrict readonly uimage2D vrs_buffer;
+layout(push_constant, std430) uniform Params {
uint max_voxel_gi_instances;
bool high_quality_vct;
bool orthogonal;
- uint pad;
+ uint view_index;
- mat3x4 cam_rotation;
+ vec4 proj_info;
+
+ float z_near;
+ float z_far;
+ float pad2;
+ float pad3;
}
params;
@@ -130,23 +153,34 @@ vec4 blend_color(vec4 src, vec4 dst) {
}
vec3 reconstruct_position(ivec2 screen_pos) {
- vec3 pos;
- pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r;
+ if (sc_use_full_projection_matrix) {
+ vec4 pos;
+ pos.xy = (2.0 * vec2(screen_pos) / vec2(scene_data.screen_size)) - 1.0;
+ pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r * 2.0 - 1.0;
+ pos.w = 1.0;
- pos.z = pos.z * 2.0 - 1.0;
- if (params.orthogonal) {
- pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ pos = scene_data.inv_projection[params.view_index] * pos;
+
+ return pos.xyz / pos.w;
} else {
- pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near));
- }
- pos.z = -pos.z;
+ vec3 pos;
+ pos.z = texelFetch(sampler2D(depth_buffer, linear_sampler), screen_pos, 0).r;
+
+ pos.z = pos.z * 2.0 - 1.0;
+ if (params.orthogonal) {
+ pos.z = ((pos.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0;
+ } else {
+ pos.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - pos.z * (params.z_far - params.z_near));
+ }
+ pos.z = -pos.z;
- pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw;
- if (!params.orthogonal) {
- pos.xy *= pos.z;
- }
+ pos.xy = vec2(screen_pos) * params.proj_info.xy + params.proj_info.zw;
+ if (!params.orthogonal) {
+ pos.xy *= pos.z;
+ }
- return pos;
+ return pos;
+ }
}
void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal, vec3 cam_specular_normal, float roughness, out vec3 diffuse_light, out vec3 specular_light) {
@@ -212,7 +246,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
diffuse = textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb;
- diffuse_accum += vec4(diffuse * weight, weight);
+ diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight);
{
vec3 specular = vec3(0.0);
@@ -226,7 +260,7 @@ void sdfvoxel_gi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_
specular = mix(specular, textureLod(sampler2DArray(lightprobe_texture, linear_sampler), pos_uvw, 0.0).rgb, (roughness - 0.2) * 1.25);
}
- specular_accum += specular * weight;
+ specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization;
}
}
@@ -545,7 +579,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
}
}
- light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
if (!voxel_gi_instances.data[index].blend_ambient) {
light.a = 1.0;
}
@@ -554,7 +588,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
//radiance
vec4 irr_light = voxel_cone_trace(voxel_gi_textures[index], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, voxel_gi_instances.data[index].bias);
- irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
if (!voxel_gi_instances.data[index].blend_ambient) {
irr_light.a = 1.0;
}
@@ -566,7 +600,6 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
vec4 fetch_normal_and_roughness(ivec2 pos) {
vec4 normal_roughness = texelFetch(sampler2D(normal_roughness_buffer, linear_sampler), pos, 0);
-
normal_roughness.xyz = normalize(normal_roughness.xyz * 2.0 - 1.0);
return normal_roughness;
}
@@ -579,9 +612,10 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
if (normal.length() > 0.5) {
//valid normal, can do GI
float roughness = normal_roughness.w;
- vertex = mat3(params.cam_rotation) * vertex;
- normal = normalize(mat3(params.cam_rotation) * normal);
- vec3 reflection = normalize(reflect(normalize(vertex), normal));
+ vec3 view = -normalize(mat3(scene_data.cam_transform) * (vertex - scene_data.eye_offset[gl_GlobalInvocationID.z].xyz));
+ vertex = mat3(scene_data.cam_transform) * vertex;
+ normal = normalize(mat3(scene_data.cam_transform) * normal);
+ vec3 reflection = normalize(reflect(-view, normal));
#ifdef USE_SDFGI
sdfgi_process(vertex, normal, reflection, roughness, ambient_light, reflection_light);
@@ -626,10 +660,36 @@ void process_gi(ivec2 pos, vec3 vertex, inout vec4 ambient_light, inout vec4 ref
void main() {
ivec2 pos = ivec2(gl_GlobalInvocationID.xy);
-#ifdef MODE_HALF_RES
- pos <<= 1;
-#endif
- if (any(greaterThanEqual(pos, params.screen_size))) { //too large, do nothing
+ uint vrs_x, vrs_y;
+ if (sc_use_vrs) {
+ ivec2 vrs_pos;
+
+ // Currently we use a 16x16 texel, possibly some day make this configurable.
+ if (sc_half_res) {
+ vrs_pos = pos >> 3;
+ } else {
+ vrs_pos = pos >> 4;
+ }
+
+ uint vrs_texel = imageLoad(vrs_buffer, vrs_pos).r;
+ // note, valid values for vrs_x and vrs_y are 1, 2 and 4.
+ vrs_x = 1 << ((vrs_texel >> 2) & 3);
+ vrs_y = 1 << (vrs_texel & 3);
+
+ if (mod(pos.x, vrs_x) != 0) {
+ return;
+ }
+
+ if (mod(pos.y, vrs_y) != 0) {
+ return;
+ }
+ }
+
+ if (sc_half_res) {
+ pos <<= 1;
+ }
+
+ if (any(greaterThanEqual(pos, scene_data.screen_size))) { //too large, do nothing
return;
}
@@ -641,10 +701,69 @@ void main() {
process_gi(pos, vertex, ambient_light, reflection_light);
-#ifdef MODE_HALF_RES
- pos >>= 1;
-#endif
+ if (sc_half_res) {
+ pos >>= 1;
+ }
imageStore(ambient_buffer, pos, ambient_light);
imageStore(reflection_buffer, pos, reflection_light);
+
+ if (sc_use_vrs) {
+ if (vrs_x > 1) {
+ imageStore(ambient_buffer, pos + ivec2(1, 0), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 0), reflection_light);
+ }
+
+ if (vrs_x > 2) {
+ imageStore(ambient_buffer, pos + ivec2(2, 0), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 0), reflection_light);
+
+ imageStore(ambient_buffer, pos + ivec2(3, 0), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 0), reflection_light);
+ }
+
+ if (vrs_y > 1) {
+ imageStore(ambient_buffer, pos + ivec2(0, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(0, 1), reflection_light);
+ }
+
+ if (vrs_y > 1 && vrs_x > 1) {
+ imageStore(ambient_buffer, pos + ivec2(1, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 1), reflection_light);
+ }
+
+ if (vrs_y > 1 && vrs_x > 2) {
+ imageStore(ambient_buffer, pos + ivec2(2, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 1), reflection_light);
+
+ imageStore(ambient_buffer, pos + ivec2(3, 1), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 1), reflection_light);
+ }
+
+ if (vrs_y > 2) {
+ imageStore(ambient_buffer, pos + ivec2(0, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(0, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(0, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(0, 3), reflection_light);
+ }
+
+ if (vrs_y > 2 && vrs_x > 1) {
+ imageStore(ambient_buffer, pos + ivec2(1, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(1, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(1, 3), reflection_light);
+ }
+
+ if (vrs_y > 2 && vrs_x > 2) {
+ imageStore(ambient_buffer, pos + ivec2(2, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(2, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(2, 3), reflection_light);
+
+ imageStore(ambient_buffer, pos + ivec2(3, 2), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 2), reflection_light);
+ imageStore(ambient_buffer, pos + ivec2(3, 3), ambient_light);
+ imageStore(reflection_buffer, pos + ivec2(3, 3), reflection_light);
+ }
+ }
}
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
index 802a410825..177dab16c7 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug.glsl
@@ -21,6 +21,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 9, std140) uniform Cascades {
@@ -37,13 +38,14 @@ layout(push_constant, std430) uniform Params {
uint max_cascades;
ivec2 screen_size;
- bool use_occlusion;
float y_mult;
- vec3 cam_extent;
- int probe_axis_size;
+ float z_near;
- mat4 cam_transform;
+ mat3x4 inv_projection;
+ // We pack these more tightly than mat3 and vec3, which will require some reconstruction trickery.
+ float cam_basis[3][3];
+ float cam_origin[3];
}
params;
@@ -79,12 +81,21 @@ void main() {
vec3 ray_pos;
vec3 ray_dir;
{
- ray_pos = params.cam_transform[3].xyz;
+ ray_pos = vec3(params.cam_origin[0], params.cam_origin[1], params.cam_origin[2]);
- ray_dir.xy = params.cam_extent.xy * ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0);
- ray_dir.z = params.cam_extent.z;
+ ray_dir.xy = ((vec2(screen_pos) / vec2(params.screen_size)) * 2.0 - 1.0);
+ ray_dir.z = params.z_near;
- ray_dir = normalize(mat3(params.cam_transform) * ray_dir);
+ ray_dir = (vec4(ray_dir, 1.0) * mat4(params.inv_projection)).xyz;
+
+ mat3 cam_basis;
+ {
+ vec3 c0 = vec3(params.cam_basis[0][0], params.cam_basis[0][1], params.cam_basis[0][2]);
+ vec3 c1 = vec3(params.cam_basis[1][0], params.cam_basis[1][1], params.cam_basis[1][2]);
+ vec3 c2 = vec3(params.cam_basis[2][0], params.cam_basis[2][1], params.cam_basis[2][2]);
+ cam_basis = mat3(c0, c1, c2);
+ }
+ ray_dir = normalize(cam_basis * ray_dir);
}
ray_pos.y *= params.y_mult;
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl
index e0be0bca12..a0ef169f03 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_debug_probes.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_debug_probes.glsl
@@ -2,13 +2,28 @@
#version 450
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
#VERSION_DEFINES
#define MAX_CASCADES 8
+#define MAX_VIEWS 2
layout(push_constant, std430) uniform Params {
- mat4 projection;
-
uint band_power;
uint sections_in_band;
uint band_mask;
@@ -58,6 +73,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 1, std140) uniform Cascades {
@@ -68,6 +84,11 @@ cascades;
layout(set = 0, binding = 4) uniform texture3D occlusion_texture;
layout(set = 0, binding = 3) uniform sampler linear_sampler;
+layout(set = 0, binding = 5, std140) uniform SceneData {
+ mat4 projection[MAX_VIEWS];
+}
+scene_data;
+
void main() {
#ifdef MODE_PROBES
probe_index = gl_InstanceIndex;
@@ -85,7 +106,7 @@ void main() {
vertex += (cascades.data[params.cascade].offset + vec3(probe_cell) * probe_cell_size) / vec3(1.0, params.y_mult, 1.0);
- gl_Position = params.projection * vec4(vertex, 1.0);
+ gl_Position = scene_data.projection[ViewIndex] * vec4(vertex, 1.0);
#endif
#ifdef MODE_VISIBILITY
@@ -144,7 +165,7 @@ void main() {
visibility = dot(texelFetch(sampler3D(occlusion_texture, linear_sampler), tex_pos, 0), layer_axis[occlusion_layer]);
- gl_Position = params.projection * vec4(vertex, 1.0);
+ gl_Position = scene_data.projection[ViewIndex] * vec4(vertex, 1.0);
#endif
}
@@ -153,16 +174,32 @@ void main() {
#version 450
+#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
+#extension GL_EXT_multiview : enable
+#endif
+
+#ifdef USE_MULTIVIEW
+#ifdef has_VK_KHR_multiview
+#define ViewIndex gl_ViewIndex
+#else // has_VK_KHR_multiview
+// !BAS! This needs to become an input once we implement our fallback!
+#define ViewIndex 0
+#endif // has_VK_KHR_multiview
+#else // USE_MULTIVIEW
+// Set to zero, not supported in non stereo
+#define ViewIndex 0
+#endif //USE_MULTIVIEW
+
#VERSION_DEFINES
+#define MAX_VIEWS 2
+
layout(location = 0) out vec4 frag_color;
layout(set = 0, binding = 2) uniform texture2DArray lightprobe_texture;
layout(set = 0, binding = 3) uniform sampler linear_sampler;
layout(push_constant, std430) uniform Params {
- mat4 projection;
-
uint band_power;
uint sections_in_band;
uint band_mask;
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
index b95fad650e..9f7449b8aa 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_direct_light.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_direct_light.glsl
@@ -45,6 +45,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 8, std140) uniform Cascades {
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl
index 9c03297f5c..4bdb0dcc72 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_integrate.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_integrate.glsl
@@ -20,6 +20,7 @@ struct CascadeData {
float to_cell; // 1/bounds * grid_size
ivec3 probe_world_offset;
uint pad;
+ vec4 pad2;
};
layout(set = 0, binding = 7, std140) uniform Cascades {
diff --git a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
index bce98f4054..bce98f4054 100644
--- a/servers/rendering/renderer_rd/shaders/sdfgi_preprocess.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sdfgi_preprocess.glsl
diff --git a/servers/rendering/renderer_rd/shaders/sky.glsl b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
index 5b4594da99..d523461600 100644
--- a/servers/rendering/renderer_rd/shaders/sky.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/sky.glsl
@@ -15,10 +15,10 @@ layout(location = 0) out vec2 uv_interp;
layout(push_constant, std430) uniform Params {
mat3 orientation;
vec4 projections[MAX_VIEWS];
- vec4 position_multiplier;
+ vec3 position;
float time;
+ vec3 pad;
float luminance_multiplier;
- float pad[2];
}
params;
@@ -55,10 +55,10 @@ layout(location = 0) in vec2 uv_interp;
layout(push_constant, std430) uniform Params {
mat3 orientation;
vec4 projections[MAX_VIEWS];
- vec4 position_multiplier;
+ vec3 position;
float time;
+ vec3 pad;
float luminance_multiplier;
- float pad[2];
}
params;
@@ -77,26 +77,29 @@ params;
layout(set = 0, binding = 0) uniform sampler material_samplers[12];
-layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 1, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
layout(set = 0, binding = 2, std140) uniform SceneData {
- bool volumetric_fog_enabled;
- float volumetric_fog_inv_length;
- float volumetric_fog_detail_spread;
-
- float fog_aerial_perspective;
-
- vec3 fog_light_color;
- float fog_sun_scatter;
-
- bool fog_enabled;
- float fog_density;
-
- float z_far;
- uint directional_light_count;
+ bool volumetric_fog_enabled; // 4 - 4
+ float volumetric_fog_inv_length; // 4 - 8
+ float volumetric_fog_detail_spread; // 4 - 12
+ float volumetric_fog_sky_affect; // 4 - 16
+
+ bool fog_enabled; // 4 - 20
+ float fog_sky_affect; // 4 - 24
+ float fog_density; // 4 - 28
+ float fog_sun_scatter; // 4 - 32
+
+ vec3 fog_light_color; // 12 - 44
+ float fog_aerial_perspective; // 4 - 48
+
+ float z_far; // 4 - 52
+ uint directional_light_count; // 4 - 56
+ uint pad1; // 4 - 60
+ uint pad2; // 4 - 64
}
scene_data;
@@ -150,6 +153,15 @@ layout(set = 3, binding = 0) uniform texture3D volumetric_fog_texture;
layout(location = 0) out vec4 frag_color;
+#ifdef USE_DEBANDING
+// https://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
+vec3 interleaved_gradient_noise(vec2 pos) {
+ const vec3 magic = vec3(0.06711056f, 0.00583715f, 52.9829189f);
+ float res = fract(magic.z * fract(dot(pos, magic.xy))) * 2.0 - 1.0;
+ return vec3(res, -res, res) / 255.0;
+}
+#endif
+
vec4 volumetric_fog_process(vec2 screen_uv) {
vec3 fog_pos = vec3(screen_uv, 1.0);
@@ -169,9 +181,7 @@ vec4 fog_process(vec3 view, vec3 sky_color) {
}
}
- float fog_amount = clamp(1.0 - exp(-scene_data.z_far * scene_data.fog_density), 0.0, 1.0);
-
- return vec4(fog_color, fog_amount);
+ return vec4(fog_color, 1.0);
}
void main() {
@@ -200,17 +210,17 @@ void main() {
#ifdef USE_CUBEMAP_PASS
#ifdef USES_HALF_RES_COLOR
- half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
+ half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) * params.luminance_multiplier;
+ quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal) / params.luminance_multiplier;
#endif
#else
#ifdef USES_HALF_RES_COLOR
- half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
+ half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;
#endif
#ifdef USES_QUARTER_RES_COLOR
- quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) * params.luminance_multiplier;
+ quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0) / params.luminance_multiplier;
#endif
#endif
@@ -220,7 +230,7 @@ void main() {
}
- frag_color.rgb = color * params.position_multiplier.w;
+ frag_color.rgb = color;
frag_color.a = alpha;
#if !defined(DISABLE_FOG) && !defined(USE_CUBEMAP_PASS)
@@ -228,12 +238,12 @@ void main() {
// Draw "fixed" fog before volumetric fog to ensure volumetric fog can appear in front of the sky.
if (scene_data.fog_enabled) {
vec4 fog = fog_process(cube_normal, frag_color.rgb);
- frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+ frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.fog_sky_affect);
}
if (scene_data.volumetric_fog_enabled) {
vec4 fog = volumetric_fog_process(uv);
- frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a);
+ frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a * scene_data.volumetric_fog_sky_affect);
}
if (custom_fog.a > 0.0) {
@@ -242,12 +252,17 @@ void main() {
#endif // DISABLE_FOG
- // Blending is disabled for Sky, so alpha doesn't blend
- // alpha is used for subsurface scattering so make sure it doesn't get applied to Sky
+ // Blending is disabled for Sky, so alpha doesn't blend.
+ // Alpha is used for subsurface scattering so make sure it doesn't get applied to Sky.
if (!AT_CUBEMAP_PASS && !AT_HALF_RES_PASS && !AT_QUARTER_RES_PASS) {
frag_color.a = 0.0;
}
- // For mobile renderer we're dividing by 2.0 as we're using a UNORM buffer
- frag_color.rgb = frag_color.rgb / params.luminance_multiplier;
+ // For mobile renderer we're multiplying by 0.5 as we're using a UNORM buffer.
+ // For both mobile and clustered, we also bake in the exposure value for the environment and camera.
+ frag_color.rgb = frag_color.rgb * params.luminance_multiplier;
+
+#ifdef USE_DEBANDING
+ frag_color.rgb += interleaved_gradient_noise(gl_FragCoord.xy);
+#endif
}
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
index eee609fb48..4658afd02d 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog.glsl
@@ -21,17 +21,17 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
#define DENSITY_SCALE 1024.0
-#include "cluster_data_inc.glsl"
-#include "light_data_inc.glsl"
+#include "../cluster_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define M_PI 3.14159265359
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
layout(push_constant, std430) uniform Params {
vec3 position;
diff --git a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
index 347fd13b28..28507e6c12 100644
--- a/servers/rendering/renderer_rd/shaders/volumetric_fog_process.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/volumetric_fog_process.glsl
@@ -19,8 +19,8 @@ layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in;
layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#endif
-#include "cluster_data_inc.glsl"
-#include "light_data_inc.glsl"
+#include "../cluster_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define M_PI 3.14159265359
@@ -53,7 +53,6 @@ layout(set = 0, binding = 7) uniform sampler linear_sampler;
#ifdef MODE_DENSITY
layout(rgba16f, set = 0, binding = 8) uniform restrict writeonly image3D density_map;
-layout(rgba16f, set = 0, binding = 9) uniform restrict readonly image3D fog_map; //unused
#endif
#ifdef MODE_FOG
@@ -85,6 +84,9 @@ struct VoxelGIData {
float normal_bias; // 4 - 88
bool blend_ambient; // 4 - 92
uint mipmaps; // 4 - 96
+
+ vec3 pad; // 12 - 108
+ float exposure_normalization; // 4 - 112
};
layout(set = 0, binding = 11, std140) uniform VoxelGIs {
@@ -106,6 +108,8 @@ struct SDFVoxelGICascadeData {
float to_probe;
ivec3 probe_world_offset;
float to_cell; // 1/bounds * grid_size
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 1, binding = 0, std140) uniform SDFGI {
@@ -271,6 +275,9 @@ const vec3 halton_map[TEMPORAL_FRAMES] = vec3[](
vec3(0.9375, 0.25925926, 0.12),
vec3(0.03125, 0.59259259, 0.32));
+// Higher values will make light in volumetric fog fade out sooner when it's occluded by shadow.
+const float INV_FOG_FADE = 10.0;
+
void main() {
vec3 fog_cell_size = 1.0 / vec3(params.fog_volume_size);
@@ -374,48 +381,50 @@ void main() {
float cell_depth_size = abs(view_pos.z - get_depth_at_pos(fog_cell_size.z, pos.z + 1));
//compute directional lights
- if (total_density > 0.001) {
+ if (total_density > 0.00005) {
for (uint i = 0; i < params.directional_light_count; i++) {
- vec3 shadow_attenuation = vec3(1.0);
-
- if (directional_lights.data[i].shadow_enabled) {
- float depth_z = -view_pos.z;
-
- vec4 pssm_coord;
- vec3 light_dir = directional_lights.data[i].direction;
- vec4 v = vec4(view_pos, 1.0);
- float z_range;
-
- if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
- pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.x;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
- pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.y;
-
- } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
- pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.z;
-
- } else {
- pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
- pssm_coord /= pssm_coord.w;
- z_range = directional_lights.data[i].shadow_z_range.w;
- }
+ if (directional_lights.data[i].volumetric_fog_energy > 0.001) {
+ vec3 shadow_attenuation = vec3(1.0);
+
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
+ float depth_z = -view_pos.z;
+
+ vec4 pssm_coord;
+ vec3 light_dir = directional_lights.data[i].direction;
+ vec4 v = vec4(view_pos, 1.0);
+ float z_range;
+
+ if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix1 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.x;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix2 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.y;
+
+ } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) {
+ pssm_coord = (directional_lights.data[i].shadow_matrix3 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.z;
+
+ } else {
+ pssm_coord = (directional_lights.data[i].shadow_matrix4 * v);
+ pssm_coord /= pssm_coord.w;
+ z_range = directional_lights.data[i].shadow_z_range.w;
+ }
- float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
- float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * directional_lights.data[i].shadow_volumetric_fog_fade);
+ float depth = texture(sampler2D(directional_shadow_atlas, linear_sampler), pssm_coord.xy).r;
+ float shadow = exp(min(0.0, (depth - pssm_coord.z)) * z_range * INV_FOG_FADE);
- shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
+ shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, view_pos.z)); //done with negative values for performance
- shadow_attenuation = mix(vec3(0.0), vec3(1.0), shadow);
- }
+ shadow_attenuation = mix(vec3(1.0 - directional_lights.data[i].shadow_opacity), vec3(1.0), shadow);
+ }
- total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy * henyey_greenstein(dot(normalize(view_pos), normalize(directional_lights.data[i].direction)), params.phase_g);
+ total_light += shadow_attenuation * directional_lights.data[i].color * directional_lights.data[i].energy * henyey_greenstein(dot(normalize(view_pos), normalize(directional_lights.data[i].direction)), params.phase_g) * directional_lights.data[i].volumetric_fog_energy;
+ }
}
// Compute light from sky
@@ -482,12 +491,12 @@ void main() {
float d = distance(omni_lights.data[light_index].position, view_pos);
float shadow_attenuation = 1.0;
- if (d * omni_lights.data[light_index].inv_radius < 1.0) {
+ if (omni_lights.data[light_index].volumetric_fog_energy > 0.001 && d * omni_lights.data[light_index].inv_radius < 1.0) {
float attenuation = get_omni_attenuation(d, omni_lights.data[light_index].inv_radius, omni_lights.data[light_index].attenuation);
vec3 light = omni_lights.data[light_index].color;
- if (omni_lights.data[light_index].shadow_enabled) {
+ if (omni_lights.data[light_index].shadow_opacity > 0.001) {
//has shadow
vec4 uv_rect = omni_lights.data[light_index].atlas_rect;
vec2 flip_offset = omni_lights.data[light_index].direction.xy;
@@ -510,9 +519,9 @@ void main() {
float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
- shadow_attenuation = exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * omni_lights.data[light_index].shadow_volumetric_fog_fade);
+ shadow_attenuation = mix(1.0 - omni_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / omni_lights.data[light_index].inv_radius * INV_FOG_FADE));
}
- total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g);
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_pos - view_pos), normalize(view_pos)), params.phase_g) * omni_lights.data[light_index].volumetric_fog_energy;
}
}
}
@@ -563,7 +572,7 @@ void main() {
float d = length(light_rel_vec);
float shadow_attenuation = 1.0;
- if (d * spot_lights.data[light_index].inv_radius < 1.0) {
+ if (spot_lights.data[light_index].volumetric_fog_energy > 0.001 && d * spot_lights.data[light_index].inv_radius < 1.0) {
float attenuation = get_omni_attenuation(d, spot_lights.data[light_index].inv_radius, spot_lights.data[light_index].attenuation);
vec3 spot_dir = spot_lights.data[light_index].direction;
@@ -573,7 +582,7 @@ void main() {
vec3 light = spot_lights.data[light_index].color;
- if (spot_lights.data[light_index].shadow_enabled) {
+ if (spot_lights.data[light_index].shadow_opacity > 0.001) {
//has shadow
vec4 uv_rect = spot_lights.data[light_index].atlas_rect;
vec2 flip_offset = spot_lights.data[light_index].direction.xy;
@@ -596,9 +605,9 @@ void main() {
float depth = texture(sampler2D(shadow_atlas, linear_sampler), pos.xy).r;
- shadow_attenuation = exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * spot_lights.data[light_index].shadow_volumetric_fog_fade);
+ shadow_attenuation = mix(1.0 - spot_lights.data[light_index].shadow_opacity, 1.0, exp(min(0.0, (depth - pos.z)) / spot_lights.data[light_index].inv_radius * INV_FOG_FADE));
}
- total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g);
+ total_light += light * attenuation * shadow_attenuation * henyey_greenstein(dot(normalize(light_rel_vec), normalize(view_pos)), params.phase_g) * spot_lights.data[light_index].volumetric_fog_energy;
}
}
}
@@ -620,7 +629,7 @@ void main() {
light += a * slight;
}
- light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject;
+ light.rgb *= voxel_gi_instances.data[i].dynamic_range * params.gi_inject * voxel_gi_instances.data[i].exposure_normalization;
total_light += light.rgb;
}
@@ -687,7 +696,7 @@ void main() {
vec3 ambient = texelFetch(sampler2DArray(sdfgi_ambient_texture, linear_sampler), uvw, 0).rgb;
- ambient_accum.rgb += ambient * weight;
+ ambient_accum.rgb += ambient * weight * sdfgi.cascades[i].exposure_normalization;
ambient_accum.a += weight;
}
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl b/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl
index 577c6d0cd0..577c6d0cd0 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/voxel_gi.glsl
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl
index fd7a2bf8ad..fd7a2bf8ad 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi_debug.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_debug.glsl
diff --git a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_sdf.glsl
index 47a611a543..47a611a543 100644
--- a/servers/rendering/renderer_rd/shaders/voxel_gi_sdf.glsl
+++ b/servers/rendering/renderer_rd/shaders/environment/voxel_gi_sdf.glsl
diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub
new file mode 100644
index 0000000000..f06a2d86e2
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/SCsub
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+Import("env")
+
+if "RD_GLSL" in env["BUILDERS"]:
+ # find all include files
+ gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")]
+
+ # find all shader code(all glsl files excluding our include files)
+ glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
+
+ # make sure we recompile shaders if include files change
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
+
+ # compile shaders
+ for glsl_file in glsl_files:
+ env.RD_GLSL(glsl_file)
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
index 92c4fc3d67..0bdf0e50aa 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl
@@ -15,11 +15,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -58,6 +58,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) out vec3 vertex_interp;
@@ -90,12 +97,12 @@ layout(location = 8) out vec4 prev_screen_position;
#ifdef MATERIAL_UNIFORMS_USED
layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms{
-
#MATERIAL_UNIFORMS
-
} material;
#endif
+float global_time;
+
#ifdef MODE_DUAL_PARABOLOID
layout(location = 9) out float dp_clip;
@@ -120,12 +127,52 @@ invariant gl_Position;
#GLOBALS
-void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
+#ifdef USE_DOUBLE_PRECISION
+// Helper functions for emulating double precision when adding floats.
+vec3 quick_two_sum(vec3 a, vec3 b, out vec3 out_p) {
+ vec3 s = a + b;
+ out_p = b - (s - a);
+ return s;
+}
+
+vec3 two_sum(vec3 a, vec3 b, out vec3 out_p) {
+ vec3 s = a + b;
+ vec3 v = s - a;
+ out_p = (a - (s - v)) + (b - v);
+ return s;
+}
+
+vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec3 out_precision) {
+ vec3 s, t, se, te;
+ s = two_sum(base_a, base_b, se);
+ t = two_sum(prec_a, prec_b, te);
+ se += t;
+ s = quick_two_sum(s, se, se);
+ se += te;
+ s = quick_two_sum(s, se, out_precision);
+ return s;
+}
+#endif
+
+void vertex_shader(in uint instance_index, in bool is_multimesh, in uint multimesh_offset, in SceneData scene_data, in mat4 model_matrix, out vec4 screen_pos) {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
#endif
+ mat4 inv_view_matrix = scene_data.inv_view_matrix;
+
+#ifdef USE_DOUBLE_PRECISION
+ vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]);
+ model_matrix[0][3] = 0.0;
+ model_matrix[1][3] = 0.0;
+ model_matrix[2][3] = 0.0;
+ vec3 view_precision = vec3(inv_view_matrix[0][3], inv_view_matrix[1][3], inv_view_matrix[2][3]);
+ inv_view_matrix[0][3] = 0.0;
+ inv_view_matrix[1][3] = 0.0;
+ inv_view_matrix[2][3] = 0.0;
+#endif
+
mat3 model_normal_matrix;
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
model_normal_matrix = transpose(inverse(mat3(model_matrix)));
@@ -133,11 +180,12 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
model_normal_matrix = mat3(model_matrix);
}
+ mat4 matrix;
+ mat4 read_model_matrix = model_matrix;
+
if (is_multimesh) {
//multimesh, instances are for it
- mat4 matrix;
-
#ifdef USE_PARTICLE_TRAILS
uint trail_size = (instances.data[instance_index].flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK;
uint stride = 3 + 1 + 1; //particles always uses this format
@@ -199,7 +247,7 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
}
}
- uint offset = stride * gl_InstanceIndex;
+ uint offset = stride * (gl_InstanceIndex + multimesh_offset);
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) {
matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0));
@@ -223,18 +271,26 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
#endif
//transpose
matrix = transpose(matrix);
- model_matrix = model_matrix * matrix;
+#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED)
+ // Normally we can bake the multimesh transform into the model matrix, but when using double precision
+ // we avoid baking it in so we can emulate high precision.
+ read_model_matrix = model_matrix * matrix;
+#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED)
+ model_matrix = read_model_matrix;
+#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED)
+#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED)
model_normal_matrix = model_normal_matrix * mat3(matrix);
}
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
@@ -287,7 +343,22 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
// using local coordinates (default)
#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED)
+#ifdef USE_DOUBLE_PRECISION
+ // We separate the basis from the origin because the basis is fine with single point precision.
+ // Then we combine the translations from the model matrix and the view matrix using emulated doubles.
+ // We add the result to the vertex and ignore the final lost precision.
+ vec3 model_origin = model_matrix[3].xyz;
+ if (is_multimesh) {
+ vertex = mat3(matrix) * vertex;
+ model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
+ }
+ vertex = mat3(model_matrix) * vertex;
+ vec3 temp_precision; // Will be ignored.
+ vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision);
+ vertex = mat3(scene_data.view_matrix) * vertex;
+#else
vertex = (modelview * vec4(vertex, 1.0)).xyz;
+#endif
#ifdef NORMAL_USED
normal = modelview_normal * normal;
#endif
@@ -316,10 +387,6 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
vertex_interp = vertex;
-#ifdef MOTION_VECTORS
- screen_pos = projection_matrix * vec4(vertex_interp, 1.0);
-#endif
-
#ifdef NORMAL_USED
normal_interp = normal;
#endif
@@ -357,6 +424,10 @@ void vertex_shader(in uint instance_index, in bool is_multimesh, in SceneData sc
gl_Position = projection_matrix * vec4(vertex_interp, 1.0);
#endif
+#ifdef MOTION_VECTORS
+ screen_pos = gl_Position;
+#endif
+
#ifdef MODE_RENDER_DEPTH
if (scene_data.pancake_shadows) {
if (gl_Position.z <= 0.00001) {
@@ -386,11 +457,14 @@ void main() {
mat4 model_matrix = instances.data[instance_index].transform;
#if defined(MOTION_VECTORS)
- vertex_shader(instance_index, is_multimesh, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
- vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position);
+ global_time = scene_data_block.prev_data.time;
+ vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_previous_offset, scene_data_block.prev_data, instances.data[instance_index].prev_transform, prev_screen_position);
+ global_time = scene_data_block.data.time;
+ vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
#else
+ global_time = scene_data_block.data.time;
vec4 screen_position;
- vertex_shader(instance_index, is_multimesh, scene_data_block.data, model_matrix, screen_position);
+ vertex_shader(instance_index, is_multimesh, draw_call.multimesh_motion_vectors_current_offset, scene_data_block.data, model_matrix, screen_position);
#endif
}
@@ -477,7 +551,6 @@ layout(location = 10) in flat uint instance_index_interp;
//defines to keep compatibility with vertex
-#define model_matrix instances.data[draw_call.instance_index].transform
#ifdef USE_MULTIVIEW
#define projection_matrix scene_data.projection_matrix_view[ViewIndex]
#define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex]
@@ -486,6 +559,8 @@ layout(location = 10) in flat uint instance_index_interp;
#define inv_projection_matrix scene_data.inv_projection_matrix
#endif
+#define global_time scene_data_block.data.time
+
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
//both required for transmittance to be enabled
#define LIGHT_TRANSMITTANCE_USED
@@ -538,7 +613,7 @@ layout(location = 0) out vec4 frag_color;
layout(location = 2) out vec2 motion_vector;
#endif
-#include "scene_forward_aa_inc.glsl"
+#include "../scene_forward_aa_inc.glsl"
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@@ -547,20 +622,20 @@ layout(location = 2) out vec2 motion_vector;
#define SPECULAR_SCHLICK_GGX
#endif
-#include "scene_forward_lights_inc.glsl"
+#include "../scene_forward_lights_inc.glsl"
-#include "scene_forward_gi_inc.glsl"
+#include "../scene_forward_gi_inc.glsl"
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
#ifndef MODE_RENDER_DEPTH
vec4 volumetric_fog_process(vec2 screen_uv, float z) {
- vec3 fog_pos = vec3(screen_uv, z * scene_data_block.data.volumetric_fog_inv_length);
+ vec3 fog_pos = vec3(screen_uv, z * implementation_data.volumetric_fog_inv_length);
if (fog_pos.z < 0.0) {
return vec4(0.0);
} else if (fog_pos.z < 1.0) {
- fog_pos.z = pow(fog_pos.z, scene_data_block.data.volumetric_fog_detail_spread);
+ fog_pos.z = pow(fog_pos.z, implementation_data.volumetric_fog_detail_spread);
}
return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos);
@@ -614,7 +689,7 @@ vec4 fog_process(vec3 vertex) {
void cluster_get_item_range(uint p_offset, out uint item_min, out uint item_max, out uint item_from, out uint item_to) {
uint item_min_max = cluster_buffer.data[p_offset];
- item_min = item_min_max & 0xFFFF;
+ item_min = item_min_max & 0xFFFFu;
item_max = item_min_max >> 16;
item_from = item_min >> 5;
@@ -634,7 +709,11 @@ void fragment_shader(in SceneData scene_data) {
//lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
+#ifdef USE_MULTIVIEW
+ vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz);
+#else
vec3 view = -normalize(vertex_interp);
+#endif
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
vec4 transmittance_color = vec4(0.0, 0.0, 0.0, 1.0);
@@ -718,6 +797,17 @@ void fragment_shader(in SceneData scene_data) {
vec2 alpha_texture_coordinate = vec2(0.0, 0.0);
#endif // ALPHA_ANTIALIASING_EDGE_USED
+ mat4 inv_view_matrix = scene_data.inv_view_matrix;
+ mat4 read_model_matrix = instances.data[instance_index].transform;
+#ifdef USE_DOUBLE_PRECISION
+ read_model_matrix[0][3] = 0.0;
+ read_model_matrix[1][3] = 0.0;
+ read_model_matrix[2][3] = 0.0;
+ inv_view_matrix[0][3] = 0.0;
+ inv_view_matrix[1][3] = 0.0;
+ inv_view_matrix[2][3] = 0.0;
+#endif
+
{
#CODE : FRAGMENT
}
@@ -802,7 +892,7 @@ void fragment_shader(in SceneData scene_data) {
fog = fog_process(vertex);
}
- if (scene_data.volumetric_fog_enabled) {
+ if (implementation_data.volumetric_fog_enabled) {
vec4 volumetric_fog = volumetric_fog_process(screen_uv, -vertex.z);
if (scene_data.fog_enabled) {
//must use the full blending equation here to blend fogs
@@ -830,8 +920,8 @@ void fragment_shader(in SceneData scene_data) {
#ifndef MODE_RENDER_DEPTH
- uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> scene_data.cluster_shift;
- uint cluster_offset = (scene_data.cluster_width * cluster_pos.y + cluster_pos.x) * (scene_data.max_cluster_element_count_div_32 + 32);
+ uvec2 cluster_pos = uvec2(gl_FragCoord.xy) >> implementation_data.cluster_shift;
+ uint cluster_offset = (implementation_data.cluster_width * cluster_pos.y + cluster_pos.x) * (implementation_data.max_cluster_element_count_div_32 + 32);
uint cluster_z = uint(clamp((-vertex.z / scene_data.z_far) * 32.0, 0.0, 31.0));
@@ -841,14 +931,14 @@ void fragment_shader(in SceneData scene_data) {
{ // process decals
- uint cluster_decal_offset = cluster_offset + scene_data.cluster_type_size * 2;
+ uint cluster_decal_offset = cluster_offset + implementation_data.cluster_type_size * 2;
uint item_min;
uint item_max;
uint item_from;
uint item_to;
- cluster_get_item_range(cluster_decal_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+ cluster_get_item_range(cluster_decal_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
#ifdef USE_SUBGROUPS
item_from = subgroupBroadcastFirst(subgroupMin(item_from));
@@ -866,9 +956,9 @@ void fragment_shader(in SceneData scene_data) {
while (merged_mask != 0) {
uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
+ merged_mask &= ~(1u << bit);
#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ if (((1u << bit) & mask) == 0) { //do not process if not originally here
continue;
}
#endif
@@ -936,9 +1026,9 @@ void fragment_shader(in SceneData scene_data) {
if (decals.data[decal_index].emission_rect != vec4(0.0)) {
//emission is additive, so its independent from albedo
if (sc_decal_use_mipmaps) {
- emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].emission_energy * fade;
+ emission += textureGrad(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, ddx * decals.data[decal_index].emission_rect.zw, ddy * decals.data[decal_index].emission_rect.zw).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade;
} else {
- emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].emission_energy * fade;
+ emission += textureLod(sampler2D(decal_atlas_srgb, decal_sampler), uv_local.xz * decals.data[decal_index].emission_rect.zw + decals.data[decal_index].emission_rect.xy, 0.0).xyz * decals.data[decal_index].modulate.rgb * decals.data[decal_index].emission_energy * fade;
}
}
}
@@ -967,6 +1057,11 @@ void fragment_shader(in SceneData scene_data) {
vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
vec3 ambient_light = vec3(0.0, 0.0, 0.0);
+#ifndef MODE_UNSHADED
+ // Used in regular draw pass and when drawing SDFs for SDFGI and materials for VoxelGI.
+ emission *= scene_data.emissive_exposure_normalization;
+#endif
+
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
if (scene_data.use_reflection_cubemap) {
@@ -977,8 +1072,10 @@ void fragment_shader(in SceneData scene_data) {
vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
vec3 ref_vec = reflect(-view, bent_normal);
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
#else
vec3 ref_vec = reflect(-view, normal);
+ ref_vec = mix(ref_vec, normal, roughness * roughness);
#endif
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
@@ -994,6 +1091,7 @@ void fragment_shader(in SceneData scene_data) {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ specular_light *= scene_data.IBL_exposure_normalization;
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
@@ -1014,7 +1112,7 @@ void fragment_shader(in SceneData scene_data) {
#else
vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
-
+ cubemap_ambient *= scene_data.IBL_exposure_normalization;
ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
}
}
@@ -1035,6 +1133,7 @@ void fragment_shader(in SceneData scene_data) {
ambient_light *= attenuation;
specular_light *= attenuation;
+ ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness);
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
float roughness_lod = mix(0.001, 0.1, clearcoat_roughness) * MAX_ROUGHNESS_LOD;
@@ -1072,15 +1171,16 @@ void fragment_shader(in SceneData scene_data) {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *
+ scene_data.emissive_exposure_normalization;
} else if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -1098,20 +1198,22 @@ void fragment_shader(in SceneData scene_data) {
uint idx = instances.data[instance_index].gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
+ float en = lightmaps.data[idx].exposure_normalization;
- ambient_light += lm_light_l0 * 0.282095f;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x;
+ ambient_light += lm_light_l0 * 0.282095f * en;
+ ambient_light += lm_light_l1n1 * 0.32573 * n.y * en;
+ ambient_light += lm_light_l1_0 * 0.32573 * n.z * en;
+ ambient_light += lm_light_l1p1 * 0.32573 * n.x * en;
if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y;
- specular_light += lm_light_l1_0 * 0.32573 * r.z;
- specular_light += lm_light_l1p1 * 0.32573 * r.x;
+ specular_light += lm_light_l1n1 * 0.32573 * r.y * en;
+ specular_light += lm_light_l1_0 * 0.32573 * r.z * en;
+ specular_light += lm_light_l1p1 * 0.32573 * r.x * en;
}
} else {
- ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
+ uint idx = instances.data[instance_index].gi_offset >> 20;
+ ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization;
}
}
#else
@@ -1191,7 +1293,8 @@ void fragment_shader(in SceneData scene_data) {
if (sc_use_forward_gi && bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
- vec3 ref_vec = normalize(reflect(normalize(vertex), normal));
+ vec3 ref_vec = normalize(reflect(-view, normal));
+ ref_vec = mix(ref_vec, normal, roughness * roughness);
//find arbitrary tangent and bitangent, then build a matrix
vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
vec3 tangent = normalize(cross(v0, normal));
@@ -1224,15 +1327,23 @@ void fragment_shader(in SceneData scene_data) {
vec2 coord;
- if (scene_data.gi_upscale_for_msaa) {
+ if (implementation_data.gi_upscale_for_msaa) {
vec2 base_coord = screen_uv;
vec2 closest_coord = base_coord;
+#ifdef USE_MULTIVIEW
+ float closest_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(base_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0);
+#else // USE_MULTIVIEW
float closest_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), base_coord, 0.0).xyz * 2.0 - 1.0);
+#endif // USE_MULTIVIEW
for (int i = 0; i < 4; i++) {
const vec2 neighbours[4] = vec2[](vec2(-1, 0), vec2(1, 0), vec2(0, -1), vec2(0, 1));
vec2 neighbour_coord = base_coord + neighbours[i] * scene_data.screen_pixel_size;
+#ifdef USE_MULTIVIEW
+ float neighbour_ang = dot(normal, textureLod(sampler2DArray(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(neighbour_coord, ViewIndex), 0.0).xyz * 2.0 - 1.0);
+#else // USE_MULTIVIEW
float neighbour_ang = dot(normal, textureLod(sampler2D(normal_roughness_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), neighbour_coord, 0.0).xyz * 2.0 - 1.0);
+#endif // USE_MULTIVIEW
if (neighbour_ang > closest_ang) {
closest_ang = neighbour_ang;
closest_coord = neighbour_coord;
@@ -1245,18 +1356,23 @@ void fragment_shader(in SceneData scene_data) {
coord = screen_uv;
}
+#ifdef USE_MULTIVIEW
+ vec4 buffer_ambient = textureLod(sampler2DArray(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(coord, ViewIndex), 0.0);
+ vec4 buffer_reflection = textureLod(sampler2DArray(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), vec3(coord, ViewIndex), 0.0);
+#else // USE_MULTIVIEW
vec4 buffer_ambient = textureLod(sampler2D(ambient_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0);
vec4 buffer_reflection = textureLod(sampler2D(reflection_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), coord, 0.0);
+#endif // USE_MULTIVIEW
ambient_light = mix(ambient_light, buffer_ambient.rgb, buffer_ambient.a);
specular_light = mix(specular_light, buffer_reflection.rgb, buffer_reflection.a);
}
#endif // !USE_LIGHTMAP
- if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) {
+ if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSAO)) {
float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r;
ao = min(ao, ssao);
- ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect);
+ ao_light_affect = mix(ao_light_affect, max(ao_light_affect, implementation_data.ssao_light_affect), implementation_data.ssao_ao_affect);
}
{ // process reflections
@@ -1264,20 +1380,32 @@ void fragment_shader(in SceneData scene_data) {
vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
- uint cluster_reflection_offset = cluster_offset + scene_data.cluster_type_size * 3;
+ uint cluster_reflection_offset = cluster_offset + implementation_data.cluster_type_size * 3;
uint item_min;
uint item_max;
uint item_from;
uint item_to;
- cluster_get_item_range(cluster_reflection_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+ cluster_get_item_range(cluster_reflection_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
#ifdef USE_SUBGROUPS
item_from = subgroupBroadcastFirst(subgroupMin(item_from));
item_to = subgroupBroadcastFirst(subgroupMax(item_to));
#endif
+#ifdef LIGHT_ANISOTROPY_USED
+ // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
+ vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
+ vec3 anisotropic_tangent = cross(anisotropic_direction, view);
+ vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
+ vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
+#else
+ vec3 bent_normal = normal;
+#endif
+ vec3 ref_vec = normalize(reflect(-view, bent_normal));
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
+
for (uint i = item_from; i < item_to; i++) {
uint mask = cluster_buffer.data[cluster_reflection_offset + i];
mask &= cluster_get_range_clip_mask(i, item_min, item_max);
@@ -1289,9 +1417,9 @@ void fragment_shader(in SceneData scene_data) {
while (merged_mask != 0) {
uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
+ merged_mask &= ~(1u << bit);
#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ if (((1u << bit) & mask) == 0) { //do not process if not originally here
continue;
}
#endif
@@ -1300,16 +1428,8 @@ void fragment_shader(in SceneData scene_data) {
if (!bool(reflections.data[reflection_index].mask & instances.data[instance_index].layer_mask)) {
continue; //not masked
}
-#ifdef LIGHT_ANISOTROPY_USED
- // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
- vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
- vec3 anisotropic_tangent = cross(anisotropic_direction, view);
- vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
- vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
-#else
- vec3 bent_normal = normal;
-#endif
- reflection_process(reflection_index, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+
+ reflection_process(reflection_index, vertex, ref_vec, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
}
@@ -1325,18 +1445,24 @@ void fragment_shader(in SceneData scene_data) {
}
//finalize ambient light here
- ambient_light *= albedo.rgb;
- ambient_light *= ao;
+ {
+#if defined(AMBIENT_LIGHT_DISABLED)
+ ambient_light = vec3(0.0, 0.0, 0.0);
+#else
+ ambient_light *= albedo.rgb;
+ ambient_light *= ao;
+
+ if (bool(implementation_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) {
+ vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0);
+ ambient_light *= 1.0 - ssil.a;
+ ambient_light += ssil.rgb * albedo.rgb;
+ }
+#endif // AMBIENT_LIGHT_DISABLED
+ }
// convert ao to direct light ao
ao = mix(1.0, ao, ao_light_affect);
- if (bool(scene_data.ss_effects_flags & SCREEN_SPACE_EFFECTS_FLAGS_USE_SSIL)) {
- vec4 ssil = textureLod(sampler2D(ssil_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv, 0.0);
- ambient_light *= 1.0 - ssil.a;
- ambient_light += ssil.rgb * albedo.rgb;
- }
-
//this saves some VGPRs
vec3 f0 = F0(metallic, specular, albedo);
@@ -1357,7 +1483,7 @@ void fragment_shader(in SceneData scene_data) {
float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y;
vec2 env = vec2(-1.04, 1.04) * a004 + r.zw;
- specular_light *= env.x * f0 + env.y;
+ specular_light *= env.x * f0 + env.y * clamp(50.0 * f0.g, 0.0, 1.0);
#endif
}
@@ -1393,7 +1519,7 @@ void fragment_shader(in SceneData scene_data) {
float shadow = 1.0;
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec3 light_dir = directional_lights.data[i].direction;
vec3 base_normal_bias = normalize(normal_interp) * (1.0 - max(0.0, dot(light_dir, -normalize(normal_interp))));
@@ -1602,7 +1728,7 @@ void fragment_shader(in SceneData scene_data) {
#ifdef LIGHT_TRANSMITTANCE_USED
float transmittance_z = transmittance_depth;
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
if (depth_z < directional_lights.data[i].shadow_split_offsets.x) {
@@ -1653,10 +1779,12 @@ void fragment_shader(in SceneData scene_data) {
float shadow = 1.0;
#ifndef SHADOWS_DISABLED
if (i < 4) {
- shadow = float(shadow0 >> (i * 8) & 0xFF) / 255.0;
+ shadow = float(shadow0 >> (i * 8u) & 0xFFu) / 255.0;
} else {
- shadow = float(shadow1 >> ((i - 4) * 8) & 0xFF) / 255.0;
+ shadow = float(shadow1 >> ((i - 4u) * 8u) & 0xFFu) / 255.0;
}
+
+ shadow = shadow * directional_lights.data[i].shadow_opacity + 1.0 - directional_lights.data[i].shadow_opacity;
#endif
blur_shadow(shadow);
@@ -1697,7 +1825,7 @@ void fragment_shader(in SceneData scene_data) {
uint item_from;
uint item_to;
- cluster_get_item_range(cluster_omni_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+ cluster_get_item_range(cluster_omni_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
#ifdef USE_SUBGROUPS
item_from = subgroupBroadcastFirst(subgroupMin(item_from));
@@ -1715,9 +1843,9 @@ void fragment_shader(in SceneData scene_data) {
while (merged_mask != 0) {
uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
+ merged_mask &= ~(1u << bit);
#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ if (((1u << bit) & mask) == 0) { //do not process if not originally here
continue;
}
#endif
@@ -1761,14 +1889,14 @@ void fragment_shader(in SceneData scene_data) {
{ //spot lights
- uint cluster_spot_offset = cluster_offset + scene_data.cluster_type_size;
+ uint cluster_spot_offset = cluster_offset + implementation_data.cluster_type_size;
uint item_min;
uint item_max;
uint item_from;
uint item_to;
- cluster_get_item_range(cluster_spot_offset + scene_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
+ cluster_get_item_range(cluster_spot_offset + implementation_data.max_cluster_element_count_div_32 + cluster_z, item_min, item_max, item_from, item_to);
#ifdef USE_SUBGROUPS
item_from = subgroupBroadcastFirst(subgroupMin(item_from));
@@ -1786,9 +1914,9 @@ void fragment_shader(in SceneData scene_data) {
while (merged_mask != 0) {
uint bit = findMSB(merged_mask);
- merged_mask &= ~(1 << bit);
+ merged_mask &= ~(1u << bit);
#ifdef USE_SUBGROUPS
- if (((1 << bit) & mask) == 0) { //do not process if not originally here
+ if (((1u << bit) & mask) == 0) { //do not process if not originally here
continue;
}
#endif
@@ -1858,8 +1986,8 @@ void fragment_shader(in SceneData scene_data) {
#ifdef MODE_RENDER_SDF
{
- vec3 local_pos = (scene_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
- ivec3 grid_pos = scene_data.sdf_offset + ivec3(local_pos * vec3(scene_data.sdf_size));
+ vec3 local_pos = (implementation_data.sdf_to_bounds * vec4(vertex, 1.0)).xyz;
+ ivec3 grid_pos = implementation_data.sdf_offset + ivec3(local_pos * vec3(implementation_data.sdf_size));
uint albedo16 = 0x1; //solid flag
albedo16 |= clamp(uint(albedo.r * 31.0), 0, 31) << 11;
@@ -1941,7 +2069,7 @@ void fragment_shader(in SceneData scene_data) {
float sGreen = floor((cGreen / pow(2.0f, exps - B - N)) + 0.5f);
float sBlue = floor((cBlue / pow(2.0f, exps - B - N)) + 0.5f);
//store as 8985 to have 2 extra neighbour bits
- uint light_rgbe = ((uint(sRed) & 0x1FF) >> 1) | ((uint(sGreen) & 0x1FF) << 8) | (((uint(sBlue) & 0x1FF) >> 1) << 17) | ((uint(exps) & 0x1F) << 25);
+ uint light_rgbe = ((uint(sRed) & 0x1FFu) >> 1) | ((uint(sGreen) & 0x1FFu) << 8) | (((uint(sBlue) & 0x1FFu) >> 1) << 17) | ((uint(exps) & 0x1Fu) << 25);
imageStore(emission_grid, grid_pos, uvec4(light_rgbe));
imageStore(emission_aniso_grid, grid_pos, uvec4(light_aniso));
@@ -1975,8 +2103,8 @@ void fragment_shader(in SceneData scene_data) {
if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_USE_VOXEL_GI)) { // process voxel_gi_instances
uint index1 = instances.data[instance_index].gi_offset & 0xFFFF;
uint index2 = instances.data[instance_index].gi_offset >> 16;
- voxel_gi_buffer.x = index1 & 0xFF;
- voxel_gi_buffer.y = index2 & 0xFF;
+ voxel_gi_buffer.x = index1 & 0xFFu;
+ voxel_gi_buffer.y = index2 & 0xFFu;
} else {
voxel_gi_buffer.x = 0xFF;
voxel_gi_buffer.y = 0xFF;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
index b700e21543..3a45ab0059 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_clustered_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered_inc.glsl
@@ -4,21 +4,23 @@
#define MAX_VOXEL_GI_INSTANCES 8
#define MAX_VIEWS 2
+#ifndef MOLTENVK_USED
#if defined(has_GL_KHR_shader_subgroup_ballot) && defined(has_GL_KHR_shader_subgroup_arithmetic)
#extension GL_KHR_shader_subgroup_ballot : enable
#extension GL_KHR_shader_subgroup_arithmetic : enable
#define USE_SUBGROUPS
-
#endif
+#endif // MOLTENVK_USED
#if defined(USE_MULTIVIEW) && defined(has_VK_KHR_multiview)
#extension GL_EXT_multiview : enable
#endif
-#include "cluster_data_inc.glsl"
-#include "decal_data_inc.glsl"
+#include "../cluster_data_inc.glsl"
+#include "../decal_data_inc.glsl"
+#include "../scene_data_inc.glsl"
#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(MODE_RENDER_SDF) || defined(MODE_RENDER_NORMAL_ROUGHNESS) || defined(MODE_RENDER_VOXEL_GI) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
#ifndef NORMAL_USED
@@ -29,8 +31,8 @@
layout(push_constant, std430) uniform DrawCall {
uint instance_index;
uint uv_offset;
- uint pad0;
- uint pad1;
+ uint multimesh_motion_vectors_current_offset;
+ uint multimesh_motion_vectors_previous_offset;
}
draw_call;
@@ -38,7 +40,7 @@ draw_call;
/* Set 0: Base Pass (never changes) */
-#include "light_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1
@@ -61,13 +63,14 @@ layout(set = 0, binding = 3) uniform sampler decal_sampler;
layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
-#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
-#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
-#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
-#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
-#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
-#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
-#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11)
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4)
+#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5)
+#define INSTANCE_FLAGS_USE_SDFGI (1 << 6)
+#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 7)
+#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 8)
+#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
+#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
+#define INSTANCE_FLAGS_PARTICLES (1 << 11)
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
@@ -105,6 +108,8 @@ directional_lights;
struct Lightmap {
mat3 normal_xform;
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
@@ -129,16 +134,18 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
}
decals;
-layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
struct SDFVoxelGICascadeData {
vec3 position;
float to_probe;
ivec3 probe_world_offset;
float to_cell; // 1/bounds * grid_size
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 0, binding = 15, std140) uniform SDFGI {
@@ -171,61 +178,27 @@ sdfgi;
/* Set 1: Render Pass (changes per render pass) */
-struct SceneData {
- mat4 projection_matrix;
- mat4 inv_projection_matrix;
- mat4 inv_view_matrix;
- mat4 view_matrix;
-
- // only used for multiview
- mat4 projection_matrix_view[MAX_VIEWS];
- mat4 inv_projection_matrix_view[MAX_VIEWS];
-
- vec2 viewport_size;
- vec2 screen_pixel_size;
+layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
+ SceneData data;
+ SceneData prev_data;
+}
+scene_data_block;
+struct ImplementationData {
uint cluster_shift;
uint cluster_width;
uint cluster_type_size;
uint max_cluster_element_count_div_32;
- // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted.
- vec4 directional_penumbra_shadow_kernel[32];
- vec4 directional_soft_shadow_kernel[32];
- vec4 penumbra_shadow_kernel[32];
- vec4 soft_shadow_kernel[32];
-
- vec4 ambient_light_color_energy;
-
- float ambient_color_sky_mix;
- bool use_ambient_light;
- bool use_ambient_cubemap;
- bool use_reflection_cubemap;
-
- mat3 radiance_inverse_xform;
-
- vec2 shadow_atlas_pixel_size;
- vec2 directional_shadow_pixel_size;
-
- uint directional_light_count;
- float dual_paraboloid_side;
- float z_far;
- float z_near;
-
uint ss_effects_flags;
float ssao_light_affect;
float ssao_ao_affect;
- bool roughness_limiter_enabled;
-
- float roughness_limiter_amount;
- float roughness_limiter_limit;
- float opaque_prepass_threshold;
- uint roughness_limiter_pad;
+ uint pad1;
mat4 sdf_to_bounds;
ivec3 sdf_offset;
- bool material_uv2_mode;
+ uint pad2;
ivec3 sdf_size;
bool gi_upscale_for_msaa;
@@ -234,30 +207,14 @@ struct SceneData {
float volumetric_fog_inv_length;
float volumetric_fog_detail_spread;
uint volumetric_fog_pad;
-
- bool fog_enabled;
- float fog_density;
- float fog_height;
- float fog_height_density;
-
- vec3 fog_light_color;
- float fog_sun_scatter;
-
- float fog_aerial_perspective;
-
- float time;
- float reflection_multiplier; // one normally, zero when rendering reflections
-
- bool pancake_shadows;
- vec2 taa_jitter;
- uvec2 pad;
};
-layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
- SceneData data;
- SceneData prev_data;
+layout(set = 1, binding = 1, std140) uniform ImplementationDataBlock {
+ ImplementationData data;
}
-scene_data_block;
+implementation_data_block;
+
+#define implementation_data implementation_data_block.data
struct InstanceData {
mat4 transform;
@@ -269,42 +226,42 @@ struct InstanceData {
vec4 lightmap_uv_scale;
};
-layout(set = 1, binding = 1, std430) buffer restrict readonly InstanceDataBuffer {
+layout(set = 1, binding = 2, std430) buffer restrict readonly InstanceDataBuffer {
InstanceData data[];
}
instances;
#ifdef USE_RADIANCE_CUBEMAP_ARRAY
-layout(set = 1, binding = 2) uniform textureCubeArray radiance_cubemap;
+layout(set = 1, binding = 3) uniform textureCubeArray radiance_cubemap;
#else
-layout(set = 1, binding = 2) uniform textureCube radiance_cubemap;
+layout(set = 1, binding = 3) uniform textureCube radiance_cubemap;
#endif
-layout(set = 1, binding = 3) uniform textureCubeArray reflection_atlas;
+layout(set = 1, binding = 4) uniform textureCubeArray reflection_atlas;
-layout(set = 1, binding = 4) uniform texture2D shadow_atlas;
+layout(set = 1, binding = 5) uniform texture2D shadow_atlas;
-layout(set = 1, binding = 5) uniform texture2D directional_shadow_atlas;
+layout(set = 1, binding = 6) uniform texture2D directional_shadow_atlas;
-layout(set = 1, binding = 6) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
+layout(set = 1, binding = 7) uniform texture2DArray lightmap_textures[MAX_LIGHTMAP_TEXTURES];
-layout(set = 1, binding = 7) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
+layout(set = 1, binding = 8) uniform texture3D voxel_gi_textures[MAX_VOXEL_GI_INSTANCES];
-layout(set = 1, binding = 8, std430) buffer restrict readonly ClusterBuffer {
+layout(set = 1, binding = 9, std430) buffer restrict readonly ClusterBuffer {
uint data[];
}
cluster_buffer;
#ifdef MODE_RENDER_SDF
-layout(r16ui, set = 1, binding = 9) uniform restrict writeonly uimage3D albedo_volume_grid;
-layout(r32ui, set = 1, binding = 10) uniform restrict writeonly uimage3D emission_grid;
-layout(r32ui, set = 1, binding = 11) uniform restrict writeonly uimage3D emission_aniso_grid;
-layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid;
+layout(r16ui, set = 1, binding = 10) uniform restrict writeonly uimage3D albedo_volume_grid;
+layout(r32ui, set = 1, binding = 11) uniform restrict writeonly uimage3D emission_grid;
+layout(r32ui, set = 1, binding = 12) uniform restrict writeonly uimage3D emission_aniso_grid;
+layout(r32ui, set = 1, binding = 13) uniform restrict uimage3D geom_facing_grid;
//still need to be present for shaders that use it, so remap them to something
#define depth_buffer shadow_atlas
@@ -313,15 +270,21 @@ layout(r32ui, set = 1, binding = 12) uniform restrict uimage3D geom_facing_grid;
#else
-layout(set = 1, binding = 9) uniform texture2D depth_buffer;
-layout(set = 1, binding = 10) uniform texture2D color_buffer;
-
-layout(set = 1, binding = 11) uniform texture2D normal_roughness_buffer;
-layout(set = 1, binding = 12) uniform texture2D ao_buffer;
-layout(set = 1, binding = 13) uniform texture2D ambient_buffer;
-layout(set = 1, binding = 14) uniform texture2D reflection_buffer;
-layout(set = 1, binding = 15) uniform texture2DArray sdfgi_lightprobe_texture;
-layout(set = 1, binding = 16) uniform texture3D sdfgi_occlusion_cascades;
+layout(set = 1, binding = 10) uniform texture2D depth_buffer;
+layout(set = 1, binding = 11) uniform texture2D color_buffer;
+
+#ifdef USE_MULTIVIEW
+layout(set = 1, binding = 12) uniform texture2DArray normal_roughness_buffer;
+layout(set = 1, binding = 14) uniform texture2DArray ambient_buffer;
+layout(set = 1, binding = 15) uniform texture2DArray reflection_buffer;
+#else // USE_MULTIVIEW
+layout(set = 1, binding = 12) uniform texture2D normal_roughness_buffer;
+layout(set = 1, binding = 14) uniform texture2D ambient_buffer;
+layout(set = 1, binding = 15) uniform texture2D reflection_buffer;
+#endif
+layout(set = 1, binding = 13) uniform texture2D ao_buffer;
+layout(set = 1, binding = 16) uniform texture2DArray sdfgi_lightprobe_texture;
+layout(set = 1, binding = 17) uniform texture3D sdfgi_occlusion_cascades;
struct VoxelGIData {
mat4 xform; // 64 - 64
@@ -333,16 +296,19 @@ struct VoxelGIData {
float normal_bias; // 4 - 88
bool blend_ambient; // 4 - 92
uint mipmaps; // 4 - 96
+
+ vec3 pad; // 12 - 108
+ float exposure_normalization; // 4 - 112
};
-layout(set = 1, binding = 17, std140) uniform VoxelGIs {
+layout(set = 1, binding = 18, std140) uniform VoxelGIs {
VoxelGIData data[MAX_VOXEL_GI_INSTANCES];
}
voxel_gi_instances;
-layout(set = 1, binding = 18) uniform texture3D volumetric_fog_texture;
+layout(set = 1, binding = 19) uniform texture3D volumetric_fog_texture;
-layout(set = 1, binding = 19) uniform texture2D ssil_buffer;
+layout(set = 1, binding = 20) uniform texture2D ssil_buffer;
#endif
diff --git a/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub
new file mode 100644
index 0000000000..f06a2d86e2
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/SCsub
@@ -0,0 +1,17 @@
+#!/usr/bin/env python
+
+Import("env")
+
+if "RD_GLSL" in env["BUILDERS"]:
+ # find all include files
+ gl_include_files = [str(f) for f in Glob("*_inc.glsl")] + [str(f) for f in Glob("../*_inc.glsl")]
+
+ # find all shader code(all glsl files excluding our include files)
+ glsl_files = [str(f) for f in Glob("*.glsl") if str(f) not in gl_include_files]
+
+ # make sure we recompile shaders if include files change
+ env.Depends([f + ".gen.h" for f in glsl_files], gl_include_files + ["#glsl_builders.py"])
+
+ # compile shaders
+ for glsl_file in glsl_files:
+ env.RD_GLSL(glsl_file)
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
index e15ebbfc91..9aeaa6d978 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile.glsl
@@ -16,11 +16,11 @@ layout(location = 0) in vec3 vertex_attrib;
//only for pure render depth when normal is not used
#ifdef NORMAL_USED
-layout(location = 1) in vec3 normal_attrib;
+layout(location = 1) in vec2 normal_attrib;
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
-layout(location = 2) in vec4 tangent_attrib;
+layout(location = 2) in vec2 tangent_attrib;
#endif
#if defined(COLOR_USED)
@@ -59,6 +59,13 @@ layout(location = 10) in uvec4 bone_attrib;
layout(location = 11) in vec4 weight_attrib;
#endif
+vec3 oct_to_vec3(vec2 e) {
+ vec3 v = vec3(e.xy, 1.0 - abs(e.x) - abs(e.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
/* Varyings */
layout(location = 0) highp out vec3 vertex_interp;
@@ -94,7 +101,7 @@ layout(set = MATERIAL_UNIFORM_SET, binding = 0, std140) uniform MaterialUniforms
#ifdef MODE_DUAL_PARABOLOID
-layout(location = 8) out highp float dp_clip;
+layout(location = 9) out highp float dp_clip;
#endif
@@ -114,9 +121,36 @@ invariant gl_Position;
#GLOBALS
-void main() {
- SceneData scene_data = scene_data_block.data;
+#define scene_data scene_data_block.data
+
+#ifdef USE_DOUBLE_PRECISION
+// Helper functions for emulating double precision when adding floats.
+vec3 quick_two_sum(vec3 a, vec3 b, out vec3 out_p) {
+ vec3 s = a + b;
+ out_p = b - (s - a);
+ return s;
+}
+
+vec3 two_sum(vec3 a, vec3 b, out vec3 out_p) {
+ vec3 s = a + b;
+ vec3 v = s - a;
+ out_p = (a - (s - v)) + (b - v);
+ return s;
+}
+
+vec3 double_add_vec3(vec3 base_a, vec3 prec_a, vec3 base_b, vec3 prec_b, out vec3 out_precision) {
+ vec3 s, t, se, te;
+ s = two_sum(base_a, base_b, se);
+ t = two_sum(prec_a, prec_b, te);
+ se += t;
+ s = quick_two_sum(s, se, se);
+ se += te;
+ s = quick_two_sum(s, se, out_precision);
+ return s;
+}
+#endif
+void main() {
vec4 instance_custom = vec4(0.0);
#if defined(COLOR_USED)
color_interp = color_attrib;
@@ -125,6 +159,17 @@ void main() {
bool is_multimesh = bool(draw_call.flags & INSTANCE_FLAGS_MULTIMESH);
mat4 model_matrix = draw_call.transform;
+ mat4 inv_view_matrix = scene_data.inv_view_matrix;
+#ifdef USE_DOUBLE_PRECISION
+ vec3 model_precision = vec3(model_matrix[0][3], model_matrix[1][3], model_matrix[2][3]);
+ model_matrix[0][3] = 0.0;
+ model_matrix[1][3] = 0.0;
+ model_matrix[2][3] = 0.0;
+ vec3 view_precision = vec3(inv_view_matrix[0][3], inv_view_matrix[1][3], inv_view_matrix[2][3]);
+ inv_view_matrix[0][3] = 0.0;
+ inv_view_matrix[1][3] = 0.0;
+ inv_view_matrix[2][3] = 0.0;
+#endif
mat3 model_normal_matrix;
if (bool(draw_call.flags & INSTANCE_FLAGS_NON_UNIFORM_SCALE)) {
@@ -133,11 +178,12 @@ void main() {
model_normal_matrix = mat3(model_matrix);
}
+ mat4 matrix;
+ mat4 read_model_matrix = model_matrix;
+
if (is_multimesh) {
//multimesh, instances are for it
- mat4 matrix;
-
#ifdef USE_PARTICLE_TRAILS
uint trail_size = (draw_call.flags >> INSTANCE_FLAGS_PARTICLE_TRAIL_SHIFT) & INSTANCE_FLAGS_PARTICLE_TRAIL_MASK;
uint stride = 3 + 1 + 1; //particles always uses this format
@@ -223,18 +269,27 @@ void main() {
#endif
//transpose
matrix = transpose(matrix);
- model_matrix = model_matrix * matrix;
+
+#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED)
+ // Normally we can bake the multimesh transform into the model matrix, but when using double precision
+ // we avoid baking it in so we can emulate high precision.
+ read_model_matrix = model_matrix * matrix;
+#if !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED)
+ model_matrix = read_model_matrix;
+#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED)
+#endif // !defined(USE_DOUBLE_PRECISION) || defined(SKIP_TRANSFORM_USED) || defined(VERTEX_WORLD_COORDS_USED) || defined(MODEL_MATRIX_USED)
model_normal_matrix = model_normal_matrix * mat3(matrix);
}
vec3 vertex = vertex_attrib;
#ifdef NORMAL_USED
- vec3 normal = normal_attrib * 2.0 - 1.0;
+ vec3 normal = oct_to_vec3(normal_attrib * 2.0 - 1.0);
#endif
#if defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
- vec3 tangent = tangent_attrib.xyz * 2.0 - 1.0;
- float binormalf = tangent_attrib.a * 2.0 - 1.0;
+ vec2 signed_tangent_attrib = tangent_attrib * 2.0 - 1.0;
+ vec3 tangent = oct_to_vec3(vec2(signed_tangent_attrib.x, abs(signed_tangent_attrib.y) * 2.0 - 1.0));
+ float binormalf = sign(signed_tangent_attrib.y);
vec3 binormal = normalize(cross(normal, tangent) * binormalf);
#endif
@@ -289,7 +344,22 @@ void main() {
// using local coordinates (default)
#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED)
+#ifdef USE_DOUBLE_PRECISION
+ // We separate the basis from the origin because the basis is fine with single point precision.
+ // Then we combine the translations from the model matrix and the view matrix using emulated doubles.
+ // We add the result to the vertex and ignore the final lost precision.
+ vec3 model_origin = model_matrix[3].xyz;
+ if (is_multimesh) {
+ vertex = mat3(matrix) * vertex;
+ model_origin = double_add_vec3(model_origin, model_precision, matrix[3].xyz, vec3(0.0), model_precision);
+ }
+ vertex = mat3(model_matrix) * vertex;
+ vec3 temp_precision;
+ vertex += double_add_vec3(model_origin, model_precision, scene_data.inv_view_matrix[3].xyz, view_precision, temp_precision);
+ vertex = mat3(scene_data.view_matrix) * vertex;
+#else
vertex = (modelview * vec4(vertex, 1.0)).xyz;
+#endif
#ifdef NORMAL_USED
normal = modelview_normal * normal;
#endif
@@ -442,7 +512,7 @@ layout(location = 6) mediump in vec3 binormal_interp;
#ifdef MODE_DUAL_PARABOLOID
-layout(location = 8) highp in float dp_clip;
+layout(location = 9) highp in float dp_clip;
#endif
@@ -460,11 +530,12 @@ layout(location = 8) highp in float dp_clip;
//defines to keep compatibility with vertex
-#define model_matrix draw_call.transform
#ifdef USE_MULTIVIEW
#define projection_matrix scene_data.projection_matrix_view[ViewIndex]
+#define inv_projection_matrix scene_data.inv_projection_matrix_view[ViewIndex]
#else
#define projection_matrix scene_data.projection_matrix
+#define inv_projection_matrix scene_data.inv_projection_matrix
#endif
#if defined(ENABLE_SSS) && defined(ENABLE_TRANSMITTANCE)
@@ -509,7 +580,7 @@ layout(location = 0) out mediump vec4 frag_color;
#endif // RENDER DEPTH
-#include "scene_forward_aa_inc.glsl"
+#include "../scene_forward_aa_inc.glsl"
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@@ -518,7 +589,7 @@ layout(location = 0) out mediump vec4 frag_color;
#define SPECULAR_SCHLICK_GGX
#endif
-#include "scene_forward_lights_inc.glsl"
+#include "../scene_forward_lights_inc.glsl"
#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
@@ -576,17 +647,22 @@ vec4 fog_process(vec3 vertex) {
#endif //!MODE_RENDER DEPTH
+#define scene_data scene_data_block.data
+
void main() {
#ifdef MODE_DUAL_PARABOLOID
if (dp_clip > 0.0)
discard;
#endif
- SceneData scene_data = scene_data_block.data;
//lay out everything, whatever is unused is optimized away anyway
vec3 vertex = vertex_interp;
+#ifdef USE_MULTIVIEW
+ vec3 view = -normalize(vertex_interp - scene_data.eye_offset[ViewIndex].xyz);
+#else
vec3 view = -normalize(vertex_interp);
+#endif
vec3 albedo = vec3(1.0);
vec3 backlight = vec3(0.0);
vec4 transmittance_color = vec4(0.0);
@@ -670,6 +746,17 @@ void main() {
vec2 alpha_texture_coordinate = vec2(0.0, 0.0);
#endif // ALPHA_ANTIALIASING_EDGE_USED
+ mat4 inv_view_matrix = scene_data.inv_view_matrix;
+ mat4 read_model_matrix = draw_call.transform;
+#ifdef USE_DOUBLE_PRECISION
+ read_model_matrix[0][3] = 0.0;
+ read_model_matrix[1][3] = 0.0;
+ read_model_matrix[2][3] = 0.0;
+ inv_view_matrix[0][3] = 0.0;
+ inv_view_matrix[1][3] = 0.0;
+ inv_view_matrix[2][3] = 0.0;
+#endif
+
{
#CODE : FRAGMENT
}
@@ -874,6 +961,11 @@ void main() {
vec3 diffuse_light = vec3(0.0, 0.0, 0.0);
vec3 ambient_light = vec3(0.0, 0.0, 0.0);
+#ifndef MODE_UNSHADED
+ // Used in regular draw pass and when drawing SDFs for SDFGI and materials for VoxelGI.
+ emission *= scene_data.emissive_exposure_normalization;
+#endif
+
#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED)
if (scene_data.use_reflection_cubemap) {
@@ -884,8 +976,10 @@ void main() {
vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
vec3 ref_vec = reflect(-view, bent_normal);
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
#else
vec3 ref_vec = reflect(-view, normal);
+ ref_vec = mix(ref_vec, normal, roughness * roughness);
#endif
float horizon = min(1.0 + dot(ref_vec, normal), 1.0);
ref_vec = scene_data.radiance_inverse_xform * ref_vec;
@@ -900,6 +994,8 @@ void main() {
specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
+ specular_light *= sc_luminance_multiplier;
+ specular_light *= scene_data.IBL_exposure_normalization;
specular_light *= horizon * horizon;
specular_light *= scene_data.ambient_light_color_energy.a;
}
@@ -920,7 +1016,8 @@ void main() {
#else
vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb;
#endif //USE_RADIANCE_CUBEMAP_ARRAY
-
+ cubemap_ambient *= sc_luminance_multiplier;
+ cubemap_ambient *= scene_data.IBL_exposure_normalization;
ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix);
}
}
@@ -935,6 +1032,7 @@ void main() {
vec3 n = normalize(normal_interp); // We want to use geometric normal, not normal_map
float NoV = max(dot(n, view), 0.0001);
vec3 ref_vec = reflect(-view, n);
+ ref_vec = mix(ref_vec, n, clearcoat_roughness * clearcoat_roughness);
// The clear coat layer assumes an IOR of 1.5 (4% reflectance)
float Fc = clearcoat * (0.04 + 0.96 * SchlickFresnel(NoV));
float attenuation = 1.0 - Fc;
@@ -977,15 +1075,16 @@ void main() {
const float c4 = 0.886227;
const float c5 = 0.247708;
ambient_light += (c1 * lightmap_captures.data[index].sh[8].rgb * (wnormal.x * wnormal.x - wnormal.y * wnormal.y) +
- c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
- c4 * lightmap_captures.data[index].sh[0].rgb -
- c5 * lightmap_captures.data[index].sh[6].rgb +
- 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
- 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
- 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
- 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
- 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
- 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z);
+ c3 * lightmap_captures.data[index].sh[6].rgb * wnormal.z * wnormal.z +
+ c4 * lightmap_captures.data[index].sh[0].rgb -
+ c5 * lightmap_captures.data[index].sh[6].rgb +
+ 2.0 * c1 * lightmap_captures.data[index].sh[4].rgb * wnormal.x * wnormal.y +
+ 2.0 * c1 * lightmap_captures.data[index].sh[7].rgb * wnormal.x * wnormal.z +
+ 2.0 * c1 * lightmap_captures.data[index].sh[5].rgb * wnormal.y * wnormal.z +
+ 2.0 * c2 * lightmap_captures.data[index].sh[3].rgb * wnormal.x +
+ 2.0 * c2 * lightmap_captures.data[index].sh[1].rgb * wnormal.y +
+ 2.0 * c2 * lightmap_captures.data[index].sh[2].rgb * wnormal.z) *
+ scene_data.emissive_exposure_normalization;
} else if (bool(draw_call.flags & INSTANCE_FLAGS_USE_LIGHTMAP)) { // has actual lightmap
bool uses_sh = bool(draw_call.flags & INSTANCE_FLAGS_USE_SH_LIGHTMAP);
@@ -994,6 +1093,8 @@ void main() {
uvw.xy = uv2 * draw_call.lightmap_uv_scale.zw + draw_call.lightmap_uv_scale.xy;
uvw.z = float((draw_call.gi_offset >> 16) & 0xFFFF);
+ uint idx = draw_call.gi_offset >> 20;
+
if (uses_sh) {
uvw.z *= 4.0; //SH textures use 4 times more data
vec3 lm_light_l0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 0.0), 0.0).rgb;
@@ -1001,22 +1102,22 @@ void main() {
vec3 lm_light_l1_0 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 2.0), 0.0).rgb;
vec3 lm_light_l1p1 = textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw + vec3(0.0, 0.0, 3.0), 0.0).rgb;
- uint idx = draw_call.gi_offset >> 20;
vec3 n = normalize(lightmaps.data[idx].normal_xform * normal);
+ float exposure_normalization = lightmaps.data[idx].exposure_normalization;
ambient_light += lm_light_l0 * 0.282095f;
- ambient_light += lm_light_l1n1 * 0.32573 * n.y;
- ambient_light += lm_light_l1_0 * 0.32573 * n.z;
- ambient_light += lm_light_l1p1 * 0.32573 * n.x;
+ ambient_light += lm_light_l1n1 * 0.32573 * n.y * exposure_normalization;
+ ambient_light += lm_light_l1_0 * 0.32573 * n.z * exposure_normalization;
+ ambient_light += lm_light_l1p1 * 0.32573 * n.x * exposure_normalization;
if (metallic > 0.01) { // since the more direct bounced light is lost, we can kind of fake it with this trick
vec3 r = reflect(normalize(-vertex), normal);
- specular_light += lm_light_l1n1 * 0.32573 * r.y;
- specular_light += lm_light_l1_0 * 0.32573 * r.z;
- specular_light += lm_light_l1p1 * 0.32573 * r.x;
+ specular_light += lm_light_l1n1 * 0.32573 * r.y * exposure_normalization;
+ specular_light += lm_light_l1_0 * 0.32573 * r.z * exposure_normalization;
+ specular_light += lm_light_l1p1 * 0.32573 * r.x * exposure_normalization;
}
} else {
- ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb;
+ ambient_light += textureLod(sampler2DArray(lightmap_textures[ofs], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw, 0.0).rgb * lightmaps.data[idx].exposure_normalization;
}
}
@@ -1031,6 +1132,19 @@ void main() {
vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0);
uint reflection_indices = draw_call.reflection_probes.x;
+
+#ifdef LIGHT_ANISOTROPY_USED
+ // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
+ vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
+ vec3 anisotropic_tangent = cross(anisotropic_direction, view);
+ vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
+ vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
+#else
+ vec3 bent_normal = normal;
+#endif
+ vec3 ref_vec = normalize(reflect(-view, bent_normal));
+ ref_vec = mix(ref_vec, bent_normal, roughness * roughness);
+
for (uint i = 0; i < 8; i++) {
uint reflection_index = reflection_indices & 0xFF;
if (i == 4) {
@@ -1042,16 +1156,8 @@ void main() {
if (reflection_index == 0xFF) {
break;
}
-#ifdef LIGHT_ANISOTROPY_USED
- // https://google.github.io/filament/Filament.html#lighting/imagebasedlights/anisotropy
- vec3 anisotropic_direction = anisotropy >= 0.0 ? binormal : tangent;
- vec3 anisotropic_tangent = cross(anisotropic_direction, view);
- vec3 anisotropic_normal = cross(anisotropic_tangent, anisotropic_direction);
- vec3 bent_normal = normalize(mix(normal, anisotropic_normal, abs(anisotropy) * clamp(5.0 * roughness, 0.0, 1.0)));
-#else
- vec3 bent_normal = normal;
-#endif
- reflection_process(reflection_index, vertex, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
+
+ reflection_process(reflection_index, vertex, ref_vec, bent_normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum);
}
if (reflection_accum.a > 0.0) {
@@ -1066,8 +1172,14 @@ void main() {
} //Reflection probes
// finalize ambient light here
- ambient_light *= albedo.rgb;
- ambient_light *= ao;
+ {
+#if defined(AMBIENT_LIGHT_DISABLED)
+ ambient_light = vec3(0.0, 0.0, 0.0);
+#else
+ ambient_light *= albedo.rgb;
+ ambient_light *= ao;
+#endif // AMBIENT_LIGHT_DISABLED
+ }
// convert ao to direct light ao
ao = mix(1.0, ao, ao_light_affect);
@@ -1129,7 +1241,7 @@ void main() {
#ifdef USE_SOFT_SHADOWS
//version with soft shadows, more expensive
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec4 pssm_coord;
@@ -1281,7 +1393,7 @@ void main() {
#else
// Soft shadow disabled version
- if (directional_lights.data[i].shadow_enabled) {
+ if (directional_lights.data[i].shadow_opacity > 0.001) {
float depth_z = -vertex.z;
vec4 pssm_coord;
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
index dd14a15837..631ff0575b 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_mobile_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/forward_mobile/scene_forward_mobile_inc.glsl
@@ -5,7 +5,8 @@
#extension GL_EXT_multiview : enable
#endif
-#include "decal_data_inc.glsl"
+#include "../decal_data_inc.glsl"
+#include "../scene_data_inc.glsl"
#if !defined(MODE_RENDER_DEPTH) || defined(MODE_RENDER_MATERIAL) || defined(TANGENT_USED) || defined(NORMAL_MAP_USED) || defined(LIGHT_ANISOTROPY_USED)
#ifndef NORMAL_USED
@@ -32,7 +33,7 @@ draw_call;
/* Set 0: Base Pass (never changes) */
-#include "light_data_inc.glsl"
+#include "../light_data_inc.glsl"
#define SAMPLER_NEAREST_CLAMP 0
#define SAMPLER_LINEAR_CLAMP 1
@@ -54,13 +55,14 @@ layout(set = 0, binding = 2) uniform sampler shadow_sampler;
layout(set = 0, binding = 3) uniform sampler decal_sampler;
layout(set = 0, binding = 4) uniform sampler light_projector_sampler;
-#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 5)
-#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 6)
-#define INSTANCE_FLAGS_USE_SDFGI (1 << 7)
-#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 8)
-#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 9)
-#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 10)
-#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 11)
+#define INSTANCE_FLAGS_NON_UNIFORM_SCALE (1 << 4)
+#define INSTANCE_FLAGS_USE_GI_BUFFERS (1 << 5)
+#define INSTANCE_FLAGS_USE_SDFGI (1 << 6)
+#define INSTANCE_FLAGS_USE_LIGHTMAP_CAPTURE (1 << 7)
+#define INSTANCE_FLAGS_USE_LIGHTMAP (1 << 8)
+#define INSTANCE_FLAGS_USE_SH_LIGHTMAP (1 << 9)
+#define INSTANCE_FLAGS_USE_VOXEL_GI (1 << 10)
+#define INSTANCE_FLAGS_PARTICLES (1 << 11)
#define INSTANCE_FLAGS_MULTIMESH (1 << 12)
#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13)
#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14)
@@ -94,6 +96,8 @@ directional_lights;
struct Lightmap {
mediump mat3 normal_xform;
+ vec3 pad;
+ float exposure_normalization;
};
layout(set = 0, binding = 9, std140) restrict readonly buffer Lightmaps {
@@ -118,81 +122,16 @@ layout(set = 0, binding = 13, std430) restrict readonly buffer Decals {
}
decals;
-layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 14, std430) restrict readonly buffer GlobalShaderUniformData {
highp vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* Set 1: Render Pass (changes per render pass) */
-struct SceneData {
- highp mat4 projection_matrix;
- highp mat4 inv_projection_matrix;
- highp mat4 inv_view_matrix;
- highp mat4 view_matrix;
-
- // only used for multiview
- highp mat4 projection_matrix_view[MAX_VIEWS];
- highp mat4 inv_projection_matrix_view[MAX_VIEWS];
-
- highp vec2 viewport_size;
- highp vec2 screen_pixel_size;
-
- // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted.
- highp vec4 directional_penumbra_shadow_kernel[32];
- highp vec4 directional_soft_shadow_kernel[32];
- highp vec4 penumbra_shadow_kernel[32];
- highp vec4 soft_shadow_kernel[32];
-
- mediump vec4 ambient_light_color_energy;
-
- mediump float ambient_color_sky_mix;
- bool use_ambient_light;
- bool use_ambient_cubemap;
- bool use_reflection_cubemap;
-
- mediump mat3 radiance_inverse_xform;
-
- highp vec2 shadow_atlas_pixel_size;
- highp vec2 directional_shadow_pixel_size;
-
- uint directional_light_count;
- mediump float dual_paraboloid_side;
- highp float z_far;
- highp float z_near;
-
- bool ssao_enabled;
- mediump float ssao_light_affect;
- mediump float ssao_ao_affect;
- bool roughness_limiter_enabled;
-
- mediump float roughness_limiter_amount;
- mediump float roughness_limiter_limit;
- mediump float opaque_prepass_threshold;
- uint roughness_limiter_pad;
-
- bool fog_enabled;
- highp float fog_density;
- highp float fog_height;
- highp float fog_height_density;
-
- mediump vec3 fog_light_color;
- mediump float fog_sun_scatter;
-
- mediump float fog_aerial_perspective;
- bool material_uv2_mode;
-
- highp float time;
- mediump float reflection_multiplier; // one normally, zero when rendering reflections
-
- bool pancake_shadows;
- uint pad1;
- uint pad2;
- uint pad3;
-};
-
layout(set = 1, binding = 0, std140) uniform SceneDataBlock {
SceneData data;
+ SceneData prev_data;
}
scene_data_block;
diff --git a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
index 61c8488a05..7488a3f2c7 100644
--- a/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/light_data_inc.glsl
@@ -15,7 +15,7 @@ struct LightData { //this structure needs to be as packed as possible
mediump float cone_attenuation;
mediump float cone_angle;
mediump float specular_amount;
- bool shadow_enabled;
+ mediump float shadow_opacity;
highp vec4 atlas_rect; // rect in the shadow atlas
highp mat4 shadow_matrix;
@@ -25,7 +25,7 @@ struct LightData { //this structure needs to be as packed as possible
highp float soft_shadow_size; // for spot, it's the size in uv coordinates of the light, for omni it's the span angle
highp float soft_shadow_scale; // scales the shadow kernel for blurrier shadows
uint mask;
- mediump float shadow_volumetric_fog_fade;
+ mediump float volumetric_fog_energy;
uint bake_mode;
highp vec4 projector_rect; //projector rect in srgb decal atlas
};
@@ -44,7 +44,7 @@ struct ReflectionData {
bool exterior;
bool box_project;
uint ambient_mode;
- uint pad;
+ float exposure_normalization;
//0-8 is intensity,8-9 is ambient, mode
highp mat4 local_matrix; // up to here for spot and omni, rest is for directional
// notes: for ambientblend, use distance to edge to blend between already existing global environment
@@ -52,7 +52,7 @@ struct ReflectionData {
struct DirectionalLightData {
mediump vec3 direction;
- mediump float energy;
+ highp float energy; // needs to be highp to avoid NaNs being created with high energy values (i.e. when using physical light units and over-exposing the image)
mediump vec3 color;
mediump float size;
mediump float specular;
@@ -60,12 +60,12 @@ struct DirectionalLightData {
highp float softshadow_angle;
highp float soft_shadow_scale;
bool blend_splits;
- bool shadow_enabled;
+ mediump float shadow_opacity;
highp float fade_from;
highp float fade_to;
uvec2 pad;
uint bake_mode;
- mediump float shadow_volumetric_fog_fade;
+ mediump float volumetric_fog_energy;
highp vec4 shadow_bias;
highp vec4 shadow_normal_bias;
highp vec4 shadow_transmittance_bias;
diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl
index acb62b812e..9f6aa7adc0 100644
--- a/servers/rendering/renderer_rd/shaders/particles.glsl
+++ b/servers/rendering/renderer_rd/shaders/particles.glsl
@@ -25,10 +25,10 @@ layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout(set = 0, binding = 1) uniform sampler material_samplers[12];
-layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalVariableData {
+layout(set = 0, binding = 2, std430) restrict readonly buffer GlobalShaderUniformData {
vec4 data[];
}
-global_variables;
+global_shader_uniforms;
/* Set 1: FRAME AND PARTICLE DATA */
@@ -458,11 +458,11 @@ void main() {
} break;
case ATTRACTOR_TYPE_VECTOR_FIELD: {
- vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents) * 2.0 - 1.0;
+ vec3 uvw_pos = (local_pos / FRAME.attractors[i].extents + 1.0) * 0.5;
if (any(lessThan(uvw_pos, vec3(0.0))) || any(greaterThan(uvw_pos, vec3(1.0)))) {
continue;
}
- vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz;
+ vec3 s = texture(sampler3D(sdf_vec_textures[FRAME.attractors[i].texture_index], material_samplers[SAMPLER_LINEAR_CLAMP]), uvw_pos).xyz * -2.0 + 1.0;
dir = mat3(FRAME.attractors[i].transform) * safe_normalize(s); //revert direction
amount = length(s);
@@ -475,7 +475,7 @@ void main() {
float particle_size = FRAME.particle_size;
-#ifdef USE_COLLISON_SCALE
+#ifdef USE_COLLISION_SCALE
particle_size *= dot(vec3(length(PARTICLE.xform[0].xyz), length(PARTICLE.xform[1].xyz), length(PARTICLE.xform[2].xyz)), vec3(0.33333333333));
diff --git a/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
new file mode 100644
index 0000000000..048257e9ef
--- /dev/null
+++ b/servers/rendering/renderer_rd/shaders/scene_data_inc.glsl
@@ -0,0 +1,69 @@
+// Scene data stores all our 3D rendering globals for a frame such as our matrices
+// where this information is independent of the different RD implementations.
+// This enables us to use this UBO in our main scene render shaders but also in
+// effects that need access to this data.
+
+struct SceneData {
+ highp mat4 projection_matrix;
+ highp mat4 inv_projection_matrix;
+ highp mat4 inv_view_matrix;
+ highp mat4 view_matrix;
+
+ // only used for multiview
+ highp mat4 projection_matrix_view[MAX_VIEWS];
+ highp mat4 inv_projection_matrix_view[MAX_VIEWS];
+ highp vec4 eye_offset[MAX_VIEWS];
+
+ highp vec2 viewport_size;
+ highp vec2 screen_pixel_size;
+
+ // Use vec4s because std140 doesn't play nice with vec2s, z and w are wasted.
+ highp vec4 directional_penumbra_shadow_kernel[32];
+ highp vec4 directional_soft_shadow_kernel[32];
+ highp vec4 penumbra_shadow_kernel[32];
+ highp vec4 soft_shadow_kernel[32];
+
+ mediump mat3 radiance_inverse_xform;
+
+ mediump vec4 ambient_light_color_energy;
+
+ mediump float ambient_color_sky_mix;
+ bool use_ambient_light;
+ bool use_ambient_cubemap;
+ bool use_reflection_cubemap;
+
+ highp vec2 shadow_atlas_pixel_size;
+ highp vec2 directional_shadow_pixel_size;
+
+ uint directional_light_count;
+ mediump float dual_paraboloid_side;
+ highp float z_far;
+ highp float z_near;
+
+ bool roughness_limiter_enabled;
+ mediump float roughness_limiter_amount;
+ mediump float roughness_limiter_limit;
+ mediump float opaque_prepass_threshold;
+
+ bool fog_enabled;
+ highp float fog_density;
+ highp float fog_height;
+ highp float fog_height_density;
+
+ mediump vec3 fog_light_color;
+ mediump float fog_sun_scatter;
+
+ mediump float fog_aerial_perspective;
+ highp float time;
+ mediump float reflection_multiplier; // one normally, zero when rendering reflections
+ bool material_uv2_mode;
+
+ vec2 taa_jitter;
+ float emissive_exposure_normalization;
+ float IBL_exposure_normalization;
+
+ bool pancake_shadows;
+ uint pad1;
+ uint pad2;
+ uint pad3;
+};
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
index c88bd0a14b..ae5e1b7251 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_gi_inc.glsl
@@ -94,7 +94,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
light += cone_weights[i] * cone_light.rgb;
}
- light *= voxel_gi_instances.data[index].dynamic_range;
+ light *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
out_diff += vec4(light * blend, blend);
//irradiance
@@ -102,7 +102,7 @@ void voxel_gi_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3
if (voxel_gi_instances.data[index].blend_ambient) {
irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95));
}
- irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range;
+ irr_light.rgb *= voxel_gi_instances.data[index].dynamic_range * voxel_gi_instances.data[index].exposure_normalization;
//irr_light=vec3(0.0);
out_spec += vec4(irr_light.rgb * blend, blend);
@@ -189,7 +189,7 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal
pos_uvw.x += float(offset.z) * sdfgi.lightprobe_uv_offset.z;
diffuse = textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb;
- diffuse_accum += vec4(diffuse * weight, weight);
+ diffuse_accum += vec4(diffuse * weight * sdfgi.cascades[cascade].exposure_normalization, weight);
if (use_specular) {
vec3 specular = vec3(0.0);
@@ -203,7 +203,7 @@ void sdfgi_process(uint cascade, vec3 cascade_pos, vec3 cam_pos, vec3 cam_normal
specular = mix(specular, textureLod(sampler2DArray(sdfgi_lightprobe_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), pos_uvw, 0.0).rgb, (roughness - 0.5) * 2.0);
}
- specular_accum += specular * weight;
+ specular_accum += specular * weight * sdfgi.cascades[cascade].exposure_normalization;
}
}
diff --git a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
index 5a308bbd02..2fba1351f7 100644
--- a/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
+++ b/servers/rendering/renderer_rd/shaders/scene_forward_lights_inc.glsl
@@ -97,11 +97,12 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance
#if defined(DIFFUSE_LAMBERT_WRAP)
- // energy conserving lambert wrap shader
- diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness)));
+ // Energy conserving lambert wrap shader.
+ // https://web.archive.org/web/20210228210901/http://blog.stevemcauley.com/2011/12/03/energy-conserving-wrapped-diffuse/
+ diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))) * (1.0 / M_PI);
#elif defined(DIFFUSE_TOON)
- diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL);
+ diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL) * (1.0 / M_PI);
#elif defined(DIFFUSE_BURLEY)
@@ -199,7 +200,10 @@ void light_compute(vec3 N, vec3 L, vec3 V, float A, vec3 light_color, float atte
#endif // LIGHT_ANISOTROPY_USED
// F
float cLdotH5 = SchlickFresnel(cLdotH);
- vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0);
+ // Calculate Fresnel using specular occlusion term from Filament:
+ // https://google.github.io/filament/Filament.html#lighting/occlusion/specularocclusion
+ float f90 = clamp(dot(f0, vec3(50.0 * 0.33)), 0.0, 1.0);
+ vec3 F = f0 + (f90 - f0) * cLdotH5;
vec3 specular_brdf_NL = cNdotL * D * F * G;
@@ -392,7 +396,7 @@ float get_omni_attenuation(float distance, float inv_range, float decay) {
float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef SHADOWS_DISABLED
- if (omni_lights.data[idx].shadow_enabled) {
+ if (omni_lights.data[idx].shadow_opacity > 0.001) {
// there is a shadowmap
vec2 texel_size = scene_data_block.data.shadow_atlas_pixel_size;
vec4 base_uv_rect = omni_lights.data[idx].atlas_rect;
@@ -495,6 +499,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
}
shadow /= float(sc_penumbra_shadow_samples);
+ shadow = mix(1.0, shadow, omni_lights.data[idx].shadow_opacity);
} else {
//no blockers found, so no shadow
@@ -513,7 +518,7 @@ float light_process_omni_shadow(uint idx, vec3 vertex, vec3 normal) {
vec2 pos = shadow_sample.xy / shadow_sample.z;
float depth = shadow_len - omni_lights.data[idx].shadow_bias;
depth *= omni_lights.data[idx].inv_radius;
- shadow = sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth);
+ shadow = mix(1.0, sample_omni_pcf_shadow(shadow_atlas, omni_lights.data[idx].soft_shadow_scale / shadow_sample.z, pos, uv_rect, flip_offset, depth), omni_lights.data[idx].shadow_opacity);
}
return shadow;
@@ -671,7 +676,7 @@ void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
#ifndef SHADOWS_DISABLED
- if (spot_lights.data[idx].shadow_enabled) {
+ if (spot_lights.data[idx].shadow_opacity > 0.001) {
vec3 light_rel_vec = spot_lights.data[idx].position - vertex;
float light_length = length(light_rel_vec);
vec3 spot_dir = spot_lights.data[idx].direction;
@@ -732,6 +737,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
}
shadow /= float(sc_penumbra_shadow_samples);
+ shadow = mix(1.0, shadow, spot_lights.data[idx].shadow_opacity);
} else {
//no blockers found, so no shadow
@@ -740,7 +746,7 @@ float light_process_spot_shadow(uint idx, vec3 vertex, vec3 normal) {
} else {
//hard shadow
vec3 shadow_uv = vec3(splane.xy * spot_lights.data[idx].atlas_rect.zw + spot_lights.data[idx].atlas_rect.xy, splane.z);
- shadow = sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv);
+ shadow = mix(1.0, sample_pcf_shadow(shadow_atlas, spot_lights.data[idx].soft_shadow_scale * scene_data_block.data.shadow_atlas_pixel_size, shadow_uv), spot_lights.data[idx].shadow_opacity);
}
return shadow;
@@ -869,7 +875,7 @@ void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 v
diffuse_light, specular_light);
}
-void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
+void reflection_process(uint ref_index, vec3 vertex, vec3 ref_vec, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) {
vec3 box_extents = reflections.data[ref_index].box_extents;
vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz;
@@ -877,8 +883,6 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
return;
}
- vec3 ref_vec = normalize(reflect(vertex, normal));
-
vec3 inner_pos = abs(local_pos / box_extents);
float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z));
//make blend more rounded
@@ -906,7 +910,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
vec4 reflection;
reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb * sc_luminance_multiplier;
-
+ reflection.rgb *= reflections.data[ref_index].exposure_normalization;
if (reflections.data[ref_index].exterior) {
reflection.rgb = mix(specular_light, reflection.rgb, blend);
}
@@ -929,6 +933,7 @@ void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughnes
vec4 ambient_out;
ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb;
+ ambient_out.rgb *= reflections.data[ref_index].exposure_normalization;
ambient_out.a = blend;
if (reflections.data[ref_index].exterior) {
ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend);
diff --git a/servers/rendering/renderer_rd/shaders/skeleton.glsl b/servers/rendering/renderer_rd/shaders/skeleton.glsl
index a893a66c94..75bea9300b 100644
--- a/servers/rendering/renderer_rd/shaders/skeleton.glsl
+++ b/servers/rendering/renderer_rd/shaders/skeleton.glsl
@@ -54,14 +54,54 @@ layout(push_constant, std430) uniform Params {
}
params;
-vec4 decode_abgr_2_10_10_10(uint base) {
- uvec4 abgr_2_10_10_10 = (uvec4(base) >> uvec4(0, 10, 20, 30)) & uvec4(0x3FF, 0x3FF, 0x3FF, 0x3);
- return vec4(abgr_2_10_10_10) / vec4(1023.0, 1023.0, 1023.0, 3.0) * 2.0 - 1.0;
+vec2 uint_to_vec2(uint base) {
+ uvec2 decode = (uvec2(base) >> uvec2(0, 16)) & uvec2(0xFFFF, 0xFFFF);
+ return vec2(decode) / vec2(65535.0, 65535.0) * 2.0 - 1.0;
}
-uint encode_abgr_2_10_10_10(vec4 base) {
- uvec4 abgr_2_10_10_10 = uvec4(clamp(ivec4((base * 0.5 + 0.5) * vec4(1023.0, 1023.0, 1023.0, 3.0)), ivec4(0), ivec4(0x3FF, 0x3FF, 0x3FF, 0x3))) << uvec4(0, 10, 20, 30);
- return abgr_2_10_10_10.x | abgr_2_10_10_10.y | abgr_2_10_10_10.z | abgr_2_10_10_10.w;
+vec3 oct_to_vec3(vec2 oct) {
+ vec3 v = vec3(oct.xy, 1.0 - abs(oct.x) - abs(oct.y));
+ float t = max(-v.z, 0.0);
+ v.xy += t * -sign(v.xy);
+ return v;
+}
+
+vec3 decode_uint_oct_to_norm(uint base) {
+ return oct_to_vec3(uint_to_vec2(base));
+}
+
+vec4 decode_uint_oct_to_tang(uint base) {
+ vec2 oct_sign_encoded = uint_to_vec2(base);
+ // Binormal sign encoded in y component
+ vec2 oct = vec2(oct_sign_encoded.x, abs(oct_sign_encoded.y) * 2.0 - 1.0);
+ return vec4(oct_to_vec3(oct), sign(oct_sign_encoded.y));
+}
+
+vec2 signNotZero(vec2 v) {
+ return mix(vec2(-1.0), vec2(1.0), greaterThanEqual(v.xy, vec2(0.0)));
+}
+
+uint vec2_to_uint(vec2 base) {
+ uvec2 enc = uvec2(clamp(ivec2(base * vec2(65535, 65535)), ivec2(0), ivec2(0xFFFF, 0xFFFF))) << uvec2(0, 16);
+ return enc.x | enc.y;
+}
+
+vec2 vec3_to_oct(vec3 e) {
+ e /= abs(e.x) + abs(e.y) + abs(e.z);
+ vec2 oct = e.z >= 0.0f ? e.xy : (vec2(1.0f) - abs(e.yx)) * signNotZero(e.xy);
+ return oct * 0.5f + 0.5f;
+}
+
+uint encode_norm_to_uint_oct(vec3 base) {
+ return vec2_to_uint(vec3_to_oct(base));
+}
+
+uint encode_tang_to_uint_oct(vec4 base) {
+ vec2 oct = vec3_to_oct(base.xyz);
+ // Encode binormal sign in y component
+ oct.y = oct.y * 0.5f + 0.5f;
+ oct.y = base.w >= 0.0f ? oct.y : 1 - oct.y;
+ return vec2_to_uint(oct);
}
void main() {
@@ -131,12 +171,12 @@ void main() {
src_offset += 3;
if (params.has_normal) {
- normal = decode_abgr_2_10_10_10(src_vertices.data[src_offset]).rgb;
+ normal = decode_uint_oct_to_norm(src_vertices.data[src_offset]);
src_offset++;
}
if (params.has_tangent) {
- tangent = decode_abgr_2_10_10_10(src_vertices.data[src_offset]);
+ tangent = decode_uint_oct_to_tang(src_vertices.data[src_offset]);
}
if (params.has_blend_shape) {
@@ -155,12 +195,12 @@ void main() {
base_offset += 3;
if (params.has_normal) {
- blend_normal += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_normal += decode_uint_oct_to_norm(src_blend_shapes.data[base_offset]) * w;
base_offset++;
}
if (params.has_tangent) {
- blend_tangent += decode_abgr_2_10_10_10(src_blend_shapes.data[base_offset]).rgb * w;
+ blend_tangent += decode_uint_oct_to_tang(src_blend_shapes.data[base_offset]).rgb * w;
}
blend_total += w;
@@ -234,12 +274,12 @@ void main() {
dst_offset += 3;
if (params.has_normal) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(vec4(normal, 0.0));
+ dst_vertices.data[dst_offset] = encode_norm_to_uint_oct(normal);
dst_offset++;
}
if (params.has_tangent) {
- dst_vertices.data[dst_offset] = encode_abgr_2_10_10_10(tangent);
+ dst_vertices.data[dst_offset] = encode_tang_to_uint_oct(tangent);
}
#endif
diff --git a/servers/rendering/renderer_rd/shaders/specular_merge.glsl b/servers/rendering/renderer_rd/shaders/specular_merge.glsl
deleted file mode 100644
index 3579c35cce..0000000000
--- a/servers/rendering/renderer_rd/shaders/specular_merge.glsl
+++ /dev/null
@@ -1,53 +0,0 @@
-#[vertex]
-
-#version 450
-
-#VERSION_DEFINES
-
-layout(location = 0) out vec2 uv_interp;
-
-void main() {
- vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0));
- uv_interp = base_arr[gl_VertexIndex];
-
- gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0);
-}
-
-#[fragment]
-
-#version 450
-
-#VERSION_DEFINES
-
-layout(location = 0) in vec2 uv_interp;
-
-layout(set = 0, binding = 0) uniform sampler2D specular;
-
-#ifdef MODE_SSR
-
-layout(set = 1, binding = 0) uniform sampler2D ssr;
-
-#endif
-
-#ifdef MODE_MERGE
-
-layout(set = 2, binding = 0) uniform sampler2D diffuse;
-
-#endif
-
-layout(location = 0) out vec4 frag_color;
-
-void main() {
- frag_color.rgb = texture(specular, uv_interp).rgb;
- frag_color.a = 0.0;
-#ifdef MODE_SSR
-
- vec4 ssr_color = texture(ssr, uv_interp);
- frag_color.rgb = mix(frag_color.rgb, ssr_color.rgb, ssr_color.a);
-#endif
-
-#ifdef MODE_MERGE
- frag_color += texture(diffuse, uv_interp);
-#endif
- //added using additive blend
-}
diff --git a/servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp
new file mode 100644
index 0000000000..c7f106eba0
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.cpp
@@ -0,0 +1,43 @@
+/*************************************************************************/
+/* forward_id_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "forward_id_storage.h"
+
+using namespace RendererRD;
+
+ForwardIDStorage *ForwardIDStorage::singleton = nullptr;
+
+ForwardIDStorage::ForwardIDStorage() {
+ singleton = this;
+}
+
+ForwardIDStorage::~ForwardIDStorage() {
+ singleton = nullptr;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h
new file mode 100644
index 0000000000..f6a74383d4
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/forward_id_storage.h
@@ -0,0 +1,68 @@
+/*************************************************************************/
+/* forward_id_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef FORWARD_ID_STORAGE_H
+#define FORWARD_ID_STORAGE_H
+
+#include "servers/rendering/storage/utilities.h"
+
+class RendererSceneRenderRD;
+
+namespace RendererRD {
+
+typedef int32_t ForwardID;
+
+enum ForwardIDType {
+ FORWARD_ID_TYPE_OMNI_LIGHT,
+ FORWARD_ID_TYPE_SPOT_LIGHT,
+ FORWARD_ID_TYPE_REFLECTION_PROBE,
+ FORWARD_ID_TYPE_DECAL,
+ FORWARD_ID_MAX,
+};
+
+class ForwardIDStorage {
+private:
+ static ForwardIDStorage *singleton;
+
+public:
+ static ForwardIDStorage *get_singleton() { return singleton; }
+
+ ForwardIDStorage();
+ virtual ~ForwardIDStorage();
+
+ virtual RendererRD::ForwardID allocate_forward_id(RendererRD::ForwardIDType p_type) { return -1; }
+ virtual void free_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id) {}
+ virtual void map_forward_id(RendererRD::ForwardIDType p_type, RendererRD::ForwardID p_id, uint32_t p_index) {}
+ virtual bool uses_forward_ids() const { return false; }
+};
+
+} // namespace RendererRD
+
+#endif // FORWARD_ID_STORAGE_H
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
index 56a4525b8e..c83473ef07 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp
@@ -30,6 +30,7 @@
#include "light_storage.h"
#include "core/config/project_settings.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
#include "texture_storage.h"
using namespace RendererRD;
@@ -45,6 +46,9 @@ LightStorage::LightStorage() {
TextureStorage *texture_storage = TextureStorage::get_singleton();
+ directional_shadow.size = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/size");
+ directional_shadow.use_16_bits = GLOBAL_GET("rendering/lights_and_shadows/directional_shadow/16_bits");
+
using_lightmap_array = true; // high end
if (using_lightmap_array) {
uint64_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE);
@@ -56,7 +60,7 @@ LightStorage::LightStorage() {
}
for (int i = 0; i < lightmap_textures.size(); i++) {
- lightmap_textures.write[i] = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ lightmap_textures.write[i] = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
}
}
@@ -64,9 +68,46 @@ LightStorage::LightStorage() {
}
LightStorage::~LightStorage() {
+ free_reflection_data();
+ free_light_data();
+
+ for (const KeyValue<int, ShadowCubemap> &E : shadow_cubemaps) {
+ RD::get_singleton()->free(E.value.cubemap);
+ }
+
singleton = nullptr;
}
+bool LightStorage::free(RID p_rid) {
+ if (owns_reflection_probe(p_rid)) {
+ reflection_probe_free(p_rid);
+ return true;
+ } else if (owns_reflection_atlas(p_rid)) {
+ reflection_atlas_free(p_rid);
+ return true;
+ } else if (owns_reflection_probe_instance(p_rid)) {
+ reflection_probe_instance_free(p_rid);
+ return true;
+ } else if (owns_light(p_rid)) {
+ light_free(p_rid);
+ return true;
+ } else if (owns_light_instance(p_rid)) {
+ light_instance_free(p_rid);
+ return true;
+ } else if (owns_lightmap(p_rid)) {
+ lightmap_free(p_rid);
+ return true;
+ } else if (owns_lightmap_instance(p_rid)) {
+ lightmap_instance_free(p_rid);
+ return true;
+ } else if (owns_shadow_atlas(p_rid)) {
+ shadow_atlas_free(p_rid);
+ return true;
+ }
+
+ return false;
+}
+
/* LIGHT */
void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
@@ -75,6 +116,7 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_ENERGY] = 1.0;
light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0;
+ light.param[RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY] = 1.0;
light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5;
light.param[RS::LIGHT_PARAM_RANGE] = 1.0;
light.param[RS::LIGHT_PARAM_SIZE] = 0.0;
@@ -88,10 +130,11 @@ void LightStorage::_light_initialize(RID p_light, RS::LightType p_type) {
light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8;
light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_BIAS] = 0.02;
+ light.param[RS::LIGHT_PARAM_SHADOW_OPACITY] = 1.0;
light.param[RS::LIGHT_PARAM_SHADOW_BLUR] = 0;
light.param[RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE] = 20.0;
- light.param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE] = 0.1;
light.param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] = 0.05;
+ light.param[RS::LIGHT_PARAM_INTENSITY] = p_type == RS::LIGHT_DIRECTIONAL ? 100000.0 : 1000.0;
light_owner.initialize_rid(p_light, light);
}
@@ -156,12 +199,12 @@ void LightStorage::light_set_param(RID p_light, RS::LightParam p_param, float p_
case RS::LIGHT_PARAM_SHADOW_PANCAKE_SIZE:
case RS::LIGHT_PARAM_SHADOW_BIAS: {
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
} break;
case RS::LIGHT_PARAM_SIZE: {
if ((light->param[p_param] > CMP_EPSILON) != (p_value > CMP_EPSILON)) {
//changing from no size to size and the opposite
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
}
} break;
default: {
@@ -177,11 +220,11 @@ void LightStorage::light_set_shadow(RID p_light, bool p_enabled) {
light->shadow = p_enabled;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_projector(RID p_light, RID p_texture) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND(!light);
@@ -199,7 +242,7 @@ void LightStorage::light_set_projector(RID p_light, RID p_texture) {
if (light->projector.is_valid()) {
texture_storage->texture_add_to_decal_atlas(light->projector, light->type == RS::LIGHT_OMNI);
}
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR);
}
}
@@ -217,7 +260,7 @@ void LightStorage::light_set_cull_mask(RID p_light, uint32_t p_mask) {
light->cull_mask = p_mask;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_distance_fade(RID p_light, bool p_enabled, float p_begin, float p_shadow, float p_length) {
@@ -237,7 +280,7 @@ void LightStorage::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled)
light->reverse_cull = p_enabled;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mode) {
@@ -247,7 +290,7 @@ void LightStorage::light_set_bake_mode(RID p_light, RS::LightBakeMode p_bake_mod
light->bake_mode = p_bake_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade) {
@@ -257,7 +300,7 @@ void LightStorage::light_set_max_sdfgi_cascade(RID p_light, uint32_t p_cascade)
light->max_sdfgi_cascade = p_cascade;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {
@@ -267,7 +310,7 @@ void LightStorage::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMo
light->omni_shadow_mode = p_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
RS::LightOmniShadowMode LightStorage::light_omni_get_shadow_mode(RID p_light) {
@@ -283,7 +326,7 @@ void LightStorage::light_directional_set_shadow_mode(RID p_light, RS::LightDirec
light->directional_shadow_mode = p_mode;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable) {
@@ -292,7 +335,7 @@ void LightStorage::light_directional_set_blend_splits(RID p_light, bool p_enable
light->directional_blend_splits = p_enable;
light->version++;
- light->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_LIGHT);
+ light->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_LIGHT);
}
bool LightStorage::light_directional_get_blend_splits(RID p_light) const {
@@ -351,7 +394,7 @@ AABB LightStorage::light_get_aabb(RID p_light) const {
switch (light->type) {
case RS::LIGHT_SPOT: {
float len = light->param[RS::LIGHT_PARAM_RANGE];
- float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
+ float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len;
return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len));
};
case RS::LIGHT_OMNI: {
@@ -366,6 +409,602 @@ AABB LightStorage::light_get_aabb(RID p_light) const {
ERR_FAIL_V(AABB());
}
+Dependency *LightStorage::light_get_dependency(RID p_light) const {
+ Light *light = light_owner.get_or_null(p_light);
+ ERR_FAIL_NULL_V(light, nullptr);
+
+ return &light->dependency;
+}
+
+/* LIGHT INSTANCE API */
+
+RID LightStorage::light_instance_create(RID p_light) {
+ RID li = light_instance_owner.make_rid(LightInstance());
+
+ LightInstance *light_instance = light_instance_owner.get_or_null(li);
+
+ light_instance->self = li;
+ light_instance->light = p_light;
+ light_instance->light_type = light_get_type(p_light);
+ if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
+ light_instance->forward_id = ForwardIDStorage::get_singleton()->allocate_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT);
+ }
+
+ return li;
+}
+
+void LightStorage::light_instance_free(RID p_light) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light);
+
+ //remove from shadow atlases..
+ for (const RID &E : light_instance->shadow_atlases) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(E);
+ ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_light));
+ uint32_t key = shadow_atlas->shadow_owners[p_light];
+ uint32_t q = (key >> QUADRANT_SHIFT) & 0x3;
+ uint32_t s = key & SHADOW_INDEX_MASK;
+
+ shadow_atlas->quadrants[q].shadows.write[s].owner = RID();
+
+ if (key & OMNI_LIGHT_FLAG) {
+ // Omni lights use two atlas spots, make sure to clear the other as well
+ shadow_atlas->quadrants[q].shadows.write[s + 1].owner = RID();
+ }
+
+ shadow_atlas->shadow_owners.erase(p_light);
+ }
+
+ if (light_instance->light_type != RS::LIGHT_DIRECTIONAL) {
+ ForwardIDStorage::get_singleton()->free_forward_id(light_instance->light_type == RS::LIGHT_OMNI ? FORWARD_ID_TYPE_OMNI_LIGHT : FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id);
+ }
+ light_instance_owner.free(p_light);
+}
+
+void LightStorage::light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ light_instance->transform = p_transform;
+}
+
+void LightStorage::light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ light_instance->aabb = p_aabb;
+}
+
+void LightStorage::light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale, float p_range_begin, const Vector2 &p_uv_scale) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ ERR_FAIL_INDEX(p_pass, 6);
+
+ light_instance->shadow_transform[p_pass].camera = p_projection;
+ light_instance->shadow_transform[p_pass].transform = p_transform;
+ light_instance->shadow_transform[p_pass].farplane = p_far;
+ light_instance->shadow_transform[p_pass].split = p_split;
+ light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale;
+ light_instance->shadow_transform[p_pass].range_begin = p_range_begin;
+ light_instance->shadow_transform[p_pass].shadow_texel_size = p_shadow_texel_size;
+ light_instance->shadow_transform[p_pass].uv_scale = p_uv_scale;
+}
+
+void LightStorage::light_instance_mark_visible(RID p_light_instance) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND(!light_instance);
+
+ light_instance->last_scene_pass = RendererSceneRenderRD::get_singleton()->get_scene_pass();
+}
+
+/* LIGHT DATA */
+
+void LightStorage::free_light_data() {
+ if (directional_light_buffer.is_valid()) {
+ RD::get_singleton()->free(directional_light_buffer);
+ directional_light_buffer = RID();
+ }
+
+ if (omni_light_buffer.is_valid()) {
+ RD::get_singleton()->free(omni_light_buffer);
+ omni_light_buffer = RID();
+ }
+
+ if (spot_light_buffer.is_valid()) {
+ RD::get_singleton()->free(spot_light_buffer);
+ spot_light_buffer = RID();
+ }
+
+ if (directional_lights != nullptr) {
+ memdelete_arr(directional_lights);
+ directional_lights = nullptr;
+ }
+
+ if (omni_lights != nullptr) {
+ memdelete_arr(omni_lights);
+ omni_lights = nullptr;
+ }
+
+ if (spot_lights != nullptr) {
+ memdelete_arr(spot_lights);
+ spot_lights = nullptr;
+ }
+
+ if (omni_light_sort != nullptr) {
+ memdelete_arr(omni_light_sort);
+ omni_light_sort = nullptr;
+ }
+
+ if (spot_light_sort != nullptr) {
+ memdelete_arr(spot_light_sort);
+ spot_light_sort = nullptr;
+ }
+}
+
+void LightStorage::set_max_lights(const uint32_t p_max_lights) {
+ max_lights = p_max_lights;
+
+ uint32_t light_buffer_size = max_lights * sizeof(LightData);
+ omni_lights = memnew_arr(LightData, max_lights);
+ omni_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
+ omni_light_sort = memnew_arr(LightInstanceDepthSort, max_lights);
+ spot_lights = memnew_arr(LightData, max_lights);
+ spot_light_buffer = RD::get_singleton()->storage_buffer_create(light_buffer_size);
+ spot_light_sort = memnew_arr(LightInstanceDepthSort, max_lights);
+ //defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(max_lights) + "\n";
+
+ max_directional_lights = RendererSceneRender::MAX_DIRECTIONAL_LIGHTS;
+ uint32_t directional_light_buffer_size = max_directional_lights * sizeof(DirectionalLightData);
+ directional_lights = memnew_arr(DirectionalLightData, max_directional_lights);
+ directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size);
+}
+
+void LightStorage::update_light_buffers(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows) {
+ ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton();
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+
+ Transform3D inverse_transform = p_camera_transform.affine_inverse();
+
+ r_directional_light_count = 0;
+ r_positional_light_count = 0;
+
+ Plane camera_plane(-p_camera_transform.basis.get_column(Vector3::AXIS_Z).normalized(), p_camera_transform.origin);
+
+ omni_light_count = 0;
+ spot_light_count = 0;
+
+ r_directional_light_soft_shadows = false;
+
+ for (int i = 0; i < (int)p_lights.size(); i++) {
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_lights[i]);
+ if (!light_instance) {
+ continue;
+ }
+ Light *light = light_owner.get_or_null(light_instance->light);
+
+ ERR_CONTINUE(light == nullptr);
+
+ switch (light->type) {
+ case RS::LIGHT_DIRECTIONAL: {
+ if (r_directional_light_count >= max_directional_lights || light->directional_sky_mode == RS::LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY) {
+ continue;
+ }
+
+ DirectionalLightData &light_data = directional_lights[r_directional_light_count];
+
+ Transform3D light_transform = light_instance->transform;
+
+ Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized();
+
+ light_data.direction[0] = direction.x;
+ light_data.direction[1] = direction.y;
+ light_data.direction[2] = direction.z;
+
+ float sign = light->negative ? -1 : 1;
+
+ light_data.energy = sign * light->param[RS::LIGHT_PARAM_ENERGY];
+
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ light_data.energy *= light->param[RS::LIGHT_PARAM_INTENSITY];
+ } else {
+ light_data.energy *= Math_PI;
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ light_data.energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
+ Color linear_col = light->color.srgb_to_linear();
+ light_data.color[0] = linear_col.r;
+ light_data.color[1] = linear_col.g;
+ light_data.color[2] = linear_col.b;
+
+ light_data.specular = light->param[RS::LIGHT_PARAM_SPECULAR];
+ light_data.volumetric_fog_energy = light->param[RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY];
+ light_data.mask = light->cull_mask;
+
+ float size = light->param[RS::LIGHT_PARAM_SIZE];
+
+ light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset
+
+ if (RendererSceneRenderRD::get_singleton()->get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) {
+ WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet.");
+ }
+
+ light_data.shadow_opacity = (p_using_shadows && light->shadow)
+ ? light->param[RS::LIGHT_PARAM_SHADOW_OPACITY]
+ : 0.0;
+
+ float angular_diameter = light->param[RS::LIGHT_PARAM_SIZE];
+ if (angular_diameter > 0.0) {
+ // I know tan(0) is 0, but let's not risk it with numerical precision.
+ // technically this will keep expanding until reaching the sun, but all we care
+ // is expand until we reach the radius of the near plane (there can't be more occluders than that)
+ angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter));
+ if (light->shadow && light->param[RS::LIGHT_PARAM_SHADOW_BLUR] > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
+ r_directional_light_soft_shadows = true;
+ }
+ } else {
+ angular_diameter = 0.0;
+ }
+
+ if (light_data.shadow_opacity > 0.001) {
+ RS::LightDirectionalShadowMode smode = light->directional_shadow_mode;
+
+ int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3);
+ light_data.blend_splits = (smode != RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL) && light->directional_blend_splits;
+ for (int j = 0; j < 4; j++) {
+ Rect2 atlas_rect = light_instance->shadow_transform[j].atlas_rect;
+ Projection matrix = light_instance->shadow_transform[j].camera;
+ float split = light_instance->shadow_transform[MIN(limit, j)].split;
+
+ Projection bias;
+ bias.set_light_bias();
+ Projection rectm;
+ rectm.set_light_atlas_rect(atlas_rect);
+
+ Transform3D modelview = (inverse_transform * light_instance->shadow_transform[j].transform).inverse();
+
+ Projection shadow_mtx = rectm * bias * matrix * modelview;
+ light_data.shadow_split_offsets[j] = split;
+ float bias_scale = light_instance->shadow_transform[j].bias_scale;
+ light_data.shadow_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0 * bias_scale;
+ light_data.shadow_normal_bias[j] = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * light_instance->shadow_transform[j].shadow_texel_size;
+ light_data.shadow_transmittance_bias[j] = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS] * bias_scale;
+ light_data.shadow_z_range[j] = light_instance->shadow_transform[j].farplane;
+ light_data.shadow_range_begin[j] = light_instance->shadow_transform[j].range_begin;
+ RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrices[j]);
+
+ Vector2 uv_scale = light_instance->shadow_transform[j].uv_scale;
+ uv_scale *= atlas_rect.size; //adapt to atlas size
+ switch (j) {
+ case 0: {
+ light_data.uv_scale1[0] = uv_scale.x;
+ light_data.uv_scale1[1] = uv_scale.y;
+ } break;
+ case 1: {
+ light_data.uv_scale2[0] = uv_scale.x;
+ light_data.uv_scale2[1] = uv_scale.y;
+ } break;
+ case 2: {
+ light_data.uv_scale3[0] = uv_scale.x;
+ light_data.uv_scale3[1] = uv_scale.y;
+ } break;
+ case 3: {
+ light_data.uv_scale4[0] = uv_scale.x;
+ light_data.uv_scale4[1] = uv_scale.y;
+ } break;
+ }
+ }
+
+ float fade_start = light->param[RS::LIGHT_PARAM_SHADOW_FADE_START];
+ light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep
+ light_data.fade_to = -light_data.shadow_split_offsets[3];
+
+ light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR];
+ light_data.softshadow_angle = angular_diameter;
+ light_data.bake_mode = light->bake_mode;
+
+ if (angular_diameter <= 0.0) {
+ light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->directional_shadow_quality_radius_get(); // Only use quality radius for PCF
+ }
+ }
+
+ r_directional_light_count++;
+ } break;
+ case RS::LIGHT_OMNI: {
+ if (omni_light_count >= max_lights) {
+ continue;
+ }
+
+ Transform3D light_transform = light_instance->transform;
+ const real_t distance = camera_plane.distance_to(light_transform.origin);
+
+ if (light->distance_fade) {
+ const float fade_begin = light->distance_fade_begin;
+ const float fade_length = light->distance_fade_length;
+
+ if (distance > fade_begin) {
+ if (distance > fade_begin + fade_length) {
+ // Out of range, don't draw this light to improve performance.
+ continue;
+ }
+ }
+ }
+
+ omni_light_sort[omni_light_count].light_instance = light_instance;
+ omni_light_sort[omni_light_count].light = light;
+ omni_light_sort[omni_light_count].depth = distance;
+ omni_light_count++;
+ } break;
+ case RS::LIGHT_SPOT: {
+ if (spot_light_count >= max_lights) {
+ continue;
+ }
+
+ Transform3D light_transform = light_instance->transform;
+ const real_t distance = camera_plane.distance_to(light_transform.origin);
+
+ if (light->distance_fade) {
+ const float fade_begin = light->distance_fade_begin;
+ const float fade_length = light->distance_fade_length;
+
+ if (distance > fade_begin) {
+ if (distance > fade_begin + fade_length) {
+ // Out of range, don't draw this light to improve performance.
+ continue;
+ }
+ }
+ }
+
+ spot_light_sort[spot_light_count].light_instance = light_instance;
+ spot_light_sort[spot_light_count].light = light;
+ spot_light_sort[spot_light_count].depth = distance;
+ spot_light_count++;
+ } break;
+ }
+
+ light_instance->last_pass = RSG::rasterizer->get_frame_number();
+ }
+
+ if (omni_light_count) {
+ SortArray<LightInstanceDepthSort> sorter;
+ sorter.sort(omni_light_sort, omni_light_count);
+ }
+
+ if (spot_light_count) {
+ SortArray<LightInstanceDepthSort> sorter;
+ sorter.sort(spot_light_sort, spot_light_count);
+ }
+
+ bool using_forward_ids = forward_id_storage->uses_forward_ids();
+
+ for (uint32_t i = 0; i < (omni_light_count + spot_light_count); i++) {
+ uint32_t index = (i < omni_light_count) ? i : i - (omni_light_count);
+ LightData &light_data = (i < omni_light_count) ? omni_lights[index] : spot_lights[index];
+ RS::LightType type = (i < omni_light_count) ? RS::LIGHT_OMNI : RS::LIGHT_SPOT;
+ LightInstance *light_instance = (i < omni_light_count) ? omni_light_sort[index].light_instance : spot_light_sort[index].light_instance;
+ Light *light = (i < omni_light_count) ? omni_light_sort[index].light : spot_light_sort[index].light;
+
+ if (using_forward_ids) {
+ forward_id_storage->map_forward_id(type == RS::LIGHT_OMNI ? RendererRD::FORWARD_ID_TYPE_OMNI_LIGHT : RendererRD::FORWARD_ID_TYPE_SPOT_LIGHT, light_instance->forward_id, index);
+ }
+
+ Transform3D light_transform = light_instance->transform;
+
+ float sign = light->negative ? -1 : 1;
+ Color linear_col = light->color.srgb_to_linear();
+
+ light_data.attenuation = light->param[RS::LIGHT_PARAM_ATTENUATION];
+
+ // Reuse fade begin, fade length and distance for shadow LOD determination later.
+ float fade_begin = 0.0;
+ float fade_shadow = 0.0;
+ float fade_length = 0.0;
+ real_t distance = 0.0;
+
+ float fade = 1.0;
+ float shadow_opacity_fade = 1.0;
+ if (light->distance_fade) {
+ fade_begin = light->distance_fade_begin;
+ fade_shadow = light->distance_fade_shadow;
+ fade_length = light->distance_fade_length;
+ distance = camera_plane.distance_to(light_transform.origin);
+
+ // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
+ if (distance > fade_begin) {
+ fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
+ }
+
+ if (distance > fade_shadow) {
+ shadow_opacity_fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_shadow) / fade_length);
+ }
+ }
+
+ float energy = sign * light->param[RS::LIGHT_PARAM_ENERGY] * fade;
+
+ if (RendererSceneRenderRD::get_singleton()->is_using_physical_light_units()) {
+ energy *= light->param[RS::LIGHT_PARAM_INTENSITY];
+
+ // Convert from Luminous Power to Luminous Intensity
+ if (type == RS::LIGHT_OMNI) {
+ energy *= 1.0 / (Math_PI * 4.0);
+ } else {
+ // Spot Lights are not physically accurate, Luminous Intensity should change in relation to the cone angle.
+ // We make this assumption to keep them easy to control.
+ energy *= 1.0 / Math_PI;
+ }
+ } else {
+ energy *= Math_PI;
+ }
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ energy *= RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ }
+
+ light_data.color[0] = linear_col.r * energy;
+ light_data.color[1] = linear_col.g * energy;
+ light_data.color[2] = linear_col.b * energy;
+ light_data.specular_amount = light->param[RS::LIGHT_PARAM_SPECULAR] * 2.0;
+ light_data.volumetric_fog_energy = light->param[RS::LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY];
+ light_data.bake_mode = light->bake_mode;
+
+ float radius = MAX(0.001, light->param[RS::LIGHT_PARAM_RANGE]);
+ light_data.inv_radius = 1.0 / radius;
+
+ Vector3 pos = inverse_transform.xform(light_transform.origin);
+
+ light_data.position[0] = pos.x;
+ light_data.position[1] = pos.y;
+ light_data.position[2] = pos.z;
+
+ Vector3 direction = inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized();
+
+ light_data.direction[0] = direction.x;
+ light_data.direction[1] = direction.y;
+ light_data.direction[2] = direction.z;
+
+ float size = light->param[RS::LIGHT_PARAM_SIZE];
+
+ light_data.size = size;
+
+ light_data.inv_spot_attenuation = 1.0f / light->param[RS::LIGHT_PARAM_SPOT_ATTENUATION];
+ float spot_angle = light->param[RS::LIGHT_PARAM_SPOT_ANGLE];
+ light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle));
+
+ light_data.mask = light->cull_mask;
+
+ light_data.atlas_rect[0] = 0;
+ light_data.atlas_rect[1] = 0;
+ light_data.atlas_rect[2] = 0;
+ light_data.atlas_rect[3] = 0;
+
+ RID projector = light->projector;
+
+ if (projector.is_valid()) {
+ Rect2 rect = texture_storage->decal_atlas_get_texture_rect(projector);
+
+ if (type == RS::LIGHT_SPOT) {
+ light_data.projector_rect[0] = rect.position.x;
+ light_data.projector_rect[1] = rect.position.y + rect.size.height; //flip because shadow is flipped
+ light_data.projector_rect[2] = rect.size.width;
+ light_data.projector_rect[3] = -rect.size.height;
+ } else {
+ light_data.projector_rect[0] = rect.position.x;
+ light_data.projector_rect[1] = rect.position.y;
+ light_data.projector_rect[2] = rect.size.width;
+ light_data.projector_rect[3] = rect.size.height * 0.5; //used by dp, so needs to be half
+ }
+ } else {
+ light_data.projector_rect[0] = 0;
+ light_data.projector_rect[1] = 0;
+ light_data.projector_rect[2] = 0;
+ light_data.projector_rect[3] = 0;
+ }
+
+ const bool needs_shadow =
+ p_using_shadows &&
+ owns_shadow_atlas(p_shadow_atlas) &&
+ shadow_atlas_owns_light_instance(p_shadow_atlas, light_instance->self) &&
+ light->shadow;
+
+ bool in_shadow_range = true;
+ if (needs_shadow && light->distance_fade) {
+ if (distance > light->distance_fade_shadow + light->distance_fade_length) {
+ // Out of range, don't draw shadows to improve performance.
+ in_shadow_range = false;
+ }
+ }
+
+ if (needs_shadow && in_shadow_range) {
+ // fill in the shadow information
+
+ light_data.shadow_opacity = light->param[RS::LIGHT_PARAM_SHADOW_OPACITY] * shadow_opacity_fade;
+
+ float shadow_texel_size = light_instance_get_shadow_texel_size(light_instance->self, p_shadow_atlas);
+ light_data.shadow_normal_bias = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * shadow_texel_size * 10.0;
+
+ if (type == RS::LIGHT_SPOT) {
+ light_data.shadow_bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] / 100.0;
+ } else { //omni
+ light_data.shadow_bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS];
+ }
+
+ light_data.transmittance_bias = light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
+
+ Vector2i omni_offset;
+ Rect2 rect = light_instance_get_shadow_atlas_rect(light_instance->self, p_shadow_atlas, omni_offset);
+
+ light_data.atlas_rect[0] = rect.position.x;
+ light_data.atlas_rect[1] = rect.position.y;
+ light_data.atlas_rect[2] = rect.size.width;
+ light_data.atlas_rect[3] = rect.size.height;
+
+ light_data.soft_shadow_scale = light->param[RS::LIGHT_PARAM_SHADOW_BLUR];
+
+ if (type == RS::LIGHT_OMNI) {
+ Transform3D proj = (inverse_transform * light_transform).inverse();
+
+ RendererRD::MaterialStorage::store_transform(proj, light_data.shadow_matrix);
+
+ if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
+ light_data.soft_shadow_size = size;
+ } else {
+ light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF
+ }
+
+ light_data.direction[0] = omni_offset.x * float(rect.size.width);
+ light_data.direction[1] = omni_offset.y * float(rect.size.height);
+ } else if (type == RS::LIGHT_SPOT) {
+ Transform3D modelview = (inverse_transform * light_transform).inverse();
+ Projection bias;
+ bias.set_light_bias();
+
+ Projection cm = light_instance->shadow_transform[0].camera;
+ Projection shadow_mtx = bias * cm * modelview;
+ RendererRD::MaterialStorage::store_camera(shadow_mtx, light_data.shadow_matrix);
+
+ if (size > 0.0 && light_data.soft_shadow_scale > 0.0) {
+ // Only enable PCSS-like soft shadows if blurring is enabled.
+ // Otherwise, performance would decrease with no visual difference.
+ float half_np = cm.get_z_near() * Math::tan(Math::deg_to_rad(spot_angle));
+ light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width;
+ } else {
+ light_data.soft_shadow_size = 0.0;
+ light_data.soft_shadow_scale *= RendererSceneRenderRD::get_singleton()->shadows_quality_radius_get(); // Only use quality radius for PCF
+ }
+ }
+ } else {
+ light_data.shadow_opacity = 0.0;
+ }
+
+ light_instance->cull_mask = light->cull_mask;
+
+ // hook for subclass to do further processing.
+ RendererSceneRenderRD::get_singleton()->setup_added_light(type, light_transform, radius, spot_angle);
+
+ r_positional_light_count++;
+ }
+
+ //update without barriers
+ if (omni_light_count) {
+ RD::get_singleton()->buffer_update(omni_light_buffer, 0, sizeof(LightData) * omni_light_count, omni_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
+ }
+
+ if (spot_light_count) {
+ RD::get_singleton()->buffer_update(spot_light_buffer, 0, sizeof(LightData) * spot_light_count, spot_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
+ }
+
+ if (r_directional_light_count) {
+ RD::get_singleton()->buffer_update(directional_light_buffer, 0, sizeof(DirectionalLightData) * r_directional_light_count, directional_lights, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
+ }
+}
+
/* REFLECTION PROBE */
RID LightStorage::reflection_probe_allocate() {
@@ -387,7 +1026,7 @@ void LightStorage::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionP
ERR_FAIL_COND(!reflection_probe);
reflection_probe->update_mode = p_mode;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_intensity(RID p_probe, float p_intensity) {
@@ -424,7 +1063,7 @@ void LightStorage::reflection_probe_set_max_distance(RID p_probe, float p_distan
reflection_probe->max_distance = p_distance;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) {
@@ -435,7 +1074,7 @@ void LightStorage::reflection_probe_set_extents(RID p_probe, const Vector3 &p_ex
return;
}
reflection_probe->extents = p_extents;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) {
@@ -443,7 +1082,7 @@ void LightStorage::reflection_probe_set_origin_offset(RID p_probe, const Vector3
ERR_FAIL_COND(!reflection_probe);
reflection_probe->origin_offset = p_offset;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable) {
@@ -451,7 +1090,7 @@ void LightStorage::reflection_probe_set_as_interior(RID p_probe, bool p_enable)
ERR_FAIL_COND(!reflection_probe);
reflection_probe->interior = p_enable;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) {
@@ -466,7 +1105,7 @@ void LightStorage::reflection_probe_set_enable_shadows(RID p_probe, bool p_enabl
ERR_FAIL_COND(!reflection_probe);
reflection_probe->enable_shadows = p_enable;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) {
@@ -474,7 +1113,7 @@ void LightStorage::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers
ERR_FAIL_COND(!reflection_probe);
reflection_probe->cull_mask = p_layers;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
}
void LightStorage::reflection_probe_set_resolution(RID p_probe, int p_resolution) {
@@ -491,7 +1130,14 @@ void LightStorage::reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_
reflection_probe->mesh_lod_threshold = p_ratio;
- reflection_probe->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+ reflection_probe->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE);
+}
+
+void LightStorage::reflection_probe_set_baked_exposure(RID p_probe, float p_exposure) {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND(!reflection_probe);
+
+ reflection_probe->baked_exposure = p_exposure;
}
AABB LightStorage::reflection_probe_get_aabb(RID p_probe) const {
@@ -561,6 +1207,13 @@ int LightStorage::reflection_probe_get_resolution(RID p_probe) const {
return reflection_probe->resolution;
}
+float LightStorage::reflection_probe_get_baked_exposure(RID p_probe) const {
+ const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_COND_V(!reflection_probe, 1.0);
+
+ return reflection_probe->baked_exposure;
+}
+
float LightStorage::reflection_probe_get_intensity(RID p_probe) const {
const ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
ERR_FAIL_COND_V(!reflection_probe, 0);
@@ -601,6 +1254,450 @@ float LightStorage::reflection_probe_get_ambient_color_energy(RID p_probe) const
return reflection_probe->ambient_color_energy;
}
+Dependency *LightStorage::reflection_probe_get_dependency(RID p_probe) const {
+ ReflectionProbe *reflection_probe = reflection_probe_owner.get_or_null(p_probe);
+ ERR_FAIL_NULL_V(reflection_probe, nullptr);
+
+ return &reflection_probe->dependency;
+}
+
+/* REFLECTION ATLAS */
+
+RID LightStorage::reflection_atlas_create() {
+ ReflectionAtlas ra;
+ ra.count = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_count");
+ ra.size = GLOBAL_GET("rendering/reflections/reflection_atlas/reflection_size");
+ ra.cluster_builder = nullptr;
+
+ return reflection_atlas_owner.make_rid(ra);
+}
+
+void LightStorage::reflection_atlas_free(RID p_ref_atlas) {
+ reflection_atlas_set_size(p_ref_atlas, 0, 0);
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);
+ if (ra->cluster_builder) {
+ memdelete(ra->cluster_builder);
+ }
+ reflection_atlas_owner.free(p_ref_atlas);
+}
+
+void LightStorage::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) {
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);
+ ERR_FAIL_COND(!ra);
+
+ if (ra->size == p_reflection_size && ra->count == p_reflection_count) {
+ return; //no changes
+ }
+
+ if (ra->cluster_builder) {
+ // only if we're using our cluster
+ ra->cluster_builder->setup(Size2i(ra->size, ra->size), max_cluster_elements, RID(), RID(), RID());
+ }
+
+ ra->size = p_reflection_size;
+ ra->count = p_reflection_count;
+
+ if (ra->reflection.is_valid()) {
+ //clear and invalidate everything
+ RD::get_singleton()->free(ra->reflection);
+ ra->reflection = RID();
+ RD::get_singleton()->free(ra->depth_buffer);
+ ra->depth_buffer = RID();
+ for (int i = 0; i < ra->reflections.size(); i++) {
+ ra->reflections.write[i].data.clear_reflection_data();
+ if (ra->reflections[i].owner.is_null()) {
+ continue;
+ }
+ reflection_probe_release_atlas_index(ra->reflections[i].owner);
+ //rp->atlasindex clear
+ }
+
+ ra->reflections.clear();
+ }
+}
+
+int LightStorage::reflection_atlas_get_size(RID p_ref_atlas) const {
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(p_ref_atlas);
+ ERR_FAIL_COND_V(!ra, 0);
+
+ return ra->size;
+}
+
+/* REFLECTION PROBE INSTANCE */
+
+RID LightStorage::reflection_probe_instance_create(RID p_probe) {
+ ReflectionProbeInstance rpi;
+ rpi.probe = p_probe;
+ rpi.forward_id = ForwardIDStorage::get_singleton()->allocate_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE);
+
+ return reflection_probe_instance_owner.make_rid(rpi);
+}
+
+void LightStorage::reflection_probe_instance_free(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ForwardIDStorage::get_singleton()->free_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id);
+ reflection_probe_release_atlas_index(p_instance);
+ reflection_probe_instance_owner.free(p_instance);
+}
+
+void LightStorage::reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!rpi);
+
+ rpi->transform = p_transform;
+ rpi->dirty = true;
+}
+
+void LightStorage::reflection_probe_release_atlas_index(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!rpi);
+
+ if (rpi->atlas.is_null()) {
+ return; //nothing to release
+ }
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
+ ERR_FAIL_COND(!atlas);
+ ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size());
+ atlas->reflections.write[rpi->atlas_index].owner = RID();
+ rpi->atlas_index = -1;
+ rpi->atlas = RID();
+}
+
+bool LightStorage::reflection_probe_instance_needs_redraw(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ if (rpi->rendering) {
+ return false;
+ }
+
+ if (rpi->dirty) {
+ return true;
+ }
+
+ if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+ return true;
+ }
+
+ return rpi->atlas_index == -1;
+}
+
+bool LightStorage::reflection_probe_instance_has_reflection(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ return rpi->atlas.is_valid();
+}
+
+bool LightStorage::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) {
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_reflection_atlas);
+
+ ERR_FAIL_COND_V(!atlas, false);
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+
+ RD::get_singleton()->draw_command_begin_label("Reflection probe render");
+
+ if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) {
+ WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings.");
+ reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count);
+ }
+
+ if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) {
+ // Invalidate reflection atlas, need to regenerate
+ RD::get_singleton()->free(atlas->reflection);
+ atlas->reflection = RID();
+
+ for (int i = 0; i < atlas->reflections.size(); i++) {
+ if (atlas->reflections[i].owner.is_null()) {
+ continue;
+ }
+ reflection_probe_release_atlas_index(atlas->reflections[i].owner);
+ }
+
+ atlas->reflections.clear();
+ }
+
+ if (atlas->reflection.is_null()) {
+ int mipmaps = MIN(RendererSceneRenderRD::get_singleton()->get_sky()->roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1);
+ mipmaps = LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering
+ {
+ //reflection atlas was unused, create:
+ RD::TextureFormat tf;
+ tf.array_layers = 6 * atlas->count;
+ tf.format = RendererSceneRenderRD::get_singleton()->_render_buffers_get_color_format();
+ tf.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+ tf.mipmaps = mipmaps;
+ tf.width = atlas->size;
+ tf.height = atlas->size;
+ tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | (RendererSceneRenderRD::get_singleton()->_render_buffers_can_be_storage() ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
+
+ atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
+ tf.width = atlas->size;
+ tf.height = atlas->size;
+ tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+ atlas->reflections.resize(atlas->count);
+ for (int i = 0; i < atlas->count; i++) {
+ atlas->reflections.write[i].data.update_reflection_data(atlas->size, mipmaps, false, atlas->reflection, i * 6, LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS, RendererSceneRenderRD::get_singleton()->get_sky()->roughness_layers, RendererSceneRenderRD::get_singleton()->_render_buffers_get_color_format());
+ for (int j = 0; j < 6; j++) {
+ atlas->reflections.write[i].fbs[j] = RendererSceneRenderRD::get_singleton()->reflection_probe_create_framebuffer(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j], atlas->depth_buffer);
+ }
+ }
+
+ Vector<RID> fb;
+ fb.push_back(atlas->depth_buffer);
+ atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb);
+ }
+
+ if (rpi->atlas_index == -1) {
+ for (int i = 0; i < atlas->reflections.size(); i++) {
+ if (atlas->reflections[i].owner.is_null()) {
+ rpi->atlas_index = i;
+ break;
+ }
+ }
+ //find the one used last
+ if (rpi->atlas_index == -1) {
+ //everything is in use, find the one least used via LRU
+ uint64_t pass_min = 0;
+
+ for (int i = 0; i < atlas->reflections.size(); i++) {
+ ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.get_or_null(atlas->reflections[i].owner);
+ if (rpi2->last_pass < pass_min) {
+ pass_min = rpi2->last_pass;
+ rpi->atlas_index = i;
+ }
+ }
+ }
+ }
+
+ if (rpi->atlas_index != -1) { // should we fail if this is still -1 ?
+ atlas->reflections.write[rpi->atlas_index].owner = p_instance;
+ }
+
+ rpi->atlas = p_reflection_atlas;
+ rpi->rendering = true;
+ rpi->dirty = false;
+ rpi->processing_layer = 1;
+ rpi->processing_side = 0;
+
+ RD::get_singleton()->draw_command_end_label();
+
+ return true;
+}
+
+bool LightStorage::reflection_probe_instance_postprocess_step(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, false);
+ ERR_FAIL_COND_V(!rpi->rendering, false);
+ ERR_FAIL_COND_V(rpi->atlas.is_null(), false);
+
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
+ if (!atlas || rpi->atlas_index == -1) {
+ //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering)
+ rpi->rendering = false;
+ return false;
+ }
+
+ if (LightStorage::get_singleton()->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) {
+ // Using real time reflections, all roughness is done in one step
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_fast_filter(false);
+ rpi->rendering = false;
+ rpi->processing_side = 0;
+ rpi->processing_layer = 1;
+ return true;
+ }
+
+ if (rpi->processing_layer > 1) {
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, 10, rpi->processing_layer, RendererSceneRenderRD::get_singleton()->get_sky()->sky_ggx_samples_quality);
+ rpi->processing_layer++;
+ if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) {
+ rpi->rendering = false;
+ rpi->processing_side = 0;
+ rpi->processing_layer = 1;
+ return true;
+ }
+ return false;
+
+ } else {
+ atlas->reflections.write[rpi->atlas_index].data.create_reflection_importance_sample(false, rpi->processing_side, rpi->processing_layer, RendererSceneRenderRD::get_singleton()->get_sky()->sky_ggx_samples_quality);
+ }
+
+ rpi->processing_side++;
+ if (rpi->processing_side == 6) {
+ rpi->processing_side = 0;
+ rpi->processing_layer++;
+ }
+
+ return false;
+}
+
+uint32_t LightStorage::reflection_probe_instance_get_resolution(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, 0);
+
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
+ ERR_FAIL_COND_V(!atlas, 0);
+ return atlas->size;
+}
+
+RID LightStorage::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, RID());
+ ERR_FAIL_INDEX_V(p_index, 6, RID());
+
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->reflections[rpi->atlas_index].fbs[p_index];
+}
+
+RID LightStorage::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, RID());
+ ERR_FAIL_INDEX_V(p_index, 6, RID());
+
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(rpi->atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->depth_fb;
+}
+
+ClusterBuilderRD *LightStorage::reflection_probe_instance_get_cluster_builder(RID p_instance, ClusterBuilderSharedDataRD *p_cluster_builder_shared) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ReflectionAtlas *ra = reflection_atlas_owner.get_or_null(rpi->atlas);
+ if (!ra) {
+ ERR_PRINT("reflection probe has no reflection atlas! Bug?");
+ return nullptr;
+ } else {
+ if (ra->cluster_builder == nullptr) {
+ ra->cluster_builder = memnew(ClusterBuilderRD);
+ ra->cluster_builder->set_shared(p_cluster_builder_shared);
+ ra->cluster_builder->setup(Size2i(ra->size, ra->size), get_max_cluster_elements(), RID(), RID(), RID());
+ }
+ return ra->cluster_builder;
+ }
+}
+
+/* REFLECTION DATA */
+
+void LightStorage::free_reflection_data() {
+ if (reflection_buffer.is_valid()) {
+ RD::get_singleton()->free(reflection_buffer);
+ reflection_buffer = RID();
+ }
+
+ if (reflections != nullptr) {
+ memdelete_arr(reflections);
+ reflections = nullptr;
+ }
+
+ if (reflection_sort != nullptr) {
+ memdelete_arr(reflection_sort);
+ reflection_sort = nullptr;
+ }
+}
+
+void LightStorage::set_max_reflection_probes(const uint32_t p_max_reflection_probes) {
+ max_reflections = p_max_reflection_probes;
+ reflections = memnew_arr(ReflectionData, max_reflections);
+ reflection_sort = memnew_arr(ReflectionProbeInstanceSort, max_reflections);
+ reflection_buffer = RD::get_singleton()->storage_buffer_create(sizeof(ReflectionData) * max_reflections);
+}
+
+void LightStorage::update_reflection_probe_buffer(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment) {
+ ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton();
+
+ reflection_count = 0;
+
+ for (uint32_t i = 0; i < (uint32_t)p_reflections.size(); i++) {
+ if (reflection_count == max_reflections) {
+ break;
+ }
+
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_reflections[i]);
+ if (!rpi) {
+ continue;
+ }
+
+ Transform3D transform = rpi->transform;
+
+ reflection_sort[reflection_count].probe_instance = rpi;
+ reflection_sort[reflection_count].depth = -p_camera_inverse_transform.xform(transform.origin).z;
+ reflection_count++;
+ }
+
+ if (reflection_count > 0) {
+ SortArray<ReflectionProbeInstanceSort> sort_array;
+ sort_array.sort(reflection_sort, reflection_count);
+ }
+
+ bool using_forward_ids = forward_id_storage->uses_forward_ids();
+ for (uint32_t i = 0; i < reflection_count; i++) {
+ ReflectionProbeInstance *rpi = reflection_sort[i].probe_instance;
+
+ if (using_forward_ids) {
+ forward_id_storage->map_forward_id(FORWARD_ID_TYPE_REFLECTION_PROBE, rpi->forward_id, i);
+ }
+
+ ReflectionProbe *probe = reflection_probe_owner.get_or_null(rpi->probe);
+
+ ReflectionData &reflection_ubo = reflections[i];
+
+ Vector3 extents = probe->extents;
+
+ rpi->cull_mask = probe->cull_mask;
+
+ reflection_ubo.box_extents[0] = extents.x;
+ reflection_ubo.box_extents[1] = extents.y;
+ reflection_ubo.box_extents[2] = extents.z;
+ reflection_ubo.index = rpi->atlas_index;
+
+ Vector3 origin_offset = probe->origin_offset;
+
+ reflection_ubo.box_offset[0] = origin_offset.x;
+ reflection_ubo.box_offset[1] = origin_offset.y;
+ reflection_ubo.box_offset[2] = origin_offset.z;
+ reflection_ubo.mask = probe->cull_mask;
+
+ reflection_ubo.intensity = probe->intensity;
+ reflection_ubo.ambient_mode = probe->ambient_mode;
+
+ reflection_ubo.exterior = !probe->interior;
+ reflection_ubo.box_project = probe->box_projection;
+ reflection_ubo.exposure_normalization = 1.0;
+
+ if (p_render_data->camera_attributes.is_valid()) {
+ float exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_render_data->camera_attributes);
+ reflection_ubo.exposure_normalization = exposure / probe->baked_exposure;
+ }
+
+ Color ambient_linear = probe->ambient_color.srgb_to_linear();
+ float interior_ambient_energy = probe->ambient_color_energy;
+ reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy;
+ reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy;
+ reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy;
+
+ Transform3D transform = rpi->transform;
+ Transform3D proj = (p_camera_inverse_transform * transform).inverse();
+ MaterialStorage::store_transform(proj, reflection_ubo.local_matrix);
+
+ // hook for subclass to do further processing.
+ RendererSceneRenderRD::get_singleton()->setup_added_reflection_probe(transform, extents);
+
+ rpi->last_pass = RSG::rasterizer->get_frame_number();
+ }
+
+ if (reflection_count) {
+ RD::get_singleton()->buffer_update(reflection_buffer, 0, reflection_count * sizeof(ReflectionData), reflections, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
+ }
+}
+
/* LIGHTMAP API */
RID LightStorage::lightmap_allocate() {
@@ -619,7 +1716,7 @@ void LightStorage::lightmap_free(RID p_rid) {
}
void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_uses_spherical_haromics) {
- RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ TextureStorage *texture_storage = TextureStorage::get_singleton();
Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
@@ -628,17 +1725,17 @@ void LightStorage::lightmap_set_textures(RID p_lightmap, RID p_light, bool p_use
//erase lightmap users
if (lm->light_texture.is_valid()) {
- RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(lm->light_texture);
+ TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(lm->light_texture);
if (t) {
t->lightmap_users.erase(p_lightmap);
}
}
- RendererRD::Texture *t = RendererRD::TextureStorage::get_singleton()->get_texture(p_light);
+ TextureStorage::Texture *t = texture_storage->get_singleton()->get_texture(p_light);
lm->light_texture = p_light;
lm->uses_spherical_harmonics = p_uses_spherical_haromics;
- RID default_2d_array = texture_storage->texture_rd_get_default(RendererRD::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ RID default_2d_array = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
if (!t) {
if (using_lightmap_array) {
if (lm->array_index >= 0) {
@@ -696,6 +1793,13 @@ void LightStorage::lightmap_set_probe_capture_data(RID p_lightmap, const PackedV
lm->tetrahedra = p_tetrahedra;
}
+void LightStorage::lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!lm);
+
+ lm->baked_exposure = p_exposure;
+}
+
PackedVector3Array LightStorage::lightmap_get_probe_capture_points(RID p_lightmap) const {
Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND_V(!lm, PackedVector3Array());
@@ -725,6 +1829,13 @@ void LightStorage::lightmap_set_probe_capture_update_speed(float p_speed) {
lightmap_probe_capture_update_speed = p_speed;
}
+Dependency *LightStorage::lightmap_get_dependency(RID p_lightmap) const {
+ Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_NULL_V(lm, nullptr);
+
+ return &lm->dependency;
+}
+
void LightStorage::lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) {
Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
ERR_FAIL_COND(!lm);
@@ -786,3 +1897,550 @@ AABB LightStorage::lightmap_get_aabb(RID p_lightmap) const {
ERR_FAIL_COND_V(!lm, AABB());
return lm->bounds;
}
+
+/* LIGHTMAP INSTANCE */
+
+RID LightStorage::lightmap_instance_create(RID p_lightmap) {
+ LightmapInstance li;
+ li.lightmap = p_lightmap;
+ return lightmap_instance_owner.make_rid(li);
+}
+
+void LightStorage::lightmap_instance_free(RID p_lightmap) {
+ lightmap_instance_owner.free(p_lightmap);
+}
+
+void LightStorage::lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) {
+ LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND(!li);
+ li->transform = p_transform;
+}
+
+/* SHADOW ATLAS API */
+
+RID LightStorage::shadow_atlas_create() {
+ return shadow_atlas_owner.make_rid(ShadowAtlas());
+}
+
+void LightStorage::shadow_atlas_free(RID p_atlas) {
+ shadow_atlas_set_size(p_atlas, 0);
+ shadow_atlas_owner.free(p_atlas);
+}
+
+void LightStorage::_update_shadow_atlas(ShadowAtlas *shadow_atlas) {
+ if (shadow_atlas->size > 0 && shadow_atlas->depth.is_null()) {
+ RD::TextureFormat tf;
+ tf.format = shadow_atlas->use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT;
+ tf.width = shadow_atlas->size;
+ tf.height = shadow_atlas->size;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ Vector<RID> fb_tex;
+ fb_tex.push_back(shadow_atlas->depth);
+ shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+}
+
+void LightStorage::shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND(!shadow_atlas);
+ ERR_FAIL_COND(p_size < 0);
+ p_size = next_power_of_2(p_size);
+
+ if (p_size == shadow_atlas->size && p_16_bits == shadow_atlas->use_16_bits) {
+ return;
+ }
+
+ // erasing atlas
+ if (shadow_atlas->depth.is_valid()) {
+ RD::get_singleton()->free(shadow_atlas->depth);
+ shadow_atlas->depth = RID();
+ }
+ for (int i = 0; i < 4; i++) {
+ //clear subdivisions
+ shadow_atlas->quadrants[i].shadows.clear();
+ shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision);
+ }
+
+ //erase shadow atlas reference from lights
+ for (const KeyValue<RID, uint32_t> &E : shadow_atlas->shadow_owners) {
+ LightInstance *li = light_instance_owner.get_or_null(E.key);
+ ERR_CONTINUE(!li);
+ li->shadow_atlases.erase(p_atlas);
+ }
+
+ //clear owners
+ shadow_atlas->shadow_owners.clear();
+
+ shadow_atlas->size = p_size;
+ shadow_atlas->use_16_bits = p_16_bits;
+}
+
+void LightStorage::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND(!shadow_atlas);
+ ERR_FAIL_INDEX(p_quadrant, 4);
+ ERR_FAIL_INDEX(p_subdivision, 16384);
+
+ uint32_t subdiv = next_power_of_2(p_subdivision);
+ if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer
+ subdiv <<= 1;
+ }
+
+ subdiv = int(Math::sqrt((float)subdiv));
+
+ //obtain the number that will be x*x
+
+ if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) {
+ return;
+ }
+
+ //erase all data from quadrant
+ for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) {
+ if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) {
+ shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
+ LightInstance *li = light_instance_owner.get_or_null(shadow_atlas->quadrants[p_quadrant].shadows[i].owner);
+ ERR_CONTINUE(!li);
+ li->shadow_atlases.erase(p_atlas);
+ }
+ }
+
+ shadow_atlas->quadrants[p_quadrant].shadows.clear();
+ shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv);
+ shadow_atlas->quadrants[p_quadrant].subdivision = subdiv;
+
+ //cache the smallest subdiv (for faster allocation in light update)
+
+ shadow_atlas->smallest_subdiv = 1 << 30;
+
+ for (int i = 0; i < 4; i++) {
+ if (shadow_atlas->quadrants[i].subdivision) {
+ shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision);
+ }
+ }
+
+ if (shadow_atlas->smallest_subdiv == 1 << 30) {
+ shadow_atlas->smallest_subdiv = 0;
+ }
+
+ //resort the size orders, simple bublesort for 4 elements..
+
+ int swaps = 0;
+ do {
+ swaps = 0;
+
+ for (int i = 0; i < 3; i++) {
+ if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) {
+ SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]);
+ swaps++;
+ }
+ }
+ } while (swaps > 0);
+}
+
+bool LightStorage::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) {
+ for (int i = p_quadrant_count - 1; i >= 0; i--) {
+ int qidx = p_in_quadrants[i];
+
+ if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
+ return false;
+ }
+
+ //look for an empty space
+ int sc = shadow_atlas->quadrants[qidx].shadows.size();
+ const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr();
+
+ int found_free_idx = -1; //found a free one
+ int found_used_idx = -1; //found existing one, must steal it
+ uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion)
+
+ for (int j = 0; j < sc; j++) {
+ if (!sarr[j].owner.is_valid()) {
+ found_free_idx = j;
+ break;
+ }
+
+ LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
+ ERR_CONTINUE(!sli);
+
+ if (sli->last_scene_pass != RendererSceneRenderRD::get_singleton()->get_scene_pass()) {
+ //was just allocated, don't kill it so soon, wait a bit..
+ if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
+ continue;
+ }
+
+ if (found_used_idx == -1 || sli->last_scene_pass < min_pass) {
+ found_used_idx = j;
+ min_pass = sli->last_scene_pass;
+ }
+ }
+ }
+
+ if (found_free_idx == -1 && found_used_idx == -1) {
+ continue; //nothing found
+ }
+
+ if (found_free_idx == -1 && found_used_idx != -1) {
+ found_free_idx = found_used_idx;
+ }
+
+ r_quadrant = qidx;
+ r_shadow = found_free_idx;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool LightStorage::_shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) {
+ for (int i = p_quadrant_count - 1; i >= 0; i--) {
+ int qidx = p_in_quadrants[i];
+
+ if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) {
+ return false;
+ }
+
+ //look for an empty space
+ int sc = shadow_atlas->quadrants[qidx].shadows.size();
+ const ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptr();
+
+ int found_idx = -1;
+ uint64_t min_pass = 0; // sum of currently selected spots, try to get the least recently used pair
+
+ for (int j = 0; j < sc - 1; j++) {
+ uint64_t pass = 0;
+
+ if (sarr[j].owner.is_valid()) {
+ LightInstance *sli = light_instance_owner.get_or_null(sarr[j].owner);
+ ERR_CONTINUE(!sli);
+
+ if (sli->last_scene_pass == RendererSceneRenderRD::get_singleton()->get_scene_pass()) {
+ continue;
+ }
+
+ //was just allocated, don't kill it so soon, wait a bit..
+ if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
+ continue;
+ }
+ pass += sli->last_scene_pass;
+ }
+
+ if (sarr[j + 1].owner.is_valid()) {
+ LightInstance *sli = light_instance_owner.get_or_null(sarr[j + 1].owner);
+ ERR_CONTINUE(!sli);
+
+ if (sli->last_scene_pass == RendererSceneRenderRD::get_singleton()->get_scene_pass()) {
+ continue;
+ }
+
+ //was just allocated, don't kill it so soon, wait a bit..
+ if (p_tick - sarr[j + 1].alloc_tick < shadow_atlas_realloc_tolerance_msec) {
+ continue;
+ }
+ pass += sli->last_scene_pass;
+ }
+
+ if (found_idx == -1 || pass < min_pass) {
+ found_idx = j;
+ min_pass = pass;
+
+ // we found two empty spots, no need to check the rest
+ if (pass == 0) {
+ break;
+ }
+ }
+ }
+
+ if (found_idx == -1) {
+ continue; //nothing found
+ }
+
+ r_quadrant = qidx;
+ r_shadow = found_idx;
+
+ return true;
+ }
+
+ return false;
+}
+
+bool LightStorage::shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!shadow_atlas, false);
+
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND_V(!li, false);
+
+ if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) {
+ return false;
+ }
+
+ uint32_t quad_size = shadow_atlas->size >> 1;
+ int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage));
+
+ int valid_quadrants[4];
+ int valid_quadrant_count = 0;
+ int best_size = -1; //best size found
+ int best_subdiv = -1; //subdiv for the best size
+
+ //find the quadrants this fits into, and the best possible size it can fit into
+ for (int i = 0; i < 4; i++) {
+ int q = shadow_atlas->size_order[i];
+ int sd = shadow_atlas->quadrants[q].subdivision;
+ if (sd == 0) {
+ continue; //unused
+ }
+
+ int max_fit = quad_size / sd;
+
+ if (best_size != -1 && max_fit > best_size) {
+ break; //too large
+ }
+
+ valid_quadrants[valid_quadrant_count++] = q;
+ best_subdiv = sd;
+
+ if (max_fit >= desired_fit) {
+ best_size = max_fit;
+ }
+ }
+
+ ERR_FAIL_COND_V(valid_quadrant_count == 0, false);
+
+ uint64_t tick = OS::get_singleton()->get_ticks_msec();
+
+ uint32_t old_key = SHADOW_INVALID;
+ uint32_t old_quadrant = SHADOW_INVALID;
+ uint32_t old_shadow = SHADOW_INVALID;
+ int old_subdivision = -1;
+
+ bool should_realloc = false;
+ bool should_redraw = false;
+
+ if (shadow_atlas->shadow_owners.has(p_light_instance)) {
+ old_key = shadow_atlas->shadow_owners[p_light_instance];
+ old_quadrant = (old_key >> QUADRANT_SHIFT) & 0x3;
+ old_shadow = old_key & SHADOW_INDEX_MASK;
+
+ should_realloc = shadow_atlas->quadrants[old_quadrant].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec);
+ should_redraw = shadow_atlas->quadrants[old_quadrant].shadows[old_shadow].version != p_light_version;
+
+ if (!should_realloc) {
+ shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = p_light_version;
+ //already existing, see if it should redraw or it's just OK
+ return should_redraw;
+ }
+
+ old_subdivision = shadow_atlas->quadrants[old_quadrant].subdivision;
+ }
+
+ bool is_omni = li->light_type == RS::LIGHT_OMNI;
+ bool found_shadow = false;
+ int new_quadrant = -1;
+ int new_shadow = -1;
+
+ if (is_omni) {
+ found_shadow = _shadow_atlas_find_omni_shadows(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow);
+ } else {
+ found_shadow = _shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, old_subdivision, tick, new_quadrant, new_shadow);
+ }
+
+ if (found_shadow) {
+ if (old_quadrant != SHADOW_INVALID) {
+ shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].version = 0;
+ shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow].owner = RID();
+
+ if (old_key & OMNI_LIGHT_FLAG) {
+ shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].version = 0;
+ shadow_atlas->quadrants[old_quadrant].shadows.write[old_shadow + 1].owner = RID();
+ }
+ }
+
+ uint32_t new_key = new_quadrant << QUADRANT_SHIFT;
+ new_key |= new_shadow;
+
+ ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow];
+ _shadow_atlas_invalidate_shadow(sh, p_atlas, shadow_atlas, new_quadrant, new_shadow);
+
+ sh->owner = p_light_instance;
+ sh->alloc_tick = tick;
+ sh->version = p_light_version;
+
+ if (is_omni) {
+ new_key |= OMNI_LIGHT_FLAG;
+
+ int new_omni_shadow = new_shadow + 1;
+ ShadowAtlas::Quadrant::Shadow *extra_sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_omni_shadow];
+ _shadow_atlas_invalidate_shadow(extra_sh, p_atlas, shadow_atlas, new_quadrant, new_omni_shadow);
+
+ extra_sh->owner = p_light_instance;
+ extra_sh->alloc_tick = tick;
+ extra_sh->version = p_light_version;
+ }
+
+ li->shadow_atlases.insert(p_atlas);
+
+ //update it in map
+ shadow_atlas->shadow_owners[p_light_instance] = new_key;
+ //make it dirty, as it should redraw anyway
+ return true;
+ }
+
+ return should_redraw;
+}
+
+void LightStorage::_shadow_atlas_invalidate_shadow(ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx) {
+ if (p_shadow->owner.is_valid()) {
+ LightInstance *sli = light_instance_owner.get_or_null(p_shadow->owner);
+ uint32_t old_key = p_shadow_atlas->shadow_owners[p_shadow->owner];
+
+ if (old_key & OMNI_LIGHT_FLAG) {
+ uint32_t s = old_key & SHADOW_INDEX_MASK;
+ uint32_t omni_shadow_idx = p_shadow_idx + (s == (uint32_t)p_shadow_idx ? 1 : -1);
+ ShadowAtlas::Quadrant::Shadow *omni_shadow = &p_shadow_atlas->quadrants[p_quadrant].shadows.write[omni_shadow_idx];
+ omni_shadow->version = 0;
+ omni_shadow->owner = RID();
+ }
+
+ p_shadow_atlas->shadow_owners.erase(p_shadow->owner);
+ p_shadow->version = 0;
+ p_shadow->owner = RID();
+ sli->shadow_atlases.erase(p_atlas);
+ }
+}
+
+void LightStorage::shadow_atlas_update(RID p_atlas) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND(!shadow_atlas);
+
+ _update_shadow_atlas(shadow_atlas);
+}
+
+/* DIRECTIONAL SHADOW */
+
+void LightStorage::update_directional_shadow_atlas() {
+ if (directional_shadow.depth.is_null() && directional_shadow.size > 0) {
+ RD::TextureFormat tf;
+ tf.format = directional_shadow.use_16_bits ? RD::DATA_FORMAT_D16_UNORM : RD::DATA_FORMAT_D32_SFLOAT;
+ tf.width = directional_shadow.size;
+ tf.height = directional_shadow.size;
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ Vector<RID> fb_tex;
+ fb_tex.push_back(directional_shadow.depth);
+ directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb_tex);
+ }
+}
+void LightStorage::directional_shadow_atlas_set_size(int p_size, bool p_16_bits) {
+ p_size = nearest_power_of_2_templated(p_size);
+
+ if (directional_shadow.size == p_size && directional_shadow.use_16_bits == p_16_bits) {
+ return;
+ }
+
+ directional_shadow.size = p_size;
+ directional_shadow.use_16_bits = p_16_bits;
+
+ if (directional_shadow.depth.is_valid()) {
+ RD::get_singleton()->free(directional_shadow.depth);
+ directional_shadow.depth = RID();
+ RendererSceneRenderRD::get_singleton()->base_uniforms_changed();
+ }
+}
+
+void LightStorage::set_directional_shadow_count(int p_count) {
+ directional_shadow.light_count = p_count;
+ directional_shadow.current_light = 0;
+}
+
+static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) {
+ int split_h = 1;
+ int split_v = 1;
+
+ while (split_h * split_v < p_shadow_count) {
+ if (split_h == split_v) {
+ split_h <<= 1;
+ } else {
+ split_v <<= 1;
+ }
+ }
+
+ Rect2i rect(0, 0, p_size, p_size);
+ rect.size.width /= split_h;
+ rect.size.height /= split_v;
+
+ rect.position.x = rect.size.width * (p_shadow_index % split_h);
+ rect.position.y = rect.size.height * (p_shadow_index / split_h);
+
+ return rect;
+}
+
+Rect2i LightStorage::get_directional_shadow_rect() {
+ return _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light);
+}
+
+int LightStorage::get_directional_light_shadow_size(RID p_light_intance) {
+ ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0);
+
+ Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0);
+
+ LightInstance *light_instance = light_instance_owner.get_or_null(p_light_intance);
+ ERR_FAIL_COND_V(!light_instance, 0);
+
+ switch (light_directional_get_shadow_mode(light_instance->light)) {
+ case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL:
+ break; //none
+ case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS:
+ r.size.height /= 2;
+ break;
+ case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS:
+ r.size /= 2;
+ break;
+ }
+
+ return MAX(r.size.width, r.size.height);
+}
+
+/* SHADOW CUBEMAPS */
+
+LightStorage::ShadowCubemap *LightStorage::_get_shadow_cubemap(int p_size) {
+ if (!shadow_cubemaps.has(p_size)) {
+ ShadowCubemap sc;
+ {
+ RD::TextureFormat tf;
+ tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32;
+ tf.width = p_size;
+ tf.height = p_size;
+ tf.texture_type = RD::TEXTURE_TYPE_CUBE;
+ tf.array_layers = 6;
+ tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT;
+ sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView());
+ }
+
+ for (int i = 0; i < 6; i++) {
+ RID side_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sc.cubemap, i, 0);
+ Vector<RID> fbtex;
+ fbtex.push_back(side_texture);
+ sc.side_fb[i] = RD::get_singleton()->framebuffer_create(fbtex);
+ }
+
+ shadow_cubemaps[p_size] = sc;
+ }
+
+ return &shadow_cubemaps[p_size];
+}
+
+RID LightStorage::get_cubemap(int p_size) {
+ ShadowCubemap *cubemap = _get_shadow_cubemap(p_size);
+
+ return cubemap->cubemap;
+}
+
+RID LightStorage::get_cubemap_fb(int p_size, int p_pass) {
+ ShadowCubemap *cubemap = _get_shadow_cubemap(p_size);
+
+ return cubemap->side_fb[p_pass];
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.h b/servers/rendering/renderer_rd/storage_rd/light_storage.h
index 3cc455692d..79006ad982 100644
--- a/servers/rendering/renderer_rd/storage_rd/light_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/light_storage.h
@@ -32,93 +32,318 @@
#define LIGHT_STORAGE_RD_H
#include "core/templates/local_vector.h"
+#include "core/templates/paged_array.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
+#include "servers/rendering/renderer_rd/cluster_builder_rd.h"
+#include "servers/rendering/renderer_rd/environment/sky.h"
+#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
#include "servers/rendering/storage/light_storage.h"
+#include "servers/rendering/storage/utilities.h"
-namespace RendererRD {
-
-/* LIGHT */
-
-struct Light {
- RS::LightType type;
- float param[RS::LIGHT_PARAM_MAX];
- Color color = Color(1, 1, 1, 1);
- RID projector;
- bool shadow = false;
- bool negative = false;
- bool reverse_cull = false;
- RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
- uint32_t max_sdfgi_cascade = 2;
- uint32_t cull_mask = 0xFFFFFFFF;
- bool distance_fade = false;
- real_t distance_fade_begin = 40.0;
- real_t distance_fade_shadow = 50.0;
- real_t distance_fade_length = 10.0;
- RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
- RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
- bool directional_blend_splits = false;
- RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
- uint64_t version = 0;
-
- RendererStorage::Dependency dependency;
-};
+struct RenderDataRD;
-/* REFLECTION PROBE */
-
-struct ReflectionProbe {
- RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
- int resolution = 256;
- float intensity = 1.0;
- RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
- Color ambient_color;
- float ambient_color_energy = 1.0;
- float max_distance = 0;
- Vector3 extents = Vector3(1, 1, 1);
- Vector3 origin_offset;
- bool interior = false;
- bool box_projection = false;
- bool enable_shadows = false;
- uint32_t cull_mask = (1 << 20) - 1;
- float mesh_lod_threshold = 0.01;
-
- RendererStorage::Dependency dependency;
-};
+namespace RendererRD {
-/* LIGHTMAP */
-
-struct Lightmap {
- RID light_texture;
- bool uses_spherical_harmonics = false;
- bool interior = false;
- AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
- int32_t array_index = -1; //unassigned
- PackedVector3Array points;
- PackedColorArray point_sh;
- PackedInt32Array tetrahedra;
- PackedInt32Array bsp_tree;
-
- struct BSP {
- static const int32_t EMPTY_LEAF = INT32_MIN;
- float plane[4];
- int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+class LightStorage : public RendererLightStorage {
+public:
+ enum ShadowAtlastQuadrant {
+ QUADRANT_SHIFT = 27,
+ OMNI_LIGHT_FLAG = 1 << 26,
+ SHADOW_INDEX_MASK = OMNI_LIGHT_FLAG - 1,
+ SHADOW_INVALID = 0xFFFFFFFF
};
- RendererStorage::Dependency dependency;
-};
-
-class LightStorage : public RendererLightStorage {
private:
static LightStorage *singleton;
+ uint32_t max_cluster_elements = 512;
/* LIGHT */
+ struct Light {
+ RS::LightType type;
+ float param[RS::LIGHT_PARAM_MAX];
+ Color color = Color(1, 1, 1, 1);
+ RID projector;
+ bool shadow = false;
+ bool negative = false;
+ bool reverse_cull = false;
+ RS::LightBakeMode bake_mode = RS::LIGHT_BAKE_DYNAMIC;
+ uint32_t max_sdfgi_cascade = 2;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ bool distance_fade = false;
+ real_t distance_fade_begin = 40.0;
+ real_t distance_fade_shadow = 50.0;
+ real_t distance_fade_length = 10.0;
+ RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID;
+ RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
+ bool directional_blend_splits = false;
+ RS::LightDirectionalSkyMode directional_sky_mode = RS::LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_AND_SKY;
+ uint64_t version = 0;
+
+ Dependency dependency;
+ };
+
mutable RID_Owner<Light, true> light_owner;
+ /* LIGHT INSTANCE */
+
+ struct LightInstance {
+ struct ShadowTransform {
+ Projection camera;
+ Transform3D transform;
+ float farplane;
+ float split;
+ float bias_scale;
+ float shadow_texel_size;
+ float range_begin;
+ Rect2 atlas_rect;
+ Vector2 uv_scale;
+ };
+
+ RS::LightType light_type = RS::LIGHT_DIRECTIONAL;
+
+ ShadowTransform shadow_transform[6];
+
+ AABB aabb;
+ RID self;
+ RID light;
+ Transform3D transform;
+
+ Vector3 light_vector;
+ Vector3 spot_vector;
+ float linear_att = 0.0;
+
+ uint64_t shadow_pass = 0;
+ uint64_t last_scene_pass = 0;
+ uint64_t last_scene_shadow_pass = 0;
+ uint64_t last_pass = 0;
+ uint32_t cull_mask = 0;
+ uint32_t light_directional_index = 0;
+
+ Rect2 directional_rect;
+
+ HashSet<RID> shadow_atlases; //shadow atlases where this light is registered
+
+ ForwardID forward_id = -1;
+
+ LightInstance() {}
+ };
+
+ mutable RID_Owner<LightInstance> light_instance_owner;
+
+ /* OMNI/SPOT LIGHT DATA */
+
+ struct LightData {
+ float position[3];
+ float inv_radius;
+ float direction[3]; // in omni, x and y are used for dual paraboloid offset
+ float size;
+
+ float color[3];
+ float attenuation;
+
+ float inv_spot_attenuation;
+ float cos_spot_angle;
+ float specular_amount;
+ float shadow_opacity;
+
+ float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv
+ float shadow_matrix[16];
+ float shadow_bias;
+ float shadow_normal_bias;
+ float transmittance_bias;
+ float soft_shadow_size;
+ float soft_shadow_scale;
+ uint32_t mask;
+ float volumetric_fog_energy;
+ uint32_t bake_mode;
+ float projector_rect[4];
+ };
+
+ struct LightInstanceDepthSort {
+ float depth;
+ LightInstance *light_instance;
+ Light *light;
+ bool operator<(const LightInstanceDepthSort &p_sort) const {
+ return depth < p_sort.depth;
+ }
+ };
+
+ uint32_t max_lights;
+ uint32_t omni_light_count = 0;
+ uint32_t spot_light_count = 0;
+ LightData *omni_lights = nullptr;
+ LightData *spot_lights = nullptr;
+ LightInstanceDepthSort *omni_light_sort = nullptr;
+ LightInstanceDepthSort *spot_light_sort = nullptr;
+ RID omni_light_buffer;
+ RID spot_light_buffer;
+
+ /* DIRECTIONAL LIGHT DATA */
+
+ struct DirectionalLightData {
+ float direction[3];
+ float energy;
+ float color[3];
+ float size;
+ float specular;
+ uint32_t mask;
+ float softshadow_angle;
+ float soft_shadow_scale;
+ uint32_t blend_splits;
+ float shadow_opacity;
+ float fade_from;
+ float fade_to;
+ uint32_t pad[2];
+ uint32_t bake_mode;
+ float volumetric_fog_energy;
+ float shadow_bias[4];
+ float shadow_normal_bias[4];
+ float shadow_transmittance_bias[4];
+ float shadow_z_range[4];
+ float shadow_range_begin[4];
+ float shadow_split_offsets[4];
+ float shadow_matrices[4][16];
+ float uv_scale1[2];
+ float uv_scale2[2];
+ float uv_scale3[2];
+ float uv_scale4[2];
+ };
+
+ uint32_t max_directional_lights;
+ DirectionalLightData *directional_lights = nullptr;
+ RID directional_light_buffer;
+
/* REFLECTION PROBE */
+
+ struct ReflectionProbe {
+ RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE;
+ int resolution = 256;
+ float intensity = 1.0;
+ RS::ReflectionProbeAmbientMode ambient_mode = RS::REFLECTION_PROBE_AMBIENT_ENVIRONMENT;
+ Color ambient_color;
+ float ambient_color_energy = 1.0;
+ float max_distance = 0;
+ Vector3 extents = Vector3(1, 1, 1);
+ Vector3 origin_offset;
+ bool interior = false;
+ bool box_projection = false;
+ bool enable_shadows = false;
+ uint32_t cull_mask = (1 << 20) - 1;
+ float mesh_lod_threshold = 0.01;
+ float baked_exposure = 1.0;
+
+ Dependency dependency;
+ };
mutable RID_Owner<ReflectionProbe, true> reflection_probe_owner;
+ /* REFLECTION ATLAS */
+
+ struct ReflectionAtlas {
+ int count = 0;
+ int size = 0;
+
+ RID reflection;
+ RID depth_buffer;
+ RID depth_fb;
+
+ struct Reflection {
+ RID owner;
+ RendererRD::SkyRD::ReflectionData data;
+ RID fbs[6];
+ };
+
+ Vector<Reflection> reflections;
+
+ ClusterBuilderRD *cluster_builder = nullptr; // only used if cluster builder is supported by the renderer.
+ };
+
+ mutable RID_Owner<ReflectionAtlas> reflection_atlas_owner;
+
+ /* REFLECTION PROBE INSTANCE */
+
+ struct ReflectionProbeInstance {
+ RID probe;
+ int atlas_index = -1;
+ RID atlas;
+
+ bool dirty = true;
+ bool rendering = false;
+ int processing_layer = 1;
+ int processing_side = 0;
+
+ uint32_t render_step = 0;
+ uint64_t last_pass = 0;
+ uint32_t cull_mask = 0;
+
+ RendererRD::ForwardID forward_id = -1;
+
+ Transform3D transform;
+ };
+
+ mutable RID_Owner<ReflectionProbeInstance> reflection_probe_instance_owner;
+
+ /* REFLECTION DATA */
+
+ enum {
+ REFLECTION_AMBIENT_DISABLED = 0,
+ REFLECTION_AMBIENT_ENVIRONMENT = 1,
+ REFLECTION_AMBIENT_COLOR = 2,
+ };
+
+ struct ReflectionData {
+ float box_extents[3];
+ float index;
+ float box_offset[3];
+ uint32_t mask;
+ float ambient[3]; // ambient color,
+ float intensity;
+ uint32_t exterior;
+ uint32_t box_project;
+ uint32_t ambient_mode;
+ float exposure_normalization;
+ float local_matrix[16]; // up to here for spot and omni, rest is for directional
+ };
+
+ struct ReflectionProbeInstanceSort {
+ float depth;
+ ReflectionProbeInstance *probe_instance;
+ bool operator<(const ReflectionProbeInstanceSort &p_sort) const {
+ return depth < p_sort.depth;
+ }
+ };
+
+ uint32_t max_reflections;
+ uint32_t reflection_count = 0;
+ // uint32_t max_reflection_probes_per_instance = 0; // seems unused
+ ReflectionData *reflections = nullptr;
+ ReflectionProbeInstanceSort *reflection_sort = nullptr;
+ RID reflection_buffer;
+
/* LIGHTMAP */
+ struct Lightmap {
+ RID light_texture;
+ bool uses_spherical_harmonics = false;
+ bool interior = false;
+ AABB bounds = AABB(Vector3(), Vector3(1, 1, 1));
+ float baked_exposure = 1.0;
+ int32_t array_index = -1; //unassigned
+ PackedVector3Array points;
+ PackedColorArray point_sh;
+ PackedInt32Array tetrahedra;
+ PackedInt32Array bsp_tree;
+
+ struct BSP {
+ static const int32_t EMPTY_LEAF = INT32_MIN;
+ float plane[4];
+ int32_t over = EMPTY_LEAF, under = EMPTY_LEAF;
+ };
+
+ Dependency dependency;
+ };
+
bool using_lightmap_array;
Vector<RID> lightmap_textures;
uint64_t lightmap_array_version = 0;
@@ -126,15 +351,103 @@ private:
mutable RID_Owner<Lightmap, true> lightmap_owner;
+ /* LIGHTMAP INSTANCE */
+
+ struct LightmapInstance {
+ RID lightmap;
+ Transform3D transform;
+ };
+
+ mutable RID_Owner<LightmapInstance> lightmap_instance_owner;
+
+ /* SHADOW ATLAS */
+
+ uint64_t shadow_atlas_realloc_tolerance_msec = 500;
+
+ struct ShadowShrinkStage {
+ RID texture;
+ RID filter_texture;
+ uint32_t size = 0;
+ };
+
+ struct ShadowAtlas {
+ struct Quadrant {
+ uint32_t subdivision = 0;
+
+ struct Shadow {
+ RID owner;
+ uint64_t version = 0;
+ uint64_t fog_version = 0; // used for fog
+ uint64_t alloc_tick = 0;
+
+ Shadow() {}
+ };
+
+ Vector<Shadow> shadows;
+
+ Quadrant() {}
+ } quadrants[4];
+
+ int size_order[4] = { 0, 1, 2, 3 };
+ uint32_t smallest_subdiv = 0;
+
+ int size = 0;
+ bool use_16_bits = true;
+
+ RID depth;
+ RID fb; //for copying
+
+ HashMap<RID, uint32_t> shadow_owners;
+ };
+
+ RID_Owner<ShadowAtlas> shadow_atlas_owner;
+
+ void _update_shadow_atlas(ShadowAtlas *shadow_atlas);
+
+ void _shadow_atlas_invalidate_shadow(ShadowAtlas::Quadrant::Shadow *p_shadow, RID p_atlas, ShadowAtlas *p_shadow_atlas, uint32_t p_quadrant, uint32_t p_shadow_idx);
+ bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
+ bool _shadow_atlas_find_omni_shadows(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow);
+
+ /* DIRECTIONAL SHADOW */
+
+ struct DirectionalShadow {
+ RID depth;
+ RID fb; //when renderign direct
+
+ int light_count = 0;
+ int size = 0;
+ bool use_16_bits = true;
+ int current_light = 0;
+ } directional_shadow;
+
+ /* SHADOW CUBEMAPS */
+
+ struct ShadowCubemap {
+ RID cubemap;
+ RID side_fb[6];
+ };
+
+ HashMap<int, ShadowCubemap> shadow_cubemaps;
+ ShadowCubemap *_get_shadow_cubemap(int p_size);
+
public:
static LightStorage *get_singleton();
LightStorage();
virtual ~LightStorage();
+ bool free(RID p_rid);
+
+ /* Settings */
+ void set_max_cluster_elements(const uint32_t p_max_cluster_elements) {
+ max_cluster_elements = p_max_cluster_elements;
+ set_max_reflection_probes(p_max_cluster_elements);
+ set_max_lights(p_max_cluster_elements);
+ }
+ uint32_t get_max_cluster_elements() const { return max_cluster_elements; }
+
/* LIGHT */
- Light *get_light(RID p_rid) { return light_owner.get_or_null(p_rid); };
bool owns_light(RID p_rid) { return light_owner.owns(p_rid); };
void _light_initialize(RID p_rid, RS::LightType p_type);
@@ -239,7 +552,7 @@ public:
const Light *light = light_owner.get_or_null(p_light);
ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL);
- return light_owner.owns(light->projector);
+ return TextureStorage::get_singleton()->owns_texture(light->projector);
}
_FORCE_INLINE_ bool light_is_negative(RID p_light) const {
@@ -256,20 +569,213 @@ public:
return light->param[RS::LIGHT_PARAM_TRANSMITTANCE_BIAS];
}
- _FORCE_INLINE_ float light_get_shadow_volumetric_fog_fade(RID p_light) const {
- const Light *light = light_owner.get_or_null(p_light);
- ERR_FAIL_COND_V(!light, 0.0);
-
- return light->param[RS::LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE];
- }
-
virtual RS::LightBakeMode light_get_bake_mode(RID p_light) override;
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) override;
virtual uint64_t light_get_version(RID p_light) const override;
+ Dependency *light_get_dependency(RID p_light) const;
+
+ /* LIGHT INSTANCE API */
+
+ bool owns_light_instance(RID p_rid) { return light_instance_owner.owns(p_rid); };
+
+ virtual RID light_instance_create(RID p_light) override;
+ virtual void light_instance_free(RID p_light) override;
+ virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) override;
+ virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) override;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) override;
+ virtual void light_instance_mark_visible(RID p_light_instance) override;
+
+ _FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->light;
+ }
+
+ _FORCE_INLINE_ Transform3D light_instance_get_base_transform(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->transform;
+ }
+
+ _FORCE_INLINE_ AABB light_instance_get_base_aabb(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->aabb;
+ }
+
+ _FORCE_INLINE_ void light_instance_set_cull_mask(RID p_light_instance, uint32_t p_cull_mask) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ li->cull_mask = p_cull_mask;
+ }
+
+ _FORCE_INLINE_ uint32_t light_instance_get_cull_mask(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->cull_mask;
+ }
+
+ _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas, Vector2i &r_omni_offset) {
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ uint32_t key = shadow_atlas->shadow_owners[li->self];
+
+ uint32_t quadrant = (key >> QUADRANT_SHIFT) & 0x3;
+ uint32_t shadow = key & SHADOW_INDEX_MASK;
+
+ ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2());
+
+ uint32_t atlas_size = shadow_atlas->size;
+ uint32_t quadrant_size = atlas_size >> 1;
+
+ uint32_t x = (quadrant & 1) * quadrant_size;
+ uint32_t y = (quadrant >> 1) * quadrant_size;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+ x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+ y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size;
+
+ if (key & OMNI_LIGHT_FLAG) {
+ if (((shadow + 1) % shadow_atlas->quadrants[quadrant].subdivision) == 0) {
+ r_omni_offset.x = 1 - int(shadow_atlas->quadrants[quadrant].subdivision);
+ r_omni_offset.y = 1;
+ } else {
+ r_omni_offset.x = 1;
+ r_omni_offset.y = 0;
+ }
+ }
+
+ uint32_t width = shadow_size;
+ uint32_t height = shadow_size;
+
+ return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size));
+ }
+
+ _FORCE_INLINE_ float light_instance_get_shadow_texel_size(RID p_light_instance, RID p_shadow_atlas) {
+#ifdef DEBUG_ENABLED
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ ERR_FAIL_COND_V(!li->shadow_atlases.has(p_shadow_atlas), 0);
+#endif
+ ShadowAtlas *shadow_atlas = shadow_atlas_owner.get_or_null(p_shadow_atlas);
+ ERR_FAIL_COND_V(!shadow_atlas, 0);
+#ifdef DEBUG_ENABLED
+ ERR_FAIL_COND_V(!shadow_atlas->shadow_owners.has(p_light_instance), 0);
+#endif
+ uint32_t key = shadow_atlas->shadow_owners[p_light_instance];
+
+ uint32_t quadrant = (key >> QUADRANT_SHIFT) & 0x3;
+
+ uint32_t quadrant_size = shadow_atlas->size >> 1;
+
+ uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision);
+
+ return float(1.0) / shadow_size;
+ }
+
+ _FORCE_INLINE_ Projection light_instance_get_shadow_camera(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].camera;
+ }
+
+ _FORCE_INLINE_ Transform3D
+ light_instance_get_shadow_transform(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].transform;
+ }
+ _FORCE_INLINE_ float light_instance_get_shadow_bias_scale(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].bias_scale;
+ }
+ _FORCE_INLINE_ float light_instance_get_shadow_range(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].farplane;
+ }
+ _FORCE_INLINE_ float light_instance_get_shadow_range_begin(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].range_begin;
+ }
+
+ _FORCE_INLINE_ Vector2 light_instance_get_shadow_uv_scale(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].uv_scale;
+ }
+
+ _FORCE_INLINE_ void light_instance_set_directional_shadow_atlas_rect(RID p_light_instance, int p_index, const Rect2 p_atlas_rect) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ li->shadow_transform[p_index].atlas_rect = p_atlas_rect;
+ }
+
+ _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].atlas_rect;
+ }
+
+ _FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].split;
+ }
+
+ _FORCE_INLINE_ float light_instance_get_directional_shadow_texel_size(RID p_light_instance, int p_index) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->shadow_transform[p_index].shadow_texel_size;
+ }
+
+ _FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ li->last_pass = p_pass;
+ }
+
+ _FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->last_pass;
+ }
+
+ _FORCE_INLINE_ void light_instance_set_shadow_pass(RID p_light_instance, uint64_t p_pass) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ li->last_scene_shadow_pass = p_pass;
+ }
+
+ _FORCE_INLINE_ uint64_t light_instance_get_shadow_pass(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->last_scene_shadow_pass;
+ }
+
+ _FORCE_INLINE_ ForwardID light_instance_get_forward_id(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->forward_id;
+ }
+
+ _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->light_type;
+ }
+
+ _FORCE_INLINE_ void light_instance_set_directional_rect(RID p_light_instance, const Rect2 &p_directional_rect) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ li->directional_rect = p_directional_rect;
+ }
+
+ _FORCE_INLINE_ Rect2 light_instance_get_directional_rect(RID p_light_instance) {
+ LightInstance *li = light_instance_owner.get_or_null(p_light_instance);
+ return li->directional_rect;
+ }
+
+ /* LIGHT DATA */
+
+ void free_light_data();
+ void set_max_lights(const uint32_t p_max_lights);
+ RID get_omni_light_buffer() { return omni_light_buffer; }
+ RID get_spot_light_buffer() { return spot_light_buffer; }
+ RID get_directional_light_buffer() { return directional_light_buffer; }
+ uint32_t get_max_directional_lights() { return max_directional_lights; }
+ bool has_directional_shadows(const uint32_t p_directional_light_count) {
+ for (uint32_t i = 0; i < p_directional_light_count; i++) {
+ if (directional_lights[i].shadow_opacity > 0.001) {
+ return true;
+ }
+ }
+ return false;
+ }
+ void update_light_buffers(RenderDataRD *p_render_data, const PagedArray<RID> &p_lights, const Transform3D &p_camera_transform, RID p_shadow_atlas, bool p_using_shadows, uint32_t &r_directional_light_count, uint32_t &r_positional_light_count, bool &r_directional_light_soft_shadows);
+
/* REFLECTION PROBE */
- ReflectionProbe *get_reflection_probe(RID p_rid) { return reflection_probe_owner.get_or_null(p_rid); };
bool owns_reflection_probe(RID p_rid) { return reflection_probe_owner.owns(p_rid); };
virtual RID reflection_probe_allocate() override;
@@ -291,6 +797,8 @@ public:
virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) override;
virtual void reflection_probe_set_mesh_lod_threshold(RID p_probe, float p_ratio) override;
+ void reflection_probe_set_baked_exposure(RID p_probe, float p_exposure);
+
virtual AABB reflection_probe_get_aabb(RID p_probe) const override;
virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const override;
virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const override;
@@ -300,6 +808,7 @@ public:
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const override;
int reflection_probe_get_resolution(RID p_probe) const;
+ float reflection_probe_get_baked_exposure(RID p_probe) const;
virtual bool reflection_probe_renders_shadows(RID p_probe) const override;
float reflection_probe_get_intensity(RID p_probe) const;
@@ -309,9 +818,98 @@ public:
Color reflection_probe_get_ambient_color(RID p_probe) const;
float reflection_probe_get_ambient_color_energy(RID p_probe) const;
+ Dependency *reflection_probe_get_dependency(RID p_probe) const;
+
+ /* REFLECTION ATLAS */
+
+ bool owns_reflection_atlas(RID p_rid) { return reflection_atlas_owner.owns(p_rid); }
+
+ virtual RID reflection_atlas_create() override;
+ virtual void reflection_atlas_free(RID p_ref_atlas) override;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) override;
+ virtual int reflection_atlas_get_size(RID p_ref_atlas) const override;
+
+ _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) {
+ ReflectionAtlas *atlas = reflection_atlas_owner.get_or_null(p_ref_atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->reflection;
+ }
+
+ /* REFLECTION PROBE INSTANCE */
+
+ bool owns_reflection_probe_instance(RID p_rid) { return reflection_probe_instance_owner.owns(p_rid); }
+
+ virtual RID reflection_probe_instance_create(RID p_probe) override;
+ virtual void reflection_probe_instance_free(RID p_instance) override;
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) override;
+ virtual void reflection_probe_release_atlas_index(RID p_instance) override;
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance) override;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance) override;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) override;
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance) override;
+
+ uint32_t reflection_probe_instance_get_resolution(RID p_instance);
+ RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index);
+ RID reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index);
+
+ _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, RID());
+
+ return rpi->probe;
+ }
+
+ _FORCE_INLINE_ RendererRD::ForwardID reflection_probe_instance_get_forward_id(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, 0);
+
+ return rpi->forward_id;
+ }
+
+ _FORCE_INLINE_ void reflection_probe_instance_set_cull_mask(RID p_instance, uint32_t p_render_pass) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!rpi);
+ rpi->cull_mask = p_render_pass;
+ }
+
+ _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND(!rpi);
+ rpi->last_pass = p_render_pass;
+ }
+
+ _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, 0);
+
+ return rpi->last_pass;
+ }
+
+ _FORCE_INLINE_ Transform3D reflection_probe_instance_get_transform(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, Transform3D());
+
+ return rpi->transform;
+ }
+
+ _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) {
+ ReflectionProbeInstance *rpi = reflection_probe_instance_owner.get_or_null(p_instance);
+ ERR_FAIL_COND_V(!rpi, -1);
+
+ return rpi->atlas_index;
+ }
+
+ ClusterBuilderRD *reflection_probe_instance_get_cluster_builder(RID p_instance, ClusterBuilderSharedDataRD *p_cluster_builder_shared);
+
+ /* REFLECTION DATA */
+
+ void free_reflection_data();
+ void set_max_reflection_probes(const uint32_t p_max_reflection_probes);
+ RID get_reflection_probe_buffer() { return reflection_buffer; }
+ void update_reflection_probe_buffer(RenderDataRD *p_render_data, const PagedArray<RID> &p_reflections, const Transform3D &p_camera_inverse_transform, RID p_environment);
+
/* LIGHTMAP */
- Lightmap *get_lightmap(RID p_rid) { return lightmap_owner.get_or_null(p_rid); };
bool owns_lightmap(RID p_rid) { return lightmap_owner.owns(p_rid); };
virtual RID lightmap_allocate() override;
@@ -322,6 +920,7 @@ public:
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) override;
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) override;
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) override;
+ virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) override;
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const override;
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const override;
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const override;
@@ -331,6 +930,8 @@ public:
virtual void lightmap_tap_sh_light(RID p_lightmap, const Vector3 &p_point, Color *r_sh) override;
virtual void lightmap_set_probe_capture_update_speed(float p_speed) override;
+ Dependency *lightmap_get_dependency(RID p_lightmap) const;
+
virtual float lightmap_get_probe_capture_update_speed() const override {
return lightmap_probe_capture_update_speed;
}
@@ -339,6 +940,11 @@ public:
ERR_FAIL_COND_V(!lm, RID());
return lm->light_texture;
}
+ _FORCE_INLINE_ float lightmap_get_baked_exposure_normalization(RID p_lightmap) const {
+ const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
+ ERR_FAIL_COND_V(!lm, 1.0);
+ return lm->baked_exposure;
+ }
_FORCE_INLINE_ int32_t lightmap_get_array_index(RID p_lightmap) const {
ERR_FAIL_COND_V(!using_lightmap_array, -1); //only for arrays
const Lightmap *lm = lightmap_owner.get_or_null(p_lightmap);
@@ -363,8 +969,113 @@ public:
ERR_FAIL_COND_V(!using_lightmap_array, lightmap_textures); //only for arrays
return lightmap_textures;
}
+
+ /* LIGHTMAP INSTANCE */
+
+ bool owns_lightmap_instance(RID p_rid) { return lightmap_instance_owner.owns(p_rid); };
+
+ virtual RID lightmap_instance_create(RID p_lightmap) override;
+ virtual void lightmap_instance_free(RID p_lightmap) override;
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) override;
+ _FORCE_INLINE_ bool lightmap_instance_is_valid(RID p_lightmap_instance) {
+ return lightmap_instance_owner.get_or_null(p_lightmap_instance) != nullptr;
+ }
+
+ _FORCE_INLINE_ RID lightmap_instance_get_lightmap(RID p_lightmap_instance) {
+ LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance);
+ return li->lightmap;
+ }
+ _FORCE_INLINE_ Transform3D lightmap_instance_get_transform(RID p_lightmap_instance) {
+ LightmapInstance *li = lightmap_instance_owner.get_or_null(p_lightmap_instance);
+ return li->transform;
+ }
+
+ /* SHADOW ATLAS API */
+
+ bool owns_shadow_atlas(RID p_rid) { return shadow_atlas_owner.owns(p_rid); };
+
+ virtual RID shadow_atlas_create() override;
+ virtual void shadow_atlas_free(RID p_atlas) override;
+
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) override;
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) override;
+ virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_instance, float p_coverage, uint64_t p_light_version) override;
+ _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) {
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!atlas, false);
+ return atlas->shadow_owners.has(p_light_intance);
+ }
+ _FORCE_INLINE_ uint32_t shadow_atlas_get_light_instance_key(RID p_atlas, RID p_light_intance) {
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!atlas, -1);
+ return atlas->shadow_owners[p_light_intance];
+ }
+
+ _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) {
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->depth;
+ }
+
+ _FORCE_INLINE_ int shadow_atlas_get_size(RID p_atlas) {
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!atlas, 0);
+ return atlas->size;
+ }
+
+ _FORCE_INLINE_ int shadow_atlas_get_quadrant_shadow_size(RID p_atlas, uint32_t p_quadrant) {
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!atlas, 0);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_quadrant, 4, 0);
+ return atlas->quadrants[p_quadrant].shadows.size();
+ }
+
+ _FORCE_INLINE_ uint32_t shadow_atlas_get_quadrant_subdivision(RID p_atlas, uint32_t p_quadrant) {
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!atlas, 0);
+ ERR_FAIL_UNSIGNED_INDEX_V(p_quadrant, 4, 0);
+ return atlas->quadrants[p_quadrant].subdivision;
+ }
+
+ _FORCE_INLINE_ RID shadow_atlas_get_fb(RID p_atlas) {
+ ShadowAtlas *atlas = shadow_atlas_owner.get_or_null(p_atlas);
+ ERR_FAIL_COND_V(!atlas, RID());
+ return atlas->fb;
+ }
+
+ virtual void shadow_atlas_update(RID p_atlas) override;
+
+ /* DIRECTIONAL SHADOW */
+
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) override;
+ virtual int get_directional_light_shadow_size(RID p_light_intance) override;
+ virtual void set_directional_shadow_count(int p_count) override;
+
+ Rect2i get_directional_shadow_rect();
+ void update_directional_shadow_atlas();
+
+ _FORCE_INLINE_ RID directional_shadow_get_texture() {
+ return directional_shadow.depth;
+ }
+
+ _FORCE_INLINE_ int directional_shadow_get_size() {
+ return directional_shadow.size;
+ }
+
+ _FORCE_INLINE_ RID direction_shadow_get_fb() {
+ return directional_shadow.fb;
+ }
+
+ _FORCE_INLINE_ void directional_shadow_increase_current_light() {
+ directional_shadow.current_light++;
+ }
+
+ /* SHADOW CUBEMAPS */
+
+ RID get_cubemap(int p_size);
+ RID get_cubemap_fb(int p_size, int p_pass);
};
} // namespace RendererRD
-#endif // !LIGHT_STORAGE_RD_H
+#endif // LIGHT_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
index 096d371b8d..6703d8e7d0 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp
@@ -85,7 +85,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[j + 3] = 0; // ignored
}
} else {
- int v = value;
+ uint32_t v = value;
gui[0] = v & 1 ? 1 : 0;
gui[1] = v & 2 ? 1 : 0;
}
@@ -112,7 +112,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[j + 3] = 0; // ignored
}
} else {
- int v = value;
+ uint32_t v = value;
gui[0] = (v & 1) ? 1 : 0;
gui[1] = (v & 2) ? 1 : 0;
gui[2] = (v & 4) ? 1 : 0;
@@ -141,7 +141,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
}
} else {
- int v = value;
+ uint32_t v = value;
gui[0] = (v & 1) ? 1 : 0;
gui[1] = (v & 2) ? 1 : 0;
gui[2] = (v & 4) ? 1 : 0;
@@ -172,75 +172,84 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_IVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 2 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_IVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 3 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
}
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_IVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
int32_t *gui = (int32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 4 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i += 4) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i += 4) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
}
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_UINT: {
@@ -267,75 +276,84 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
}
} break;
case ShaderLanguage::TYPE_UVEC2: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 2 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 2 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 2, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 2, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ }
+ gui[j + 2] = 0; // ignored
+ gui[j + 3] = 0; // ignored
}
- gui[j + 2] = 0; // ignored
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector2i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
}
} break;
case ShaderLanguage::TYPE_UVEC3: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 3 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 3 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0, j = 0; i < count; i += 3, j += 4) {
- if (i < s) {
- gui[j] = r[i];
- gui[j + 1] = r[i + 1];
- gui[j + 2] = r[i + 2];
- } else {
- gui[j] = 0;
- gui[j + 1] = 0;
- gui[j + 2] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0, j = 0; i < count; i += 3, j += 4) {
+ if (i < s) {
+ gui[j] = r[i];
+ gui[j + 1] = r[i + 1];
+ gui[j + 2] = r[i + 2];
+ } else {
+ gui[j] = 0;
+ gui[j + 1] = 0;
+ gui[j + 2] = 0;
+ }
+ gui[j + 3] = 0; // ignored
}
- gui[j + 3] = 0; // ignored
+ } else {
+ Vector3i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
}
} break;
case ShaderLanguage::TYPE_UVEC4: {
- Vector<int> iv = value;
- int s = iv.size();
uint32_t *gui = (uint32_t *)data;
+ if (p_array_size > 0) {
+ Vector<int> iv = value;
+ int s = iv.size();
+ int count = 4 * p_array_size;
- if (p_array_size <= 0) {
- p_array_size = 1;
- }
- int count = 4 * p_array_size;
-
- const int *r = iv.ptr();
- for (int i = 0; i < count; i++) {
- if (i < s) {
- gui[i] = r[i];
- gui[i + 1] = r[i + 1];
- gui[i + 2] = r[i + 2];
- gui[i + 3] = r[i + 3];
- } else {
- gui[i] = 0;
- gui[i + 1] = 0;
- gui[i + 2] = 0;
- gui[i + 3] = 0;
+ const int *r = iv.ptr();
+ for (int i = 0; i < count; i++) {
+ if (i < s) {
+ gui[i] = r[i];
+ gui[i + 1] = r[i + 1];
+ gui[i + 2] = r[i + 2];
+ gui[i + 3] = r[i + 3];
+ } else {
+ gui[i] = 0;
+ gui[i + 1] = 0;
+ gui[i + 2] = 0;
+ gui[i + 3] = 0;
+ }
}
+ } else {
+ Vector4i v = value;
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
} break;
case ShaderLanguage::TYPE_FLOAT: {
@@ -514,13 +532,20 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[1] = v.y;
gui[2] = v.z;
gui[3] = v.w;
- } else {
+ } else if (value.get_type() == Variant::PLANE) {
Plane v = value;
gui[0] = v.normal.x;
gui[1] = v.normal.y;
gui[2] = v.normal.z;
gui[3] = v.d;
+ } else {
+ Vector4 v = value;
+
+ gui[0] = v.x;
+ gui[1] = v.y;
+ gui[2] = v.z;
+ gui[3] = v.w;
}
}
} break;
@@ -670,7 +695,7 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[i + 15] = 1;
}
}
- } else {
+ } else if (value.get_type() == Variant::TRANSFORM3D) {
Transform3D v = value;
gui[0] = v.basis.rows[0][0];
gui[1] = v.basis.rows[1][0];
@@ -691,6 +716,13 @@ _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataTy
gui[13] = v.origin.y;
gui[14] = v.origin.z;
gui[15] = 1;
+ } else {
+ Projection v = value;
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ gui[i * 4 + j] = v.columns[i][j];
+ }
+ }
}
} break;
default: {
@@ -702,7 +734,7 @@ _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type,
switch (type) {
case ShaderLanguage::TYPE_BOOL: {
uint32_t *gui = (uint32_t *)data;
- *gui = value[0].boolean ? 1 : 0;
+ gui[0] = value[0].boolean ? 1 : 0;
} break;
case ShaderLanguage::TYPE_BVEC2: {
uint32_t *gui = (uint32_t *)data;
@@ -871,7 +903,9 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
case ShaderLanguage::TYPE_BVEC3:
case ShaderLanguage::TYPE_IVEC3:
case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_VEC3:
+ case ShaderLanguage::TYPE_VEC3: {
+ memset(data, 0, 12 * p_array_size);
+ } break;
case ShaderLanguage::TYPE_BVEC4:
case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC4:
@@ -894,9 +928,9 @@ _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type,
}
///////////////////////////////////////////////////////////////////////////
-// MaterialData
+// MaterialStorage::MaterialData
-void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
+void MaterialStorage::MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
bool uses_global_buffer = false;
@@ -909,14 +943,20 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
continue; //instance uniforms don't appear in the buffer
}
+ if (E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (E.value.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
//this is a global variable, get the index to it
- GlobalVariables::Variable *gv = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *gv = material_storage->global_shader_uniforms.variables.getptr(E.key);
uint32_t index = 0;
if (gv) {
index = gv->buffer_index;
} else {
- WARN_PRINT("Shader uses global uniform '" + E.key + "', but it was removed at some point. Material will not display correctly.");
+ WARN_PRINT("Shader uses global parameter '" + E.key + "', but it was removed at some point. Material will not display correctly.");
}
uint32_t offset = p_uniform_offsets[E.value.order];
@@ -967,33 +1007,33 @@ void MaterialData::update_uniform_buffer(const HashMap<StringName, ShaderLanguag
if (uses_global_buffer != (global_buffer_E != nullptr)) {
if (uses_global_buffer) {
- global_buffer_E = material_storage->global_variables.materials_using_buffer.push_back(self);
+ global_buffer_E = material_storage->global_shader_uniforms.materials_using_buffer.push_back(self);
} else {
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
global_buffer_E = nullptr;
}
}
}
-MaterialData::~MaterialData() {
+MaterialStorage::MaterialData::~MaterialData() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
if (global_buffer_E) {
//unregister global buffers
- material_storage->global_variables.materials_using_buffer.erase(global_buffer_E);
+ material_storage->global_shader_uniforms.materials_using_buffer.erase(global_buffer_E);
}
if (global_texture_E) {
//unregister global textures
for (const KeyValue<StringName, uint64_t> &E : used_global_textures) {
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
}
//unregister material from those using global textures
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
}
if (uniform_buffer.is_valid()) {
@@ -1001,14 +1041,14 @@ MaterialData::~MaterialData() {
}
}
-void MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
+void MaterialStorage::MaterialData::update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) {
TextureStorage *texture_storage = TextureStorage::get_singleton();
MaterialStorage *material_storage = MaterialStorage::get_singleton();
#ifdef TOOLS_ENABLED
- Texture *roughness_detect_texture = nullptr;
+ TextureStorage::Texture *roughness_detect_texture = nullptr;
RS::TextureDetectRoughnessChannel roughness_channel = RS::TEXTURE_DETECT_ROUGHNESS_R;
- Texture *normal_detect_texture = nullptr;
+ TextureStorage::Texture *normal_detect_texture = nullptr;
#endif
bool uses_global_textures = false;
@@ -1020,13 +1060,19 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
Vector<RID> textures;
+ if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue;
+ }
+
if (p_texture_uniforms[i].global) {
uses_global_textures = true;
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(uniform_name);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(uniform_name);
if (v) {
if (v->buffer_index >= 0) {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
+ WARN_PRINT("Shader uses global parameter texture '" + String(uniform_name) + "', but it changed type and is no longer a texture!.");
} else {
HashMap<StringName, uint64_t>::Iterator E = used_global_textures.find(uniform_name);
@@ -1041,7 +1087,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
}
} else {
- WARN_PRINT("Shader uses global uniform texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
+ WARN_PRINT("Shader uses global parameter texture '" + String(uniform_name) + "', but it was removed at some point. Material will not display correctly.");
}
} else {
HashMap<StringName, Variant>::ConstIterator V = p_parameters.find(uniform_name);
@@ -1091,19 +1137,22 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
case ShaderLanguage::TYPE_SAMPLER2D: {
switch (p_texture_uniforms[i].hint) {
case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK);
+ } break;
+ case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_TRANSPARENT);
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ANISOTROPY: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_ANISO);
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
} break;
case ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_NORMAL);
} break;
default: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
} break;
}
} break;
@@ -1111,27 +1160,27 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
case ShaderLanguage::TYPE_SAMPLERCUBE: {
switch (p_texture_uniforms[i].hint) {
case ShaderLanguage::ShaderNode::Uniform::HINT_DEFAULT_BLACK: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK);
} break;
default: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_WHITE);
} break;
}
} break;
case ShaderLanguage::TYPE_SAMPLERCUBEARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK);
} break;
case ShaderLanguage::TYPE_ISAMPLER3D:
case ShaderLanguage::TYPE_USAMPLER3D:
case ShaderLanguage::TYPE_SAMPLER3D: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
} break;
case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
case ShaderLanguage::TYPE_USAMPLER2DARRAY:
case ShaderLanguage::TYPE_SAMPLER2DARRAY: {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE);
} break;
default: {
@@ -1153,7 +1202,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
bool srgb = p_use_linear_color && p_texture_uniforms[i].use_color;
for (int j = 0; j < textures.size(); j++) {
- Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
+ TextureStorage::Texture *tex = TextureStorage::get_singleton()->get_texture(textures[j]);
if (tex) {
rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
@@ -1175,7 +1224,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
#endif
}
if (rd_texture.is_null()) {
- rd_texture = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE);
+ rd_texture = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_WHITE);
}
#ifdef TOOLS_ENABLED
if (roughness_detect_texture && normal_detect_texture && !normal_detect_texture->path.is_empty()) {
@@ -1193,7 +1242,7 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
if (E.value != global_textures_pass) {
to_delete.push_back(E.key);
- GlobalVariables::Variable *v = material_storage->global_variables.variables.getptr(E.key);
+ GlobalShaderUniforms::Variable *v = material_storage->global_shader_uniforms.variables.getptr(E.key);
if (v) {
v->texture_materials.erase(self);
}
@@ -1207,23 +1256,23 @@ void MaterialData::update_textures(const HashMap<StringName, Variant> &p_paramet
//handle registering/unregistering global textures
if (uses_global_textures != (global_texture_E != nullptr)) {
if (uses_global_textures) {
- global_texture_E = material_storage->global_variables.materials_using_texture.push_back(self);
+ global_texture_E = material_storage->global_shader_uniforms.materials_using_texture.push_back(self);
} else {
- material_storage->global_variables.materials_using_texture.erase(global_texture_E);
+ material_storage->global_shader_uniforms.materials_using_texture.erase(global_texture_E);
global_texture_E = nullptr;
}
}
}
}
-void MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
+void MaterialStorage::MaterialData::free_parameters_uniform_set(RID p_uniform_set) {
if (p_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(p_uniform_set)) {
RD::get_singleton()->uniform_set_set_invalidation_callback(p_uniform_set, nullptr, nullptr);
RD::get_singleton()->free(p_uniform_set);
}
}
-bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier) {
+bool MaterialStorage::MaterialData::update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier) {
if ((uint32_t)ubo_data.size() != p_ubo_size) {
p_uniform_dirty = true;
if (uniform_buffer.is_valid()) {
@@ -1247,7 +1296,7 @@ bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Varia
//check whether buffer changed
if (p_uniform_dirty && ubo_data.size()) {
- update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), true);
+ update_uniform_buffer(p_uniforms, p_uniform_offsets, p_parameters, ubo_data.ptrw(), ubo_data.size(), p_use_linear_color);
RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw(), p_barrier);
}
@@ -1272,7 +1321,7 @@ bool MaterialData::update_parameters_uniform_set(const HashMap<StringName, Varia
update_textures(p_parameters, p_default_texture_params, p_texture_uniforms, texture_cache.ptrw(), true);
}
- if (p_ubo_size == 0 && p_texture_uniforms.size() == 0) {
+ if (p_ubo_size == 0 && (p_texture_uniforms.size() == 0)) {
// This material does not require an uniform set, so don't create it.
return false;
}
@@ -1441,22 +1490,22 @@ MaterialStorage::MaterialStorage() {
shader_data_request_func[i] = nullptr;
}
- static_assert(sizeof(GlobalVariables::Value) == 16);
+ static_assert(sizeof(GlobalShaderUniforms::Value) == 16);
- global_variables.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
- global_variables.buffer_values = memnew_arr(GlobalVariables::Value, global_variables.buffer_size);
- memset(global_variables.buffer_values, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size);
- global_variables.buffer_usage = memnew_arr(GlobalVariables::ValueUsage, global_variables.buffer_size);
- global_variables.buffer_dirty_regions = memnew_arr(bool, global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE);
- global_variables.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalVariables::Value) * global_variables.buffer_size);
+ global_shader_uniforms.buffer_size = MAX(4096, (int)GLOBAL_GET("rendering/limits/global_shader_variables/buffer_size"));
+ global_shader_uniforms.buffer_values = memnew_arr(GlobalShaderUniforms::Value, global_shader_uniforms.buffer_size);
+ memset(global_shader_uniforms.buffer_values, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_usage = memnew_arr(GlobalShaderUniforms::ValueUsage, global_shader_uniforms.buffer_size);
+ global_shader_uniforms.buffer_dirty_regions = memnew_arr(bool, global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE);
+ global_shader_uniforms.buffer = RD::get_singleton()->storage_buffer_create(sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size);
}
MaterialStorage::~MaterialStorage() {
- memdelete_arr(global_variables.buffer_values);
- memdelete_arr(global_variables.buffer_usage);
- memdelete_arr(global_variables.buffer_dirty_regions);
- RD::get_singleton()->free(global_variables.buffer);
+ memdelete_arr(global_shader_uniforms.buffer_values);
+ memdelete_arr(global_shader_uniforms.buffer_usage);
+ memdelete_arr(global_shader_uniforms.buffer_dirty_regions);
+ RD::get_singleton()->free(global_shader_uniforms.buffer);
// buffers
@@ -1481,6 +1530,18 @@ MaterialStorage::~MaterialStorage() {
singleton = nullptr;
}
+bool MaterialStorage::free(RID p_rid) {
+ if (owns_shader(p_rid)) {
+ shader_free(p_rid);
+ return true;
+ } else if (owns_material(p_rid)) {
+ material_free(p_rid);
+ return true;
+ }
+
+ return false;
+}
+
/* Samplers */
void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
@@ -1577,17 +1638,17 @@ void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) {
}
}
-/* GLOBAL VARIABLE API */
+/* GLOBAL SHADER UNIFORM API */
-int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
+int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) {
int32_t idx = 0;
- while (idx + p_elements <= global_variables.buffer_size) {
- if (global_variables.buffer_usage[idx].elements == 0) {
+ while (idx + p_elements <= global_shader_uniforms.buffer_size) {
+ if (global_shader_uniforms.buffer_usage[idx].elements == 0) {
bool valid = true;
for (uint32_t i = 1; i < p_elements; i++) {
- if (global_variables.buffer_usage[idx + i].elements > 0) {
+ if (global_shader_uniforms.buffer_usage[idx + i].elements > 0) {
valid = false;
- idx += i + global_variables.buffer_usage[idx + i].elements;
+ idx += i + global_shader_uniforms.buffer_usage[idx + i].elements;
break;
}
}
@@ -1598,17 +1659,17 @@ int32_t MaterialStorage::_global_variable_allocate(uint32_t p_elements) {
return idx;
} else {
- idx += global_variables.buffer_usage[idx].elements;
+ idx += global_shader_uniforms.buffer_usage[idx].elements;
}
}
return -1;
}
-void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value) {
+void MaterialStorage::_global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
bool b = p_value;
bv.x = b ? 1.0 : 0.0;
bv.y = 0.0;
@@ -1617,7 +1678,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_BVEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1625,7 +1686,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1633,7 +1694,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_BVEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
uint32_t bvec = p_value;
bv.x = (bvec & 1) ? 1.0 : 0.0;
bv.y = (bvec & 2) ? 1.0 : 0.0;
@@ -1641,7 +1702,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = (bvec & 8) ? 1.0 : 0.0;
} break;
case RS::GLOBAL_VAR_TYPE_INT: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
int32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1649,7 +1710,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC2: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1657,7 +1718,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC3: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1665,7 +1726,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_IVEC4: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1673,7 +1734,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_RECT2I: {
- GlobalVariables::ValueInt &bv = *(GlobalVariables::ValueInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueInt &bv = *(GlobalShaderUniforms::ValueInt *)&global_shader_uniforms.buffer_values[p_index];
Rect2i v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1681,7 +1742,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_UINT: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
uint32_t v = p_value;
bv.x = v;
bv.y = 0;
@@ -1689,7 +1750,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC2: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector2i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1697,7 +1758,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC3: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector3i v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1705,7 +1766,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_UVEC4: {
- GlobalVariables::ValueUInt &bv = *(GlobalVariables::ValueUInt *)&global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::ValueUInt &bv = *(GlobalShaderUniforms::ValueUInt *)&global_shader_uniforms.buffer_values[p_index];
Vector<int32_t> v = p_value;
bv.x = v.size() >= 1 ? v[0] : 0;
bv.y = v.size() >= 2 ? v[1] : 0;
@@ -1713,7 +1774,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size() >= 4 ? v[3] : 0;
} break;
case RS::GLOBAL_VAR_TYPE_FLOAT: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
float v = p_value;
bv.x = v;
bv.y = 0;
@@ -1721,7 +1782,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector2 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1729,7 +1790,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC3: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Vector3 v = p_value;
bv.x = v.x;
bv.y = v.y;
@@ -1737,7 +1798,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = 0;
} break;
case RS::GLOBAL_VAR_TYPE_VEC4: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Plane v = p_value;
bv.x = v.normal.x;
bv.y = v.normal.y;
@@ -1745,14 +1806,14 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.d;
} break;
case RS::GLOBAL_VAR_TYPE_COLOR: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Color v = p_value;
bv.x = v.r;
bv.y = v.g;
bv.z = v.b;
bv.w = v.a;
- GlobalVariables::Value &bv_linear = global_variables.buffer_values[p_index + 1];
+ GlobalShaderUniforms::Value &bv_linear = global_shader_uniforms.buffer_values[p_index + 1];
v = v.srgb_to_linear();
bv_linear.x = v.r;
bv_linear.y = v.g;
@@ -1761,7 +1822,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_RECT2: {
- GlobalVariables::Value &bv = global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value &bv = global_shader_uniforms.buffer_values[p_index];
Rect2 v = p_value;
bv.x = v.position.x;
bv.y = v.position.y;
@@ -1769,7 +1830,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
bv.w = v.size.y;
} break;
case RS::GLOBAL_VAR_TYPE_MAT2: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 4) {
m2.resize(4);
@@ -1786,7 +1847,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT3: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Basis v = p_value;
bv[0].x = v.rows[0][0];
bv[0].y = v.rows[1][0];
@@ -1805,7 +1866,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_MAT4: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Vector<float> m2 = p_value;
if (m2.size() < 16) {
@@ -1834,7 +1895,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM_2D: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform2D v = p_value;
bv[0].x = v.columns[0][0];
bv[0].y = v.columns[0][1];
@@ -1853,7 +1914,7 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
} break;
case RS::GLOBAL_VAR_TYPE_TRANSFORM: {
- GlobalVariables::Value *bv = &global_variables.buffer_values[p_index];
+ GlobalShaderUniforms::Value *bv = &global_shader_uniforms.buffer_values[p_index];
Transform3D v = p_value;
bv[0].x = v.basis.rows[0][0];
bv[0].y = v.basis.rows[1][0];
@@ -1882,15 +1943,15 @@ void MaterialStorage::_global_variable_store_in_buffer(int32_t p_index, RS::Glob
}
}
-void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
+void MaterialStorage::_global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements) {
int32_t prev_chunk = -1;
for (int32_t i = 0; i < p_elements; i++) {
- int32_t chunk = (p_index + i) / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ int32_t chunk = (p_index + i) / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
if (chunk != prev_chunk) {
- if (!global_variables.buffer_dirty_regions[chunk]) {
- global_variables.buffer_dirty_regions[chunk] = true;
- global_variables.buffer_dirty_region_count++;
+ if (!global_shader_uniforms.buffer_dirty_regions[chunk]) {
+ global_shader_uniforms.buffer_dirty_regions[chunk] = true;
+ global_shader_uniforms.buffer_dirty_region_count++;
}
}
@@ -1898,16 +1959,16 @@ void MaterialStorage::_global_variable_mark_buffer_dirty(int32_t p_index, int32_
}
}
-void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) {
- ERR_FAIL_COND(global_variables.variables.has(p_name));
- GlobalVariables::Variable gv;
+void MaterialStorage::global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) {
+ ERR_FAIL_COND(global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable gv;
gv.type = p_type;
gv.value = p_value;
gv.buffer_index = -1;
if (p_type >= RS::GLOBAL_VAR_TYPE_SAMPLER2D) {
//is texture
- global_variables.must_update_texture_materials = true; //normally there are none
+ global_shader_uniforms.must_update_texture_materials = true; //normally there are none
} else {
gv.buffer_elements = 1;
if (p_type == RS::GLOBAL_VAR_TYPE_COLOR || p_type == RS::GLOBAL_VAR_TYPE_MAT2) {
@@ -1924,56 +1985,56 @@ void MaterialStorage::global_variable_add(const StringName &p_name, RS::GlobalVa
}
//is vector, allocate in buffer and update index
- gv.buffer_index = _global_variable_allocate(gv.buffer_elements);
+ gv.buffer_index = _global_shader_uniform_allocate(gv.buffer_elements);
ERR_FAIL_COND_MSG(gv.buffer_index < 0, vformat("Failed allocating global variable '%s' out of buffer memory. Consider increasing it in the Project Settings.", String(p_name)));
- global_variables.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = gv.buffer_elements;
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
- global_variables.must_update_buffer_materials = true; //normally there are none
+ global_shader_uniforms.must_update_buffer_materials = true; //normally there are none
}
- global_variables.variables[p_name] = gv;
+ global_shader_uniforms.variables[p_name] = gv;
}
-void MaterialStorage::global_variable_remove(const StringName &p_name) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_parameter_remove(const StringName &p_name) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return;
}
- const GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ const GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
if (gv.buffer_index >= 0) {
- global_variables.buffer_usage[gv.buffer_index].elements = 0;
- global_variables.must_update_buffer_materials = true;
+ global_shader_uniforms.buffer_usage[gv.buffer_index].elements = 0;
+ global_shader_uniforms.must_update_buffer_materials = true;
} else {
- global_variables.must_update_texture_materials = true;
+ global_shader_uniforms.must_update_texture_materials = true;
}
- global_variables.variables.erase(p_name);
+ global_shader_uniforms.variables.erase(p_name);
}
-Vector<StringName> MaterialStorage::global_variable_get_list() const {
+Vector<StringName> MaterialStorage::global_shader_parameter_get_list() const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Vector<StringName>(), "This function should never be used outside the editor, it can severely damage performance.");
}
Vector<StringName> names;
- for (const KeyValue<StringName, GlobalVariables::Variable> &E : global_variables.variables) {
+ for (const KeyValue<StringName, GlobalShaderUniforms::Variable> &E : global_shader_uniforms.variables) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
return names;
}
-void MaterialStorage::global_variable_set(const StringName &p_name, const Variant &p_value) {
- ERR_FAIL_COND(!global_variables.variables.has(p_name));
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+void MaterialStorage::global_shader_parameter_set(const StringName &p_name, const Variant &p_value) {
+ ERR_FAIL_COND(!global_shader_uniforms.variables.has(p_name));
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.value = p_value;
if (gv.override.get_type() == Variant::NIL) {
if (gv.buffer_index >= 0) {
//buffer
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -1986,26 +2047,26 @@ void MaterialStorage::global_variable_set(const StringName &p_name, const Varian
}
}
-void MaterialStorage::global_variable_set_override(const StringName &p_name, const Variant &p_value) {
- if (!global_variables.variables.has(p_name)) {
+void MaterialStorage::global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return; //variable may not exist
}
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- GlobalVariables::Variable &gv = global_variables.variables[p_name];
+ GlobalShaderUniforms::Variable &gv = global_shader_uniforms.variables[p_name];
gv.override = p_value;
if (gv.buffer_index >= 0) {
//buffer
if (gv.override.get_type() == Variant::NIL) {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.value);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.value);
} else {
- _global_variable_store_in_buffer(gv.buffer_index, gv.type, gv.override);
+ _global_shader_uniform_store_in_buffer(gv.buffer_index, gv.type, gv.override);
}
- _global_variable_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
+ _global_shader_uniform_mark_buffer_dirty(gv.buffer_index, gv.buffer_elements);
} else {
//texture
MaterialStorage *material_storage = MaterialStorage::get_singleton();
@@ -2017,42 +2078,42 @@ void MaterialStorage::global_variable_set_override(const StringName &p_name, con
}
}
-Variant MaterialStorage::global_variable_get(const StringName &p_name) const {
+Variant MaterialStorage::global_shader_parameter_get(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(Variant(), "This function should never be used outside the editor, it can severely damage performance.");
}
- if (!global_variables.variables.has(p_name)) {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return Variant();
}
- return global_variables.variables[p_name].value;
+ return global_shader_uniforms.variables[p_name].value;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type_internal(const StringName &p_name) const {
- if (!global_variables.variables.has(p_name)) {
+RS::GlobalShaderParameterType MaterialStorage::global_shader_parameter_get_type_internal(const StringName &p_name) const {
+ if (!global_shader_uniforms.variables.has(p_name)) {
return RS::GLOBAL_VAR_TYPE_MAX;
}
- return global_variables.variables[p_name].type;
+ return global_shader_uniforms.variables[p_name].type;
}
-RS::GlobalVariableType MaterialStorage::global_variable_get_type(const StringName &p_name) const {
+RS::GlobalShaderParameterType MaterialStorage::global_shader_parameter_get_type(const StringName &p_name) const {
if (!Engine::get_singleton()->is_editor_hint()) {
ERR_FAIL_V_MSG(RS::GLOBAL_VAR_TYPE_MAX, "This function should never be used outside the editor, it can severely damage performance.");
}
- return global_variable_get_type_internal(p_name);
+ return global_shader_parameter_get_type_internal(p_name);
}
-void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
+void MaterialStorage::global_shader_parameters_load_settings(bool p_load_textures) {
List<PropertyInfo> settings;
ProjectSettings::get_singleton()->get_property_list(&settings);
for (const PropertyInfo &E : settings) {
if (E.name.begins_with("shader_globals/")) {
StringName name = E.name.get_slice("/", 1);
- Dictionary d = ProjectSettings::get_singleton()->get(E.name);
+ Dictionary d = GLOBAL_GET(E.name);
ERR_CONTINUE(!d.has("type"));
ERR_CONTINUE(!d.has("value"));
@@ -2090,11 +2151,11 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
"samplerCube",
};
- RS::GlobalVariableType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
+ RS::GlobalShaderParameterType gvtype = RS::GLOBAL_VAR_TYPE_MAX;
for (int i = 0; i < RS::GLOBAL_VAR_TYPE_MAX; i++) {
if (global_var_type_names[i] == type) {
- gvtype = RS::GlobalVariableType(i);
+ gvtype = RS::GlobalShaderParameterType(i);
break;
}
}
@@ -2116,53 +2177,55 @@ void MaterialStorage::global_variables_load_settings(bool p_load_textures) {
value = resource;
}
- if (global_variables.variables.has(name)) {
+ if (global_shader_uniforms.variables.has(name)) {
//has it, update it
- global_variable_set(name, value);
+ global_shader_parameter_set(name, value);
} else {
- global_variable_add(name, gvtype, value);
+ global_shader_parameter_add(name, gvtype, value);
}
}
}
}
-void MaterialStorage::global_variables_clear() {
- global_variables.variables.clear(); //not right but for now enough
+void MaterialStorage::global_shader_parameters_clear() {
+ global_shader_uniforms.variables.clear(); //not right but for now enough
}
-RID MaterialStorage::global_variables_get_storage_buffer() const {
- return global_variables.buffer;
+RID MaterialStorage::global_shader_uniforms_get_storage_buffer() const {
+ return global_shader_uniforms.buffer;
}
-int32_t MaterialStorage::global_variables_instance_allocate(RID p_instance) {
- ERR_FAIL_COND_V(global_variables.instance_buffer_pos.has(p_instance), -1);
- int32_t pos = _global_variable_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- global_variables.instance_buffer_pos[p_instance] = pos; //save anyway
+int32_t MaterialStorage::global_shader_parameters_instance_allocate(RID p_instance) {
+ ERR_FAIL_COND_V(global_shader_uniforms.instance_buffer_pos.has(p_instance), -1);
+ int32_t pos = _global_shader_uniform_allocate(ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
+ global_shader_uniforms.instance_buffer_pos[p_instance] = pos; //save anyway
ERR_FAIL_COND_V_MSG(pos < 0, -1, "Too many instances using shader instance variables. Increase buffer size in Project Settings.");
- global_variables.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
+ global_shader_uniforms.buffer_usage[pos].elements = ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES;
return pos;
}
-void MaterialStorage::global_variables_instance_free(RID p_instance) {
- ERR_FAIL_COND(!global_variables.instance_buffer_pos.has(p_instance));
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+void MaterialStorage::global_shader_parameters_instance_free(RID p_instance) {
+ ERR_FAIL_COND(!global_shader_uniforms.instance_buffer_pos.has(p_instance));
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos >= 0) {
- global_variables.buffer_usage[pos].elements = 0;
+ global_shader_uniforms.buffer_usage[pos].elements = 0;
}
- global_variables.instance_buffer_pos.erase(p_instance);
+ global_shader_uniforms.instance_buffer_pos.erase(p_instance);
}
-void MaterialStorage::global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) {
- if (!global_variables.instance_buffer_pos.has(p_instance)) {
+void MaterialStorage::global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count) {
+ if (!global_shader_uniforms.instance_buffer_pos.has(p_instance)) {
return; //just not allocated, ignore
}
- int32_t pos = global_variables.instance_buffer_pos[p_instance];
+ int32_t pos = global_shader_uniforms.instance_buffer_pos[p_instance];
if (pos < 0) {
return; //again, not allocated, ignore
}
ERR_FAIL_INDEX(p_index, ShaderLanguage::MAX_INSTANCE_UNIFORM_INDICES);
- ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+
+ Variant::Type value_type = p_value.get_type();
+ ERR_FAIL_COND_MSG(p_value.get_type() > Variant::COLOR, "Unsupported variant type for instance parameter: " + Variant::get_type_name(value_type)); //anything greater not supported
const ShaderLanguage::DataType datatype_from_value[Variant::COLOR + 1] = {
ShaderLanguage::TYPE_MAX, //nil
@@ -2177,71 +2240,88 @@ void MaterialStorage::global_variables_instance_update(RID p_instance, int p_ind
ShaderLanguage::TYPE_VEC3, // vec3
ShaderLanguage::TYPE_IVEC3, //vec3i
ShaderLanguage::TYPE_MAX, //xform2d not supported here
+ ShaderLanguage::TYPE_VEC4, //vec4
+ ShaderLanguage::TYPE_IVEC4, //vec4i
ShaderLanguage::TYPE_VEC4, //plane
ShaderLanguage::TYPE_VEC4, //quat
ShaderLanguage::TYPE_MAX, //aabb not supported here
ShaderLanguage::TYPE_MAX, //basis not supported here
ShaderLanguage::TYPE_MAX, //xform not supported here
+ ShaderLanguage::TYPE_MAX, //projection not supported here
ShaderLanguage::TYPE_VEC4 //color
};
- ShaderLanguage::DataType datatype = datatype_from_value[p_value.get_type()];
-
- ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(p_value.get_type())); //anything greater not supported
+ ShaderLanguage::DataType datatype = ShaderLanguage::TYPE_MAX;
+ if (value_type == Variant::INT && p_flags_count > 0) {
+ switch (p_flags_count) {
+ case 1:
+ datatype = ShaderLanguage::TYPE_BVEC2;
+ break;
+ case 2:
+ datatype = ShaderLanguage::TYPE_BVEC3;
+ break;
+ case 3:
+ datatype = ShaderLanguage::TYPE_BVEC4;
+ break;
+ }
+ } else {
+ datatype = datatype_from_value[value_type];
+ }
+ ERR_FAIL_COND_MSG(datatype == ShaderLanguage::TYPE_MAX, "Unsupported variant type for instance parameter: " + Variant::get_type_name(value_type)); //anything greater not supported
pos += p_index;
- _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_variables.buffer_values[pos], true); //instances always use linear color in this renderer
- _global_variable_mark_buffer_dirty(pos, 1);
+ _fill_std140_variant_ubo_value(datatype, 0, p_value, (uint8_t *)&global_shader_uniforms.buffer_values[pos], true); //instances always use linear color in this renderer
+ _global_shader_uniform_mark_buffer_dirty(pos, 1);
}
-void MaterialStorage::_update_global_variables() {
+void MaterialStorage::_update_global_shader_uniforms() {
MaterialStorage *material_storage = MaterialStorage::get_singleton();
- if (global_variables.buffer_dirty_region_count > 0) {
- uint32_t total_regions = global_variables.buffer_size / GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
- if (total_regions / global_variables.buffer_dirty_region_count <= 4) {
+ if (global_shader_uniforms.buffer_dirty_region_count > 0) {
+ uint32_t total_regions = global_shader_uniforms.buffer_size / GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
+ if (total_regions / global_shader_uniforms.buffer_dirty_region_count <= 4) {
// 25% of regions dirty, just update all buffer
- RD::get_singleton()->buffer_update(global_variables.buffer, 0, sizeof(GlobalVariables::Value) * global_variables.buffer_size, global_variables.buffer_values);
- memset(global_variables.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
+ RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, 0, sizeof(GlobalShaderUniforms::Value) * global_shader_uniforms.buffer_size, global_shader_uniforms.buffer_values);
+ memset(global_shader_uniforms.buffer_dirty_regions, 0, sizeof(bool) * total_regions);
} else {
- uint32_t region_byte_size = sizeof(GlobalVariables::Value) * GlobalVariables::BUFFER_DIRTY_REGION_SIZE;
+ uint32_t region_byte_size = sizeof(GlobalShaderUniforms::Value) * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE;
for (uint32_t i = 0; i < total_regions; i++) {
- if (global_variables.buffer_dirty_regions[i]) {
- RD::get_singleton()->buffer_update(global_variables.buffer, i * region_byte_size, region_byte_size, &global_variables.buffer_values[i * GlobalVariables::BUFFER_DIRTY_REGION_SIZE]);
+ if (global_shader_uniforms.buffer_dirty_regions[i]) {
+ RD::get_singleton()->buffer_update(global_shader_uniforms.buffer, i * region_byte_size, region_byte_size, &global_shader_uniforms.buffer_values[i * GlobalShaderUniforms::BUFFER_DIRTY_REGION_SIZE]);
- global_variables.buffer_dirty_regions[i] = false;
+ global_shader_uniforms.buffer_dirty_regions[i] = false;
}
}
}
- global_variables.buffer_dirty_region_count = 0;
+ global_shader_uniforms.buffer_dirty_region_count = 0;
}
- if (global_variables.must_update_buffer_materials) {
+ if (global_shader_uniforms.must_update_buffer_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_buffer) {
+ for (const RID &E : global_shader_uniforms.materials_using_buffer) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, true, false);
}
- global_variables.must_update_buffer_materials = false;
+ global_shader_uniforms.must_update_buffer_materials = false;
}
- if (global_variables.must_update_texture_materials) {
+ if (global_shader_uniforms.must_update_texture_materials) {
// only happens in the case of a buffer variable added or removed,
// so not often.
- for (const RID &E : global_variables.materials_using_texture) {
+ for (const RID &E : global_shader_uniforms.materials_using_texture) {
Material *material = material_storage->get_material(E);
ERR_CONTINUE(!material); //wtf
material_storage->_material_queue_update(material, false, true);
}
- global_variables.must_update_texture_materials = false;
+ global_shader_uniforms.must_update_texture_materials = false;
}
}
@@ -2334,38 +2414,49 @@ void MaterialStorage::shader_set_code(RID p_shader, const String &p_code) {
if (shader->data) {
for (const KeyValue<StringName, HashMap<int, RID>> &E : shader->default_texture_parameter) {
for (const KeyValue<int, RID> &E2 : E.value) {
- shader->data->set_default_texture_param(E.key, E2.value, E2.key);
+ shader->data->set_default_texture_parameter(E.key, E2.value, E2.key);
}
}
}
}
if (shader->data) {
+ shader->data->set_path_hint(shader->path_hint);
shader->data->set_code(p_code);
}
for (Material *E : shader->owners) {
Material *material = E;
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
}
+void MaterialStorage::shader_set_path_hint(RID p_shader, const String &p_path) {
+ Shader *shader = shader_owner.get_or_null(p_shader);
+ ERR_FAIL_COND(!shader);
+
+ shader->path_hint = p_path;
+ if (shader->data) {
+ shader->data->set_path_hint(p_path);
+ }
+}
+
String MaterialStorage::shader_get_code(RID p_shader) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, String());
return shader->code;
}
-void MaterialStorage::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
+void MaterialStorage::get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
if (shader->data) {
- return shader->data->get_param_list(p_param_list);
+ return shader->data->get_shader_uniform_list(p_param_list);
}
}
-void MaterialStorage::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
+void MaterialStorage::shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND(!shader);
@@ -2384,7 +2475,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin
}
}
if (shader->data) {
- shader->data->set_default_texture_param(p_name, p_texture, p_index);
+ shader->data->set_default_texture_parameter(p_name, p_texture, p_index);
}
for (Material *E : shader->owners) {
Material *material = E;
@@ -2392,7 +2483,7 @@ void MaterialStorage::shader_set_default_texture_param(RID p_shader, const Strin
}
}
-RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const {
+RID MaterialStorage::shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, RID());
if (shader->default_texture_parameter.has(p_name) && shader->default_texture_parameter[p_name].has(p_index)) {
@@ -2402,7 +2493,7 @@ RID MaterialStorage::shader_get_default_texture_param(RID p_shader, const String
return RID();
}
-Variant MaterialStorage::shader_get_param_default(RID p_shader, const StringName &p_param) const {
+Variant MaterialStorage::shader_get_parameter_default(RID p_shader, const StringName &p_param) const {
Shader *shader = shader_owner.get_or_null(p_shader);
ERR_FAIL_COND_V(!shader, Variant());
if (shader->data) {
@@ -2436,7 +2527,7 @@ void MaterialStorage::_material_uniform_set_erased(void *p_material) {
// if a texture is deleted, so re-create it.
MaterialStorage::get_singleton()->_material_queue_update(material, false, true);
}
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
}
@@ -2465,8 +2556,8 @@ void MaterialStorage::_update_queued_materials() {
material_update_list.remove(&material->update_element);
if (uniforms_changed) {
- //some implementations such as 3D renderer cache the matreial uniform set, so update is required
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ //some implementations such as 3D renderer cache the material uniform set, so update is required
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
}
}
@@ -2507,7 +2598,7 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
}
if (p_shader.is_null()) {
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
material->shader_id = 0;
return;
}
@@ -2530,10 +2621,19 @@ void MaterialStorage::material_set_shader(RID p_material, RID p_shader) {
material->data->set_next_pass(material->next_pass);
material->data->set_render_priority(material->priority);
//updating happens later
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
_material_queue_update(material, true, true);
}
+MaterialStorage::ShaderData *MaterialStorage::material_get_shader_data(RID p_material) {
+ const MaterialStorage::Material *material = MaterialStorage::get_singleton()->get_material(p_material);
+ if (material && material->shader && material->shader->data) {
+ return material->shader->data;
+ }
+
+ return nullptr;
+}
+
void MaterialStorage::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) {
Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
@@ -2546,7 +2646,7 @@ void MaterialStorage::material_set_param(RID p_material, const StringName &p_par
}
if (material->shader && material->shader->data) { //shader is valid
- bool is_texture = material->shader->data->is_param_texture(p_param);
+ bool is_texture = material->shader->data->is_parameter_texture(p_param);
_material_queue_update(material, !is_texture, is_texture);
} else {
_material_queue_update(material, true, true);
@@ -2576,7 +2676,7 @@ void MaterialStorage::material_set_next_pass(RID p_material, RID p_next_material
material->data->set_next_pass(p_next_material);
}
- material->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ material->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
}
void MaterialStorage::material_set_render_priority(RID p_material, int priority) {
@@ -2626,7 +2726,7 @@ void MaterialStorage::material_get_instance_shader_parameters(RID p_material, Li
}
}
-void MaterialStorage::material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) {
+void MaterialStorage::material_update_dependency(RID p_material, DependencyTracker *p_instance) {
Material *material = material_owner.get_or_null(p_material);
ERR_FAIL_COND(!material);
p_instance->update_dependency(&material->dependency);
@@ -2635,12 +2735,12 @@ void MaterialStorage::material_update_dependency(RID p_material, RendererStorage
}
}
-void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) {
+void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialStorage::MaterialDataRequestFunction p_function) {
ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX);
material_data_request_func[p_shader_type] = p_function;
}
-MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
+MaterialStorage::MaterialDataRequestFunction MaterialStorage::material_get_data_request_function(ShaderType p_shader_type) {
ERR_FAIL_INDEX_V(p_shader_type, SHADER_TYPE_MAX, nullptr);
return material_data_request_func[p_shader_type];
}
diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h
index f83df05355..fb25e56ed3 100644
--- a/servers/rendering/renderer_rd/storage_rd/material_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h
@@ -31,168 +31,73 @@
#ifndef MATERIAL_STORAGE_RD_H
#define MATERIAL_STORAGE_RD_H
+#include "core/math/projection.h"
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/shader_language.h"
#include "servers/rendering/storage/material_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
-class MaterialStorage;
-
-/* SHADER Structs */
-
-enum ShaderType {
- SHADER_TYPE_2D,
- SHADER_TYPE_3D,
- SHADER_TYPE_PARTICLES,
- SHADER_TYPE_SKY,
- SHADER_TYPE_FOG,
- SHADER_TYPE_MAX
-};
-
-struct ShaderData {
- virtual void set_code(const String &p_Code) = 0;
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const = 0;
-
- virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
- virtual bool is_param_texture(const StringName &p_param) const = 0;
- virtual bool is_animated() const = 0;
- virtual bool casts_shadows() const = 0;
- virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
- virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
-
- virtual ~ShaderData() {}
-};
-
-typedef ShaderData *(*ShaderDataRequestFunction)();
-
-struct Material;
-
-struct Shader {
- ShaderData *data = nullptr;
- String code;
- ShaderType type;
- HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
- HashSet<Material *> owners;
-};
-
-/* Material structs */
-
-struct MaterialData {
- void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
- void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
-
- virtual void set_render_priority(int p_priority) = 0;
- virtual void set_next_pass(RID p_pass) = 0;
- virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
- virtual ~MaterialData();
-
- //to be used internally by update_parameters, in the most common configuration of material parameters
- bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
- void free_parameters_uniform_set(RID p_uniform_set);
-
-private:
- friend class MaterialStorage;
- RID self;
- List<RID>::Element *global_buffer_E = nullptr;
- List<RID>::Element *global_texture_E = nullptr;
- uint64_t global_textures_pass = 0;
- HashMap<StringName, uint64_t> used_global_textures;
-
- //internally by update_parameters_uniform_set
- Vector<uint8_t> ubo_data;
- RID uniform_buffer;
- Vector<RID> texture_cache;
-};
-
-typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
-
-struct Material {
- RID self;
- MaterialData *data = nullptr;
- Shader *shader = nullptr;
- //shortcut to shader data and type
- ShaderType shader_type = SHADER_TYPE_MAX;
- uint32_t shader_id = 0;
- bool uniform_dirty = false;
- bool texture_dirty = false;
- HashMap<StringName, Variant> params;
- int32_t priority = 0;
- RID next_pass;
- SelfList<Material> update_element;
-
- RendererStorage::Dependency dependency;
-
- Material() :
- update_element(this) {}
-};
-
-/* Global variable structs */
-struct GlobalVariables {
- enum {
- BUFFER_DIRTY_REGION_SIZE = 1024
- };
- struct Variable {
- HashSet<RID> texture_materials; // materials using this
-
- RS::GlobalVariableType type;
- Variant value;
- Variant override;
- int32_t buffer_index; //for vectors
- int32_t buffer_elements; //for vectors
+class MaterialStorage : public RendererMaterialStorage {
+public:
+ enum ShaderType {
+ SHADER_TYPE_2D,
+ SHADER_TYPE_3D,
+ SHADER_TYPE_PARTICLES,
+ SHADER_TYPE_SKY,
+ SHADER_TYPE_FOG,
+ SHADER_TYPE_MAX
};
- HashMap<StringName, Variable> variables;
+ struct ShaderData {
+ virtual void set_code(const String &p_Code) = 0;
+ virtual void set_path_hint(const String &p_hint) = 0;
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const = 0;
- struct Value {
- float x;
- float y;
- float z;
- float w;
- };
+ virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const = 0;
+ virtual bool is_parameter_texture(const StringName &p_param) const = 0;
+ virtual bool is_animated() const = 0;
+ virtual bool casts_shadows() const = 0;
+ virtual Variant get_default_parameter(const StringName &p_parameter) const = 0;
+ virtual RS::ShaderNativeSourceCode get_native_source_code() const { return RS::ShaderNativeSourceCode(); }
- struct ValueInt {
- int32_t x;
- int32_t y;
- int32_t z;
- int32_t w;
+ virtual ~ShaderData() {}
};
- struct ValueUInt {
- uint32_t x;
- uint32_t y;
- uint32_t z;
- uint32_t w;
- };
-
- struct ValueUsage {
- uint32_t elements = 0;
- };
+ struct MaterialData {
+ void update_uniform_buffer(const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const HashMap<StringName, Variant> &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color);
+ void update_textures(const HashMap<StringName, Variant> &p_parameters, const HashMap<StringName, HashMap<int, RID>> &p_default_textures, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, RID *p_textures, bool p_use_linear_color);
- List<RID> materials_using_buffer;
- List<RID> materials_using_texture;
+ virtual void set_render_priority(int p_priority) = 0;
+ virtual void set_next_pass(RID p_pass) = 0;
+ virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0;
+ virtual ~MaterialData();
- RID buffer;
- Value *buffer_values = nullptr;
- ValueUsage *buffer_usage = nullptr;
- bool *buffer_dirty_regions = nullptr;
- uint32_t buffer_dirty_region_count = 0;
+ //to be used internally by update_parameters, in the most common configuration of material parameters
+ bool update_parameters_uniform_set(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty, const HashMap<StringName, ShaderLanguage::ShaderNode::Uniform> &p_uniforms, const uint32_t *p_uniform_offsets, const Vector<ShaderCompiler::GeneratedCode::Texture> &p_texture_uniforms, const HashMap<StringName, HashMap<int, RID>> &p_default_texture_params, uint32_t p_ubo_size, RID &uniform_set, RID p_shader, uint32_t p_shader_uniform_set, bool p_use_linear_color, uint32_t p_barrier = RD::BARRIER_MASK_ALL);
+ void free_parameters_uniform_set(RID p_uniform_set);
- uint32_t buffer_size;
+ private:
+ friend class MaterialStorage;
- bool must_update_texture_materials = false;
- bool must_update_buffer_materials = false;
+ RID self;
+ List<RID>::Element *global_buffer_E = nullptr;
+ List<RID>::Element *global_texture_E = nullptr;
+ uint64_t global_textures_pass = 0;
+ HashMap<StringName, uint64_t> used_global_textures;
- HashMap<RID, int32_t> instance_buffer_pos;
-};
+ //internally by update_parameters_uniform_set
+ Vector<uint8_t> ubo_data;
+ RID uniform_buffer;
+ Vector<RID> texture_cache;
+ };
-class MaterialStorage : public RendererMaterialStorage {
private:
- friend struct MaterialData;
static MaterialStorage *singleton;
/* Samplers */
@@ -205,22 +110,116 @@ private:
RID quad_index_buffer;
RID quad_index_array;
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
+
+ struct GlobalShaderUniforms {
+ enum {
+ BUFFER_DIRTY_REGION_SIZE = 1024
+ };
+ struct Variable {
+ HashSet<RID> texture_materials; // materials using this
+
+ RS::GlobalShaderParameterType type;
+ Variant value;
+ Variant override;
+ int32_t buffer_index; //for vectors
+ int32_t buffer_elements; //for vectors
+ };
+
+ HashMap<StringName, Variable> variables;
+
+ struct Value {
+ float x;
+ float y;
+ float z;
+ float w;
+ };
+
+ struct ValueInt {
+ int32_t x;
+ int32_t y;
+ int32_t z;
+ int32_t w;
+ };
+
+ struct ValueUInt {
+ uint32_t x;
+ uint32_t y;
+ uint32_t z;
+ uint32_t w;
+ };
+
+ struct ValueUsage {
+ uint32_t elements = 0;
+ };
+
+ List<RID> materials_using_buffer;
+ List<RID> materials_using_texture;
+
+ RID buffer;
+ Value *buffer_values = nullptr;
+ ValueUsage *buffer_usage = nullptr;
+ bool *buffer_dirty_regions = nullptr;
+ uint32_t buffer_dirty_region_count = 0;
+
+ uint32_t buffer_size;
+
+ bool must_update_texture_materials = false;
+ bool must_update_buffer_materials = false;
+
+ HashMap<RID, int32_t> instance_buffer_pos;
+ } global_shader_uniforms;
+
+ int32_t _global_shader_uniform_allocate(uint32_t p_elements);
+ void _global_shader_uniform_store_in_buffer(int32_t p_index, RS::GlobalShaderParameterType p_type, const Variant &p_value);
+ void _global_shader_uniform_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
- GlobalVariables global_variables;
+ /* SHADER API */
- int32_t _global_variable_allocate(uint32_t p_elements);
- void _global_variable_store_in_buffer(int32_t p_index, RS::GlobalVariableType p_type, const Variant &p_value);
- void _global_variable_mark_buffer_dirty(int32_t p_index, int32_t p_elements);
+ struct Material;
- /* SHADER API */
+ struct Shader {
+ ShaderData *data = nullptr;
+ String code;
+ String path_hint;
+ ShaderType type;
+ HashMap<StringName, HashMap<int, RID>> default_texture_parameter;
+ HashSet<Material *> owners;
+ };
+ typedef ShaderData *(*ShaderDataRequestFunction)();
ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX];
+
mutable RID_Owner<Shader, true> shader_owner;
+ Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); }
/* MATERIAL API */
+
+ typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *);
+
+ struct Material {
+ RID self;
+ MaterialData *data = nullptr;
+ Shader *shader = nullptr;
+ //shortcut to shader data and type
+ ShaderType shader_type = SHADER_TYPE_MAX;
+ uint32_t shader_id = 0;
+ bool uniform_dirty = false;
+ bool texture_dirty = false;
+ HashMap<StringName, Variant> params;
+ int32_t priority = 0;
+ RID next_pass;
+ SelfList<Material> update_element;
+
+ Dependency dependency;
+
+ Material() :
+ update_element(this) {}
+ };
+
MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX];
mutable RID_Owner<Material, true> material_owner;
+ Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
SelfList<Material>::List material_update_list;
@@ -232,6 +231,100 @@ public:
MaterialStorage();
virtual ~MaterialStorage();
+ bool free(RID p_rid);
+
+ /* Helpers */
+
+ static _FORCE_INLINE_ void store_transform(const Transform3D &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[1][0];
+ p_array[2] = p_mtx.basis.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.basis.rows[0][1];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.basis.rows[0][2];
+ p_array[9] = p_mtx.basis.rows[1][2];
+ p_array[10] = p_mtx.basis.rows[2][2];
+ p_array[11] = 0;
+ p_array[12] = p_mtx.origin.x;
+ p_array[13] = p_mtx.origin.y;
+ p_array[14] = p_mtx.origin.z;
+ p_array[15] = 1;
+ }
+
+ static _FORCE_INLINE_ void store_basis_3x4(const Basis &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
+ p_array[11] = 0;
+ }
+
+ static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.rows[0][0];
+ p_array[1] = p_mtx.rows[1][0];
+ p_array[2] = p_mtx.rows[2][0];
+ p_array[3] = 0;
+ p_array[4] = p_mtx.rows[0][1];
+ p_array[5] = p_mtx.rows[1][1];
+ p_array[6] = p_mtx.rows[2][1];
+ p_array[7] = 0;
+ p_array[8] = p_mtx.rows[0][2];
+ p_array[9] = p_mtx.rows[1][2];
+ p_array[10] = p_mtx.rows[2][2];
+ p_array[11] = 0;
+ }
+
+ static _FORCE_INLINE_ void store_transform_transposed_3x4(const Transform3D &p_mtx, float *p_array) {
+ p_array[0] = p_mtx.basis.rows[0][0];
+ p_array[1] = p_mtx.basis.rows[0][1];
+ p_array[2] = p_mtx.basis.rows[0][2];
+ p_array[3] = p_mtx.origin.x;
+ p_array[4] = p_mtx.basis.rows[1][0];
+ p_array[5] = p_mtx.basis.rows[1][1];
+ p_array[6] = p_mtx.basis.rows[1][2];
+ p_array[7] = p_mtx.origin.y;
+ p_array[8] = p_mtx.basis.rows[2][0];
+ p_array[9] = p_mtx.basis.rows[2][1];
+ p_array[10] = p_mtx.basis.rows[2][2];
+ p_array[11] = p_mtx.origin.z;
+ }
+
+ static _FORCE_INLINE_ void store_camera(const Projection &p_mtx, float *p_array) {
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ p_array[i * 4 + j] = p_mtx.columns[i][j];
+ }
+ }
+ }
+
+ static _FORCE_INLINE_ void store_soft_shadow_kernel(const float *p_kernel, float *p_array) {
+ for (int i = 0; i < 128; i++) {
+ p_array[i] = p_kernel[i];
+ }
+ }
+
+ // http://andrewthall.org/papers/df64_qf128.pdf
+#ifdef REAL_T_IS_DOUBLE
+ static _FORCE_INLINE_ void split_double(double a, float *ahi, float *alo) {
+ const double SPLITTER = (1 << 29) + 1;
+ double t = a * SPLITTER;
+ double thi = t - (t - a);
+ double tlo = a - thi;
+ *ahi = (float)thi;
+ *alo = (float)tlo;
+ }
+#endif
+
/* Samplers */
_FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) {
@@ -249,32 +342,31 @@ public:
RID get_quad_index_array() { return quad_index_array; }
- /* GLOBAL VARIABLE API */
+ /* GLOBAL SHADER UNIFORM API */
- void _update_global_variables();
+ void _update_global_shader_uniforms();
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) override;
- virtual void global_variable_remove(const StringName &p_name) override;
- virtual Vector<StringName> global_variable_get_list() const override;
+ virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) override;
+ virtual void global_shader_parameter_remove(const StringName &p_name) override;
+ virtual Vector<StringName> global_shader_parameter_get_list() const override;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) override;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) override;
- virtual Variant global_variable_get(const StringName &p_name) const override;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const override;
- RS::GlobalVariableType global_variable_get_type_internal(const StringName &p_name) const;
+ virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) override;
+ virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) override;
+ virtual Variant global_shader_parameter_get(const StringName &p_name) const override;
+ virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const override;
+ RS::GlobalShaderParameterType global_shader_parameter_get_type_internal(const StringName &p_name) const;
- virtual void global_variables_load_settings(bool p_load_textures = true) override;
- virtual void global_variables_clear() override;
+ virtual void global_shader_parameters_load_settings(bool p_load_textures = true) override;
+ virtual void global_shader_parameters_clear() override;
- virtual int32_t global_variables_instance_allocate(RID p_instance) override;
- virtual void global_variables_instance_free(RID p_instance) override;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) override;
+ virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) override;
+ virtual void global_shader_parameters_instance_free(RID p_instance) override;
+ virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) override;
- RID global_variables_get_storage_buffer() const;
+ RID global_shader_uniforms_get_storage_buffer() const;
/* SHADER API */
- Shader *get_shader(RID p_rid) { return shader_owner.get_or_null(p_rid); };
bool owns_shader(RID p_rid) { return shader_owner.owns(p_rid); };
virtual RID shader_allocate() override;
@@ -282,19 +374,19 @@ public:
virtual void shader_free(RID p_rid) override;
virtual void shader_set_code(RID p_shader, const String &p_code) override;
+ virtual void shader_set_path_hint(RID p_shader, const String &p_path) override;
virtual String shader_get_code(RID p_shader) const override;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
+ virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const override;
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const override;
- virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const override;
+ virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) override;
+ virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const override;
+ virtual Variant shader_get_parameter_default(RID p_shader, const StringName &p_param) const override;
void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function);
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const override;
/* MATERIAL API */
- Material *get_material(RID p_rid) { return material_owner.get_or_null(p_rid); };
bool owns_material(RID p_rid) { return material_owner.owns(p_rid); };
void _material_queue_update(Material *material, bool p_uniform, bool p_texture);
@@ -305,6 +397,7 @@ public:
virtual void material_free(RID p_rid) override;
virtual void material_set_shader(RID p_material, RID p_shader) override;
+ ShaderData *material_get_shader_data(RID p_material);
virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) override;
virtual Variant material_get_param(RID p_material, const StringName &p_param) const override;
@@ -317,7 +410,7 @@ public:
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) override;
- virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) override;
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) override;
void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function);
MaterialDataRequestFunction material_get_data_request_function(ShaderType p_shader_type);
@@ -339,4 +432,4 @@ public:
} // namespace RendererRD
-#endif // !MATERIAL_STORAGE_RD_H
+#endif // MATERIAL_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
index 1e0d67f269..1e74d31383 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "mesh_storage.h"
+#include "../../rendering_server_globals.h"
using namespace RendererRD;
@@ -196,6 +197,24 @@ MeshStorage::~MeshStorage() {
singleton = nullptr;
}
+bool MeshStorage::free(RID p_rid) {
+ if (owns_mesh(p_rid)) {
+ mesh_free(p_rid);
+ return true;
+ } else if (owns_mesh_instance(p_rid)) {
+ mesh_instance_free(p_rid);
+ return true;
+ } else if (owns_multimesh(p_rid)) {
+ multimesh_free(p_rid);
+ return true;
+ } else if (owns_skeleton(p_rid)) {
+ skeleton_free(p_rid);
+ return true;
+ }
+
+ return false;
+}
+
/* MESH API */
RID MeshStorage::mesh_allocate() {
@@ -210,6 +229,8 @@ void MeshStorage::mesh_free(RID p_rid) {
mesh_clear(p_rid);
mesh_set_shadow_mesh(p_rid, RID());
Mesh *mesh = mesh_owner.get_or_null(p_rid);
+ ERR_FAIL_COND(!mesh);
+
mesh->dependency.deleted_notify(p_rid);
if (mesh->instances.size()) {
ERR_PRINT("deleting mesh with active instances");
@@ -218,7 +239,7 @@ void MeshStorage::mesh_free(RID p_rid) {
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
}
mesh_owner.free(p_rid);
@@ -325,8 +346,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
bool use_as_storage = (p_surface.skin_data.size() || mesh->blend_shape_count > 0);
- s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
- s->vertex_buffer_size = p_surface.vertex_data.size();
+ if (p_surface.vertex_data.size()) {
+ s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data, use_as_storage);
+ s->vertex_buffer_size = p_surface.vertex_data.size();
+ }
if (p_surface.attribute_data.size()) {
s->attribute_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.attribute_data.size(), p_surface.attribute_data);
@@ -343,7 +366,7 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
if (p_surface.index_count) {
- bool is_index_16 = p_surface.vertex_count <= 65536;
+ bool is_index_16 = p_surface.vertex_count <= 65536 && p_surface.vertex_count > 0;
s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false);
s->index_count = p_surface.index_count;
@@ -362,6 +385,8 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
}
}
+ ERR_FAIL_COND_MSG(!p_surface.index_count && !p_surface.vertex_count, "Meshes must contain a vertex array, an index array, or both");
+
s->aabb = p_surface.aabb;
s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them.
@@ -375,7 +400,11 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
RD::Uniform u;
u.binding = 0;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
- u.append_id(s->vertex_buffer);
+ if (s->vertex_buffer.is_valid()) {
+ u.append_id(s->vertex_buffer);
+ } else {
+ u.append_id(default_rd_storage_buffer);
+ }
uniforms.push_back(u);
}
{
@@ -414,7 +443,10 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
mesh->bone_aabbs.resize(p_surface.bone_aabbs.size());
}
for (int i = 0; i < p_surface.bone_aabbs.size(); i++) {
- mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]);
+ const AABB &bone = p_surface.bone_aabbs[i];
+ if (bone.has_volume()) {
+ mesh->bone_aabbs.write[i].merge_with(bone);
+ }
}
mesh->aabb.merge_with(p_surface.aabb);
}
@@ -429,12 +461,12 @@ void MeshStorage::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface)
_mesh_instance_add_surface(mi, mesh, mesh->surface_count - 1);
}
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
mesh->material_cache.clear();
@@ -465,6 +497,7 @@ void MeshStorage::mesh_surface_update_vertex_region(RID p_mesh, int p_surface, i
ERR_FAIL_COND(!mesh);
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
ERR_FAIL_COND(p_data.size() == 0);
+ ERR_FAIL_COND(mesh->surfaces[p_surface]->vertex_buffer.is_null());
uint64_t data_size = p_data.size();
const uint8_t *r = p_data.ptr();
@@ -501,7 +534,7 @@ void MeshStorage::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_mat
ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count);
mesh->surfaces[p_surface]->material = p_material;
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MATERIAL);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MATERIAL);
mesh->material_cache.clear();
}
@@ -522,7 +555,9 @@ RS::SurfaceData MeshStorage::mesh_get_surface(RID p_mesh, int p_surface) const {
RS::SurfaceData sd;
sd.format = s.format;
- sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ if (s.vertex_buffer.is_valid()) {
+ sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer);
+ }
if (s.attribute_buffer.is_valid()) {
sd.attribute_data = RD::get_singleton()->buffer_get_data(s.attribute_buffer);
}
@@ -692,7 +727,7 @@ void MeshStorage::mesh_set_shadow_mesh(RID p_mesh, RID p_shadow_mesh) {
shadow_mesh->shadow_owners.insert(mesh);
}
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
void MeshStorage::mesh_clear(RID p_mesh) {
@@ -700,7 +735,9 @@ void MeshStorage::mesh_clear(RID p_mesh) {
ERR_FAIL_COND(!mesh);
for (uint32_t i = 0; i < mesh->surface_count; i++) {
Mesh::Surface &s = *mesh->surfaces[i];
- RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ if (s.vertex_buffer.is_valid()) {
+ RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions
+ }
if (s.attribute_buffer.is_valid()) {
RD::get_singleton()->free(s.attribute_buffer);
}
@@ -740,12 +777,12 @@ void MeshStorage::mesh_clear(RID p_mesh) {
_mesh_instance_clear(mi);
}
mesh->has_bone_weights = false;
- mesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ mesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
for (Mesh *E : mesh->shadow_owners) {
Mesh *shadow_owner = E;
shadow_owner->shadow_mesh = RID();
- shadow_owner->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ shadow_owner->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
}
@@ -756,6 +793,13 @@ bool MeshStorage::mesh_needs_instance(RID p_mesh, bool p_has_skeleton) {
return mesh->blend_shape_count > 0 || (mesh->has_bone_weights && p_has_skeleton);
}
+Dependency *MeshStorage::mesh_get_dependency(RID p_mesh) const {
+ Mesh *mesh = mesh_owner.get_or_null(p_mesh);
+ ERR_FAIL_COND_V(!mesh, nullptr);
+
+ return &mesh->dependency;
+}
+
/* MESH INSTANCE */
RID MeshStorage::mesh_instance_create(RID p_base) {
@@ -839,7 +883,7 @@ void MeshStorage::_mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint3
}
MeshInstance::Surface s;
- if (mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) {
+ if ((mesh->blend_shape_count > 0 || (mesh->surfaces[p_surface]->format & RS::ARRAY_FORMAT_BONES)) && mesh->surfaces[p_surface]->vertex_buffer_size > 0) {
//surface warrants transform
s.vertex_buffer = RD::get_singleton()->vertex_buffer_create(mesh->surfaces[p_surface]->vertex_buffer_size, Vector<uint8_t>(), true);
@@ -1048,10 +1092,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_NORMAL: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
-
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
@@ -1060,9 +1103,9 @@ void MeshStorage::_mesh_surface_generate_version_for_input_mask(Mesh::Surface::V
} break;
case RS::ARRAY_TANGENT: {
vd.offset = stride;
+ vd.format = RD::DATA_FORMAT_R16G16_UNORM;
+ stride += sizeof(uint16_t) * 2;
- vd.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32;
- stride += sizeof(uint32_t);
if (mis) {
buffer = mis->vertex_buffer;
} else {
@@ -1187,7 +1230,13 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
if (multimesh->data_cache_dirty_regions) {
memdelete_arr(multimesh->data_cache_dirty_regions);
multimesh->data_cache_dirty_regions = nullptr;
- multimesh->data_cache_used_dirty_regions = 0;
+ multimesh->data_cache_dirty_region_count = 0;
+ }
+
+ if (multimesh->previous_data_cache_dirty_regions) {
+ memdelete_arr(multimesh->previous_data_cache_dirty_regions);
+ multimesh->previous_data_cache_dirty_regions = nullptr;
+ multimesh->previous_data_cache_dirty_region_count = 0;
}
multimesh->instances = p_instances;
@@ -1204,12 +1253,65 @@ void MeshStorage::multimesh_allocate_data(RID p_multimesh, int p_instances, RS::
multimesh->aabb = AABB();
multimesh->aabb_dirty = false;
multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances);
+ multimesh->motion_vectors_current_offset = 0;
+ multimesh->motion_vectors_previous_offset = 0;
+ multimesh->motion_vectors_last_change = -1;
if (multimesh->instances) {
- multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4);
+ uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float);
+ if (multimesh->motion_vectors_enabled) {
+ buffer_size *= 2;
+ }
+ multimesh->buffer = RD::get_singleton()->storage_buffer_create(buffer_size);
}
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH);
+}
+
+bool MeshStorage::_multimesh_enable_motion_vectors(RID p_multimesh) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, false);
+
+ if (multimesh->motion_vectors_enabled) {
+ return false;
+ }
+
+ multimesh->motion_vectors_enabled = true;
+
+ multimesh->motion_vectors_current_offset = 0;
+ multimesh->motion_vectors_previous_offset = 0;
+ multimesh->motion_vectors_last_change = -1;
+
+ if (!multimesh->data_cache.is_empty()) {
+ multimesh->data_cache.append_array(multimesh->data_cache);
+ }
+
+ if (multimesh->buffer_set) {
+ RD::get_singleton()->barrier();
+ Vector<uint8_t> buffer_data = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ if (!multimesh->data_cache.is_empty()) {
+ memcpy(buffer_data.ptrw(), multimesh->data_cache.ptr(), buffer_data.size());
+ }
+
+ RD::get_singleton()->free(multimesh->buffer);
+ uint32_t buffer_size = multimesh->instances * multimesh->stride_cache * sizeof(float) * 2;
+ multimesh->buffer = RD::get_singleton()->storage_buffer_create(buffer_size);
+ RD::get_singleton()->buffer_update(multimesh->buffer, 0, buffer_data.size(), buffer_data.ptr(), RD::BARRIER_MASK_NO_BARRIER);
+ RD::get_singleton()->buffer_update(multimesh->buffer, buffer_data.size(), buffer_data.size(), buffer_data.ptr());
+ multimesh->uniform_set_3d = RID(); // Cleared by dependency
+ return true;
+ }
+ return false; // Update the transforms uniform set cache
+}
+
+void MeshStorage::_multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset) {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND(!multimesh);
+ r_current_offset = multimesh->motion_vectors_current_offset;
+ if (RSG::rasterizer->get_frame_number() - multimesh->motion_vectors_last_change >= 2) {
+ multimesh->motion_vectors_previous_offset = multimesh->motion_vectors_current_offset;
+ }
+ r_prev_offset = multimesh->motion_vectors_previous_offset;
}
int MeshStorage::multimesh_get_instance_count(RID p_multimesh) const {
@@ -1237,13 +1339,13 @@ void MeshStorage::multimesh_set_mesh(RID p_multimesh, RID p_mesh) {
//need to re-create AABB unfortunately, calling this has a penalty
if (multimesh->buffer_set) {
Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
- const uint8_t *r = buffer.ptr();
+ const uint8_t *r = buffer.ptr() + multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float);
const float *data = reinterpret_cast<const float *>(r);
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
}
}
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MESH);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MESH);
}
#define MULTIMESH_DIRTY_REGION_SIZE 512
@@ -1252,10 +1354,14 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
if (multimesh->data_cache.size() > 0) {
return; //already local
}
- ERR_FAIL_COND(multimesh->data_cache.size() > 0);
+
// this means that the user wants to load/save individual elements,
// for this, the data must reside on CPU, so just copy it there.
- multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache);
+ uint32_t buffer_size = multimesh->instances * multimesh->stride_cache;
+ if (multimesh->motion_vectors_enabled) {
+ buffer_size *= 2;
+ }
+ multimesh->data_cache.resize(buffer_size);
{
float *w = multimesh->data_cache.ptrw();
@@ -1266,15 +1372,48 @@ void MeshStorage::_multimesh_make_local(MultiMesh *multimesh) const {
memcpy(w, r, buffer.size());
}
} else {
- memset(w, 0, (size_t)multimesh->instances * multimesh->stride_cache * sizeof(float));
+ memset(w, 0, buffer_size * sizeof(float));
}
}
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
+ memset(multimesh->data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool));
+ multimesh->data_cache_dirty_region_count = 0;
+
+ multimesh->previous_data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count);
+ memset(multimesh->previous_data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool));
+ multimesh->previous_data_cache_dirty_region_count = 0;
+}
+
+void MeshStorage::_multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh) {
+ ERR_FAIL_COND(multimesh->data_cache.is_empty());
+
+ if (!multimesh->motion_vectors_enabled) {
+ return;
+ }
+
+ uint32_t frame = RSG::rasterizer->get_frame_number();
+ if (multimesh->motion_vectors_last_change != frame) {
+ multimesh->motion_vectors_previous_offset = multimesh->motion_vectors_current_offset;
+ multimesh->motion_vectors_current_offset = multimesh->instances - multimesh->motion_vectors_current_offset;
+ multimesh->motion_vectors_last_change = frame;
+
+ if (multimesh->previous_data_cache_dirty_region_count > 0) {
+ uint8_t *data = (uint8_t *)multimesh->data_cache.ptrw();
+ uint32_t current_ofs = multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float);
+ uint32_t previous_ofs = multimesh->motion_vectors_previous_offset * multimesh->stride_cache * sizeof(float);
+ uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
+ uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
+ uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
+ uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
+ for (uint32_t i = 0; i < visible_region_count; i++) {
+ if (multimesh->previous_data_cache_dirty_regions[i]) {
+ uint32_t offset = i * region_size;
+ memcpy(data + current_ofs + offset, data + previous_ofs + offset, MIN(region_size, size - offset));
+ }
+ }
+ }
}
- multimesh->data_cache_used_dirty_regions = 0;
}
void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) {
@@ -1285,7 +1424,7 @@ void MeshStorage::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool
#endif
if (!multimesh->data_cache_dirty_regions[region_index]) {
multimesh->data_cache_dirty_regions[region_index] = true;
- multimesh->data_cache_used_dirty_regions++;
+ multimesh->data_cache_dirty_region_count++;
}
if (p_aabb) {
@@ -1306,7 +1445,7 @@ void MeshStorage::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, b
for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
if (!multimesh->data_cache_dirty_regions[i]) {
multimesh->data_cache_dirty_regions[i] = true;
- multimesh->data_cache_used_dirty_regions++;
+ multimesh->data_cache_dirty_region_count++;
}
}
}
@@ -1371,11 +1510,12 @@ void MeshStorage::multimesh_instance_set_transform(RID p_multimesh, int p_index,
ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D);
_multimesh_make_local(multimesh);
+ _multimesh_update_motion_vectors_data_cache(multimesh);
{
float *w = multimesh->data_cache.ptrw();
- float *dataptr = w + p_index * multimesh->stride_cache;
+ float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache;
dataptr[0] = p_transform.basis.rows[0][0];
dataptr[1] = p_transform.basis.rows[0][1];
@@ -1401,11 +1541,12 @@ void MeshStorage::multimesh_instance_set_transform_2d(RID p_multimesh, int p_ind
ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D);
_multimesh_make_local(multimesh);
+ _multimesh_update_motion_vectors_data_cache(multimesh);
{
float *w = multimesh->data_cache.ptrw();
- float *dataptr = w + p_index * multimesh->stride_cache;
+ float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache;
dataptr[0] = p_transform.columns[0][0];
dataptr[1] = p_transform.columns[1][0];
@@ -1427,11 +1568,12 @@ void MeshStorage::multimesh_instance_set_color(RID p_multimesh, int p_index, con
ERR_FAIL_COND(!multimesh->uses_colors);
_multimesh_make_local(multimesh);
+ _multimesh_update_motion_vectors_data_cache(multimesh);
{
float *w = multimesh->data_cache.ptrw();
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+ float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->color_offset_cache;
dataptr[0] = p_color.r;
dataptr[1] = p_color.g;
@@ -1449,11 +1591,12 @@ void MeshStorage::multimesh_instance_set_custom_data(RID p_multimesh, int p_inde
ERR_FAIL_COND(!multimesh->uses_custom_data);
_multimesh_make_local(multimesh);
+ _multimesh_update_motion_vectors_data_cache(multimesh);
{
float *w = multimesh->data_cache.ptrw();
- float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+ float *dataptr = w + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->custom_data_offset_cache;
dataptr[0] = p_color.r;
dataptr[1] = p_color.g;
@@ -1471,6 +1614,13 @@ RID MeshStorage::multimesh_get_mesh(RID p_multimesh) const {
return multimesh->mesh;
}
+Dependency *MeshStorage::multimesh_get_dependency(RID p_multimesh) const {
+ MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
+ ERR_FAIL_COND_V(!multimesh, nullptr);
+
+ return &multimesh->dependency;
+}
+
Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p_index) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
ERR_FAIL_COND_V(!multimesh, Transform3D());
@@ -1483,7 +1633,7 @@ Transform3D MeshStorage::multimesh_instance_get_transform(RID p_multimesh, int p
{
const float *r = multimesh->data_cache.ptr();
- const float *dataptr = r + p_index * multimesh->stride_cache;
+ const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache;
t.basis.rows[0][0] = dataptr[0];
t.basis.rows[0][1] = dataptr[1];
@@ -1514,7 +1664,7 @@ Transform2D MeshStorage::multimesh_instance_get_transform_2d(RID p_multimesh, in
{
const float *r = multimesh->data_cache.ptr();
- const float *dataptr = r + p_index * multimesh->stride_cache;
+ const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache;
t.columns[0][0] = dataptr[0];
t.columns[1][0] = dataptr[1];
@@ -1539,7 +1689,7 @@ Color MeshStorage::multimesh_instance_get_color(RID p_multimesh, int p_index) co
{
const float *r = multimesh->data_cache.ptr();
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache;
+ const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->color_offset_cache;
c.r = dataptr[0];
c.g = dataptr[1];
@@ -1562,7 +1712,7 @@ Color MeshStorage::multimesh_instance_get_custom_data(RID p_multimesh, int p_ind
{
const float *r = multimesh->data_cache.ptr();
- const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache;
+ const float *dataptr = r + (multimesh->motion_vectors_current_offset + p_index) * multimesh->stride_cache + multimesh->custom_data_offset_cache;
c.r = dataptr[0];
c.g = dataptr[1];
@@ -1578,31 +1728,32 @@ void MeshStorage::multimesh_set_buffer(RID p_multimesh, const Vector<float> &p_b
ERR_FAIL_COND(!multimesh);
ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache));
+ if (multimesh->motion_vectors_enabled) {
+ uint32_t frame = RSG::rasterizer->get_frame_number();
+
+ if (multimesh->motion_vectors_last_change != frame) {
+ multimesh->motion_vectors_previous_offset = multimesh->motion_vectors_current_offset;
+ multimesh->motion_vectors_current_offset = multimesh->instances - multimesh->motion_vectors_current_offset;
+ multimesh->motion_vectors_last_change = frame;
+ }
+ }
+
{
const float *r = p_buffer.ptr();
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r);
+ RD::get_singleton()->buffer_update(multimesh->buffer, multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float), p_buffer.size() * sizeof(float), r);
multimesh->buffer_set = true;
}
if (multimesh->data_cache.size()) {
- //if we have a data cache, just update it
- multimesh->data_cache = p_buffer;
- {
- //clear dirty since nothing will be dirty anymore
- uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
- multimesh->data_cache_used_dirty_regions = 0;
- }
-
- _multimesh_mark_all_dirty(multimesh, false, true); //update AABB
+ float *cache_data = multimesh->data_cache.ptrw();
+ memcpy(cache_data + (multimesh->motion_vectors_current_offset * multimesh->stride_cache), p_buffer.ptr(), p_buffer.size() * sizeof(float));
+ _multimesh_mark_all_dirty(multimesh, true, true); //update AABB
} else if (multimesh->mesh.is_valid()) {
//if we have a mesh set, we need to re-generate the AABB from the new data
const float *data = p_buffer.ptr();
_multimesh_re_create_aabb(multimesh, data, multimesh->instances);
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
@@ -1611,20 +1762,19 @@ Vector<float> MeshStorage::multimesh_get_buffer(RID p_multimesh) const {
ERR_FAIL_COND_V(!multimesh, Vector<float>());
if (multimesh->buffer.is_null()) {
return Vector<float>();
- } else if (multimesh->data_cache.size()) {
- return multimesh->data_cache;
} else {
- //get from memory
-
- Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
Vector<float> ret;
ret.resize(multimesh->instances * multimesh->stride_cache);
- {
- float *w = ret.ptrw();
- const uint8_t *r = buffer.ptr();
- memcpy(w, r, buffer.size());
- }
+ float *w = ret.ptrw();
+ if (multimesh->data_cache.size()) {
+ const uint8_t *r = (uint8_t *)multimesh->data_cache.ptr() + multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float);
+ memcpy(w, r, ret.size() * sizeof(float));
+ } else {
+ Vector<uint8_t> buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer);
+ const uint8_t *r = buffer.ptr() + multimesh->motion_vectors_current_offset * multimesh->stride_cache * sizeof(float);
+ memcpy(w, r, ret.size() * sizeof(float));
+ }
return ret;
}
}
@@ -1644,7 +1794,7 @@ void MeshStorage::multimesh_set_visible_instances(RID p_multimesh, int p_visible
multimesh->visible_instances = p_visible;
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES);
}
int MeshStorage::multimesh_get_visible_instances(RID p_multimesh) const {
@@ -1667,43 +1817,45 @@ void MeshStorage::_update_dirty_multimeshes() {
MultiMesh *multimesh = multimesh_dirty_list;
if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists
- const float *data = multimesh->data_cache.ptr();
uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances;
+ uint32_t buffer_offset = multimesh->motion_vectors_current_offset * multimesh->stride_cache;
+ const float *data = multimesh->data_cache.ptr() + buffer_offset;
- if (multimesh->data_cache_used_dirty_regions) {
+ uint32_t total_dirty_regions = multimesh->data_cache_dirty_region_count + multimesh->previous_data_cache_dirty_region_count;
+ if (total_dirty_regions != 0) {
uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t visible_region_count = visible_instances == 0 ? 0 : (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1;
uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float);
-
- if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) {
+ if (total_dirty_regions > 32 || total_dirty_regions > visible_region_count / 2) {
//if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much
- RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
+ RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float), MIN(visible_region_count * region_size, multimesh->instances * (uint32_t)multimesh->stride_cache * (uint32_t)sizeof(float)), data);
} else {
//not that many regions? update them all
for (uint32_t i = 0; i < visible_region_count; i++) {
- if (multimesh->data_cache_dirty_regions[i]) {
+ if (multimesh->data_cache_dirty_regions[i] || multimesh->previous_data_cache_dirty_regions[i]) {
uint32_t offset = i * region_size;
uint32_t size = multimesh->stride_cache * (uint32_t)multimesh->instances * (uint32_t)sizeof(float);
uint32_t region_start_index = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * i;
- RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[region_start_index]);
+ RD::get_singleton()->buffer_update(multimesh->buffer, buffer_offset * sizeof(float) + offset, MIN(region_size, size - offset), &data[region_start_index], RD::BARRIER_MASK_NO_BARRIER);
}
}
+ RD::get_singleton()->barrier(RD::BARRIER_MASK_NO_BARRIER, RD::BARRIER_MASK_ALL);
}
- for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) {
- multimesh->data_cache_dirty_regions[i] = false;
- }
+ memcpy(multimesh->previous_data_cache_dirty_regions, multimesh->data_cache_dirty_regions, data_cache_dirty_region_count * sizeof(bool));
+ memset(multimesh->data_cache_dirty_regions, 0, data_cache_dirty_region_count * sizeof(bool));
- multimesh->data_cache_used_dirty_regions = 0;
+ multimesh->previous_data_cache_dirty_region_count = multimesh->data_cache_dirty_region_count;
+ multimesh->data_cache_dirty_region_count = 0;
}
if (multimesh->aabb_dirty) {
//aabb is dirty..
_multimesh_re_create_aabb(multimesh, data, visible_instances);
multimesh->aabb_dirty = false;
- multimesh->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ multimesh->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
@@ -1781,7 +1933,7 @@ void MeshStorage::skeleton_allocate_data(RID p_skeleton, int p_bones, bool p_2d_
}
}
- skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA);
+ skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_DATA);
}
int MeshStorage::skeleton_get_bone_count(RID p_skeleton) const {
@@ -1887,6 +2039,7 @@ Transform2D MeshStorage::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bo
void MeshStorage::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) {
Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
+ ERR_FAIL_NULL(skeleton);
ERR_FAIL_COND(!skeleton->use_2d);
skeleton->base_transform_2d = p_base_transform;
@@ -1902,7 +2055,7 @@ void MeshStorage::_update_dirty_skeletons() {
skeleton_dirty_list = skeleton->dirty_list;
- skeleton->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES);
+ skeleton->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_SKELETON_BONES);
skeleton->version++;
@@ -1913,7 +2066,7 @@ void MeshStorage::_update_dirty_skeletons() {
skeleton_dirty_list = nullptr;
}
-void MeshStorage::skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) {
+void MeshStorage::skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) {
Skeleton *skeleton = skeleton_owner.get_or_null(p_skeleton);
ERR_FAIL_COND(!skeleton);
diff --git a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
index 7ce019cf98..6a7400631d 100644
--- a/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/mesh_storage.h
@@ -35,245 +35,156 @@
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
#include "servers/rendering/renderer_rd/shaders/skeleton.glsl.gen.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/storage/mesh_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
-/* Mesh */
-
-enum DefaultRDBuffer {
- DEFAULT_RD_BUFFER_VERTEX,
- DEFAULT_RD_BUFFER_NORMAL,
- DEFAULT_RD_BUFFER_TANGENT,
- DEFAULT_RD_BUFFER_COLOR,
- DEFAULT_RD_BUFFER_TEX_UV,
- DEFAULT_RD_BUFFER_TEX_UV2,
- DEFAULT_RD_BUFFER_CUSTOM0,
- DEFAULT_RD_BUFFER_CUSTOM1,
- DEFAULT_RD_BUFFER_CUSTOM2,
- DEFAULT_RD_BUFFER_CUSTOM3,
- DEFAULT_RD_BUFFER_BONES,
- DEFAULT_RD_BUFFER_WEIGHTS,
- DEFAULT_RD_BUFFER_MAX,
-};
+class MeshStorage : public RendererMeshStorage {
+public:
+ enum DefaultRDBuffer {
+ DEFAULT_RD_BUFFER_VERTEX,
+ DEFAULT_RD_BUFFER_NORMAL,
+ DEFAULT_RD_BUFFER_TANGENT,
+ DEFAULT_RD_BUFFER_COLOR,
+ DEFAULT_RD_BUFFER_TEX_UV,
+ DEFAULT_RD_BUFFER_TEX_UV2,
+ DEFAULT_RD_BUFFER_CUSTOM0,
+ DEFAULT_RD_BUFFER_CUSTOM1,
+ DEFAULT_RD_BUFFER_CUSTOM2,
+ DEFAULT_RD_BUFFER_CUSTOM3,
+ DEFAULT_RD_BUFFER_BONES,
+ DEFAULT_RD_BUFFER_WEIGHTS,
+ DEFAULT_RD_BUFFER_MAX,
+ };
-struct MeshInstance;
-
-struct Mesh {
- struct Surface {
- RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
- uint32_t format = 0;
-
- RID vertex_buffer;
- RID attribute_buffer;
- RID skin_buffer;
- uint32_t vertex_count = 0;
- uint32_t vertex_buffer_size = 0;
- uint32_t skin_buffer_size = 0;
-
- // A different pipeline needs to be allocated
- // depending on the inputs available in the
- // material.
- // There are never that many geometry/material
- // combinations, so a simple array is the most
- // cache-efficient structure.
-
- struct Version {
- uint32_t input_mask = 0;
- RD::VertexFormatID vertex_format = 0;
- RID vertex_array;
- };
+private:
+ static MeshStorage *singleton;
- SpinLock version_lock; //needed to access versions
- Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
+ RID default_rd_storage_buffer;
- RID index_buffer;
- RID index_array;
- uint32_t index_count = 0;
+ /* Mesh */
- struct LOD {
- float edge_length = 0.0;
- uint32_t index_count = 0;
- RID index_buffer;
- RID index_array;
- };
+ RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
- LOD *lods = nullptr;
- uint32_t lod_count = 0;
+ struct MeshInstance;
+
+ struct Mesh {
+ struct Surface {
+ RS::PrimitiveType primitive = RS::PRIMITIVE_POINTS;
+ uint32_t format = 0;
+
+ RID vertex_buffer;
+ RID attribute_buffer;
+ RID skin_buffer;
+ uint32_t vertex_count = 0;
+ uint32_t vertex_buffer_size = 0;
+ uint32_t skin_buffer_size = 0;
+
+ // A different pipeline needs to be allocated
+ // depending on the inputs available in the
+ // material.
+ // There are never that many geometry/material
+ // combinations, so a simple array is the most
+ // cache-efficient structure.
+
+ struct Version {
+ uint32_t input_mask = 0;
+ RD::VertexFormatID vertex_format = 0;
+ RID vertex_array;
+ };
+
+ SpinLock version_lock; //needed to access versions
+ Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
- AABB aabb;
+ RID index_buffer;
+ RID index_array;
+ uint32_t index_count = 0;
- Vector<AABB> bone_aabbs;
+ struct LOD {
+ float edge_length = 0.0;
+ uint32_t index_count = 0;
+ RID index_buffer;
+ RID index_array;
+ };
- RID blend_shape_buffer;
+ LOD *lods = nullptr;
+ uint32_t lod_count = 0;
- RID material;
+ AABB aabb;
- uint32_t render_index = 0;
- uint64_t render_pass = 0;
+ Vector<AABB> bone_aabbs;
- uint32_t multimesh_render_index = 0;
- uint64_t multimesh_render_pass = 0;
+ RID blend_shape_buffer;
- uint32_t particles_render_index = 0;
- uint64_t particles_render_pass = 0;
+ RID material;
- RID uniform_set;
- };
+ uint32_t render_index = 0;
+ uint64_t render_pass = 0;
- uint32_t blend_shape_count = 0;
- RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
+ uint32_t multimesh_render_index = 0;
+ uint64_t multimesh_render_pass = 0;
- Surface **surfaces = nullptr;
- uint32_t surface_count = 0;
+ uint32_t particles_render_index = 0;
+ uint64_t particles_render_pass = 0;
- Vector<AABB> bone_aabbs;
+ RID uniform_set;
+ };
- bool has_bone_weights = false;
+ uint32_t blend_shape_count = 0;
+ RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED;
- AABB aabb;
- AABB custom_aabb;
+ Surface **surfaces = nullptr;
+ uint32_t surface_count = 0;
- Vector<RID> material_cache;
+ Vector<AABB> bone_aabbs;
- List<MeshInstance *> instances;
+ bool has_bone_weights = false;
- RID shadow_mesh;
- HashSet<Mesh *> shadow_owners;
+ AABB aabb;
+ AABB custom_aabb;
- RendererStorage::Dependency dependency;
-};
+ Vector<RID> material_cache;
-/* Mesh Instance */
+ List<MeshInstance *> instances;
-struct MeshInstance {
- Mesh *mesh = nullptr;
- RID skeleton;
- struct Surface {
- RID vertex_buffer;
- RID uniform_set;
+ RID shadow_mesh;
+ HashSet<Mesh *> shadow_owners;
- Mesh::Surface::Version *versions = nullptr; //allocated on demand
- uint32_t version_count = 0;
+ Dependency dependency;
};
- LocalVector<Surface> surfaces;
- LocalVector<float> blend_weights;
-
- RID blend_weights_buffer;
- List<MeshInstance *>::Element *I = nullptr; //used to erase itself
- uint64_t skeleton_version = 0;
- bool dirty = false;
- bool weights_dirty = false;
- SelfList<MeshInstance> weight_update_list;
- SelfList<MeshInstance> array_update_list;
- MeshInstance() :
- weight_update_list(this), array_update_list(this) {}
-};
-
-/* MultiMesh */
-
-struct MultiMesh {
- RID mesh;
- int instances = 0;
- RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
- bool uses_colors = false;
- bool uses_custom_data = false;
- int visible_instances = -1;
- AABB aabb;
- bool aabb_dirty = false;
- bool buffer_set = false;
- uint32_t stride_cache = 0;
- uint32_t color_offset_cache = 0;
- uint32_t custom_data_offset_cache = 0;
-
- Vector<float> data_cache; //used if individual setting is used
- bool *data_cache_dirty_regions = nullptr;
- uint32_t data_cache_used_dirty_regions = 0;
-
- RID buffer; //storage buffer
- RID uniform_set_3d;
- RID uniform_set_2d;
-
- bool dirty = false;
- MultiMesh *dirty_list = nullptr;
-
- RendererStorage::Dependency dependency;
-};
-/* Skeleton */
-
-struct SkeletonShader {
- struct PushConstant {
- uint32_t has_normal;
- uint32_t has_tangent;
- uint32_t has_skeleton;
- uint32_t has_blend_shape;
+ mutable RID_Owner<Mesh, true> mesh_owner;
- uint32_t vertex_count;
- uint32_t vertex_stride;
- uint32_t skin_stride;
- uint32_t skin_weight_offset;
+ /* Mesh Instance API */
- uint32_t blend_shape_count;
- uint32_t normalized_blend_shapes;
- uint32_t pad0;
- uint32_t pad1;
- };
+ struct MeshInstance {
+ Mesh *mesh = nullptr;
+ RID skeleton;
+ struct Surface {
+ RID vertex_buffer;
+ RID uniform_set;
- enum {
- UNIFORM_SET_INSTANCE = 0,
- UNIFORM_SET_SURFACE = 1,
- UNIFORM_SET_SKELETON = 2,
- };
- enum {
- SHADER_MODE_2D,
- SHADER_MODE_3D,
- SHADER_MODE_MAX
+ Mesh::Surface::Version *versions = nullptr; //allocated on demand
+ uint32_t version_count = 0;
+ };
+ LocalVector<Surface> surfaces;
+ LocalVector<float> blend_weights;
+
+ RID blend_weights_buffer;
+ List<MeshInstance *>::Element *I = nullptr; //used to erase itself
+ uint64_t skeleton_version = 0;
+ bool dirty = false;
+ bool weights_dirty = false;
+ SelfList<MeshInstance> weight_update_list;
+ SelfList<MeshInstance> array_update_list;
+ MeshInstance() :
+ weight_update_list(this), array_update_list(this) {}
};
- SkeletonShaderRD shader;
- RID version;
- RID version_shader[SHADER_MODE_MAX];
- RID pipeline[SHADER_MODE_MAX];
-
- RID default_skeleton_uniform_set;
-};
-
-struct Skeleton {
- bool use_2d = false;
- int size = 0;
- Vector<float> data;
- RID buffer;
-
- bool dirty = false;
- Skeleton *dirty_list = nullptr;
- Transform2D base_transform_2d;
-
- RID uniform_set_3d;
- RID uniform_set_mi;
-
- uint64_t version = 1;
-
- RendererStorage::Dependency dependency;
-};
-
-class MeshStorage : public RendererMeshStorage {
-private:
- static MeshStorage *singleton;
-
- RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX];
- RID default_rd_storage_buffer;
-
- /* Mesh */
-
- mutable RID_Owner<Mesh, true> mesh_owner;
-
void _mesh_surface_generate_version_for_input_mask(Mesh::Surface::Version &v, Mesh::Surface *s, uint32_t p_input_mask, MeshInstance::Surface *mis = nullptr);
- /* Mesh Instance API */
-
void _mesh_instance_clear(MeshInstance *mi);
void _mesh_instance_add_surface(MeshInstance *mi, Mesh *mesh, uint32_t p_surface);
@@ -284,18 +195,106 @@ private:
/* MultiMesh */
+ struct MultiMesh {
+ RID mesh;
+ int instances = 0;
+ RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D;
+ bool uses_colors = false;
+ bool uses_custom_data = false;
+ int visible_instances = -1;
+ AABB aabb;
+ bool aabb_dirty = false;
+ bool buffer_set = false;
+ bool motion_vectors_enabled = false;
+ uint32_t motion_vectors_current_offset = 0;
+ uint32_t motion_vectors_previous_offset = 0;
+ uint64_t motion_vectors_last_change = -1;
+ uint32_t stride_cache = 0;
+ uint32_t color_offset_cache = 0;
+ uint32_t custom_data_offset_cache = 0;
+
+ Vector<float> data_cache; //used if individual setting is used
+ bool *data_cache_dirty_regions = nullptr;
+ uint32_t data_cache_dirty_region_count = 0;
+ bool *previous_data_cache_dirty_regions = nullptr;
+ uint32_t previous_data_cache_dirty_region_count = 0;
+
+ RID buffer; //storage buffer
+ RID uniform_set_3d;
+ RID uniform_set_2d;
+
+ bool dirty = false;
+ MultiMesh *dirty_list = nullptr;
+
+ Dependency dependency;
+ };
+
mutable RID_Owner<MultiMesh, true> multimesh_owner;
MultiMesh *multimesh_dirty_list = nullptr;
_FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const;
+ _FORCE_INLINE_ void _multimesh_update_motion_vectors_data_cache(MultiMesh *multimesh);
_FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb);
_FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb);
_FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances);
/* Skeleton */
- SkeletonShader skeleton_shader;
+ struct SkeletonShader {
+ struct PushConstant {
+ uint32_t has_normal;
+ uint32_t has_tangent;
+ uint32_t has_skeleton;
+ uint32_t has_blend_shape;
+
+ uint32_t vertex_count;
+ uint32_t vertex_stride;
+ uint32_t skin_stride;
+ uint32_t skin_weight_offset;
+
+ uint32_t blend_shape_count;
+ uint32_t normalized_blend_shapes;
+ uint32_t pad0;
+ uint32_t pad1;
+ };
+
+ enum {
+ UNIFORM_SET_INSTANCE = 0,
+ UNIFORM_SET_SURFACE = 1,
+ UNIFORM_SET_SKELETON = 2,
+ };
+ enum {
+ SHADER_MODE_2D,
+ SHADER_MODE_3D,
+ SHADER_MODE_MAX
+ };
+
+ SkeletonShaderRD shader;
+ RID version;
+ RID version_shader[SHADER_MODE_MAX];
+ RID pipeline[SHADER_MODE_MAX];
+
+ RID default_skeleton_uniform_set;
+ } skeleton_shader;
+
+ struct Skeleton {
+ bool use_2d = false;
+ int size = 0;
+ Vector<float> data;
+ RID buffer;
+
+ bool dirty = false;
+ Skeleton *dirty_list = nullptr;
+ Transform2D base_transform_2d;
+
+ RID uniform_set_3d;
+ RID uniform_set_mi;
+
+ uint64_t version = 1;
+
+ Dependency dependency;
+ };
mutable RID_Owner<Skeleton, true> skeleton_owner;
@@ -309,11 +308,12 @@ public:
MeshStorage();
virtual ~MeshStorage();
- RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; }
+ bool free(RID p_rid);
+
+ RID get_default_rd_storage_buffer() const { return default_rd_storage_buffer; }
/* MESH API */
- Mesh *get_mesh(RID p_rid) { return mesh_owner.get_or_null(p_rid); };
bool owns_mesh(RID p_rid) { return mesh_owner.owns(p_rid); };
virtual RID mesh_allocate() override;
@@ -398,13 +398,11 @@ public:
return s->index_count ? s->index_count : s->vertex_count;
}
- _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t *r_index_count = nullptr) const {
+ _FORCE_INLINE_ uint32_t mesh_surface_get_lod(void *p_surface, float p_model_scale, float p_distance_threshold, float p_mesh_lod_threshold, uint32_t &r_index_count) const {
Mesh::Surface *s = reinterpret_cast<Mesh::Surface *>(p_surface);
int32_t current_lod = -1;
- if (r_index_count) {
- *r_index_count = s->index_count;
- }
+ r_index_count = s->index_count;
for (uint32_t i = 0; i < s->lod_count; i++) {
float screen_size = s->lods[i].edge_length * p_model_scale / p_distance_threshold;
if (screen_size > p_mesh_lod_threshold) {
@@ -415,9 +413,7 @@ public:
if (current_lod == -1) {
return 0;
} else {
- if (r_index_count) {
- *r_index_count = s->lods[current_lod].index_count;
- }
+ r_index_count = s->lods[current_lod].index_count;
return current_lod + 1;
}
}
@@ -542,10 +538,11 @@ public:
return s->particles_render_index;
}
+ Dependency *mesh_get_dependency(RID p_mesh) const;
+
/* MESH INSTANCE API */
- MeshInstance *get_mesh_instance(RID p_rid) { return mesh_instance_owner.get_or_null(p_rid); };
- bool owns_mesh_instance(RID p_rid) { return mesh_instance_owner.owns(p_rid); };
+ bool owns_mesh_instance(RID p_rid) const { return mesh_instance_owner.owns(p_rid); };
virtual RID mesh_instance_create(RID p_base) override;
virtual void mesh_instance_free(RID p_rid) override;
@@ -556,7 +553,6 @@ public:
/* MULTIMESH API */
- MultiMesh *get_multimesh(RID p_rid) { return multimesh_owner.get_or_null(p_rid); };
bool owns_multimesh(RID p_rid) { return multimesh_owner.owns(p_rid); };
virtual RID multimesh_allocate() override;
@@ -588,6 +584,8 @@ public:
virtual AABB multimesh_get_aabb(RID p_multimesh) const override;
void _update_dirty_multimeshes();
+ bool _multimesh_enable_motion_vectors(RID p_multimesh);
+ void _multimesh_get_motion_vectors_offsets(RID p_multimesh, uint32_t &r_current_offset, uint32_t &r_prev_offset);
_FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const {
MultiMesh *multimesh = multimesh_owner.get_or_null(p_multimesh);
@@ -654,10 +652,11 @@ public:
return multimesh->uniform_set_2d;
}
+ Dependency *multimesh_get_dependency(RID p_multimesh) const;
+
/* SKELETON API */
- Skeleton *get_skeleton(RID p_rid) { return skeleton_owner.get_or_null(p_rid); };
- bool owns_skeleton(RID p_rid) { return skeleton_owner.owns(p_rid); };
+ bool owns_skeleton(RID p_rid) const { return skeleton_owner.owns(p_rid); };
virtual RID skeleton_allocate() override;
virtual void skeleton_initialize(RID p_skeleton) override;
@@ -672,7 +671,7 @@ public:
virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) override;
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const override;
- virtual void skeleton_update_dependency(RID p_skeleton, RendererStorage::DependencyTracker *p_instance) override;
+ virtual void skeleton_update_dependency(RID p_skeleton, DependencyTracker *p_instance) override;
void _update_dirty_skeletons();
@@ -703,4 +702,4 @@ public:
} // namespace RendererRD
-#endif // !MESH_STORAGE_RD_H
+#endif // MESH_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
index 58a96ed1f9..854976692e 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp
@@ -29,8 +29,8 @@
/*************************************************************************/
#include "particles_storage.h"
+
#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/rendering_server_globals.h"
#include "texture_storage.h"
@@ -55,8 +55,8 @@ ParticlesStorage::ParticlesStorage() {
particles_modes.push_back("");
particles_shader.shader.initialize(particles_modes, String());
}
- MaterialStorage::get_singleton()->shader_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
- MaterialStorage::get_singleton()->material_set_data_request_function(SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
+ MaterialStorage::get_singleton()->shader_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_shader_funcs);
+ MaterialStorage::get_singleton()->material_set_data_request_function(MaterialStorage::SHADER_TYPE_PARTICLES, _create_particles_material_funcs);
{
ShaderCompiler::DefaultIdentifierActions actions;
@@ -103,7 +103,7 @@ ParticlesStorage::ParticlesStorage() {
actions.render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n";
actions.render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n";
actions.render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n";
- actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISON_SCALE\n";
+ actions.render_mode_defines["collision_use_scale"] = "#define USE_COLLISION_SCALE\n";
actions.sampler_array_name = "material_samplers";
actions.base_texture_binding_index = 1;
@@ -113,7 +113,7 @@ ParticlesStorage::ParticlesStorage() {
actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP;
actions.default_repeat = ShaderLanguage::REPEAT_ENABLE;
- actions.global_buffer_array_variable = "global_variables.data";
+ actions.global_buffer_array_variable = "global_shader_uniforms.data";
particles_shader.compiler.initialize(actions);
}
@@ -135,7 +135,7 @@ void process() {
material_storage->material_initialize(particles_shader.default_material);
material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader);
- ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ ParticleProcessMaterialData *md = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0);
Vector<RD::Uniform> uniforms;
@@ -165,7 +165,7 @@ void process() {
RD::Uniform u;
u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;
u.binding = 2;
- u.append_id(material_storage->global_variables_get_storage_buffer());
+ u.append_id(material_storage->global_shader_uniforms_get_storage_buffer());
uniforms.push_back(u);
}
@@ -209,6 +209,21 @@ ParticlesStorage::~ParticlesStorage() {
singleton = nullptr;
}
+bool ParticlesStorage::free(RID p_rid) {
+ if (owns_particles(p_rid)) {
+ particles_free(p_rid);
+ return true;
+ } else if (owns_particles_collision(p_rid)) {
+ particles_collision_free(p_rid);
+ return true;
+ } else if (owns_particles_collision_instance(p_rid)) {
+ particles_collision_instance_free(p_rid);
+ return true;
+ }
+
+ return false;
+}
+
/* PARTICLES */
RID ParticlesStorage::particles_allocate() {
@@ -321,7 +336,7 @@ void ParticlesStorage::particles_set_amount(RID p_particles, int p_amount) {
particles->prev_phase = 0;
particles->clear = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_lifetime(RID p_particles, double p_lifetime) {
@@ -356,7 +371,7 @@ void ParticlesStorage::particles_set_custom_aabb(RID p_particles, const AABB &p_
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_COND(!particles);
particles->custom_aabb = p_aabb;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_set_speed_scale(RID p_particles, double p_scale) {
@@ -370,7 +385,7 @@ void ParticlesStorage::particles_set_use_local_coordinates(RID p_particles, bool
ERR_FAIL_COND(!particles);
particles->use_local_coords = p_enable;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
@@ -386,7 +401,7 @@ void ParticlesStorage::particles_set_fixed_fps(RID p_particles, int p_fps) {
particles->prev_phase = 0;
particles->clear = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_interpolate(RID p_particles, bool p_enable) {
@@ -410,7 +425,7 @@ void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, doub
p_length = MIN(10.0, p_length);
particles->trails_enabled = p_enable;
- particles->trail_length = p_length;
+ particles->trail_lifetime = p_length;
_particles_free_data(particles);
@@ -419,7 +434,7 @@ void ParticlesStorage::particles_set_trails(RID p_particles, bool p_enable, doub
particles->prev_phase = 0;
particles->clear = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vector<Transform3D> &p_bind_poses) {
@@ -436,7 +451,7 @@ void ParticlesStorage::particles_set_trail_bind_poses(RID p_particles, const Vec
particles->trail_bind_poses = p_bind_poses;
particles->trail_bind_poses_dirty = true;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES);
}
void ParticlesStorage::particles_set_collision_base_size(RID p_particles, real_t p_size) {
@@ -458,7 +473,7 @@ void ParticlesStorage::particles_set_process_material(RID p_particles, RID p_mat
ERR_FAIL_COND(!particles);
particles->process_material = p_material;
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_PARTICLES); //the instance buffer may have changed
}
RID ParticlesStorage::particles_get_process_material(RID p_particles) const {
@@ -545,7 +560,7 @@ void ParticlesStorage::particles_emit(RID p_particles, const Transform3D &p_tran
int32_t idx = particles->emission_buffer->particle_count;
if (idx < particles->emission_buffer->particle_max) {
- RendererStorageRD::store_transform(p_transform, particles->emission_buffer->data[idx].xform);
+ RendererRD::MaterialStorage::store_transform(p_transform, particles->emission_buffer->data[idx].xform);
particles->emission_buffer->data[idx].velocity[0] = p_velocity.x;
particles->emission_buffer->data[idx].velocity[1] = p_velocity.y;
@@ -766,9 +781,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
frame_params.randomness = p_particles->randomness;
if (p_particles->use_local_coords) {
- RendererStorageRD::store_transform(Transform3D(), frame_params.emission_transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), frame_params.emission_transform);
} else {
- RendererStorageRD::store_transform(p_particles->emission_transform, frame_params.emission_transform);
+ RendererRD::MaterialStorage::store_transform(p_particles->emission_transform, frame_params.emission_transform);
}
frame_params.cycle = p_particles->cycle_number;
@@ -858,7 +873,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
ParticlesFrameParams::Attractor &attr = frame_params.attractors[frame_params.attractor_count];
- RendererStorageRD::store_transform(to_collider, attr.transform);
+ RendererRD::MaterialStorage::store_transform(to_collider, attr.transform);
attr.strength = pc->attractor_strength;
attr.attenuation = pc->attractor_attenuation;
attr.directionality = pc->attractor_directionality;
@@ -906,7 +921,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
ParticlesFrameParams::Collider &col = frame_params.colliders[frame_params.collider_count];
- RendererStorageRD::store_transform(to_collider, col.transform);
+ RendererRD::MaterialStorage::store_transform(to_collider, col.transform);
switch (pc->type) {
case RS::PARTICLES_COLLISION_TYPE_SPHERE_COLLIDE: {
col.type = ParticlesFrameParams::COLLISION_TYPE_SPHERE;
@@ -988,14 +1003,13 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
for (uint32_t i = 0; i < ParticlesFrameParams::MAX_3D_TEXTURES; i++) {
RID rd_tex;
if (i < collision_3d_textures_used) {
- Texture *t = TextureStorage::get_singleton()->get_texture(collision_3d_textures[i]);
- if (t && t->type == Texture::TYPE_3D) {
- rd_tex = t->rd_texture;
+ if (TextureStorage::get_singleton()->texture_get_type(collision_3d_textures[i]) == TextureStorage::TYPE_3D) {
+ rd_tex = TextureStorage::get_singleton()->texture_get_rd_texture(collision_3d_textures[i]);
}
}
if (rd_tex == RID()) {
- rd_tex = texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_3D_WHITE);
+ rd_tex = texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_3D_WHITE);
}
u.append_id(rd_tex);
}
@@ -1008,7 +1022,7 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
if (collision_heightmap_texture.is_valid()) {
u.append_id(collision_heightmap_texture);
} else {
- u.append_id(texture_storage->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK));
+ u.append_id(texture_storage->texture_rd_get_default(TextureStorage::DEFAULT_RD_TEXTURE_BLACK));
}
uniforms.push_back(u);
}
@@ -1074,9 +1088,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta
RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr());
- ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, SHADER_TYPE_PARTICLES));
+ ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES));
if (!m) {
- m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, SHADER_TYPE_PARTICLES));
+ m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES));
}
ERR_FAIL_COND(!m);
@@ -1203,10 +1217,12 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
RD::get_singleton()->compute_list_dispatch_threads(compute_list, particles->amount, 1, 1);
RD::get_singleton()->compute_list_end();
- RendererStorageRD::base_singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
+ RendererCompositorRD::singleton->get_effects()->sort_buffer(particles->particles_sort_uniform_set, particles->amount);
}
- copy_push_constant.total_particles *= copy_push_constant.total_particles;
+ if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
+ copy_push_constant.total_particles *= particles->trail_bind_poses.size();
+ }
RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin();
uint32_t copy_pipeline = do_sort ? ParticlesShader::COPY_MODE_FILL_INSTANCES_WITH_SORT_BUFFER : ParticlesShader::COPY_MODE_FILL_INSTANCES;
@@ -1229,10 +1245,10 @@ void ParticlesStorage::particles_set_view_axis(RID p_particles, const Vector3 &p
void ParticlesStorage::_particles_update_buffers(Particles *particles) {
uint32_t userdata_count = 0;
- const Material *material = MaterialStorage::get_singleton()->get_material(particles->process_material);
- if (material && material->shader && material->shader->data) {
- const ParticlesShaderData *shader_data = static_cast<const ParticlesShaderData *>(material->shader->data);
- userdata_count = shader_data->userdata_count;
+ MaterialStorage::ShaderData *shader_data = MaterialStorage::get_singleton()->material_get_shader_data(particles->process_material);
+ if (shader_data) {
+ const ParticlesShaderData *particle_shader_data = static_cast<const ParticlesShaderData *>(shader_data);
+ userdata_count = particle_shader_data->userdata_count;
}
if (userdata_count != particles->userdata_count) {
@@ -1321,10 +1337,7 @@ void ParticlesStorage::update_particles() {
}
}
-#ifndef _MSC_VER
-#warning Should use display refresh rate for all this
-#endif
-
+ // TODO: Should use display refresh rate for all this.
float screen_hz = 60;
int fixed_fps = 0;
@@ -1338,7 +1351,7 @@ void ParticlesStorage::update_particles() {
int history_size = 1;
int trail_steps = 1;
if (particles->trails_enabled && particles->trail_bind_poses.size() > 1) {
- history_size = MAX(1, int(particles->trail_length * fixed_fps));
+ history_size = MAX(1, int(particles->trail_lifetime * fixed_fps));
trail_steps = particles->trail_bind_poses.size();
}
@@ -1383,7 +1396,7 @@ void ParticlesStorage::update_particles() {
}
for (int i = 0; i < particles->trail_bind_poses.size(); i++) {
- RendererStorageRD::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
+ RendererRD::MaterialStorage::store_transform(particles->trail_bind_poses[i], &particles_shader.pose_update_buffer[i * 16]);
}
RD::get_singleton()->buffer_update(particles->trail_bind_pose_buffer, 0, particles->trail_bind_poses.size() * 16 * sizeof(float), particles_shader.pose_update_buffer.ptr());
@@ -1457,14 +1470,14 @@ void ParticlesStorage::update_particles() {
// In local mode, particle positions are calculated locally (relative to the node position)
// and they're also drawn locally.
// It works as expected, so we just pass an identity transform.
- RendererStorageRD::store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
+ RendererRD::MaterialStorage::store_transform(Transform3D(), copy_push_constant.inv_emission_transform);
} else {
// In global mode, particle positions are calculated globally (relative to the canvas origin)
// but they're drawn locally.
// So, we need to pass the inverse of the emission transform to bring the
// particles to local coordinates before drawing.
Transform3D inv = particles->emission_transform.affine_inverse();
- RendererStorageRD::store_transform(inv, copy_push_constant.inv_emission_transform);
+ RendererRD::MaterialStorage::store_transform(inv, copy_push_constant.inv_emission_transform);
}
copy_push_constant.total_particles = total_amount;
@@ -1500,10 +1513,17 @@ void ParticlesStorage::update_particles() {
RD::get_singleton()->compute_list_end();
}
- particles->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
}
+Dependency *ParticlesStorage::particles_get_dependency(RID p_particles) const {
+ Particles *particles = particles_owner.get_or_null(p_particles);
+ ERR_FAIL_NULL_V(particles, nullptr);
+
+ return &particles->dependency;
+}
+
bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
ERR_FAIL_COND_V_MSG(RSG::threaded, false, "This function should never be used with threaded rendering, as it stalls the renderer.");
const Particles *particles = particles_owner.get_or_null(p_particles);
@@ -1513,6 +1533,9 @@ bool ParticlesStorage::particles_is_inactive(RID p_particles) const {
/* Particles SHADER */
+void ParticlesStorage::ParticlesShaderData::set_path_hint(const String &p_path) {
+ path = p_path;
+}
void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
ParticlesStorage *particles_storage = ParticlesStorage::get_singleton();
//compile
@@ -1578,7 +1601,7 @@ void ParticlesStorage::ParticlesShaderData::set_code(const String &p_code) {
valid = true;
}
-void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const StringName &p_name, RID p_texture, int p_index) {
+void ParticlesStorage::ParticlesShaderData::set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index) {
if (!p_texture.is_valid()) {
if (default_texture_params.has(p_name) && default_texture_params[p_name].has(p_index)) {
default_texture_params[p_name].erase(p_index);
@@ -1595,7 +1618,7 @@ void ParticlesStorage::ParticlesShaderData::set_default_texture_param(const Stri
}
}
-void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p_param_list) const {
+void ParticlesStorage::ParticlesShaderData::get_shader_uniform_list(List<PropertyInfo> *p_param_list) const {
HashMap<int, StringName> order;
for (const KeyValue<StringName, ShaderLanguage::ShaderNode::Uniform> &E : uniforms) {
@@ -1610,7 +1633,22 @@ void ParticlesStorage::ParticlesShaderData::get_param_list(List<PropertyInfo> *p
}
}
+ String last_group;
for (const KeyValue<int, StringName> &E : order) {
+ String group = uniforms[E.value].group;
+ if (!uniforms[E.value].subgroup.is_empty()) {
+ group += "::" + uniforms[E.value].subgroup;
+ }
+
+ if (group != last_group) {
+ PropertyInfo pi;
+ pi.usage = PROPERTY_USAGE_GROUP;
+ pi.name = group;
+ p_param_list->push_back(pi);
+
+ last_group = group;
+ }
+
PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E.value]);
pi.name = E.value;
p_param_list->push_back(pi);
@@ -1632,7 +1670,7 @@ void ParticlesStorage::ParticlesShaderData::get_instance_param_list(List<Rendere
}
}
-bool ParticlesStorage::ParticlesShaderData::is_param_texture(const StringName &p_param) const {
+bool ParticlesStorage::ParticlesShaderData::is_parameter_texture(const StringName &p_param) const {
if (!uniforms.has(p_param)) {
return false;
}
@@ -1668,21 +1706,21 @@ ParticlesStorage::ParticlesShaderData::~ParticlesShaderData() {
}
}
-ShaderData *ParticlesStorage::_create_particles_shader_func() {
+MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() {
ParticlesShaderData *shader_data = memnew(ParticlesShaderData);
return shader_data;
}
-bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
- return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3);
+bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) {
+ return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3, true);
}
-ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() {
+ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() {
free_parameters_uniform_set(uniform_set);
}
-MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
- ParticlesMaterialData *material_data = memnew(ParticlesMaterialData);
+MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) {
+ ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData);
material_data->shader_data = p_shader;
//update will happen later anyway so do nothing.
return material_data;
@@ -1756,7 +1794,7 @@ void ParticlesStorage::particles_collision_set_collision_type(RID p_particles_co
particles_collision->heightfield_texture = RID();
}
particles_collision->type = p_type;
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_cull_mask(RID p_particles_collision, uint32_t p_cull_mask) {
@@ -1770,7 +1808,7 @@ void ParticlesStorage::particles_collision_set_sphere_radius(RID p_particles_col
ERR_FAIL_COND(!particles_collision);
particles_collision->radius = p_radius;
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_collision, const Vector3 &p_extents) {
@@ -1778,7 +1816,7 @@ void ParticlesStorage::particles_collision_set_box_extents(RID p_particles_colli
ERR_FAIL_COND(!particles_collision);
particles_collision->extents = p_extents;
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_attractor_strength(RID p_particles_collision, real_t p_strength) {
@@ -1812,7 +1850,7 @@ void ParticlesStorage::particles_collision_set_field_texture(RID p_particles_col
void ParticlesStorage::particles_collision_height_field_update(RID p_particles_collision) {
ParticlesCollision *particles_collision = particles_collision_owner.get_or_null(p_particles_collision);
ERR_FAIL_COND(!particles_collision);
- particles_collision->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ particles_collision->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void ParticlesStorage::particles_collision_set_height_field_resolution(RID p_particles_collision, RS::ParticlesCollisionHeightfieldResolution p_resolution) {
@@ -1851,8 +1889,6 @@ AABB ParticlesStorage::particles_collision_get_aabb(RID p_particles_collision) c
return aabb;
}
}
-
- return AABB();
}
Vector3 ParticlesStorage::particles_collision_get_extents(RID p_particles_collision) const {
@@ -1867,6 +1903,15 @@ bool ParticlesStorage::particles_collision_is_heightfield(RID p_particles_collis
return particles_collision->type == RS::PARTICLES_COLLISION_TYPE_HEIGHTFIELD_COLLIDE;
}
+Dependency *ParticlesStorage::particles_collision_get_dependency(RID p_particles_collision) const {
+ ParticlesCollision *pc = particles_collision_owner.get_or_null(p_particles_collision);
+ ERR_FAIL_NULL_V(pc, nullptr);
+
+ return &pc->dependency;
+}
+
+/* Particles collision instance */
+
RID ParticlesStorage::particles_collision_instance_create(RID p_collision) {
ParticlesCollisionInstance pci;
pci.collision = p_collision;
diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
index 115633d17a..a9cc98abb9 100644
--- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h
@@ -37,237 +37,209 @@
#include "servers/rendering/renderer_rd/shaders/particles.glsl.gen.h"
#include "servers/rendering/renderer_rd/shaders/particles_copy.glsl.gen.h"
#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/shader_compiler.h"
#include "servers/rendering/storage/particles_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
-/* PARTICLES */
-
-struct ParticleData {
- float xform[16];
- float velocity[3];
- uint32_t active;
- float color[4];
- float custom[3];
- float lifetime;
-};
+class ParticlesStorage : public RendererParticlesStorage {
+private:
+ static ParticlesStorage *singleton;
-struct ParticlesFrameParams {
- enum {
- MAX_ATTRACTORS = 32,
- MAX_COLLIDERS = 32,
- MAX_3D_TEXTURES = 7
- };
+ /* PARTICLES */
- enum AttractorType {
- ATTRACTOR_TYPE_SPHERE,
- ATTRACTOR_TYPE_BOX,
- ATTRACTOR_TYPE_VECTOR_FIELD,
+ struct ParticleData {
+ float xform[16];
+ float velocity[3];
+ uint32_t active;
+ float color[4];
+ float custom[3];
+ float lifetime;
};
- struct Attractor {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
+ struct ParticlesFrameParams {
+ enum {
+ MAX_ATTRACTORS = 32,
+ MAX_COLLIDERS = 32,
+ MAX_3D_TEXTURES = 7
+ };
- uint32_t texture_index; //texture index for vector field
- float strength;
- float attenuation;
- float directionality;
- };
+ enum AttractorType {
+ ATTRACTOR_TYPE_SPHERE,
+ ATTRACTOR_TYPE_BOX,
+ ATTRACTOR_TYPE_VECTOR_FIELD,
+ };
- enum CollisionType {
- COLLISION_TYPE_SPHERE,
- COLLISION_TYPE_BOX,
- COLLISION_TYPE_SDF,
- COLLISION_TYPE_HEIGHT_FIELD,
- COLLISION_TYPE_2D_SDF,
+ struct Attractor {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
- };
+ uint32_t texture_index; //texture index for vector field
+ float strength;
+ float attenuation;
+ float directionality;
+ };
- struct Collider {
- float transform[16];
- float extents[3]; //exents or radius
- uint32_t type;
+ enum CollisionType {
+ COLLISION_TYPE_SPHERE,
+ COLLISION_TYPE_BOX,
+ COLLISION_TYPE_SDF,
+ COLLISION_TYPE_HEIGHT_FIELD,
+ COLLISION_TYPE_2D_SDF,
- uint32_t texture_index; //texture index for vector field
- real_t scale;
- uint32_t pad[2];
- };
+ };
- uint32_t emitting;
- float system_phase;
- float prev_system_phase;
- uint32_t cycle;
+ struct Collider {
+ float transform[16];
+ float extents[3]; //exents or radius
+ uint32_t type;
- real_t explosiveness;
- real_t randomness;
- float time;
- float delta;
+ uint32_t texture_index; //texture index for vector field
+ float scale;
+ uint32_t pad[2];
+ };
- uint32_t frame;
- uint32_t pad0;
- uint32_t pad1;
- uint32_t pad2;
+ uint32_t emitting;
+ float system_phase;
+ float prev_system_phase;
+ uint32_t cycle;
- uint32_t random_seed;
- uint32_t attractor_count;
- uint32_t collider_count;
- float particle_size;
+ float explosiveness;
+ float randomness;
+ float time;
+ float delta;
- float emission_transform[16];
+ uint32_t frame;
+ uint32_t pad0;
+ uint32_t pad1;
+ uint32_t pad2;
- Attractor attractors[MAX_ATTRACTORS];
- Collider colliders[MAX_COLLIDERS];
-};
+ uint32_t random_seed;
+ uint32_t attractor_count;
+ uint32_t collider_count;
+ float particle_size;
-struct ParticleEmissionBufferData {
-};
+ float emission_transform[16];
-struct ParticleEmissionBuffer {
- struct Data {
- float xform[16];
- float velocity[3];
- uint32_t flags;
- float color[4];
- float custom[4];
+ Attractor attractors[MAX_ATTRACTORS];
+ Collider colliders[MAX_COLLIDERS];
};
- int32_t particle_count;
- int32_t particle_max;
- uint32_t pad1;
- uint32_t pad2;
- Data data[1]; //its 2020 and empty arrays are still non standard in C++
-};
-
-struct Particles {
- RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
- bool inactive = true;
- double inactive_time = 0.0;
- bool emitting = false;
- bool one_shot = false;
- int amount = 0;
- double lifetime = 1.0;
- double pre_process_time = 0.0;
- real_t explosiveness = 0.0;
- real_t randomness = 0.0;
- bool restart_request = false;
- AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
- bool use_local_coords = true;
- bool has_collision_cache = false;
-
- bool has_sdf_collision = false;
- Transform2D sdf_collision_transform;
- Rect2 sdf_collision_to_screen;
- RID sdf_collision_texture;
-
- RID process_material;
- uint32_t frame_counter = 0;
- RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
-
- RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
-
- Vector<RID> draw_passes;
- Vector<Transform3D> trail_bind_poses;
- bool trail_bind_poses_dirty = false;
- RID trail_bind_pose_buffer;
- RID trail_bind_pose_uniform_set;
-
- RID particle_buffer;
- RID particle_instance_buffer;
- RID frame_params_buffer;
-
- uint32_t userdata_count = 0;
-
- RID particles_material_uniform_set;
- RID particles_copy_uniform_set;
- RID particles_transforms_buffer_uniform_set;
- RID collision_textures_uniform_set;
-
- RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
- uint32_t collision_3d_textures_used = 0;
- RID collision_heightmap_texture;
-
- RID particles_sort_buffer;
- RID particles_sort_uniform_set;
+ struct ParticleEmissionBufferData {
+ };
- bool dirty = false;
- Particles *update_list = nullptr;
+ struct ParticleEmissionBuffer {
+ struct Data {
+ float xform[16];
+ float velocity[3];
+ uint32_t flags;
+ float color[4];
+ float custom[4];
+ };
- RID sub_emitter;
+ int32_t particle_count;
+ int32_t particle_max;
+ uint32_t pad1;
+ uint32_t pad2;
+ Data data[1]; //its 2020 and empty arrays are still non standard in C++
+ };
- double phase = 0.0;
- double prev_phase = 0.0;
- uint64_t prev_ticks = 0;
- uint32_t random_seed = 0;
+ struct Particles {
+ RS::ParticlesMode mode = RS::PARTICLES_MODE_3D;
+ bool inactive = true;
+ double inactive_time = 0.0;
+ bool emitting = false;
+ bool one_shot = false;
+ int amount = 0;
+ double lifetime = 1.0;
+ double pre_process_time = 0.0;
+ real_t explosiveness = 0.0;
+ real_t randomness = 0.0;
+ bool restart_request = false;
+ AABB custom_aabb = AABB(Vector3(-4, -4, -4), Vector3(8, 8, 8));
+ bool use_local_coords = false;
+ bool has_collision_cache = false;
+
+ bool has_sdf_collision = false;
+ Transform2D sdf_collision_transform;
+ Rect2 sdf_collision_to_screen;
+ RID sdf_collision_texture;
+
+ RID process_material;
+ uint32_t frame_counter = 0;
+ RS::ParticlesTransformAlign transform_align = RS::PARTICLES_TRANSFORM_ALIGN_DISABLED;
+
+ RS::ParticlesDrawOrder draw_order = RS::PARTICLES_DRAW_ORDER_INDEX;
+
+ Vector<RID> draw_passes;
+ Vector<Transform3D> trail_bind_poses;
+ bool trail_bind_poses_dirty = false;
+ RID trail_bind_pose_buffer;
+ RID trail_bind_pose_uniform_set;
+
+ RID particle_buffer;
+ RID particle_instance_buffer;
+ RID frame_params_buffer;
- uint32_t cycle_number = 0;
+ uint32_t userdata_count = 0;
- double speed_scale = 1.0;
+ RID particles_material_uniform_set;
+ RID particles_copy_uniform_set;
+ RID particles_transforms_buffer_uniform_set;
+ RID collision_textures_uniform_set;
- int fixed_fps = 30;
- bool interpolate = true;
- bool fractional_delta = false;
- double frame_remainder = 0;
- real_t collision_base_size = 0.01;
+ RID collision_3d_textures[ParticlesFrameParams::MAX_3D_TEXTURES];
+ uint32_t collision_3d_textures_used = 0;
+ RID collision_heightmap_texture;
- bool clear = true;
+ RID particles_sort_buffer;
+ RID particles_sort_uniform_set;
- bool force_sub_emit = false;
+ bool dirty = false;
+ Particles *update_list = nullptr;
- Transform3D emission_transform;
+ RID sub_emitter;
- Vector<uint8_t> emission_buffer_data;
+ double phase = 0.0;
+ double prev_phase = 0.0;
+ uint64_t prev_ticks = 0;
+ uint32_t random_seed = 0;
- ParticleEmissionBuffer *emission_buffer = nullptr;
- RID emission_storage_buffer;
+ uint32_t cycle_number = 0;
- HashSet<RID> collisions;
+ double speed_scale = 1.0;
- RendererStorage::Dependency dependency;
+ int fixed_fps = 30;
+ bool interpolate = true;
+ bool fractional_delta = false;
+ double frame_remainder = 0;
+ real_t collision_base_size = 0.01;
- double trail_length = 1.0;
- bool trails_enabled = false;
- LocalVector<ParticlesFrameParams> frame_history;
- LocalVector<ParticlesFrameParams> trail_params;
+ bool clear = true;
- Particles() {
- }
-};
+ bool force_sub_emit = false;
-/* Particles Collision */
+ Transform3D emission_transform;
-struct ParticlesCollision {
- RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
- uint32_t cull_mask = 0xFFFFFFFF;
- float radius = 1.0;
- Vector3 extents = Vector3(1, 1, 1);
- float attractor_strength = 1.0;
- float attractor_attenuation = 1.0;
- float attractor_directionality = 0.0;
- RID field_texture;
- RID heightfield_texture;
- RID heightfield_fb;
- Size2i heightfield_fb_size;
+ Vector<uint8_t> emission_buffer_data;
- RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+ ParticleEmissionBuffer *emission_buffer = nullptr;
+ RID emission_storage_buffer;
- RendererStorage::Dependency dependency;
-};
+ HashSet<RID> collisions;
-struct ParticlesCollisionInstance {
- RID collision;
- Transform3D transform;
- bool active = false;
-};
+ Dependency dependency;
-class ParticlesStorage : public RendererParticlesStorage {
-private:
- static ParticlesStorage *singleton;
+ double trail_lifetime = 0.3;
+ bool trails_enabled = false;
+ LocalVector<ParticlesFrameParams> frame_history;
+ LocalVector<ParticlesFrameParams> trail_params;
- /* PARTICLES */
+ Particles() {
+ }
+ };
void _particles_process(Particles *p_particles, double p_delta);
void _particles_allocate_emission_buffer(Particles *particles);
@@ -340,7 +312,7 @@ private:
/* Particle Shader */
- struct ParticlesShaderData : public ShaderData {
+ struct ParticlesShaderData : public MaterialStorage::ShaderData {
bool valid = false;
RID version;
bool uses_collision = false;
@@ -363,10 +335,11 @@ private:
uint32_t userdata_count = 0;
virtual void set_code(const String &p_Code);
- virtual void set_default_texture_param(const StringName &p_name, RID p_texture, int p_index);
- virtual void get_param_list(List<PropertyInfo> *p_param_list) const;
+ virtual void set_path_hint(const String &p_hint);
+ virtual void set_default_texture_parameter(const StringName &p_name, RID p_texture, int p_index);
+ virtual void get_shader_uniform_list(List<PropertyInfo> *p_param_list) const;
virtual void get_instance_param_list(List<RendererMaterialStorage::InstanceShaderParam> *p_param_list) const;
- virtual bool is_param_texture(const StringName &p_param) const;
+ virtual bool is_parameter_texture(const StringName &p_param) const;
virtual bool is_animated() const;
virtual bool casts_shadows() const;
virtual Variant get_default_parameter(const StringName &p_parameter) const;
@@ -376,28 +349,52 @@ private:
virtual ~ParticlesShaderData();
};
- ShaderData *_create_particles_shader_func();
- static ShaderData *_create_particles_shader_funcs() {
+ MaterialStorage::ShaderData *_create_particles_shader_func();
+ static MaterialStorage::ShaderData *_create_particles_shader_funcs() {
return ParticlesStorage::get_singleton()->_create_particles_shader_func();
}
- struct ParticlesMaterialData : public MaterialData {
+ struct ParticleProcessMaterialData : public MaterialStorage::MaterialData {
ParticlesShaderData *shader_data = nullptr;
RID uniform_set;
virtual void set_render_priority(int p_priority) {}
virtual void set_next_pass(RID p_pass) {}
virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty);
- virtual ~ParticlesMaterialData();
+ virtual ~ParticleProcessMaterialData();
};
- MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
- static MaterialData *_create_particles_material_funcs(ShaderData *p_shader) {
+ MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader);
+ static MaterialStorage::MaterialData *_create_particles_material_funcs(MaterialStorage::ShaderData *p_shader) {
return ParticlesStorage::get_singleton()->_create_particles_material_func(static_cast<ParticlesShaderData *>(p_shader));
}
/* Particles Collision */
+ struct ParticlesCollision {
+ RS::ParticlesCollisionType type = RS::PARTICLES_COLLISION_TYPE_SPHERE_ATTRACT;
+ uint32_t cull_mask = 0xFFFFFFFF;
+ float radius = 1.0;
+ Vector3 extents = Vector3(1, 1, 1);
+ float attractor_strength = 1.0;
+ float attractor_attenuation = 1.0;
+ float attractor_directionality = 0.0;
+ RID field_texture;
+ RID heightfield_texture;
+ RID heightfield_fb;
+ Size2i heightfield_fb_size;
+
+ RS::ParticlesCollisionHeightfieldResolution heightfield_resolution = RS::PARTICLES_COLLISION_HEIGHTFIELD_RESOLUTION_1024;
+
+ Dependency dependency;
+ };
+
+ struct ParticlesCollisionInstance {
+ RID collision;
+ Transform3D transform;
+ bool active = false;
+ };
+
mutable RID_Owner<ParticlesCollision, true> particles_collision_owner;
mutable RID_Owner<ParticlesCollisionInstance> particles_collision_instance_owner;
@@ -408,9 +405,10 @@ public:
ParticlesStorage();
virtual ~ParticlesStorage();
+ bool free(RID p_rid);
+
/* PARTICLES */
- Particles *get_particles(RID p_rid) { return particles_owner.get_or_null(p_rid); }
bool owns_particles(RID p_rid) { return particles_owner.owns(p_rid); }
virtual RID particles_allocate() override;
@@ -525,9 +523,10 @@ public:
virtual void update_particles() override;
+ Dependency *particles_get_dependency(RID p_particles) const;
+
/* Particles Collision */
- ParticlesCollision *get_particles_collision(RID p_rid) { return particles_collision_owner.get_or_null(p_rid); }
bool owns_particles_collision(RID p_rid) { return particles_collision_owner.owns(p_rid); }
virtual RID particles_collision_allocate() override;
@@ -549,8 +548,9 @@ public:
virtual bool particles_collision_is_heightfield(RID p_particles_collision) const override;
virtual RID particles_collision_get_heightfield_framebuffer(RID p_particles_collision) const override;
+ Dependency *particles_collision_get_dependency(RID p_particles) const;
+
//used from 2D and 3D
- ParticlesCollisionInstance *get_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.get_or_null(p_rid); }
bool owns_particles_collision_instance(RID p_rid) { return particles_collision_instance_owner.owns(p_rid); }
virtual RID particles_collision_instance_create(RID p_collision) override;
@@ -561,4 +561,4 @@ public:
} // namespace RendererRD
-#endif // !PARTICLES_STORAGE_RD_H
+#endif // PARTICLES_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h
new file mode 100644
index 0000000000..d904012914
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/render_buffer_custom_data_rd.h
@@ -0,0 +1,48 @@
+/*************************************************************************/
+/* render_buffer_custom_data_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDER_BUFFER_CUSTOM_DATA_RD_H
+#define RENDER_BUFFER_CUSTOM_DATA_RD_H
+
+#include "core/object/ref_counted.h"
+
+class RenderSceneBuffersRD;
+
+class RenderBufferCustomDataRD : public RefCounted {
+ GDCLASS(RenderBufferCustomDataRD, RefCounted);
+
+public:
+ virtual void configure(RenderSceneBuffersRD *p_render_buffers) = 0;
+ virtual void free_data() = 0; // called on cleanup
+
+private:
+};
+
+#endif // RENDER_BUFFER_CUSTOM_DATA_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
new file mode 100644
index 0000000000..0c2092f03e
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp
@@ -0,0 +1,587 @@
+/*************************************************************************/
+/* render_scene_buffers_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+
+RenderSceneBuffersRD::RenderSceneBuffersRD() {
+}
+
+RenderSceneBuffersRD::~RenderSceneBuffersRD() {
+ cleanup();
+
+ data_buffers.clear();
+}
+
+void RenderSceneBuffersRD::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("has_texture", "context", "name"), &RenderSceneBuffersRD::has_texture);
+ // FIXME we can't pass RD::DataFormat, RD::TextureSamples and RD::TextureView in ClassDB, need to solve views differently...
+ // ClassDB::bind_method(D_METHOD("create_texture", "context", "name", "data_format", "usage_bits", "texture_samples", "size", "layers", "mipmaps", "unique"), &RenderSceneBuffersRD::create_texture);
+ // ClassDB::bind_method(D_METHOD("create_texture_from_format", "context", "name", "format", "view", "unique"), &RenderSceneBuffersRD::create_texture_from_format);
+ // ClassDB::bind_method(D_METHOD("create_texture_view", "context", "name", "view_name", "view"), &RenderSceneBuffersRD::has_texture);
+ ClassDB::bind_method(D_METHOD("get_texture", "context", "name"), &RenderSceneBuffersRD::get_texture);
+ // ClassDB::bind_method(D_METHOD("get_texture_format", "context", "name"), &RenderSceneBuffersRD::get_texture_format);
+ ClassDB::bind_method(D_METHOD("get_texture_slice", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice);
+ ClassDB::bind_method(D_METHOD("get_texture_slice_size", "context", "name", "layer", "mipmap"), &RenderSceneBuffersRD::get_texture_slice_size);
+ ClassDB::bind_method(D_METHOD("clear_context", "context"), &RenderSceneBuffersRD::clear_context);
+}
+
+void RenderSceneBuffersRD::update_sizes(NamedTexture &p_named_texture) {
+ ERR_FAIL_COND(p_named_texture.texture.is_null());
+
+ uint32_t size = p_named_texture.format.array_layers * p_named_texture.format.mipmaps;
+ p_named_texture.sizes.resize(size);
+
+ Size2i mipmap_size = Size2i(p_named_texture.format.width, p_named_texture.format.height);
+
+ for (uint32_t mipmap = 0; mipmap < p_named_texture.format.mipmaps; mipmap++) {
+ for (uint32_t layer = 0; layer < p_named_texture.format.array_layers; layer++) {
+ uint32_t index = layer * p_named_texture.format.mipmaps + mipmap;
+
+ p_named_texture.sizes.ptrw()[index] = mipmap_size;
+ }
+
+ mipmap_size.width = MAX(1, mipmap_size.width >> 1);
+ mipmap_size.height = MAX(1, mipmap_size.height >> 1);
+ }
+}
+
+void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) {
+ if (p_named_texture.texture.is_valid()) {
+ RD::get_singleton()->free(p_named_texture.texture);
+ }
+ p_named_texture.texture = RID();
+ p_named_texture.slices.clear(); // slices should be freed automatically as dependents...
+}
+
+void RenderSceneBuffersRD::cleanup() {
+ // Free our data buffers (but don't destroy them)
+ for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
+ E.value->free_data();
+ }
+
+ // Clear our named textures
+ for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
+ free_named_texture(E.value);
+ }
+ named_textures.clear();
+
+ // old stuff, to be re-evaluated...
+
+ for (int i = 0; i < luminance.fb.size(); i++) {
+ RD::get_singleton()->free(luminance.fb[i]);
+ }
+ luminance.fb.clear();
+
+ for (int i = 0; i < luminance.reduce.size(); i++) {
+ RD::get_singleton()->free(luminance.reduce[i]);
+ }
+ luminance.reduce.clear();
+
+ if (luminance.current_fb.is_valid()) {
+ RD::get_singleton()->free(luminance.current_fb);
+ luminance.current_fb = RID();
+ }
+
+ if (luminance.current.is_valid()) {
+ RD::get_singleton()->free(luminance.current);
+ luminance.current = RID();
+ }
+}
+
+void RenderSceneBuffersRD::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+
+ ERR_FAIL_COND_MSG(p_view_count == 0, "Must have at least 1 view");
+
+ target_size = p_target_size;
+ internal_size = p_internal_size;
+
+ // FIXME, right now we do this because only our clustered renderer supports FSR upscale
+ // this does mean that with linear upscale if we use subpasses, we could get into trouble.
+ if (!can_be_storage) {
+ internal_size = target_size;
+ }
+
+ if (p_use_taa) {
+ // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness.
+ // This restores sharpness in still images to be roughly at the same level as without TAA,
+ // but moving scenes will still be blurrier.
+ p_texture_mipmap_bias -= 0.5;
+ }
+
+ if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) {
+ // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness.
+ // If both TAA and FXAA are enabled, combine their negative LOD biases together.
+ p_texture_mipmap_bias -= 0.25;
+ }
+
+ material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
+
+ // need to check if we really need to do this here..
+ RendererSceneRenderRD::get_singleton()->update_uniform_sets();
+
+ render_target = p_render_target;
+ fsr_sharpness = p_fsr_sharpness;
+ msaa_3d = p_msaa_3d;
+ screen_space_aa = p_screen_space_aa;
+ use_taa = p_use_taa;
+ use_debanding = p_use_debanding;
+ view_count = p_view_count;
+
+ // cleanout any old buffers we had.
+ cleanup();
+
+ // create our 3D render buffers
+ {
+ // Create our color buffer(s)
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | (can_be_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0) | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ usage_bits |= RD::TEXTURE_USAGE_INPUT_ATTACHMENT_BIT; // only needed when using subpasses in the mobile renderer
+
+ // our internal texture should have MSAA support if applicable
+ if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
+ usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ }
+
+ create_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR, base_data_format, usage_bits);
+ }
+
+ // Create our depth buffer
+ {
+ // TODO Lazy create this in case we've got an external depth buffer
+
+ RD::DataFormat format;
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
+
+ if (msaa_3d == RS::VIEWPORT_MSAA_DISABLED) {
+ format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, (RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT)) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT;
+ usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+ } else {
+ format = RD::DATA_FORMAT_R32_SFLOAT;
+ usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ }
+
+ create_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, format, usage_bits);
+ }
+
+ // VRS (note, our vrs object will only be set if VRS is supported)
+ RID vrs_texture;
+ RS::ViewportVRSMode vrs_mode = texture_storage->render_target_get_vrs_mode(p_render_target);
+ if (vrs && vrs_mode != RS::VIEWPORT_VRS_DISABLED) {
+ uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+ vrs_texture = create_texture(RB_SCOPE_VRS, RB_TEXTURE, RD::DATA_FORMAT_R8_UINT, usage_bits, RD::TEXTURE_SAMPLES_1, vrs->get_vrs_texture_size(internal_size));
+ }
+
+ for (KeyValue<StringName, Ref<RenderBufferCustomDataRD>> &E : data_buffers) {
+ E.value->configure(this);
+ }
+}
+
+void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) {
+ fsr_sharpness = p_fsr_sharpness;
+}
+
+void RenderSceneBuffersRD::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
+ RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton();
+ material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias);
+}
+
+void RenderSceneBuffersRD::set_use_debanding(bool p_use_debanding) {
+ use_debanding = p_use_debanding;
+}
+
+// Named textures
+
+bool RenderSceneBuffersRD::has_texture(const StringName &p_context, const StringName &p_texture_name) const {
+ NTKey key(p_context, p_texture_name);
+
+ return named_textures.has(key);
+}
+
+RID RenderSceneBuffersRD::create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples, const Size2i p_size, const uint32_t p_layers, const uint32_t p_mipmaps, bool p_unique) {
+ // Keep some useful data, we use default values when these are 0.
+ Size2i size = p_size == Size2i(0, 0) ? internal_size : p_size;
+ uint32_t layers = p_layers == 0 ? view_count : p_layers;
+ uint32_t mipmaps = p_mipmaps == 0 ? 1 : p_mipmaps;
+
+ // Create our texture
+ RD::TextureFormat tf;
+ tf.format = p_data_format;
+ if (layers > 1) {
+ tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ }
+
+ tf.width = size.x;
+ tf.height = size.y;
+ tf.depth = 1;
+ tf.array_layers = layers;
+ tf.mipmaps = mipmaps;
+ tf.usage_bits = p_usage_bits;
+ tf.samples = p_texture_samples;
+
+ return create_texture_from_format(p_context, p_texture_name, tf, RD::TextureView(), p_unique);
+}
+
+RID RenderSceneBuffersRD::create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view, bool p_unique) {
+ // TODO p_unique, if p_unique is true, this is a texture that can be shared. This will be implemented later as an optimisation.
+
+ NTKey key(p_context, p_texture_name);
+
+ // check if this is a known texture
+ if (named_textures.has(key)) {
+ return named_textures[key].texture;
+ }
+
+ // Add a new entry..
+ NamedTexture &named_texture = named_textures[key];
+ named_texture.format = p_texture_format;
+ named_texture.is_unique = p_unique;
+ named_texture.texture = RD::get_singleton()->texture_create(p_texture_format, p_view);
+
+ Array arr;
+ arr.push_back(p_context);
+ arr.push_back(p_texture_name);
+ RD::get_singleton()->set_resource_name(named_texture.texture, String("RenderBuffer {0}/{1}").format(arr));
+
+ update_sizes(named_texture);
+
+ // The rest is lazy created..
+
+ return named_texture.texture;
+}
+
+RID RenderSceneBuffersRD::create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view) {
+ NTKey view_key(p_context, p_view_name);
+
+ // check if this is a known texture
+ if (named_textures.has(view_key)) {
+ return named_textures[view_key].texture;
+ }
+
+ NTKey key(p_context, p_texture_name);
+
+ ERR_FAIL_COND_V(!named_textures.has(key), RID());
+
+ NamedTexture &named_texture = named_textures[key];
+ NamedTexture &view_texture = named_textures[view_key];
+
+ view_texture.format = named_texture.format;
+ view_texture.is_unique = named_texture.is_unique;
+
+ view_texture.texture = RD::get_singleton()->texture_create_shared(p_view, named_texture.texture);
+
+ Array arr;
+ arr.push_back(p_context);
+ arr.push_back(p_view_name);
+ RD::get_singleton()->set_resource_name(view_texture.texture, String("RenderBuffer View {0}/{1}").format(arr));
+
+ update_sizes(named_texture);
+
+ return view_texture.texture;
+}
+
+RID RenderSceneBuffersRD::get_texture(const StringName &p_context, const StringName &p_texture_name) const {
+ NTKey key(p_context, p_texture_name);
+
+ ERR_FAIL_COND_V(!named_textures.has(key), RID());
+
+ return named_textures[key].texture;
+}
+
+const RD::TextureFormat RenderSceneBuffersRD::get_texture_format(const StringName &p_context, const StringName &p_texture_name) const {
+ NTKey key(p_context, p_texture_name);
+
+ ERR_FAIL_COND_V(!named_textures.has(key), RD::TextureFormat());
+
+ return named_textures[key].format;
+}
+
+RID RenderSceneBuffersRD::get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
+ NTKey key(p_context, p_texture_name);
+
+ // check if this is a known texture
+ ERR_FAIL_COND_V(!named_textures.has(key), RID());
+ NamedTexture &named_texture = named_textures[key];
+ ERR_FAIL_COND_V(named_texture.texture.is_null(), RID());
+
+ // check if we're in bounds
+ ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, RID());
+ ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, RID());
+
+ // if we don't have multiple layers or mipmaps, we can just return our texture as is
+ if (named_texture.format.array_layers == 1 && named_texture.format.mipmaps == 1) {
+ return named_texture.texture;
+ }
+
+ // get our index and make sure we have enough entries in our slices vector
+ uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
+ while (named_texture.slices.size() <= int(index)) {
+ named_texture.slices.push_back(RID());
+ }
+
+ // create our slice if we don't have it already
+ if (named_texture.slices[index].is_null()) {
+ named_texture.slices.ptrw()[index] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), named_texture.texture, p_layer, p_mipmap);
+
+ Array arr;
+ arr.push_back(p_context);
+ arr.push_back(p_texture_name);
+ arr.push_back(itos(p_layer));
+ arr.push_back(itos(p_mipmap));
+ RD::get_singleton()->set_resource_name(named_texture.slices[index], String("RenderBuffer {0}/{1} slice {2}/{3}").format(arr));
+ }
+
+ // and return our slice
+ return named_texture.slices[index];
+}
+
+Size2i RenderSceneBuffersRD::get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap) {
+ NTKey key(p_context, p_texture_name);
+
+ // check if this is a known texture
+ ERR_FAIL_COND_V(!named_textures.has(key), Size2i());
+ NamedTexture &named_texture = named_textures[key];
+ ERR_FAIL_COND_V(named_texture.texture.is_null(), Size2i());
+
+ // check if we're in bounds
+ ERR_FAIL_UNSIGNED_INDEX_V(p_layer, named_texture.format.array_layers, Size2i());
+ ERR_FAIL_UNSIGNED_INDEX_V(p_mipmap, named_texture.format.mipmaps, Size2i());
+
+ // get our index
+ uint32_t index = p_layer * named_texture.format.mipmaps + p_mipmap;
+
+ // and return our size
+ return named_texture.sizes[index];
+}
+
+void RenderSceneBuffersRD::clear_context(const StringName &p_context) {
+ Vector<NTKey> to_free; // free these
+
+ // Find all entries for our context, we don't want to free them yet or our loop fails.
+ for (KeyValue<NTKey, NamedTexture> &E : named_textures) {
+ if (E.key.context == p_context) {
+ to_free.push_back(E.key);
+ }
+ }
+
+ // Now free these and remove them from our textures
+ for (NTKey &key : to_free) {
+ free_named_texture(named_textures[key]);
+ named_textures.erase(key);
+ }
+}
+
+// Allocate shared buffers
+void RenderSceneBuffersRD::allocate_blur_textures() {
+ if (has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0)) {
+ // already allocated...
+ return;
+ }
+
+ uint32_t mipmaps_required = Image::get_image_required_mipmaps(internal_size.x, internal_size.y, Image::FORMAT_RGBAH);
+
+ uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+ if (can_be_storage) {
+ usage_bits += RD::TEXTURE_USAGE_STORAGE_BIT;
+ } else {
+ usage_bits += RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+
+ create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, internal_size, view_count, mipmaps_required);
+ create_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y >> 1), view_count, mipmaps_required - 1);
+
+ // if !can_be_storage we need a half width version
+ if (!can_be_storage) {
+ create_texture(RB_SCOPE_BUFFERS, RB_TEX_HALF_BLUR, base_data_format, usage_bits, RD::TEXTURE_SAMPLES_1, Size2i(internal_size.x >> 1, internal_size.y), 1, mipmaps_required);
+ }
+
+ // TODO redo this:
+ if (!can_be_storage) {
+ // create 4 weight textures, 2 full size, 2 half size
+
+ RD::TextureFormat tf;
+ tf.format = RD::DATA_FORMAT_R16_SFLOAT; // We could probably use DATA_FORMAT_R8_SNORM if we don't pre-multiply by blur_size but that depends on whether we can remove DEPTH_GAP
+ tf.width = internal_size.x;
+ tf.height = internal_size.y;
+ tf.texture_type = RD::TEXTURE_TYPE_2D;
+ tf.array_layers = 1; // Our DOF effect handles one eye per turn
+ tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ tf.mipmaps = 1;
+ for (uint32_t i = 0; i < 4; i++) {
+ // associated blur texture
+ RID texture;
+ if (i == 1) {
+ texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 0);
+ } else if (i == 2) {
+ texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_1, 0, 0);
+ } else if (i == 3) {
+ texture = get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0, 0, 1);
+ }
+
+ // create weight texture
+ weight_buffers[i].weight = RD::get_singleton()->texture_create(tf, RD::TextureView());
+
+ // create frame buffer
+ Vector<RID> fb;
+ if (i != 0) {
+ fb.push_back(texture);
+ }
+ fb.push_back(weight_buffers[i].weight);
+ weight_buffers[i].fb = RD::get_singleton()->framebuffer_create(fb);
+
+ if (i == 1) {
+ // next 2 are half size
+ tf.width = MAX(1u, tf.width >> 1);
+ tf.height = MAX(1u, tf.height >> 1);
+ }
+ }
+ }
+}
+
+// Data buffers
+
+bool RenderSceneBuffersRD::has_custom_data(const StringName &p_name) {
+ return data_buffers.has(p_name);
+}
+
+void RenderSceneBuffersRD::set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data) {
+ if (p_data.is_valid()) {
+ data_buffers[p_name] = p_data;
+ } else if (has_custom_data(p_name)) {
+ data_buffers.erase(p_name);
+ }
+}
+
+Ref<RenderBufferCustomDataRD> RenderSceneBuffersRD::get_custom_data(const StringName &p_name) const {
+ ERR_FAIL_COND_V(!data_buffers.has(p_name), Ref<RenderBufferCustomDataRD>());
+
+ Ref<RenderBufferCustomDataRD> ret = data_buffers[p_name];
+
+ return ret;
+}
+
+// Depth texture
+
+RID RenderSceneBuffersRD::get_depth_texture() {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID depth = texture_storage->render_target_get_override_depth(render_target);
+ if (depth.is_valid()) {
+ return depth;
+ } else {
+ return get_texture(RB_SCOPE_BUFFERS, RB_TEX_DEPTH);
+ }
+}
+
+RID RenderSceneBuffersRD::get_depth_texture(const uint32_t p_layer) {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID depth_slice = texture_storage->render_target_get_override_depth_slice(render_target, p_layer);
+ if (depth_slice.is_valid()) {
+ return depth_slice;
+ } else {
+ return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_DEPTH, p_layer, 0);
+ }
+}
+
+// Velocity texture.
+
+void RenderSceneBuffersRD::ensure_velocity() {
+ if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
+ uint32_t usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
+
+ if (msaa_3d != RS::VIEWPORT_MSAA_DISABLED) {
+ uint32_t msaa_usage_bits = usage_bits | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
+
+ const RD::TextureSamples ts[RS::VIEWPORT_MSAA_MAX] = {
+ RD::TEXTURE_SAMPLES_1,
+ RD::TEXTURE_SAMPLES_2,
+ RD::TEXTURE_SAMPLES_4,
+ RD::TEXTURE_SAMPLES_8,
+ };
+
+ RD::TextureSamples texture_samples = ts[msaa_3d];
+
+ create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, RD::DATA_FORMAT_R16G16_SFLOAT, msaa_usage_bits, texture_samples);
+ }
+
+ create_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, RD::DATA_FORMAT_R16G16_SFLOAT, usage_bits);
+ }
+}
+
+bool RenderSceneBuffersRD::has_velocity_buffer(bool p_has_msaa) {
+ if (p_has_msaa) {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
+ } else {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID velocity = texture_storage->render_target_get_override_velocity(render_target);
+ if (velocity.is_valid()) {
+ return true;
+ } else {
+ return has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
+ }
+ }
+}
+
+RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa) {
+ if (p_get_msaa) {
+ if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA)) {
+ return RID();
+ } else {
+ return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA);
+ }
+ } else {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID velocity = texture_storage->render_target_get_override_velocity(render_target);
+ if (velocity.is_valid()) {
+ return velocity;
+ } else if (!has_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY)) {
+ return RID();
+ } else {
+ return get_texture(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY);
+ }
+ }
+}
+
+RID RenderSceneBuffersRD::get_velocity_buffer(bool p_get_msaa, uint32_t p_layer) {
+ if (p_get_msaa) {
+ return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY_MSAA, p_layer, 0);
+ } else {
+ RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
+ RID velocity_slice = texture_storage->render_target_get_override_velocity_slice(render_target, p_layer);
+ if (velocity_slice.is_valid()) {
+ return velocity_slice;
+ } else {
+ return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_VELOCITY, p_layer, 0);
+ }
+ }
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
new file mode 100644
index 0000000000..6907f69b93
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h
@@ -0,0 +1,226 @@
+/*************************************************************************/
+/* render_scene_buffers_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDER_SCENE_BUFFERS_RD_H
+#define RENDER_SCENE_BUFFERS_RD_H
+
+#include "../effects/vrs.h"
+#include "../framebuffer_cache_rd.h"
+#include "core/templates/hash_map.h"
+#include "render_buffer_custom_data_rd.h"
+#include "servers/rendering/rendering_device.h"
+#include "servers/rendering/rendering_method.h"
+#include "servers/rendering/storage/render_scene_buffers.h"
+
+#define RB_SCOPE_BUFFERS SNAME("render_buffers")
+#define RB_SCOPE_VRS SNAME("VRS")
+
+#define RB_TEXTURE SNAME("texture")
+#define RB_TEX_COLOR SNAME("color")
+#define RB_TEX_COLOR_MSAA SNAME("color_msaa")
+#define RB_TEX_DEPTH SNAME("depth")
+#define RB_TEX_DEPTH_MSAA SNAME("depth_msaa")
+#define RB_TEX_VELOCITY SNAME("velocity")
+#define RB_TEX_VELOCITY_MSAA SNAME("velocity_msaa")
+
+#define RB_TEX_BLUR_0 SNAME("blur_0")
+#define RB_TEX_BLUR_1 SNAME("blur_1")
+#define RB_TEX_HALF_BLUR SNAME("half_blur") // only for raster!
+
+#define RB_TEX_BACK_DEPTH SNAME("back_depth")
+
+class RenderSceneBuffersRD : public RenderSceneBuffers {
+ GDCLASS(RenderSceneBuffersRD, RenderSceneBuffers);
+
+private:
+ bool can_be_storage = true;
+ uint32_t max_cluster_elements = 512;
+ RD::DataFormat base_data_format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;
+ RendererRD::VRS *vrs = nullptr;
+ uint64_t auto_exposure_version = 1;
+
+ // Our render target represents our final destination that we display on screen.
+ RID render_target;
+ Size2i target_size = Size2i(0, 0);
+ uint32_t view_count = 1;
+
+ // The internal size of the textures we render 3D to in case we render at a lower resolution and upscale
+ Size2i internal_size = Size2i(0, 0);
+ float fsr_sharpness = 0.2f;
+
+ // Aliassing settings
+ RS::ViewportMSAA msaa_3d = RS::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+ bool use_taa = false;
+ bool use_debanding = false;
+
+ // Named Textures
+
+ struct NTKey {
+ StringName context;
+ StringName buffer_name;
+
+ bool operator==(const NTKey &p_val) const {
+ return (context == p_val.context) && (buffer_name == p_val.buffer_name);
+ }
+
+ static uint32_t hash(const NTKey &p_val) {
+ // FIXME, properly hash two stringnames together
+ uint32_t h = p_val.context.hash();
+ h = hash_murmur3_one_32(p_val.buffer_name.hash(), h);
+ return hash_fmix32(h);
+ }
+
+ NTKey() {}
+ NTKey(const StringName p_context, const StringName p_texture_name) {
+ context = p_context;
+ buffer_name = p_texture_name;
+ }
+ };
+
+ struct NamedTexture {
+ // Cache the data used to create our texture
+ RD::TextureFormat format;
+ bool is_unique; // If marked as unique, we return it into our pool
+
+ // Our texture objects, slices are lazy (i.e. only created when requested).
+ RID texture;
+ Vector<RID> slices;
+ Vector<Size2i> sizes;
+ };
+
+ mutable HashMap<NTKey, NamedTexture, NTKey> named_textures;
+ void update_sizes(NamedTexture &p_named_texture);
+ void free_named_texture(NamedTexture &p_named_texture);
+
+ // Data buffers
+ mutable HashMap<StringName, Ref<RenderBufferCustomDataRD>> data_buffers;
+
+protected:
+ static void _bind_methods();
+
+public:
+ RenderSceneBuffersRD();
+ virtual ~RenderSceneBuffersRD();
+
+ // info from our renderer
+ void set_can_be_storage(const bool p_can_be_storage) { can_be_storage = p_can_be_storage; }
+ void set_max_cluster_elements(const uint32_t p_max_elements) { max_cluster_elements = p_max_elements; }
+ uint32_t get_max_cluster_elements() { return max_cluster_elements; }
+ void set_base_data_format(const RD::DataFormat p_base_data_format) { base_data_format = p_base_data_format; }
+ RD::DataFormat get_base_data_format() const { return base_data_format; }
+ void set_vrs(RendererRD::VRS *p_vrs) { vrs = p_vrs; }
+
+ void cleanup();
+ virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) override;
+ virtual void set_fsr_sharpness(float p_fsr_sharpness) override;
+ virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias) override;
+ virtual void set_use_debanding(bool p_use_debanding) override;
+
+ // Named Textures
+
+ bool has_texture(const StringName &p_context, const StringName &p_texture_name) const;
+ RID create_texture(const StringName &p_context, const StringName &p_texture_name, const RD::DataFormat p_data_format, const uint32_t p_usage_bits, const RD::TextureSamples p_texture_samples = RD::TEXTURE_SAMPLES_1, const Size2i p_size = Size2i(0, 0), const uint32_t p_layers = 0, const uint32_t p_mipmaps = 1, bool p_unique = true);
+ RID create_texture_from_format(const StringName &p_context, const StringName &p_texture_name, const RD::TextureFormat &p_texture_format, RD::TextureView p_view = RD::TextureView(), bool p_unique = true);
+ RID create_texture_view(const StringName &p_context, const StringName &p_texture_name, const StringName p_view_name, RD::TextureView p_view = RD::TextureView());
+ RID get_texture(const StringName &p_context, const StringName &p_texture_name) const;
+ const RD::TextureFormat get_texture_format(const StringName &p_context, const StringName &p_texture_name) const;
+ RID get_texture_slice(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
+ Size2i get_texture_slice_size(const StringName &p_context, const StringName &p_texture_name, const uint32_t p_layer, const uint32_t p_mipmap);
+
+ void clear_context(const StringName &p_context);
+
+ // Allocate shared buffers
+ void allocate_blur_textures();
+
+ // Custom data
+ bool has_custom_data(const StringName &p_name);
+ void set_custom_data(const StringName &p_name, Ref<RenderBufferCustomDataRD> p_data);
+ Ref<RenderBufferCustomDataRD> get_custom_data(const StringName &p_name) const;
+
+ // Getters
+
+ _FORCE_INLINE_ RID get_render_target() const { return render_target; }
+ _FORCE_INLINE_ uint32_t get_view_count() const { return view_count; }
+ _FORCE_INLINE_ Size2i get_internal_size() const { return internal_size; }
+ _FORCE_INLINE_ Size2i get_target_size() const { return target_size; }
+ _FORCE_INLINE_ float get_fsr_sharpness() const { return fsr_sharpness; }
+ _FORCE_INLINE_ RS::ViewportMSAA get_msaa_3d() const { return msaa_3d; }
+ _FORCE_INLINE_ RS::ViewportScreenSpaceAA get_screen_space_aa() const { return screen_space_aa; }
+ _FORCE_INLINE_ bool get_use_taa() const { return use_taa; }
+ _FORCE_INLINE_ bool get_use_debanding() const { return use_debanding; }
+
+ uint64_t get_auto_exposure_version() const { return auto_exposure_version; }
+ void set_auto_exposure_version(const uint64_t p_auto_exposure_version) { auto_exposure_version = p_auto_exposure_version; }
+
+ // For our internal textures we provide some easy access methods.
+
+ _FORCE_INLINE_ RID get_internal_texture() const {
+ return get_texture(RB_SCOPE_BUFFERS, RB_TEX_COLOR);
+ }
+ _FORCE_INLINE_ RID get_internal_texture(const uint32_t p_layer) {
+ return get_texture_slice(RB_SCOPE_BUFFERS, RB_TEX_COLOR, p_layer, 0);
+ }
+
+ RID get_depth_texture();
+ RID get_depth_texture(const uint32_t p_layer);
+
+ // back buffer (color)
+ RID get_back_buffer_texture() const { return has_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) ? get_texture(RB_SCOPE_BUFFERS, RB_TEX_BLUR_0) : RID(); } // We (re)use our blur texture here.
+
+ // Velocity, currently only used by TAA (Clustered) but we'll be using this in other places soon too.
+
+ void ensure_velocity();
+ bool has_velocity_buffer(bool p_has_msaa);
+ RID get_velocity_buffer(bool p_get_msaa);
+ RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer);
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ // Everything after this needs to be re-evaluated, this is all old implementation
+
+ struct WeightBuffers {
+ RID weight;
+ RID fb; // FB with both texture and weight writing into one level lower
+ };
+
+ // 2 full size, 2 half size
+ WeightBuffers weight_buffers[4]; // Only used in raster
+
+ struct Luminance {
+ Vector<RID> reduce;
+ RID current;
+
+ // used only on mobile renderer
+ Vector<RID> fb;
+ RID current_fb;
+ } luminance;
+};
+
+#endif // RENDER_SCENE_BUFFERS_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
new file mode 100644
index 0000000000..7dd790d1da
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.cpp
@@ -0,0 +1,252 @@
+/*************************************************************************/
+/* render_scene_data_rd.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "render_scene_data_rd.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
+#include "servers/rendering/renderer_rd/storage_rd/light_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
+#include "servers/rendering/rendering_server_default.h"
+
+RID RenderSceneDataRD::create_uniform_buffer() {
+ return RD::get_singleton()->uniform_buffer_create(sizeof(UBODATA));
+}
+
+void RenderSceneDataRD::update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers) {
+ RendererSceneRenderRD *render_scene_render = RendererSceneRenderRD::get_singleton();
+
+ UBODATA ubo_data;
+ memset(&ubo_data, 0, sizeof(UBODATA));
+
+ // just for easy access..
+ UBO &ubo = ubo_data.ubo;
+ UBO &prev_ubo = ubo_data.prev_ubo;
+
+ Projection correction;
+ correction.set_depth_correction(p_flip_y);
+ correction.add_jitter_offset(taa_jitter);
+ Projection projection = correction * cam_projection;
+
+ //store camera into ubo
+ RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix);
+ RendererRD::MaterialStorage::store_camera(projection.inverse(), ubo.inv_projection_matrix);
+ RendererRD::MaterialStorage::store_transform(cam_transform, ubo.inv_view_matrix);
+ RendererRD::MaterialStorage::store_transform(cam_transform.affine_inverse(), ubo.view_matrix);
+
+#ifdef REAL_T_IS_DOUBLE
+ RendererRD::MaterialStorage::split_double(-cam_transform.origin.x, &ubo.inv_view_matrix[12], &ubo.inv_view_matrix[3]);
+ RendererRD::MaterialStorage::split_double(-cam_transform.origin.y, &ubo.inv_view_matrix[13], &ubo.inv_view_matrix[7]);
+ RendererRD::MaterialStorage::split_double(-cam_transform.origin.z, &ubo.inv_view_matrix[14], &ubo.inv_view_matrix[11]);
+#endif
+
+ for (uint32_t v = 0; v < view_count; v++) {
+ projection = correction * view_projection[v];
+ RendererRD::MaterialStorage::store_camera(projection, ubo.projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(projection.inverse(), ubo.inv_projection_matrix_view[v]);
+
+ ubo.eye_offset[v][0] = view_eye_offset[v].x;
+ ubo.eye_offset[v][1] = view_eye_offset[v].y;
+ ubo.eye_offset[v][2] = view_eye_offset[v].z;
+ ubo.eye_offset[v][3] = 0.0;
+ }
+
+ ubo.taa_jitter[0] = taa_jitter.x;
+ ubo.taa_jitter[1] = taa_jitter.y;
+
+ ubo.z_far = z_far;
+ ubo.z_near = z_near;
+
+ ubo.pancake_shadows = p_pancake_shadows;
+
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_penumbra_shadow_kernel_get(), ubo.directional_penumbra_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->directional_soft_shadow_kernel_get(), ubo.directional_soft_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->penumbra_shadow_kernel_get(), ubo.penumbra_shadow_kernel);
+ RendererRD::MaterialStorage::store_soft_shadow_kernel(render_scene_render->soft_shadow_kernel_get(), ubo.soft_shadow_kernel);
+
+ ubo.viewport_size[0] = p_screen_size.x;
+ ubo.viewport_size[1] = p_screen_size.y;
+
+ Size2 screen_pixel_size = Vector2(1.0, 1.0) / Size2(p_screen_size);
+ ubo.screen_pixel_size[0] = screen_pixel_size.x;
+ ubo.screen_pixel_size[1] = screen_pixel_size.y;
+
+ ubo.shadow_atlas_pixel_size[0] = shadow_atlas_pixel_size.x;
+ ubo.shadow_atlas_pixel_size[1] = shadow_atlas_pixel_size.y;
+
+ ubo.directional_shadow_pixel_size[0] = directional_shadow_pixel_size.x;
+ ubo.directional_shadow_pixel_size[1] = directional_shadow_pixel_size.y;
+
+ ubo.time = time;
+
+ ubo.directional_light_count = directional_light_count;
+ ubo.dual_paraboloid_side = dual_paraboloid_side;
+ ubo.opaque_prepass_threshold = opaque_prepass_threshold;
+ ubo.material_uv2_mode = material_uv2_mode;
+
+ ubo.fog_enabled = false;
+
+ if (p_debug_mode == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) {
+ ubo.use_ambient_light = true;
+ ubo.ambient_light_color_energy[0] = 1;
+ ubo.ambient_light_color_energy[1] = 1;
+ ubo.ambient_light_color_energy[2] = 1;
+ ubo.ambient_light_color_energy[3] = 1.0;
+ ubo.use_ambient_cubemap = false;
+ ubo.use_reflection_cubemap = false;
+ } else if (p_env.is_valid()) {
+ RS::EnvironmentBG env_bg = render_scene_render->environment_get_background(p_env);
+ RS::EnvironmentAmbientSource ambient_src = render_scene_render->environment_get_ambient_source(p_env);
+
+ float bg_energy_multiplier = render_scene_render->environment_get_bg_energy_multiplier(p_env);
+
+ ubo.ambient_light_color_energy[3] = bg_energy_multiplier;
+
+ ubo.ambient_color_sky_mix = render_scene_render->environment_get_ambient_sky_contribution(p_env);
+
+ //ambient
+ if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) {
+ Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : render_scene_render->environment_get_bg_color(p_env);
+ color = color.srgb_to_linear();
+
+ ubo.ambient_light_color_energy[0] = color.r * bg_energy_multiplier;
+ ubo.ambient_light_color_energy[1] = color.g * bg_energy_multiplier;
+ ubo.ambient_light_color_energy[2] = color.b * bg_energy_multiplier;
+ ubo.use_ambient_light = true;
+ ubo.use_ambient_cubemap = false;
+ } else {
+ float energy = render_scene_render->environment_get_ambient_light_energy(p_env);
+ Color color = render_scene_render->environment_get_ambient_light(p_env);
+ color = color.srgb_to_linear();
+ ubo.ambient_light_color_energy[0] = color.r * energy;
+ ubo.ambient_light_color_energy[1] = color.g * energy;
+ ubo.ambient_light_color_energy[2] = color.b * energy;
+
+ Basis sky_transform = render_scene_render->environment_get_sky_orientation(p_env);
+ sky_transform = sky_transform.inverse() * cam_transform.basis;
+ RendererRD::MaterialStorage::store_transform_3x3(sky_transform, ubo.radiance_inverse_xform);
+
+ ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY;
+ ubo.use_ambient_light = ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR;
+ }
+
+ //specular
+ RS::EnvironmentReflectionSource ref_src = render_scene_render->environment_get_reflection_source(p_env);
+ if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) {
+ ubo.use_reflection_cubemap = true;
+ } else {
+ ubo.use_reflection_cubemap = false;
+ }
+
+ ubo.fog_enabled = render_scene_render->environment_get_fog_enabled(p_env);
+ ubo.fog_density = render_scene_render->environment_get_fog_density(p_env);
+ ubo.fog_height = render_scene_render->environment_get_fog_height(p_env);
+ ubo.fog_height_density = render_scene_render->environment_get_fog_height_density(p_env);
+ ubo.fog_aerial_perspective = render_scene_render->environment_get_fog_aerial_perspective(p_env);
+
+ Color fog_color = render_scene_render->environment_get_fog_light_color(p_env).srgb_to_linear();
+ float fog_energy = render_scene_render->environment_get_fog_light_energy(p_env);
+
+ ubo.fog_light_color[0] = fog_color.r * fog_energy;
+ ubo.fog_light_color[1] = fog_color.g * fog_energy;
+ ubo.fog_light_color[2] = fog_color.b * fog_energy;
+
+ ubo.fog_sun_scatter = render_scene_render->environment_get_fog_sun_scatter(p_env);
+ } else {
+ if (p_reflection_probe_instance.is_valid() && RendererRD::LightStorage::get_singleton()->reflection_probe_is_interior(p_reflection_probe_instance)) {
+ ubo.use_ambient_light = false;
+ } else {
+ ubo.use_ambient_light = true;
+ Color clear_color = p_default_bg_color;
+ clear_color = clear_color.srgb_to_linear();
+ ubo.ambient_light_color_energy[0] = clear_color.r;
+ ubo.ambient_light_color_energy[1] = clear_color.g;
+ ubo.ambient_light_color_energy[2] = clear_color.b;
+ ubo.ambient_light_color_energy[3] = 1.0;
+ }
+
+ ubo.use_ambient_cubemap = false;
+ ubo.use_reflection_cubemap = false;
+ }
+
+ if (p_camera_attributes.is_valid()) {
+ ubo.emissive_exposure_normalization = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes);
+ ubo.IBL_exposure_normalization = 1.0;
+ if (p_env.is_valid()) {
+ RID sky_rid = render_scene_render->environment_get_sky(p_env);
+ if (sky_rid.is_valid()) {
+ float current_exposure = RSG::camera_attributes->camera_attributes_get_exposure_normalization_factor(p_camera_attributes) * render_scene_render->environment_get_bg_intensity(p_env) / p_luminance_multiplier;
+ ubo.IBL_exposure_normalization = current_exposure / MAX(0.001, render_scene_render->get_sky()->sky_get_baked_exposure(sky_rid));
+ }
+ }
+ } else if (emissive_exposure_normalization > 0.0) {
+ // This branch is triggered when using render_material().
+ // Emissive is set outside the function.
+ ubo.emissive_exposure_normalization = emissive_exposure_normalization;
+ // IBL isn't used don't set it.
+ } else {
+ ubo.emissive_exposure_normalization = 1.0;
+ ubo.IBL_exposure_normalization = 1.0;
+ }
+
+ ubo.roughness_limiter_enabled = p_opaque_render_buffers && render_scene_render->screen_space_roughness_limiter_is_active();
+ ubo.roughness_limiter_amount = render_scene_render->screen_space_roughness_limiter_get_amount();
+ ubo.roughness_limiter_limit = render_scene_render->screen_space_roughness_limiter_get_limit();
+
+ if (calculate_motion_vectors) {
+ // Q : Should we make a complete copy or should we define a separate UBO with just the components we need?
+ memcpy(&prev_ubo, &ubo, sizeof(UBO));
+
+ Projection prev_correction;
+ prev_correction.set_depth_correction(true);
+ prev_correction.add_jitter_offset(prev_taa_jitter);
+ Projection prev_projection = prev_correction * prev_cam_projection;
+
+ //store camera into ubo
+ RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix);
+ RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), prev_ubo.inv_projection_matrix);
+ RendererRD::MaterialStorage::store_transform(prev_cam_transform, prev_ubo.inv_view_matrix);
+ RendererRD::MaterialStorage::store_transform(prev_cam_transform.affine_inverse(), prev_ubo.view_matrix);
+
+ for (uint32_t v = 0; v < view_count; v++) {
+ prev_projection = prev_correction * view_projection[v];
+ RendererRD::MaterialStorage::store_camera(prev_projection, prev_ubo.projection_matrix_view[v]);
+ RendererRD::MaterialStorage::store_camera(prev_projection.inverse(), prev_ubo.inv_projection_matrix_view[v]);
+ }
+ prev_ubo.taa_jitter[0] = prev_taa_jitter.x;
+ prev_ubo.taa_jitter[1] = prev_taa_jitter.y;
+ prev_ubo.time -= time_step;
+ }
+
+ uniform_buffer = p_uniform_buffer;
+ RD::get_singleton()->buffer_update(uniform_buffer, 0, sizeof(UBODATA), &ubo, RD::BARRIER_MASK_RASTER);
+}
+
+RID RenderSceneDataRD::get_uniform_buffer() {
+ return uniform_buffer;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
new file mode 100644
index 0000000000..9c031acc1e
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/render_scene_data_rd.h
@@ -0,0 +1,156 @@
+/*************************************************************************/
+/* render_scene_data_rd.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDER_SCENE_DATA_RD_H
+#define RENDER_SCENE_DATA_RD_H
+
+#include "render_scene_buffers_rd.h"
+#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering/rendering_device.h"
+
+// This is a container for data related to rendering a single frame of a viewport where we load this data into a UBO
+// that can be used by the main scene shader but also by various effects.
+
+class RenderSceneDataRD {
+public:
+ bool calculate_motion_vectors = false;
+
+ Transform3D cam_transform;
+ Projection cam_projection;
+ Vector2 taa_jitter;
+ bool cam_orthogonal = false;
+
+ // For stereo rendering
+ uint32_t view_count = 1;
+ Vector3 view_eye_offset[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+
+ Transform3D prev_cam_transform;
+ Projection prev_cam_projection;
+ Vector2 prev_taa_jitter;
+ Projection prev_view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+
+ float z_near = 0.0;
+ float z_far = 0.0;
+
+ float lod_distance_multiplier = 0.0;
+ float screen_mesh_lod_threshold = 0.0;
+
+ uint32_t directional_light_count = 0;
+ float dual_paraboloid_side = 0.0;
+ float opaque_prepass_threshold = 0.0;
+ bool material_uv2_mode = false;
+ float emissive_exposure_normalization = 0.0;
+
+ Size2 shadow_atlas_pixel_size;
+ Size2 directional_shadow_pixel_size;
+
+ float time;
+ float time_step;
+
+ RID create_uniform_buffer();
+ void update_ubo(RID p_uniform_buffer, RS::ViewportDebugDraw p_debug_mode, RID p_env, RID p_reflection_probe_instance, RID p_camera_attributes, bool p_flip_y, bool p_pancake_shadows, const Size2i &p_screen_size, const Color &p_default_bg_color, float p_luminance_multiplier, bool p_opaque_render_buffers);
+ RID get_uniform_buffer();
+
+private:
+ RID uniform_buffer; // loaded into this uniform buffer (supplied externally)
+
+ // This struct is loaded into Set 1 - Binding 0, populated at start of rendering a frame, must match with shader code
+ struct UBO {
+ float projection_matrix[16];
+ float inv_projection_matrix[16];
+ float inv_view_matrix[16];
+ float view_matrix[16];
+
+ float projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+ float inv_projection_matrix_view[RendererSceneRender::MAX_RENDER_VIEWS][16];
+ float eye_offset[RendererSceneRender::MAX_RENDER_VIEWS][4];
+
+ float viewport_size[2];
+ float screen_pixel_size[2];
+
+ float directional_penumbra_shadow_kernel[128]; //32 vec4s
+ float directional_soft_shadow_kernel[128];
+ float penumbra_shadow_kernel[128];
+ float soft_shadow_kernel[128];
+
+ float radiance_inverse_xform[12];
+
+ float ambient_light_color_energy[4];
+
+ float ambient_color_sky_mix;
+ uint32_t use_ambient_light;
+ uint32_t use_ambient_cubemap;
+ uint32_t use_reflection_cubemap;
+
+ float shadow_atlas_pixel_size[2];
+ float directional_shadow_pixel_size[2];
+
+ uint32_t directional_light_count;
+ float dual_paraboloid_side;
+ float z_far;
+ float z_near;
+
+ uint32_t roughness_limiter_enabled;
+ float roughness_limiter_amount;
+ float roughness_limiter_limit;
+ float opaque_prepass_threshold;
+
+ // Fog
+ uint32_t fog_enabled;
+ float fog_density;
+ float fog_height;
+ float fog_height_density;
+
+ float fog_light_color[3];
+ float fog_sun_scatter;
+
+ float fog_aerial_perspective;
+ float time;
+ float reflection_multiplier;
+ uint32_t material_uv2_mode;
+
+ float taa_jitter[2];
+ float emissive_exposure_normalization; // Needed to normalize emissive when using physical units.
+ float IBL_exposure_normalization; // Adjusts for baked exposure.
+
+ uint32_t pancake_shadows;
+ uint32_t pad1;
+ uint32_t pad2;
+ uint32_t pad3;
+ };
+
+ struct UBODATA {
+ UBO ubo;
+ UBO prev_ubo;
+ };
+};
+
+#endif // RENDER_SCENE_DATA_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
index 329c23bad0..077fde58b8 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp
@@ -29,15 +29,18 @@
/*************************************************************************/
#include "texture_storage.h"
+
#include "../effects/copy_effects.h"
+#include "../framebuffer_cache_rd.h"
#include "material_storage.h"
+#include "servers/rendering/renderer_rd/renderer_scene_render_rd.h"
using namespace RendererRD;
///////////////////////////////////////////////////////////////////////////
-// CanvasTexture
+// TextureStorage::CanvasTexture
-void CanvasTexture::clear_sets() {
+void TextureStorage::CanvasTexture::clear_sets() {
if (cleared_cache) {
return;
}
@@ -52,14 +55,14 @@ void CanvasTexture::clear_sets() {
cleared_cache = true;
}
-CanvasTexture::~CanvasTexture() {
+TextureStorage::CanvasTexture::~CanvasTexture() {
clear_sets();
}
///////////////////////////////////////////////////////////////////////////
-// Texture
+// TextureStorage::Texture
-void Texture::cleanup() {
+void TextureStorage::Texture::cleanup() {
if (RD::get_singleton()->texture_is_valid(rd_texture_srgb)) {
//erase this first, as it's a dependency of the one below
RD::get_singleton()->free(rd_texture_srgb);
@@ -96,6 +99,7 @@ TextureStorage::TextureStorage() {
Vector<uint8_t> pv;
pv.resize(16 * 4);
for (int i = 0; i < 16; i++) {
+ // Opaque white.
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 255);
pv.set(i * 4 + 2, 255);
@@ -109,6 +113,7 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Opaque black.
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
pv.set(i * 4 + 2, 0);
@@ -122,6 +127,21 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Transparent black.
+ pv.set(i * 4 + 0, 0);
+ pv.set(i * 4 + 1, 0);
+ pv.set(i * 4 + 2, 0);
+ pv.set(i * 4 + 3, 0);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_TRANSPARENT] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ // Opaque normal map "flat" color.
pv.set(i * 4 + 0, 128);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
@@ -135,6 +155,7 @@ TextureStorage::TextureStorage() {
}
for (int i = 0; i < 16; i++) {
+ // Opaque flowmap "flat" color.
pv.set(i * 4 + 0, 255);
pv.set(i * 4 + 1, 128);
pv.set(i * 4 + 2, 255);
@@ -191,7 +212,7 @@ TextureStorage::TextureStorage() {
}
}
- { //create default cubemap
+ { //create default black cubemap array
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -219,7 +240,35 @@ TextureStorage::TextureStorage() {
}
}
- { //create default cubemap array
+ { //create default white cubemap array
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.array_layers = 6;
+ tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ tformat.texture_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
+
+ Vector<uint8_t> pv;
+ pv.resize(16 * 4);
+ for (int i = 0; i < 16; i++) {
+ pv.set(i * 4 + 0, 255);
+ pv.set(i * 4 + 1, 255);
+ pv.set(i * 4 + 2, 255);
+ pv.set(i * 4 + 3, 255);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ for (int i = 0; i < 6; i++) {
+ vpv.push_back(pv);
+ }
+ default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
+ { //create default black cubemap
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -247,7 +296,7 @@ TextureStorage::TextureStorage() {
}
}
- { //create default cubemap white array
+ { //create default white cubemap
RD::TextureFormat tformat;
tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;
@@ -349,7 +398,6 @@ TextureStorage::TextureStorage() {
Vector<uint8_t> pv;
pv.resize(16 * 4);
-
for (int i = 0; i < 16; i++) {
pv.set(i * 4 + 0, 0);
pv.set(i * 4 + 1, 0);
@@ -358,7 +406,6 @@ TextureStorage::TextureStorage() {
}
{
- //take the chance and initialize decal atlas to something
Vector<Vector<uint8_t>> vpv;
vpv.push_back(pv);
decal_atlas.texture = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
@@ -366,6 +413,31 @@ TextureStorage::TextureStorage() {
}
}
+ { //create default VRS
+
+ RD::TextureFormat tformat;
+ tformat.format = RD::DATA_FORMAT_R8_UINT;
+ tformat.width = 4;
+ tformat.height = 4;
+ tformat.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;
+ if (RD::get_singleton()->has_feature(RD::SUPPORTS_ATTACHMENT_VRS)) {
+ tformat.usage_bits |= RD::TEXTURE_USAGE_VRS_ATTACHMENT_BIT;
+ }
+ tformat.texture_type = RD::TEXTURE_TYPE_2D;
+
+ Vector<uint8_t> pv;
+ pv.resize(4 * 4);
+ for (int i = 0; i < 4 * 4; i++) {
+ pv.set(i, 0);
+ }
+
+ {
+ Vector<Vector<uint8_t>> vpv;
+ vpv.push_back(pv);
+ default_rd_textures[DEFAULT_RD_TEXTURE_VRS] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv);
+ }
+ }
+
{
Vector<String> sdf_modes;
sdf_modes.push_back("\n#define MODE_LOAD\n");
@@ -388,6 +460,8 @@ TextureStorage::TextureStorage() {
TextureStorage::~TextureStorage() {
rt_sdf.shader.version_free(rt_sdf.shader_version);
+ free_decal_data();
+
if (decal_atlas.textures.size()) {
ERR_PRINT("Decal Atlas: " + itos(decal_atlas.textures.size()) + " textures were not removed from the atlas.");
}
@@ -406,6 +480,27 @@ TextureStorage::~TextureStorage() {
singleton = nullptr;
}
+bool TextureStorage::free(RID p_rid) {
+ if (owns_texture(p_rid)) {
+ texture_free(p_rid);
+ return true;
+ } else if (owns_canvas_texture(p_rid)) {
+ canvas_texture_free(p_rid);
+ return true;
+ } else if (owns_decal(p_rid)) {
+ decal_free(p_rid);
+ return true;
+ } else if (owns_decal_instance(p_rid)) {
+ decal_instance_free(p_rid);
+ return true;
+ } else if (owns_render_target(p_rid)) {
+ render_target_free(p_rid);
+ return true;
+ }
+
+ return false;
+}
+
bool TextureStorage::can_create_resources_async() const {
return true;
}
@@ -486,7 +581,7 @@ bool TextureStorage::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasIte
ct = t->canvas_texture;
} else {
- ct = get_canvas_texture(p_texture);
+ ct = canvas_texture_owner.get_or_null(p_texture);
}
if (!ct) {
@@ -604,12 +699,14 @@ void TextureStorage::texture_free(RID p_texture) {
}
void TextureStorage::texture_2d_initialize(RID p_texture, const Ref<Image> &p_image) {
+ ERR_FAIL_COND(p_image.is_null());
+
TextureToRDFormat ret_format;
Ref<Image> image = _validate_texture_format(p_image, ret_format);
Texture texture;
- texture.type = Texture::TYPE_2D;
+ texture.type = TextureStorage::TYPE_2D;
texture.width = p_image->get_width();
texture.height = p_image->get_height();
@@ -705,7 +802,7 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<R
Texture texture;
- texture.type = Texture::TYPE_LAYERED;
+ texture.type = TextureStorage::TYPE_LAYERED;
texture.layered_type = p_layered_type;
texture.width = p_layers[0]->get_width();
@@ -726,6 +823,8 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<R
case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: {
texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY;
} break;
+ default:
+ ERR_FAIL(); // Shouldn't happen, silence warnings.
}
texture.rd_format = ret_format.format;
@@ -835,7 +934,7 @@ void TextureStorage::texture_3d_initialize(RID p_texture, Image::Format p_format
Texture texture;
- texture.type = Texture::TYPE_3D;
+ texture.type = TextureStorage::TYPE_3D;
texture.width = p_width;
texture.height = p_height;
texture.depth = p_depth;
@@ -927,7 +1026,7 @@ void TextureStorage::_texture_2d_update(RID p_texture, const Ref<Image> &p_image
ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height);
ERR_FAIL_COND(p_image->get_format() != tex->format);
- if (tex->type == Texture::TYPE_LAYERED) {
+ if (tex->type == TextureStorage::TYPE_LAYERED) {
ERR_FAIL_INDEX(p_layer, tex->layers);
}
@@ -947,7 +1046,7 @@ void TextureStorage::texture_2d_update(RID p_texture, const Ref<Image> &p_image,
void TextureStorage::texture_3d_update(RID p_texture, const Vector<Ref<Image>> &p_data) {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->type != Texture::TYPE_3D);
+ ERR_FAIL_COND(tex->type != TextureStorage::TYPE_3D);
Image::Image3DValidateError verr = Image::validate_3d_image(tex->format, tex->width, tex->height, tex->depth, tex->mipmaps > 1, p_data);
if (verr != Image::VALIDATE_3D_OK) {
@@ -1025,9 +1124,7 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
- Ref<Image> image;
- image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
image->fill(Color(1, 0, 1, 1));
texture_2d_initialize(p_texture, image);
@@ -1036,9 +1133,7 @@ void TextureStorage::texture_2d_placeholder_initialize(RID p_texture) {
void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS::TextureLayeredType p_layered_type) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
- Ref<Image> image;
- image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
image->fill(Color(1, 0, 1, 1));
Vector<Ref<Image>> images;
@@ -1057,9 +1152,7 @@ void TextureStorage::texture_2d_layered_placeholder_initialize(RID p_texture, RS
void TextureStorage::texture_3d_placeholder_initialize(RID p_texture) {
//this could be better optimized to reuse an existing image , done this way
//for now to get it working
- Ref<Image> image;
- image.instantiate();
- image->create(4, 4, false, Image::FORMAT_RGBA8);
+ Ref<Image> image = Image::create_empty(4, 4, false, Image::FORMAT_RGBA8);
image->fill(Color(1, 0, 1, 1));
Vector<Ref<Image>> images;
@@ -1082,9 +1175,7 @@ Ref<Image> TextureStorage::texture_2d_get(RID p_texture) const {
#endif
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
- Ref<Image> image;
- image.instantiate();
- image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+ Ref<Image> image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (tex->format != tex->validated_format) {
image->convert(tex->format);
@@ -1105,9 +1196,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
Vector<uint8_t> data = RD::get_singleton()->texture_get_data(tex->rd_texture, p_layer);
ERR_FAIL_COND_V(data.size() == 0, Ref<Image>());
- Ref<Image> image;
- image.instantiate();
- image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
+ Ref<Image> image = Image::create_from_data(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data);
ERR_FAIL_COND_V(image->is_empty(), Ref<Image>());
if (tex->format != tex->validated_format) {
image->convert(tex->format);
@@ -1119,7 +1208,7 @@ Ref<Image> TextureStorage::texture_2d_layer_get(RID p_texture, int p_layer) cons
Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND_V(!tex, Vector<Ref<Image>>());
- ERR_FAIL_COND_V(tex->type != Texture::TYPE_3D, Vector<Ref<Image>>());
+ ERR_FAIL_COND_V(tex->type != TextureStorage::TYPE_3D, Vector<Ref<Image>>());
Vector<uint8_t> all_data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0);
@@ -1133,9 +1222,7 @@ Vector<Ref<Image>> TextureStorage::texture_3d_get(RID p_texture) const {
ERR_FAIL_COND_V(bs.offset + bs.buffer_size > (uint32_t)all_data.size(), Vector<Ref<Image>>());
Vector<uint8_t> sub_region = all_data.slice(bs.offset, bs.offset + bs.buffer_size);
- Ref<Image> img;
- img.instantiate();
- img->create(bs.size.width, bs.size.height, false, tex->validated_format, sub_region);
+ Ref<Image> img = Image::create_from_data(bs.size.width, bs.size.height, false, tex->validated_format, sub_region);
ERR_FAIL_COND_V(img->is_empty(), Vector<Ref<Image>>());
if (tex->format != tex->validated_format) {
img->convert(tex->format);
@@ -1195,7 +1282,7 @@ void TextureStorage::texture_replace(RID p_texture, RID p_by_texture) {
void TextureStorage::texture_set_size_override(RID p_texture, int p_width, int p_height) {
Texture *tex = texture_owner.get_or_null(p_texture);
ERR_FAIL_COND(!tex);
- ERR_FAIL_COND(tex->type != Texture::TYPE_2D);
+ ERR_FAIL_COND(tex->type != TextureStorage::TYPE_2D);
tex->width_2d = p_width;
tex->height_2d = p_height;
@@ -1249,6 +1336,13 @@ Size2 TextureStorage::texture_size_with_proxy(RID p_proxy) {
return texture_2d_get_size(p_proxy);
}
+RID TextureStorage::texture_get_rd_texture_rid(RID p_texture, bool p_srgb) const {
+ Texture *tex = texture_owner.get_or_null(p_texture);
+ ERR_FAIL_COND_V(!tex, RID());
+
+ return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture;
+}
+
Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, TextureToRDFormat &r_format) {
Ref<Image> image = p_image->duplicate();
@@ -1398,9 +1492,7 @@ Ref<Image> TextureStorage::_validate_texture_format(const Ref<Image> &p_image, T
} break;
case Image::FORMAT_RGBE9995: {
r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32;
-#ifndef _MSC_VER
-#warning TODO need to make a function in Image to swap bits for this
-#endif
+ // TODO: Need to make a function in Image to swap bits for this.
r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY;
r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY;
r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY;
@@ -1712,7 +1804,7 @@ void TextureStorage::decal_set_extents(RID p_decal, const Vector3 &p_extents) {
Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->extents = p_extents;
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID p_texture) {
@@ -1736,7 +1828,7 @@ void TextureStorage::decal_set_texture(RID p_decal, RS::DecalTexture p_type, RID
texture_add_to_decal_atlas(decal->textures[p_type]);
}
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_DECAL);
+ decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_DECAL);
}
void TextureStorage::decal_set_emission_energy(RID p_decal, float p_energy) {
@@ -1761,7 +1853,7 @@ void TextureStorage::decal_set_cull_mask(RID p_decal, uint32_t p_layers) {
Decal *decal = decal_owner.get_or_null(p_decal);
ERR_FAIL_COND(!decal);
decal->cull_mask = p_layers;
- decal->dependency.changed_notify(RendererStorage::DEPENDENCY_CHANGED_AABB);
+ decal->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
}
void TextureStorage::decal_set_distance_fade(RID p_decal, bool p_enabled, float p_begin, float p_length) {
@@ -1807,8 +1899,15 @@ AABB TextureStorage::decal_get_aabb(RID p_decal) const {
return AABB(-decal->extents, decal->extents * 2.0);
}
+Dependency *TextureStorage::decal_get_dependency(RID p_decal) {
+ Decal *decal = decal_owner.get_or_null(p_decal);
+ ERR_FAIL_COND_V(!decal, nullptr);
+
+ return &decal->dependency;
+}
+
void TextureStorage::update_decal_atlas() {
- RendererRD::CopyEffects *copy_effects = RendererRD::CopyEffects::get_singleton();
+ CopyEffects *copy_effects = CopyEffects::get_singleton();
ERR_FAIL_NULL(copy_effects);
if (!decal_atlas.dirty) {
@@ -2032,18 +2131,260 @@ void TextureStorage::texture_remove_from_decal_atlas(RID p_texture, bool p_panor
}
}
+/* DECAL INSTANCE API */
+
+RID TextureStorage::decal_instance_create(RID p_decal) {
+ DecalInstance di;
+ di.decal = p_decal;
+ di.forward_id = ForwardIDStorage::get_singleton()->allocate_forward_id(FORWARD_ID_TYPE_DECAL);
+ return decal_instance_owner.make_rid(di);
+}
+
+void TextureStorage::decal_instance_free(RID p_decal_instance) {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ ForwardIDStorage::get_singleton()->free_forward_id(FORWARD_ID_TYPE_DECAL, di->forward_id);
+ decal_instance_owner.free(p_decal_instance);
+}
+
+void TextureStorage::decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ ERR_FAIL_COND(!di);
+ di->transform = p_transform;
+}
+
+/* DECAL DATA API */
+
+void TextureStorage::free_decal_data() {
+ if (decal_buffer.is_valid()) {
+ RD::get_singleton()->free(decal_buffer);
+ decal_buffer = RID();
+ }
+
+ if (decals != nullptr) {
+ memdelete_arr(decals);
+ decals = nullptr;
+ }
+
+ if (decal_sort != nullptr) {
+ memdelete_arr(decal_sort);
+ decal_sort = nullptr;
+ }
+}
+
+void TextureStorage::set_max_decals(const uint32_t p_max_decals) {
+ max_decals = p_max_decals;
+ uint32_t decal_buffer_size = max_decals * sizeof(DecalData);
+ decals = memnew_arr(DecalData, max_decals);
+ decal_sort = memnew_arr(DecalInstanceSort, max_decals);
+ decal_buffer = RD::get_singleton()->storage_buffer_create(decal_buffer_size);
+}
+
+void TextureStorage::update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform) {
+ ForwardIDStorage *forward_id_storage = ForwardIDStorage::get_singleton();
+
+ Transform3D uv_xform;
+ uv_xform.basis.scale(Vector3(2.0, 1.0, 2.0));
+ uv_xform.origin = Vector3(-1.0, 0.0, -1.0);
+
+ uint32_t decals_size = p_decals.size();
+
+ decal_count = 0;
+
+ for (uint32_t i = 0; i < decals_size; i++) {
+ if (decal_count == max_decals) {
+ break;
+ }
+
+ DecalInstance *decal_instance = decal_instance_owner.get_or_null(p_decals[i]);
+ if (!decal_instance) {
+ continue;
+ }
+ Decal *decal = decal_owner.get_or_null(decal_instance->decal);
+
+ Transform3D xform = decal_instance->transform;
+
+ real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+
+ if (decal->distance_fade) {
+ float fade_begin = decal->distance_fade_begin;
+ float fade_length = decal->distance_fade_length;
+
+ if (distance > fade_begin) {
+ if (distance > fade_begin + fade_length) {
+ continue; // do not use this decal, its invisible
+ }
+ }
+ }
+
+ decal_sort[decal_count].decal_instance = decal_instance;
+ decal_sort[decal_count].decal = decal;
+ decal_sort[decal_count].depth = distance;
+ decal_count++;
+ }
+
+ if (decal_count > 0) {
+ SortArray<DecalInstanceSort> sort_array;
+ sort_array.sort(decal_sort, decal_count);
+ }
+
+ bool using_forward_ids = forward_id_storage->uses_forward_ids();
+ for (uint32_t i = 0; i < decal_count; i++) {
+ DecalInstance *decal_instance = decal_sort[i].decal_instance;
+ Decal *decal = decal_sort[i].decal;
+
+ if (using_forward_ids) {
+ forward_id_storage->map_forward_id(FORWARD_ID_TYPE_DECAL, decal_instance->forward_id, i);
+ }
+
+ decal_instance->cull_mask = decal->cull_mask;
+
+ Transform3D xform = decal_instance->transform;
+ float fade = 1.0;
+
+ if (decal->distance_fade) {
+ const real_t distance = -p_camera_inverse_xform.xform(xform.origin).z;
+ const float fade_begin = decal->distance_fade_begin;
+ const float fade_length = decal->distance_fade_length;
+
+ if (distance > fade_begin) {
+ // Use `smoothstep()` to make opacity changes more gradual and less noticeable to the player.
+ fade = Math::smoothstep(0.0f, 1.0f, 1.0f - float(distance - fade_begin) / fade_length);
+ }
+ }
+
+ DecalData &dd = decals[i];
+
+ Vector3 decal_extents = decal->extents;
+
+ Transform3D scale_xform;
+ scale_xform.basis.scale(decal_extents);
+ Transform3D to_decal_xform = (p_camera_inverse_xform * xform * scale_xform * uv_xform).affine_inverse();
+ MaterialStorage::store_transform(to_decal_xform, dd.xform);
+
+ Vector3 normal = xform.basis.get_column(Vector3::AXIS_Y).normalized();
+ normal = p_camera_inverse_xform.basis.xform(normal); //camera is normalized, so fine
+
+ dd.normal[0] = normal.x;
+ dd.normal[1] = normal.y;
+ dd.normal[2] = normal.z;
+ dd.normal_fade = decal->normal_fade;
+
+ RID albedo_tex = decal->textures[RS::DECAL_TEXTURE_ALBEDO];
+ RID emission_tex = decal->textures[RS::DECAL_TEXTURE_EMISSION];
+ if (albedo_tex.is_valid()) {
+ Rect2 rect = decal_atlas_get_texture_rect(albedo_tex);
+ dd.albedo_rect[0] = rect.position.x;
+ dd.albedo_rect[1] = rect.position.y;
+ dd.albedo_rect[2] = rect.size.x;
+ dd.albedo_rect[3] = rect.size.y;
+ } else {
+ if (!emission_tex.is_valid()) {
+ continue; //no albedo, no emission, no decal.
+ }
+ dd.albedo_rect[0] = 0;
+ dd.albedo_rect[1] = 0;
+ dd.albedo_rect[2] = 0;
+ dd.albedo_rect[3] = 0;
+ }
+
+ RID normal_tex = decal->textures[RS::DECAL_TEXTURE_NORMAL];
+
+ if (normal_tex.is_valid()) {
+ Rect2 rect = decal_atlas_get_texture_rect(normal_tex);
+ dd.normal_rect[0] = rect.position.x;
+ dd.normal_rect[1] = rect.position.y;
+ dd.normal_rect[2] = rect.size.x;
+ dd.normal_rect[3] = rect.size.y;
+
+ Basis normal_xform = p_camera_inverse_xform.basis * xform.basis.orthonormalized();
+ MaterialStorage::store_basis_3x4(normal_xform, dd.normal_xform);
+ } else {
+ dd.normal_rect[0] = 0;
+ dd.normal_rect[1] = 0;
+ dd.normal_rect[2] = 0;
+ dd.normal_rect[3] = 0;
+ }
+
+ RID orm_tex = decal->textures[RS::DECAL_TEXTURE_ORM];
+ if (orm_tex.is_valid()) {
+ Rect2 rect = decal_atlas_get_texture_rect(orm_tex);
+ dd.orm_rect[0] = rect.position.x;
+ dd.orm_rect[1] = rect.position.y;
+ dd.orm_rect[2] = rect.size.x;
+ dd.orm_rect[3] = rect.size.y;
+ } else {
+ dd.orm_rect[0] = 0;
+ dd.orm_rect[1] = 0;
+ dd.orm_rect[2] = 0;
+ dd.orm_rect[3] = 0;
+ }
+
+ if (emission_tex.is_valid()) {
+ Rect2 rect = decal_atlas_get_texture_rect(emission_tex);
+ dd.emission_rect[0] = rect.position.x;
+ dd.emission_rect[1] = rect.position.y;
+ dd.emission_rect[2] = rect.size.x;
+ dd.emission_rect[3] = rect.size.y;
+ } else {
+ dd.emission_rect[0] = 0;
+ dd.emission_rect[1] = 0;
+ dd.emission_rect[2] = 0;
+ dd.emission_rect[3] = 0;
+ }
+
+ Color modulate = decal->modulate;
+ dd.modulate[0] = modulate.r;
+ dd.modulate[1] = modulate.g;
+ dd.modulate[2] = modulate.b;
+ dd.modulate[3] = modulate.a * fade;
+ dd.emission_energy = decal->emission_energy * fade;
+ dd.albedo_mix = decal->albedo_mix;
+ dd.mask = decal->cull_mask;
+ dd.upper_fade = decal->upper_fade;
+ dd.lower_fade = decal->lower_fade;
+
+ // hook for subclass to do further processing.
+ RendererSceneRenderRD::get_singleton()->setup_added_decal(xform, decal_extents);
+ }
+
+ if (decal_count > 0) {
+ RD::get_singleton()->buffer_update(decal_buffer, 0, sizeof(DecalData) * decal_count, decals, RD::BARRIER_MASK_RASTER | RD::BARRIER_MASK_COMPUTE);
+ }
+}
+
/* RENDER TARGET API */
+RID TextureStorage::RenderTarget::get_framebuffer() {
+ // Note that if we're using an overridden color buffer, we're likely cycling through a texture chain.
+ // this is where our framebuffer cache comes in clutch..
+
+ if (msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(view_count, color_multisample, overridden.color.is_valid() ? overridden.color : color);
+ } else {
+ return FramebufferCacheRD::get_singleton()->get_cache_multiview(view_count, overridden.color.is_valid() ? overridden.color : color);
+ }
+}
+
void TextureStorage::_clear_render_target(RenderTarget *rt) {
- //free in reverse dependency order
- if (rt->framebuffer.is_valid()) {
- RD::get_singleton()->free(rt->framebuffer);
+ // clear overrides, we assume these are freed by the object that created them
+ rt->overridden.color = RID();
+ rt->overridden.depth = RID();
+ rt->overridden.velocity = RID();
+ rt->overridden.cached_slices.clear(); // these are automatically freed when their parent textures are freed so just clear
+
+ // free in reverse dependency order
+ if (rt->framebuffer_uniform_set.is_valid()) {
rt->framebuffer_uniform_set = RID(); //chain deleted
}
if (rt->color.is_valid()) {
RD::get_singleton()->free(rt->color);
}
+ rt->color_slices.clear(); // these are automatically freed.
+
+ if (rt->color_multisample.is_valid()) {
+ RD::get_singleton()->free(rt->color_multisample);
+ }
if (rt->backbuffer.is_valid()) {
RD::get_singleton()->free(rt->backbuffer);
@@ -2054,8 +2395,8 @@ void TextureStorage::_clear_render_target(RenderTarget *rt) {
_render_target_clear_sdf(rt);
- rt->framebuffer = RID();
rt->color = RID();
+ rt->color_multisample = RID();
}
void TextureStorage::_update_render_target(RenderTarget *rt) {
@@ -2077,35 +2418,49 @@ void TextureStorage::_update_render_target(RenderTarget *rt) {
rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB;
rt->image_format = rt->is_transparent ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8;
- RD::TextureFormat rd_format;
+ RD::TextureFormat rd_color_attachment_format;
RD::TextureView rd_view;
{ //attempt register
- rd_format.format = rt->color_format;
- rd_format.width = rt->size.width;
- rd_format.height = rt->size.height;
- rd_format.depth = 1;
- rd_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
- rd_format.mipmaps = 1;
- if (rd_format.array_layers > 1) { // why are we not using rt->texture_type ??
- rd_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
+ rd_color_attachment_format.format = rt->color_format;
+ rd_color_attachment_format.width = rt->size.width;
+ rd_color_attachment_format.height = rt->size.height;
+ rd_color_attachment_format.depth = 1;
+ rd_color_attachment_format.array_layers = rt->view_count; // for stereo we create two (or more) layers, need to see if we can make fallback work like this too if we don't have multiview
+ rd_color_attachment_format.mipmaps = 1;
+ if (rd_color_attachment_format.array_layers > 1) { // why are we not using rt->texture_type ??
+ rd_color_attachment_format.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;
} else {
- rd_format.texture_type = RD::TEXTURE_TYPE_2D;
+ rd_color_attachment_format.texture_type = RD::TEXTURE_TYPE_2D;
+ }
+ rd_color_attachment_format.samples = RD::TEXTURE_SAMPLES_1;
+ rd_color_attachment_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
+ rd_color_attachment_format.usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT; // FIXME we need this only when FSR is enabled
+ rd_color_attachment_format.shareable_formats.push_back(rt->color_format);
+ rd_color_attachment_format.shareable_formats.push_back(rt->color_format_srgb);
+ if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ rd_color_attachment_format.is_resolve_buffer = true;
}
- rd_format.samples = RD::TEXTURE_SAMPLES_1;
- rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
- rd_format.shareable_formats.push_back(rt->color_format);
- rd_format.shareable_formats.push_back(rt->color_format_srgb);
}
- rt->color = RD::get_singleton()->texture_create(rd_format, rd_view);
+ // TODO see if we can lazy create this once we actually use it as we may not need to create this if we have an overridden color buffer...
+ rt->color = RD::get_singleton()->texture_create(rd_color_attachment_format, rd_view);
ERR_FAIL_COND(rt->color.is_null());
- Vector<RID> fb_textures;
- fb_textures.push_back(rt->color);
- rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures, RenderingDevice::INVALID_ID, rt->view_count);
- if (rt->framebuffer.is_null()) {
- _clear_render_target(rt);
- ERR_FAIL_COND(rt->framebuffer.is_null());
+ if (rt->msaa != RS::VIEWPORT_MSAA_DISABLED) {
+ // Use the texture format of the color attachment for the multisample color attachment.
+ RD::TextureFormat rd_color_multisample_format = rd_color_attachment_format;
+ const RD::TextureSamples texture_samples[RS::VIEWPORT_MSAA_MAX] = {
+ RD::TEXTURE_SAMPLES_1,
+ RD::TEXTURE_SAMPLES_2,
+ RD::TEXTURE_SAMPLES_4,
+ RD::TEXTURE_SAMPLES_8,
+ };
+ rd_color_multisample_format.samples = texture_samples[rt->msaa];
+ rd_color_multisample_format.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
+ RD::TextureView rd_view_multisample;
+ rd_color_multisample_format.is_resolve_buffer = false;
+ rt->color_multisample = RD::get_singleton()->texture_create(rd_color_multisample_format, rd_view_multisample);
+ ERR_FAIL_COND(rt->color_multisample.is_null());
}
{ //update texture
@@ -2216,6 +2571,11 @@ void TextureStorage::render_target_set_position(RID p_render_target, int p_x, in
//unused for this render target
}
+Point2i TextureStorage::render_target_get_position(RID p_render_target) const {
+ //unused for this render target
+ return Point2i();
+}
+
void TextureStorage::render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND(!rt);
@@ -2227,6 +2587,13 @@ void TextureStorage::render_target_set_size(RID p_render_target, int p_width, in
}
}
+Size2i TextureStorage::render_target_get_size(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, Size2i());
+
+ return rt->size;
+}
+
RID TextureStorage::render_target_get_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
@@ -2234,7 +2601,72 @@ RID TextureStorage::render_target_get_texture(RID p_render_target) {
return rt->texture;
}
-void TextureStorage::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) {
+void TextureStorage::render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->overridden.color = p_color_texture;
+ rt->overridden.depth = p_depth_texture;
+ rt->overridden.velocity = p_velocity_texture;
+}
+
+RID TextureStorage::render_target_get_override_color(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.color;
+}
+
+RID TextureStorage::render_target_get_override_depth(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.depth;
+}
+
+RID TextureStorage::render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->overridden.depth.is_null()) {
+ return RID();
+ } else if (rt->view_count == 1) {
+ return rt->overridden.depth;
+ } else {
+ RenderTarget::RTOverridden::SliceKey key(rt->overridden.depth, p_layer);
+
+ if (!rt->overridden.cached_slices.has(key)) {
+ rt->overridden.cached_slices[key] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->overridden.depth, p_layer, 0);
+ }
+
+ return rt->overridden.cached_slices[key];
+ }
+}
+
+RID TextureStorage::render_target_get_override_velocity(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->overridden.velocity;
+}
+
+RID TextureStorage::render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->overridden.velocity.is_null()) {
+ return RID();
+ } else if (rt->view_count == 1) {
+ return rt->overridden.velocity;
+ } else {
+ RenderTarget::RTOverridden::SliceKey key(rt->overridden.velocity, p_layer);
+
+ if (!rt->overridden.cached_slices.has(key)) {
+ rt->overridden.cached_slices[key] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->overridden.velocity, p_layer, 0);
+ }
+
+ return rt->overridden.cached_slices[key];
+ }
}
void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_is_transparent) {
@@ -2244,10 +2676,21 @@ void TextureStorage::render_target_set_transparent(RID p_render_target, bool p_i
_update_render_target(rt);
}
+bool TextureStorage::render_target_get_transparent(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, false);
+
+ return rt->is_transparent;
+}
+
void TextureStorage::render_target_set_direct_to_screen(RID p_render_target, bool p_value) {
}
-bool TextureStorage::render_target_was_used(RID p_render_target) {
+bool TextureStorage::render_target_get_direct_to_screen(RID p_render_target) const {
+ return false;
+}
+
+bool TextureStorage::render_target_was_used(RID p_render_target) const {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, false);
return rt->was_used;
@@ -2259,25 +2702,58 @@ void TextureStorage::render_target_set_as_unused(RID p_render_target) {
rt->was_used = false;
}
-Size2 TextureStorage::render_target_get_size(RID p_render_target) {
+void TextureStorage::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
- ERR_FAIL_COND_V(!rt, Size2());
+ ERR_FAIL_COND(!rt);
+ if (p_msaa == rt->msaa) {
+ return;
+ }
- return rt->size;
+ rt->msaa = p_msaa;
+ _update_render_target(rt);
+}
+
+RS::ViewportMSAA TextureStorage::render_target_get_msaa(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RS::VIEWPORT_MSAA_DISABLED);
+
+ return rt->msaa;
}
RID TextureStorage::render_target_get_rd_framebuffer(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
- return rt->framebuffer;
+ return rt->get_framebuffer();
}
RID TextureStorage::render_target_get_rd_texture(RID p_render_target) {
RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
ERR_FAIL_COND_V(!rt, RID());
- return rt->color;
+ if (rt->overridden.color.is_valid()) {
+ return rt->overridden.color;
+ } else {
+ return rt->color;
+ }
+}
+
+RID TextureStorage::render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ if (rt->view_count == 1) {
+ return rt->color;
+ } else {
+ ERR_FAIL_UNSIGNED_INDEX_V(p_layer, rt->view_count, RID());
+ if (rt->color_slices.size() == 0) {
+ for (uint32_t v = 0; v < rt->view_count; v++) {
+ RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->color, v, 0);
+ rt->color_slices.push_back(slice);
+ }
+ }
+ return rt->color_slices[p_layer];
+ }
}
RID TextureStorage::render_target_get_rd_backbuffer(RID p_render_target) {
@@ -2330,7 +2806,7 @@ void TextureStorage::render_target_do_clear_request(RID p_render_target) {
}
Vector<Color> clear_colors;
clear_colors.push_back(rt->clear_color);
- RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
+ RD::get_singleton()->draw_list_begin(rt->get_framebuffer(), RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors);
RD::get_singleton()->draw_list_end();
rt->clear_requested = false;
}
@@ -2751,3 +3227,31 @@ void TextureStorage::render_target_set_backbuffer_uniform_set(RID p_render_targe
ERR_FAIL_COND(!rt);
rt->backbuffer_uniform_set = p_uniform_set;
}
+
+void TextureStorage::render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->vrs_mode = p_mode;
+}
+
+RS::ViewportVRSMode TextureStorage::render_target_get_vrs_mode(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RS::VIEWPORT_VRS_DISABLED);
+
+ return rt->vrs_mode;
+}
+
+void TextureStorage::render_target_set_vrs_texture(RID p_render_target, RID p_texture) {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND(!rt);
+
+ rt->vrs_texture = p_texture;
+}
+
+RID TextureStorage::render_target_get_vrs_texture(RID p_render_target) const {
+ RenderTarget *rt = render_target_owner.get_or_null(p_render_target);
+ ERR_FAIL_COND_V(!rt, RID());
+
+ return rt->vrs_texture;
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.h b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
index 901f764085..f4737eb63d 100644
--- a/servers/rendering/renderer_rd/storage_rd/texture_storage.h
+++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.h
@@ -31,249 +31,144 @@
#ifndef TEXTURE_STORAGE_RD_H
#define TEXTURE_STORAGE_RD_H
+#include "core/templates/local_vector.h"
+#include "core/templates/paged_array.h"
#include "core/templates/rid_owner.h"
#include "servers/rendering/renderer_rd/shaders/canvas_sdf.glsl.gen.h"
-#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/renderer_rd/storage_rd/forward_id_storage.h"
+#include "servers/rendering/rendering_server_default.h"
#include "servers/rendering/storage/texture_storage.h"
+#include "servers/rendering/storage/utilities.h"
namespace RendererRD {
-enum DefaultRDTexture {
- DEFAULT_RD_TEXTURE_WHITE,
- DEFAULT_RD_TEXTURE_BLACK,
- DEFAULT_RD_TEXTURE_NORMAL,
- DEFAULT_RD_TEXTURE_ANISO,
- DEFAULT_RD_TEXTURE_DEPTH,
- DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
- DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
- DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
- DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
- DEFAULT_RD_TEXTURE_3D_WHITE,
- DEFAULT_RD_TEXTURE_3D_BLACK,
- DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
- DEFAULT_RD_TEXTURE_2D_UINT,
- DEFAULT_RD_TEXTURE_MAX
-};
+class LightStorage;
+class MaterialStorage;
-class CanvasTexture {
+class TextureStorage : public RendererTextureStorage {
public:
- RID diffuse;
- RID normal_map;
- RID specular;
- Color specular_color = Color(1, 1, 1, 1);
- float shininess = 1.0;
-
- RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
- RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
- RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
-
- Size2i size_cache = Size2i(1, 1);
- bool use_normal_cache = false;
- bool use_specular_cache = false;
- bool cleared_cache = true;
-
- void clear_sets();
- ~CanvasTexture();
-};
+ enum DefaultRDTexture {
+ DEFAULT_RD_TEXTURE_WHITE,
+ DEFAULT_RD_TEXTURE_BLACK,
+ DEFAULT_RD_TEXTURE_TRANSPARENT,
+ DEFAULT_RD_TEXTURE_NORMAL,
+ DEFAULT_RD_TEXTURE_ANISO,
+ DEFAULT_RD_TEXTURE_DEPTH,
+ DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER,
+ DEFAULT_RD_TEXTURE_CUBEMAP_BLACK,
+ DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK,
+ DEFAULT_RD_TEXTURE_CUBEMAP_WHITE,
+ DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_WHITE,
+ DEFAULT_RD_TEXTURE_3D_WHITE,
+ DEFAULT_RD_TEXTURE_3D_BLACK,
+ DEFAULT_RD_TEXTURE_2D_ARRAY_WHITE,
+ DEFAULT_RD_TEXTURE_2D_UINT,
+ DEFAULT_RD_TEXTURE_VRS,
+ DEFAULT_RD_TEXTURE_MAX
+ };
-class Texture {
-public:
- enum Type {
+ enum TextureType {
TYPE_2D,
TYPE_LAYERED,
TYPE_3D
};
- Type type;
- RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
-
- RenderingDevice::TextureType rd_type;
- RID rd_texture;
- RID rd_texture_srgb;
- RenderingDevice::DataFormat rd_format;
- RenderingDevice::DataFormat rd_format_srgb;
-
- RD::TextureView rd_view;
+private:
+ friend class LightStorage;
+ friend class MaterialStorage;
- Image::Format format;
- Image::Format validated_format;
+ static TextureStorage *singleton;
- int width;
- int height;
- int depth;
- int layers;
- int mipmaps;
+ RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
- int height_2d;
- int width_2d;
+ /* Canvas Texture API */
- struct BufferSlice3D {
- Size2i size;
- uint32_t offset = 0;
- uint32_t buffer_size = 0;
+ class CanvasTexture {
+ public:
+ RID diffuse;
+ RID normal_map;
+ RID specular;
+ Color specular_color = Color(1, 1, 1, 1);
+ float shininess = 1.0;
+
+ RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT;
+ RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT;
+ RID uniform_sets[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX];
+
+ Size2i size_cache = Size2i(1, 1);
+ bool use_normal_cache = false;
+ bool use_specular_cache = false;
+ bool cleared_cache = true;
+
+ void clear_sets();
+ ~CanvasTexture();
};
- Vector<BufferSlice3D> buffer_slices_3d;
- uint32_t buffer_size_3d = 0;
-
- bool is_render_target;
- bool is_proxy;
- Ref<Image> image_cache_2d;
- String path;
+ RID_Owner<CanvasTexture, true> canvas_texture_owner;
- RID proxy_to;
- Vector<RID> proxies;
-
- HashSet<RID> lightmap_users;
-
- RS::TextureDetectCallback detect_3d_callback = nullptr;
- void *detect_3d_callback_ud = nullptr;
-
- RS::TextureDetectCallback detect_normal_callback = nullptr;
- void *detect_normal_callback_ud = nullptr;
-
- RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
- void *detect_roughness_callback_ud = nullptr;
-
- CanvasTexture *canvas_texture = nullptr;
-
- void cleanup();
-};
-
-struct DecalAtlas {
- struct Texture {
- int panorama_to_dp_users;
- int users;
- Rect2 uv_rect;
- };
-
- struct SortItem {
- RID texture;
- Size2i pixel_size;
- Size2i size;
- Point2i pos;
-
- bool operator<(const SortItem &p_item) const {
- //sort larger to smaller
- if (size.height == p_item.size.height) {
- return size.width > p_item.size.width;
- } else {
- return size.height > p_item.size.height;
- }
- }
- };
+ /* Texture API */
- HashMap<RID, Texture> textures;
- bool dirty = true;
- int mipmaps = 5;
+ class Texture {
+ public:
+ TextureType type;
+ RS::TextureLayeredType layered_type = RS::TEXTURE_LAYERED_2D_ARRAY;
- RID texture;
- RID texture_srgb;
- struct MipMap {
- RID fb;
- RID texture;
- Size2i size;
- };
- Vector<MipMap> texture_mipmaps;
+ RenderingDevice::TextureType rd_type;
+ RID rd_texture;
+ RID rd_texture_srgb;
+ RenderingDevice::DataFormat rd_format;
+ RenderingDevice::DataFormat rd_format_srgb;
- Size2i size;
-};
+ RD::TextureView rd_view;
-struct Decal {
- Vector3 extents = Vector3(1, 1, 1);
- RID textures[RS::DECAL_TEXTURE_MAX];
- float emission_energy = 1.0;
- float albedo_mix = 1.0;
- Color modulate = Color(1, 1, 1, 1);
- uint32_t cull_mask = (1 << 20) - 1;
- float upper_fade = 0.3;
- float lower_fade = 0.3;
- bool distance_fade = false;
- float distance_fade_begin = 10;
- float distance_fade_length = 1;
- float normal_fade = 0.0;
-
- RendererStorage::Dependency dependency;
-};
+ Image::Format format;
+ Image::Format validated_format;
-struct RenderTarget {
- Size2i size;
- uint32_t view_count;
- RID framebuffer;
- RID color;
+ int width;
+ int height;
+ int depth;
+ int layers;
+ int mipmaps;
- //used for retrieving from CPU
- RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
- Image::Format image_format = Image::FORMAT_L8;
+ int height_2d;
+ int width_2d;
- bool is_transparent = false;
+ struct BufferSlice3D {
+ Size2i size;
+ uint32_t offset = 0;
+ uint32_t buffer_size = 0;
+ };
+ Vector<BufferSlice3D> buffer_slices_3d;
+ uint32_t buffer_size_3d = 0;
- bool sdf_enabled = false;
+ bool is_render_target;
+ bool is_proxy;
- RID backbuffer; //used for effects
- RID backbuffer_fb;
- RID backbuffer_mipmap0;
+ Ref<Image> image_cache_2d;
+ String path;
- Vector<RID> backbuffer_mipmaps;
+ RID proxy_to;
+ Vector<RID> proxies;
- RID framebuffer_uniform_set;
- RID backbuffer_uniform_set;
+ HashSet<RID> lightmap_users;
- RID sdf_buffer_write;
- RID sdf_buffer_write_fb;
- RID sdf_buffer_process[2];
- RID sdf_buffer_read;
- RID sdf_buffer_process_uniform_sets[2];
- RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
- RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
- Size2i process_size;
+ RS::TextureDetectCallback detect_3d_callback = nullptr;
+ void *detect_3d_callback_ud = nullptr;
- //texture generated for this owner (nor RD).
- RID texture;
- bool was_used;
+ RS::TextureDetectCallback detect_normal_callback = nullptr;
+ void *detect_normal_callback_ud = nullptr;
- //clear request
- bool clear_requested;
- Color clear_color;
-};
+ RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr;
+ void *detect_roughness_callback_ud = nullptr;
-struct RenderTargetSDF {
- enum {
- SHADER_LOAD,
- SHADER_LOAD_SHRINK,
- SHADER_PROCESS,
- SHADER_PROCESS_OPTIMIZED,
- SHADER_STORE,
- SHADER_STORE_SHRINK,
- SHADER_MAX
- };
+ CanvasTexture *canvas_texture = nullptr;
- struct PushConstant {
- int32_t size[2];
- int32_t stride;
- int32_t shift;
- int32_t base_size[2];
- int32_t pad[2];
+ void cleanup();
};
- CanvasSdfShaderRD shader;
- RID shader_version;
- RID pipelines[SHADER_MAX];
-};
-
-class TextureStorage : public RendererTextureStorage {
-private:
- static TextureStorage *singleton;
-
- /* Canvas Texture API */
-
- RID_Owner<RendererRD::CanvasTexture, true> canvas_texture_owner;
-
- /* Texture API */
-
//textures can be created from threads, so this RID_Owner is thread safe
mutable RID_Owner<Texture, true> texture_owner;
+ Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
struct TextureToRDFormat {
RD::DataFormat format;
@@ -297,13 +192,202 @@ private:
/* DECAL API */
- DecalAtlas decal_atlas;
+ struct DecalAtlas {
+ struct Texture {
+ int panorama_to_dp_users;
+ int users;
+ Rect2 uv_rect;
+ };
+
+ struct SortItem {
+ RID texture;
+ Size2i pixel_size;
+ Size2i size;
+ Point2i pos;
+
+ bool operator<(const SortItem &p_item) const {
+ //sort larger to smaller
+ if (size.height == p_item.size.height) {
+ return size.width > p_item.size.width;
+ } else {
+ return size.height > p_item.size.height;
+ }
+ }
+ };
+
+ HashMap<RID, Texture> textures;
+ bool dirty = true;
+ int mipmaps = 5;
+
+ RID texture;
+ RID texture_srgb;
+ struct MipMap {
+ RID fb;
+ RID texture;
+ Size2i size;
+ };
+ Vector<MipMap> texture_mipmaps;
+
+ Size2i size;
+ } decal_atlas;
+
+ struct Decal {
+ Vector3 extents = Vector3(1, 1, 1);
+ RID textures[RS::DECAL_TEXTURE_MAX];
+ float emission_energy = 1.0;
+ float albedo_mix = 1.0;
+ Color modulate = Color(1, 1, 1, 1);
+ uint32_t cull_mask = (1 << 20) - 1;
+ float upper_fade = 0.3;
+ float lower_fade = 0.3;
+ bool distance_fade = false;
+ float distance_fade_begin = 40.0;
+ float distance_fade_length = 10.0;
+ float normal_fade = 0.0;
+
+ Dependency dependency;
+ };
mutable RID_Owner<Decal, true> decal_owner;
+ /* DECAL INSTANCE */
+
+ struct DecalInstance {
+ RID decal;
+ Transform3D transform;
+ uint32_t cull_mask = 0;
+ RendererRD::ForwardID forward_id = -1;
+ };
+
+ mutable RID_Owner<DecalInstance> decal_instance_owner;
+
+ /* DECAL DATA (UBO) */
+
+ struct DecalData {
+ float xform[16];
+ float inv_extents[3];
+ float albedo_mix;
+ float albedo_rect[4];
+ float normal_rect[4];
+ float orm_rect[4];
+ float emission_rect[4];
+ float modulate[4];
+ float emission_energy;
+ uint32_t mask;
+ float upper_fade;
+ float lower_fade;
+ float normal_xform[12];
+ float normal[3];
+ float normal_fade;
+ };
+
+ struct DecalInstanceSort {
+ float depth;
+ DecalInstance *decal_instance;
+ Decal *decal;
+ bool operator<(const DecalInstanceSort &p_sort) const {
+ return depth < p_sort.depth;
+ }
+ };
+
+ uint32_t max_decals = 0;
+ uint32_t decal_count = 0;
+ DecalData *decals = nullptr;
+ DecalInstanceSort *decal_sort = nullptr;
+ RID decal_buffer;
+
/* RENDER TARGET API */
+ struct RenderTarget {
+ Size2i size;
+ uint32_t view_count;
+ RID color;
+ Vector<RID> color_slices;
+ RID color_multisample; // Needed when MSAA is enabled.
+
+ RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED;
+
+ //used for retrieving from CPU
+ RD::DataFormat color_format = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ RD::DataFormat color_format_srgb = RD::DATA_FORMAT_R4G4_UNORM_PACK8;
+ Image::Format image_format = Image::FORMAT_L8;
+
+ bool is_transparent = false;
+
+ bool sdf_enabled = false;
+
+ RID backbuffer; //used for effects
+ RID backbuffer_fb;
+ RID backbuffer_mipmap0;
+
+ Vector<RID> backbuffer_mipmaps;
+
+ RID framebuffer_uniform_set;
+ RID backbuffer_uniform_set;
+
+ RID sdf_buffer_write;
+ RID sdf_buffer_write_fb;
+ RID sdf_buffer_process[2];
+ RID sdf_buffer_read;
+ RID sdf_buffer_process_uniform_sets[2];
+ RS::ViewportSDFOversize sdf_oversize = RS::VIEWPORT_SDF_OVERSIZE_120_PERCENT;
+ RS::ViewportSDFScale sdf_scale = RS::VIEWPORT_SDF_SCALE_50_PERCENT;
+ Size2i process_size;
+
+ // VRS
+ RS::ViewportVRSMode vrs_mode = RS::VIEWPORT_VRS_DISABLED;
+ RID vrs_texture;
+
+ // overridden textures
+ struct RTOverridden {
+ RID color;
+ RID depth;
+ RID velocity;
+
+ // In a multiview scenario, which is the most likely where we
+ // override our destination textures, we need to obtain slices
+ // for each layer of these textures.
+ // These are likely changing every frame as we loop through
+ // texture chains hence we add a cache to manage these slices.
+ // For this we define a key using the RID of the texture and
+ // the layer for which we create a slice.
+ struct SliceKey {
+ RID rid;
+ uint32_t layer = 0;
+
+ bool operator==(const SliceKey &p_val) const {
+ return (rid == p_val.rid) && (layer == p_val.layer);
+ }
+
+ static uint32_t hash(const SliceKey &p_val) {
+ uint32_t h = hash_one_uint64(p_val.rid.get_id());
+ h = hash_murmur3_one_32(p_val.layer, h);
+ return hash_fmix32(h);
+ }
+
+ SliceKey() {}
+ SliceKey(RID p_rid, uint32_t p_layer) {
+ rid = p_rid;
+ layer = p_layer;
+ }
+ };
+
+ mutable HashMap<SliceKey, RID, SliceKey> cached_slices;
+ } overridden;
+
+ //texture generated for this owner (nor RD).
+ RID texture;
+ bool was_used;
+
+ //clear request
+ bool clear_requested;
+ Color clear_color;
+
+ RID get_framebuffer();
+ };
+
mutable RID_Owner<RenderTarget> render_target_owner;
+ RenderTarget *get_render_target(RID p_rid) const { return render_target_owner.get_or_null(p_rid); };
void _clear_render_target(RenderTarget *rt);
void _update_render_target(RenderTarget *rt);
@@ -312,13 +396,33 @@ private:
void _render_target_clear_sdf(RenderTarget *rt);
Rect2i _render_target_get_sdf_rect(const RenderTarget *rt) const;
- RenderTargetSDF rt_sdf;
+ struct RenderTargetSDF {
+ enum {
+ SHADER_LOAD,
+ SHADER_LOAD_SHRINK,
+ SHADER_PROCESS,
+ SHADER_PROCESS_OPTIMIZED,
+ SHADER_STORE,
+ SHADER_STORE_SHRINK,
+ SHADER_MAX
+ };
+
+ struct PushConstant {
+ int32_t size[2];
+ int32_t stride;
+ int32_t shift;
+ int32_t base_size[2];
+ int32_t pad[2];
+ };
+
+ CanvasSdfShaderRD shader;
+ RID shader_version;
+ RID pipelines[SHADER_MAX];
+ } rt_sdf;
public:
static TextureStorage *get_singleton();
- RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX];
-
_FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) {
return default_rd_textures[p_texture];
}
@@ -326,9 +430,10 @@ public:
TextureStorage();
virtual ~TextureStorage();
+ bool free(RID p_rid);
+
/* Canvas Texture API */
- CanvasTexture *get_canvas_texture(RID p_rid) { return canvas_texture_owner.get_or_null(p_rid); };
bool owns_canvas_texture(RID p_rid) { return canvas_texture_owner.owns(p_rid); };
virtual RID canvas_texture_allocate() override;
@@ -345,8 +450,7 @@ public:
/* Texture API */
- Texture *get_texture(RID p_rid) { return texture_owner.get_or_null(p_rid); };
- bool owns_texture(RID p_rid) { return texture_owner.owns(p_rid); };
+ bool owns_texture(RID p_rid) const { return texture_owner.owns(p_rid); };
virtual bool can_create_resources_async() const override;
@@ -387,13 +491,32 @@ public:
virtual Size2 texture_size_with_proxy(RID p_proxy) override;
+ virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const override;
+
//internal usage
+ _FORCE_INLINE_ TextureType texture_get_type(RID p_texture) {
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
+ if (tex == nullptr) {
+ return TYPE_2D;
+ }
+
+ return tex->type;
+ }
+
+ _FORCE_INLINE_ int texture_get_layers(RID p_texture) {
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
+ if (tex == nullptr) {
+ return 1;
+ }
+
+ return tex->layers;
+ }
_FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) {
if (p_texture.is_null()) {
return RID();
}
- RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
if (!tex) {
return RID();
@@ -405,7 +528,7 @@ public:
if (p_texture.is_null()) {
return Size2i();
}
- RendererRD::Texture *tex = texture_owner.get_or_null(p_texture);
+ RendererRD::TextureStorage::Texture *tex = texture_owner.get_or_null(p_texture);
if (!tex) {
return Size2i();
@@ -417,8 +540,7 @@ public:
void update_decal_atlas();
- Decal *get_decal(RID p_rid) { return decal_owner.get_or_null(p_rid); };
- bool owns_decal(RID p_rid) { return decal_owner.owns(p_rid); };
+ bool owns_decal(RID p_rid) const { return decal_owner.owns(p_rid); };
RID decal_atlas_get_texture() const;
RID decal_atlas_get_texture_srgb() const;
@@ -512,23 +634,67 @@ public:
}
virtual AABB decal_get_aabb(RID p_decal) const override;
+ Dependency *decal_get_dependency(RID p_decal);
+
+ /* DECAL INSTANCE API */
+
+ bool owns_decal_instance(RID p_rid) const { return decal_instance_owner.owns(p_rid); }
+
+ virtual RID decal_instance_create(RID p_decal) override;
+ virtual void decal_instance_free(RID p_decal_instance) override;
+ virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) override;
+
+ _FORCE_INLINE_ RID decal_instance_get_base(RID p_decal_instance) const {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ return di->decal;
+ }
+
+ _FORCE_INLINE_ RendererRD::ForwardID decal_instance_get_forward_id(RID p_decal_instance) const {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ return di->forward_id;
+ }
+
+ _FORCE_INLINE_ Transform3D decal_instance_get_transform(RID p_decal_instance) const {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ return di->transform;
+ }
+
+ _FORCE_INLINE_ ForwardID decal_instance_get_forward_id(RID p_decal_instance) {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ return di->forward_id;
+ }
+
+ _FORCE_INLINE_ void decal_instance_set_cullmask(RID p_decal_instance, uint32_t p_cull_mask) const {
+ DecalInstance *di = decal_instance_owner.get_or_null(p_decal_instance);
+ di->cull_mask = p_cull_mask;
+ }
+
+ /* DECAL DATA API */
+
+ void free_decal_data();
+ void set_max_decals(const uint32_t p_max_decals);
+ RID get_decal_buffer() { return decal_buffer; }
+ void update_decal_buffer(const PagedArray<RID> &p_decals, const Transform3D &p_camera_inverse_xform);
/* RENDER TARGET API */
- RenderTarget *get_render_target(RID p_rid) { return render_target_owner.get_or_null(p_rid); };
- bool owns_render_target(RID p_rid) { return render_target_owner.owns(p_rid); };
+ bool owns_render_target(RID p_rid) const { return render_target_owner.owns(p_rid); };
virtual RID render_target_create() override;
virtual void render_target_free(RID p_rid) override;
virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) override;
+ virtual Point2i render_target_get_position(RID p_render_target) const override;
virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) override;
- virtual RID render_target_get_texture(RID p_render_target) override;
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) override;
+ virtual Size2i render_target_get_size(RID p_render_target) const override;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) override;
+ virtual bool render_target_get_transparent(RID p_render_target) const override;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) override;
- virtual bool render_target_was_used(RID p_render_target) override;
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const override;
+ virtual bool render_target_was_used(RID p_render_target) const override;
virtual void render_target_set_as_unused(RID p_render_target) override;
+ virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) override;
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const override;
void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps);
void render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color);
@@ -549,9 +715,23 @@ public:
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) override;
bool render_target_is_sdf_enabled(RID p_render_target) const;
- Size2 render_target_get_size(RID p_render_target);
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) override;
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const override;
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) override;
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const override;
+
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) override;
+ virtual RID render_target_get_override_color(RID p_render_target) const override;
+ virtual RID render_target_get_override_depth(RID p_render_target) const override;
+ RID render_target_get_override_depth_slice(RID p_render_target, const uint32_t p_layer) const;
+ virtual RID render_target_get_override_velocity(RID p_render_target) const override;
+ RID render_target_get_override_velocity_slice(RID p_render_target, const uint32_t p_layer) const;
+
+ virtual RID render_target_get_texture(RID p_render_target) override;
+
RID render_target_get_rd_framebuffer(RID p_render_target);
RID render_target_get_rd_texture(RID p_render_target);
+ RID render_target_get_rd_texture_slice(RID p_render_target, uint32_t p_layer);
RID render_target_get_rd_backbuffer(RID p_render_target);
RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target);
@@ -564,4 +744,4 @@ public:
} // namespace RendererRD
-#endif // !_TEXTURE_STORAGE_RD_H
+#endif // TEXTURE_STORAGE_RD_H
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.cpp b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
new file mode 100644
index 0000000000..625f089f66
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.cpp
@@ -0,0 +1,331 @@
+/*************************************************************************/
+/* utilities.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "utilities.h"
+#include "../environment/fog.h"
+#include "../environment/gi.h"
+#include "light_storage.h"
+#include "mesh_storage.h"
+#include "particles_storage.h"
+#include "texture_storage.h"
+
+using namespace RendererRD;
+
+Utilities *Utilities::singleton = nullptr;
+
+Utilities::Utilities() {
+ singleton = this;
+}
+
+Utilities::~Utilities() {
+ singleton = nullptr;
+}
+
+/* INSTANCES */
+
+RS::InstanceType Utilities::get_base_type(RID p_rid) const {
+ if (RendererRD::MeshStorage::get_singleton()->owns_mesh(p_rid)) {
+ return RS::INSTANCE_MESH;
+ }
+ if (RendererRD::MeshStorage::get_singleton()->owns_multimesh(p_rid)) {
+ return RS::INSTANCE_MULTIMESH;
+ }
+ if (RendererRD::LightStorage::get_singleton()->owns_reflection_probe(p_rid)) {
+ return RS::INSTANCE_REFLECTION_PROBE;
+ }
+ if (RendererRD::TextureStorage::get_singleton()->owns_decal(p_rid)) {
+ return RS::INSTANCE_DECAL;
+ }
+ if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) {
+ return RS::INSTANCE_VOXEL_GI;
+ }
+ if (RendererRD::LightStorage::get_singleton()->owns_light(p_rid)) {
+ return RS::INSTANCE_LIGHT;
+ }
+ if (RendererRD::LightStorage::get_singleton()->owns_lightmap(p_rid)) {
+ return RS::INSTANCE_LIGHTMAP;
+ }
+ if (RendererRD::ParticlesStorage::get_singleton()->owns_particles(p_rid)) {
+ return RS::INSTANCE_PARTICLES;
+ }
+ if (RendererRD::ParticlesStorage::get_singleton()->owns_particles_collision(p_rid)) {
+ return RS::INSTANCE_PARTICLES_COLLISION;
+ }
+ if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {
+ return RS::INSTANCE_FOG_VOLUME;
+ }
+ if (owns_visibility_notifier(p_rid)) {
+ return RS::INSTANCE_VISIBLITY_NOTIFIER;
+ }
+
+ return RS::INSTANCE_NONE;
+}
+
+bool Utilities::free(RID p_rid) {
+ if (RendererRD::LightStorage::get_singleton()->free(p_rid)) {
+ return true;
+ } else if (RendererRD::MaterialStorage::get_singleton()->free(p_rid)) {
+ return true;
+ } else if (RendererRD::MeshStorage::get_singleton()->free(p_rid)) {
+ return true;
+ } else if (RendererRD::ParticlesStorage::get_singleton()->free(p_rid)) {
+ return true;
+ } else if (RendererRD::TextureStorage::get_singleton()->free(p_rid)) {
+ return true;
+ } else if (RendererRD::GI::get_singleton()->owns_voxel_gi(p_rid)) {
+ RendererRD::GI::get_singleton()->voxel_gi_free(p_rid);
+ return true;
+ } else if (RendererRD::Fog::get_singleton()->owns_fog_volume(p_rid)) {
+ RendererRD::Fog::get_singleton()->fog_volume_free(p_rid);
+ return true;
+ } else if (owns_visibility_notifier(p_rid)) {
+ visibility_notifier_free(p_rid);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/* DEPENDENCIES */
+
+void Utilities::base_update_dependency(RID p_base, DependencyTracker *p_instance) {
+ if (MeshStorage::get_singleton()->owns_mesh(p_base)) {
+ Dependency *dependency = MeshStorage::get_singleton()->mesh_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (MeshStorage::get_singleton()->owns_multimesh(p_base)) {
+ Dependency *dependency = MeshStorage::get_singleton()->multimesh_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+
+ RID mesh = MeshStorage::get_singleton()->multimesh_get_mesh(p_base);
+ if (mesh.is_valid()) {
+ base_update_dependency(mesh, p_instance);
+ }
+ } else if (LightStorage::get_singleton()->owns_reflection_probe(p_base)) {
+ Dependency *dependency = LightStorage::get_singleton()->reflection_probe_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (TextureStorage::get_singleton()->owns_decal(p_base)) {
+ Dependency *dependency = TextureStorage::get_singleton()->decal_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (GI::get_singleton()->owns_voxel_gi(p_base)) {
+ Dependency *dependency = GI::get_singleton()->voxel_gi_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (LightStorage::get_singleton()->owns_lightmap(p_base)) {
+ Dependency *dependency = LightStorage::get_singleton()->lightmap_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (LightStorage::get_singleton()->owns_light(p_base)) {
+ Dependency *dependency = LightStorage::get_singleton()->light_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles(p_base)) {
+ Dependency *dependency = ParticlesStorage::get_singleton()->particles_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (ParticlesStorage::get_singleton()->owns_particles_collision(p_base)) {
+ Dependency *dependency = ParticlesStorage::get_singleton()->particles_collision_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (Fog::get_singleton()->owns_fog_volume(p_base)) {
+ Dependency *dependency = Fog::get_singleton()->fog_volume_get_dependency(p_base);
+ p_instance->update_dependency(dependency);
+ } else if (owns_visibility_notifier(p_base)) {
+ VisibilityNotifier *vn = get_visibility_notifier(p_base);
+ p_instance->update_dependency(&vn->dependency);
+ }
+}
+
+/* VISIBILITY NOTIFIER */
+
+RID Utilities::visibility_notifier_allocate() {
+ return visibility_notifier_owner.allocate_rid();
+}
+
+void Utilities::visibility_notifier_initialize(RID p_notifier) {
+ visibility_notifier_owner.initialize_rid(p_notifier, VisibilityNotifier());
+}
+
+void Utilities::visibility_notifier_free(RID p_notifier) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ vn->dependency.deleted_notify(p_notifier);
+ visibility_notifier_owner.free(p_notifier);
+}
+
+void Utilities::visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->aabb = p_aabb;
+ vn->dependency.changed_notify(Dependency::DEPENDENCY_CHANGED_AABB);
+}
+
+void Utilities::visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND(!vn);
+ vn->enter_callback = p_enter_callbable;
+ vn->exit_callback = p_exit_callable;
+}
+
+AABB Utilities::visibility_notifier_get_aabb(RID p_notifier) const {
+ const VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND_V(!vn, AABB());
+ return vn->aabb;
+}
+
+void Utilities::visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) {
+ VisibilityNotifier *vn = visibility_notifier_owner.get_or_null(p_notifier);
+ ERR_FAIL_COND(!vn);
+
+ if (p_enter) {
+ if (!vn->enter_callback.is_null()) {
+ if (p_deferred) {
+ vn->enter_callback.call_deferred();
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->enter_callback.callp(nullptr, 0, r, ce);
+ }
+ }
+ } else {
+ if (!vn->exit_callback.is_null()) {
+ if (p_deferred) {
+ vn->exit_callback.call_deferred();
+ } else {
+ Variant r;
+ Callable::CallError ce;
+ vn->exit_callback.callp(nullptr, 0, r, ce);
+ }
+ }
+ }
+}
+
+/* TIMING */
+
+void Utilities::capture_timestamps_begin() {
+ RD::get_singleton()->capture_timestamp("Frame Begin");
+}
+
+void Utilities::capture_timestamp(const String &p_name) {
+ RD::get_singleton()->capture_timestamp(p_name);
+}
+
+uint32_t Utilities::get_captured_timestamps_count() const {
+ return RD::get_singleton()->get_captured_timestamps_count();
+}
+
+uint64_t Utilities::get_captured_timestamps_frame() const {
+ return RD::get_singleton()->get_captured_timestamps_frame();
+}
+
+uint64_t Utilities::get_captured_timestamp_gpu_time(uint32_t p_index) const {
+ return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index);
+}
+
+uint64_t Utilities::get_captured_timestamp_cpu_time(uint32_t p_index) const {
+ return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index);
+}
+
+String Utilities::get_captured_timestamp_name(uint32_t p_index) const {
+ return RD::get_singleton()->get_captured_timestamp_name(p_index);
+}
+
+/* MISC */
+
+void Utilities::update_dirty_resources() {
+ MaterialStorage::get_singleton()->_update_global_shader_uniforms(); //must do before materials, so it can queue them for update
+ MaterialStorage::get_singleton()->_update_queued_materials();
+ MeshStorage::get_singleton()->_update_dirty_multimeshes();
+ MeshStorage::get_singleton()->_update_dirty_skeletons();
+ TextureStorage::get_singleton()->update_decal_atlas();
+}
+
+bool Utilities::has_os_feature(const String &p_feature) const {
+ if (!RD::get_singleton()) {
+ return false;
+ }
+
+ if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
+#if !defined(ANDROID_ENABLED) && !defined(IOS_ENABLED)
+ // Some Android devices report support for S3TC but we don't expect that and don't export the textures.
+ // This could be fixed but so few devices support it that it doesn't seem useful (and makes bigger APKs).
+ // For good measure we do the same hack for iOS, just in case.
+ if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+#endif
+
+ if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
+ if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) {
+ return true;
+ }
+
+ return false;
+}
+
+void Utilities::update_memory_info() {
+ texture_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TEXTURES);
+ buffer_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_BUFFERS);
+ total_mem_cache = RenderingDevice::get_singleton()->get_memory_usage(RenderingDevice::MEMORY_TOTAL);
+}
+
+uint64_t Utilities::get_rendering_info(RS::RenderingInfo p_info) {
+ if (p_info == RS::RENDERING_INFO_TEXTURE_MEM_USED) {
+ return texture_mem_cache;
+ } else if (p_info == RS::RENDERING_INFO_BUFFER_MEM_USED) {
+ return buffer_mem_cache;
+ } else if (p_info == RS::RENDERING_INFO_VIDEO_MEM_USED) {
+ return total_mem_cache;
+ }
+ return 0;
+}
+
+String Utilities::get_video_adapter_name() const {
+ return RenderingDevice::get_singleton()->get_device_name();
+}
+
+String Utilities::get_video_adapter_vendor() const {
+ return RenderingDevice::get_singleton()->get_device_vendor_name();
+}
+
+RenderingDevice::DeviceType Utilities::get_video_adapter_type() const {
+ return RenderingDevice::get_singleton()->get_device_type();
+}
+
+String Utilities::get_video_adapter_api_version() const {
+ return RenderingDevice::get_singleton()->get_device_api_version();
+}
+
+Size2i Utilities::get_maximum_viewport_size() const {
+ RenderingDevice *device = RenderingDevice::get_singleton();
+
+ int max_x = device->limit_get(RenderingDevice::LIMIT_MAX_VIEWPORT_DIMENSIONS_X);
+ int max_y = device->limit_get(RenderingDevice::LIMIT_MAX_VIEWPORT_DIMENSIONS_Y);
+ return Size2i(max_x, max_y);
+}
diff --git a/servers/rendering/renderer_rd/storage_rd/utilities.h b/servers/rendering/renderer_rd/storage_rd/utilities.h
new file mode 100644
index 0000000000..dda656c380
--- /dev/null
+++ b/servers/rendering/renderer_rd/storage_rd/utilities.h
@@ -0,0 +1,124 @@
+/*************************************************************************/
+/* utilities.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef UTILITIES_RD_H
+#define UTILITIES_RD_H
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering/storage/utilities.h"
+
+namespace RendererRD {
+
+/* VISIBILITY NOTIFIER */
+
+struct VisibilityNotifier {
+ AABB aabb;
+ Callable enter_callback;
+ Callable exit_callback;
+ Dependency dependency;
+};
+
+class Utilities : public RendererUtilities {
+private:
+ static Utilities *singleton;
+
+ /* VISIBILITY NOTIFIER */
+
+ mutable RID_Owner<VisibilityNotifier> visibility_notifier_owner;
+
+ /* MISC */
+
+ //keep cached since it can be called form any thread
+ uint64_t texture_mem_cache = 0;
+ uint64_t buffer_mem_cache = 0;
+ uint64_t total_mem_cache = 0;
+
+public:
+ static Utilities *get_singleton() { return singleton; }
+
+ Utilities();
+ virtual ~Utilities() override;
+
+ /* INSTANCES */
+
+ virtual RS::InstanceType get_base_type(RID p_rid) const override;
+ virtual bool free(RID p_rid) override;
+
+ /* DEPENDENCIES */
+
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) override;
+
+ /* VISIBILITY NOTIFIER */
+
+ VisibilityNotifier *get_visibility_notifier(RID p_rid) { return visibility_notifier_owner.get_or_null(p_rid); };
+ bool owns_visibility_notifier(RID p_rid) const { return visibility_notifier_owner.owns(p_rid); };
+
+ virtual RID visibility_notifier_allocate() override;
+ virtual void visibility_notifier_initialize(RID p_notifier) override;
+ virtual void visibility_notifier_free(RID p_notifier) override;
+
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) override;
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) override;
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const override;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) override;
+
+ /* TIMING */
+
+ virtual void capture_timestamps_begin() override;
+ virtual void capture_timestamp(const String &p_name) override;
+ virtual uint32_t get_captured_timestamps_count() const override;
+ virtual uint64_t get_captured_timestamps_frame() const override;
+ virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const override;
+ virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const override;
+ virtual String get_captured_timestamp_name(uint32_t p_index) const override;
+
+ /* MISC */
+
+ virtual void update_dirty_resources() override;
+ virtual void set_debug_generate_wireframes(bool p_generate) override {}
+
+ virtual bool has_os_feature(const String &p_feature) const override;
+
+ virtual void update_memory_info() override;
+
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) override;
+
+ virtual String get_video_adapter_name() const override;
+ virtual String get_video_adapter_vendor() const override;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const override;
+ virtual String get_video_adapter_api_version() const override;
+
+ virtual Size2i get_maximum_viewport_size() const override;
+};
+
+} // namespace RendererRD
+
+#endif // UTILITIES_RD_H
diff --git a/servers/rendering/renderer_rd/uniform_set_cache_rd.h b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
index e49cf4dafa..bca8b02178 100644
--- a/servers/rendering/renderer_rd/uniform_set_cache_rd.h
+++ b/servers/rendering/renderer_rd/uniform_set_cache_rd.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef UNIFORM_SET_CACHE_H
-#define UNIFORM_SET_CACHE_H
+#ifndef UNIFORM_SET_CACHE_RD_H
+#define UNIFORM_SET_CACHE_RD_H
#include "core/templates/local_vector.h"
#include "core/templates/paged_allocator.h"
@@ -57,13 +57,13 @@ class UniformSetCacheRD : public Object {
Cache *hash_table[HASH_TABLE_SIZE] = {};
static _FORCE_INLINE_ uint32_t _hash_uniform(const RD::Uniform &u, uint32_t h) {
- h = hash_djb2_one_32(u.uniform_type, h);
- h = hash_djb2_one_32(u.binding, h);
+ h = hash_murmur3_one_32(u.uniform_type, h);
+ h = hash_murmur3_one_32(u.binding, h);
uint32_t rsize = u.get_id_count();
for (uint32_t j = 0; j < rsize; j++) {
- h = hash_djb2_one_64(u.get_id(j).get_id(), h);
+ h = hash_murmur3_one_64(u.get_id(j).get_id(), h);
}
- return h;
+ return hash_fmix32(h);
}
static _FORCE_INLINE_ bool _compare_uniform(const RD::Uniform &a, const RD::Uniform &b) {
@@ -154,8 +154,8 @@ class UniformSetCacheRD : public Object {
public:
template <typename... Args>
RID get_cache(RID p_shader, uint32_t p_set, Args... args) {
- uint32_t h = hash_djb2_one_64(p_shader.get_id());
- h = hash_djb2_one_32(p_set, h);
+ uint32_t h = hash_murmur3_one_64(p_shader.get_id());
+ h = hash_murmur3_one_32(p_set, h);
h = _hash_args(h, args...);
uint32_t table_idx = h % HASH_TABLE_SIZE;
@@ -163,7 +163,7 @@ public:
const Cache *c = hash_table[table_idx];
while (c) {
- if (c->hash == h && c->set == p_set && c->shader == p_shader && _compare_args(0, c->uniforms, args...)) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader && sizeof...(Args) == c->uniforms.size() && _compare_args(0, c->uniforms, args...)) {
return c->cache;
}
c = c->next;
@@ -180,18 +180,20 @@ public:
template <typename... Args>
RID get_cache_vec(RID p_shader, uint32_t p_set, const Vector<RD::Uniform> &p_uniforms) {
- uint32_t h = hash_djb2_one_64(p_shader.get_id());
- h = hash_djb2_one_32(p_set, h);
+ uint32_t h = hash_murmur3_one_64(p_shader.get_id());
+ h = hash_murmur3_one_32(p_set, h);
for (int i = 0; i < p_uniforms.size(); i++) {
h = _hash_uniform(p_uniforms[i], h);
}
+ h = hash_fmix32(h);
+
uint32_t table_idx = h % HASH_TABLE_SIZE;
{
const Cache *c = hash_table[table_idx];
while (c) {
- if (c->hash == h && c->set == p_set && c->shader == p_shader) {
+ if (c->hash == h && c->set == p_set && c->shader == p_shader && (uint32_t)p_uniforms.size() == c->uniforms.size()) {
bool all_ok = true;
for (int i = 0; i < p_uniforms.size(); i++) {
if (!_compare_uniform(p_uniforms[i], c->uniforms[i])) {
@@ -218,4 +220,4 @@ public:
~UniformSetCacheRD();
};
-#endif // UNIFORMSETCACHE_H
+#endif // UNIFORM_SET_CACHE_RD_H
diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp
index 6f427272b5..348f6e4695 100644
--- a/servers/rendering/renderer_scene_cull.cpp
+++ b/servers/rendering/renderer_scene_cull.cpp
@@ -93,10 +93,10 @@ void RendererSceneCull::camera_set_environment(RID p_camera, RID p_env) {
camera->env = p_env;
}
-void RendererSceneCull::camera_set_camera_effects(RID p_camera, RID p_fx) {
+void RendererSceneCull::camera_set_camera_attributes(RID p_camera, RID p_attributes) {
Camera *camera = camera_owner.get_or_null(p_camera);
ERR_FAIL_COND(!camera);
- camera->effects = p_fx;
+ camera->attributes = p_attributes;
}
void RendererSceneCull::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) {
@@ -357,13 +357,14 @@ void RendererSceneCull::scenario_initialize(RID p_rid) {
Scenario *scenario = scenario_owner.get_or_null(p_rid);
scenario->self = p_rid;
- scenario->reflection_probe_shadow_atlas = scene_render->shadow_atlas_create();
- scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest
- scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4);
- scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
- scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
- scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
- scenario->reflection_atlas = scene_render->reflection_atlas_create();
+ scenario->reflection_probe_shadow_atlas = RSG::light_storage->shadow_atlas_create();
+ RSG::light_storage->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest
+ RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4);
+ RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4);
+ RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4);
+ RSG::light_storage->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8);
+
+ scenario->reflection_atlas = RSG::light_storage->reflection_atlas_create();
scenario->instance_aabbs.set_page_pool(&instance_aabb_page_pool);
scenario->instance_data.set_page_pool(&instance_data_page_pool);
@@ -378,10 +379,10 @@ void RendererSceneCull::scenario_set_environment(RID p_scenario, RID p_environme
scenario->environment = p_environment;
}
-void RendererSceneCull::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) {
+void RendererSceneCull::scenario_set_camera_attributes(RID p_scenario, RID p_camera_attributes) {
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
- scenario->camera_effects = p_camera_effects;
+ scenario->camera_attributes = p_camera_attributes;
}
void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
@@ -393,7 +394,7 @@ void RendererSceneCull::scenario_set_fallback_environment(RID p_scenario, RID p_
void RendererSceneCull::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) {
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
ERR_FAIL_COND(!scenario);
- scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
+ RSG::light_storage->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count);
}
bool RendererSceneCull::is_scenario(RID p_scenario) const {
@@ -470,12 +471,12 @@ void RendererSceneCull::_instance_update_mesh_instance(Instance *p_instance) {
p_instance->mesh_instance = RSG::mesh_storage->mesh_instance_create(p_instance->base);
} else {
- RSG::storage->free(p_instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_free(p_instance->mesh_instance);
p_instance->mesh_instance = RID();
}
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- scene_render->geometry_instance_set_mesh_instance(geom->geometry_instance, p_instance->mesh_instance);
+ geom->geometry_instance->set_mesh_instance(p_instance->mesh_instance);
if (p_instance->scenario && p_instance->array_index >= 0) {
InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
@@ -506,7 +507,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
if (instance->mesh_instance.is_valid()) {
- RSG::storage->free(instance->mesh_instance);
+ RSG::mesh_storage->mesh_instance_free(instance->mesh_instance);
instance->mesh_instance = RID();
// no need to set instance data flag here, as it was freed above
}
@@ -534,11 +535,11 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
scenario->directional_lights.erase(light->D);
light->D = nullptr;
}
- scene_render->free(light->instance);
+ RSG::light_storage->light_instance_free(light->instance);
} break;
case RS::INSTANCE_PARTICLES_COLLISION: {
InstanceParticlesCollisionData *collision = static_cast<InstanceParticlesCollisionData *>(instance->base_data);
- RSG::storage->free(collision->instance);
+ RSG::utilities->free(collision->instance);
} break;
case RS::INSTANCE_FOG_VOLUME: {
InstanceFogVolumeData *volume = static_cast<InstanceFogVolumeData *>(instance->base_data);
@@ -549,14 +550,14 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
- scene_render->free(reflection_probe->instance);
+ RSG::light_storage->reflection_probe_instance_free(reflection_probe->instance);
if (reflection_probe->update_list.in_list()) {
reflection_probe_render_list.remove(&reflection_probe->update_list);
}
} break;
case RS::INSTANCE_DECAL: {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(instance->base_data);
- scene_render->free(decal->instance);
+ RSG::texture_storage->decal_instance_free(decal->instance);
} break;
case RS::INSTANCE_LIGHTMAP: {
@@ -565,7 +566,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
while (lightmap_data->users.begin()) {
instance_geometry_set_lightmap((*lightmap_data->users.begin())->self, RID(), Rect2(), 0);
}
- scene_render->free(lightmap_data->instance);
+ RSG::light_storage->lightmap_instance_free(lightmap_data->instance);
} break;
case RS::INSTANCE_VOXEL_GI: {
InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(instance->base_data);
@@ -607,7 +608,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base = RID();
if (p_base.is_valid()) {
- instance->base_type = RSG::storage->get_base_type(p_base);
+ instance->base_type = RSG::utilities->get_base_type(p_base);
// fix up a specific malfunctioning case before the switch, so it can be handled
if (instance->base_type == RS::INSTANCE_NONE && RendererSceneOcclusionCull::get_singleton()->is_occluder(p_base)) {
@@ -626,7 +627,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
light->D = scenario->directional_lights.push_back(instance);
}
- light->instance = scene_render->light_instance_create(p_base);
+ light->instance = RSG::light_storage->light_instance_create(p_base);
instance->base_data = light;
} break;
@@ -637,20 +638,22 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
instance->base_data = geom;
geom->geometry_instance = scene_render->geometry_instance_create(p_base);
- scene_render->geometry_instance_set_skeleton(geom->geometry_instance, instance->skeleton);
- scene_render->geometry_instance_set_material_override(geom->geometry_instance, instance->material_override);
- scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, instance->material_overlay);
- scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, instance->materials);
- scene_render->geometry_instance_set_transform(geom->geometry_instance, instance->transform, instance->aabb, instance->transformed_aabb);
- scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, instance->layer_mask);
- scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, instance->lod_bias);
- scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, instance->baked_light);
- scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, instance->dynamic_gi);
- scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
- scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
- scene_render->geometry_instance_set_transparency(geom->geometry_instance, instance->transparency);
+ ERR_FAIL_NULL(geom->geometry_instance);
+
+ geom->geometry_instance->set_skeleton(instance->skeleton);
+ geom->geometry_instance->set_material_override(instance->material_override);
+ geom->geometry_instance->set_material_overlay(instance->material_overlay);
+ geom->geometry_instance->set_surface_materials(instance->materials);
+ geom->geometry_instance->set_transform(instance->transform, instance->aabb, instance->transformed_aabb);
+ geom->geometry_instance->set_layer_mask(instance->layer_mask);
+ geom->geometry_instance->set_lod_bias(instance->lod_bias);
+ geom->geometry_instance->set_transparency(instance->transparency);
+ geom->geometry_instance->set_use_baked_light(instance->baked_light);
+ geom->geometry_instance->set_use_dynamic_gi(instance->dynamic_gi);
+ geom->geometry_instance->set_use_lightmap(RID(), instance->lightmap_uv_scale, instance->lightmap_slice_index);
+ geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
if (instance->lightmap_sh.size() == 9) {
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, instance->lightmap_sh.ptr());
+ geom->geometry_instance->set_lightmap_capture(instance->lightmap_sh.ptr());
}
for (Instance *E : instance->visibility_dependencies) {
@@ -682,19 +685,19 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
reflection_probe->owner = instance;
instance->base_data = reflection_probe;
- reflection_probe->instance = scene_render->reflection_probe_instance_create(p_base);
+ reflection_probe->instance = RSG::light_storage->reflection_probe_instance_create(p_base);
} break;
case RS::INSTANCE_DECAL: {
InstanceDecalData *decal = memnew(InstanceDecalData);
decal->owner = instance;
instance->base_data = decal;
- decal->instance = scene_render->decal_instance_create(p_base);
+ decal->instance = RSG::texture_storage->decal_instance_create(p_base);
} break;
case RS::INSTANCE_LIGHTMAP: {
InstanceLightmapData *lightmap_data = memnew(InstanceLightmapData);
instance->base_data = lightmap_data;
- lightmap_data->instance = scene_render->lightmap_instance_create(p_base);
+ lightmap_data->instance = RSG::light_storage->lightmap_instance_create(p_base);
} break;
case RS::INSTANCE_VOXEL_GI: {
InstanceVoxelGIData *voxel_gi = memnew(InstanceVoxelGIData);
@@ -724,7 +727,7 @@ void RendererSceneCull::instance_set_base(RID p_instance, RID p_base) {
}
//forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it
- RSG::storage->base_update_dependency(p_base, &instance->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_base, &instance->dependency_tracker);
}
_instance_queue_update(instance, true, true);
@@ -756,7 +759,7 @@ void RendererSceneCull::instance_set_scenario(RID p_instance, RID p_scenario) {
} break;
case RS::INSTANCE_REFLECTION_PROBE: {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(instance->base_data);
- scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
+ RSG::light_storage->reflection_probe_release_atlas_index(reflection_probe->instance);
} break;
case RS::INSTANCE_PARTICLES_COLLISION: {
@@ -836,7 +839,8 @@ void RendererSceneCull::instance_set_layer_mask(RID p_instance, uint32_t p_mask)
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_layer_mask(geom->geometry_instance, p_mask);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_layer_mask(p_mask);
}
}
@@ -848,7 +852,8 @@ void RendererSceneCull::instance_geometry_set_transparency(RID p_instance, float
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_transparency(geom->geometry_instance, p_transparency);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_transparency(p_transparency);
}
}
@@ -864,12 +869,7 @@ void RendererSceneCull::instance_set_transform(RID p_instance, const Transform3D
for (int i = 0; i < 4; i++) {
const Vector3 &v = i < 3 ? p_transform.basis.rows[i] : p_transform.origin;
- ERR_FAIL_COND(Math::is_inf(v.x));
- ERR_FAIL_COND(Math::is_nan(v.x));
- ERR_FAIL_COND(Math::is_inf(v.y));
- ERR_FAIL_COND(Math::is_nan(v.y));
- ERR_FAIL_COND(Math::is_inf(v.z));
- ERR_FAIL_COND(Math::is_nan(v.z));
+ ERR_FAIL_COND(!v.is_finite());
}
#endif
@@ -1009,7 +1009,8 @@ void RendererSceneCull::instance_attach_skeleton(RID p_instance, RID p_skeleton)
_instance_update_mesh_instance(instance);
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_skeleton(geom->geometry_instance, p_skeleton);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_skeleton(p_skeleton);
}
}
@@ -1129,7 +1130,8 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_use_baked_light(geom->geometry_instance, p_enabled);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_use_baked_light(p_enabled);
}
} break;
@@ -1149,7 +1151,8 @@ void RendererSceneCull::instance_geometry_set_flag(RID p_instance, RS::InstanceF
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_use_dynamic_gi(geom->geometry_instance, p_enabled);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_use_dynamic_gi(p_enabled);
}
} break;
@@ -1207,7 +1210,9 @@ void RendererSceneCull::instance_geometry_set_cast_shadows_setting(RID p_instanc
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_cast_double_sided_shadows(geom->geometry_instance, instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
+ ERR_FAIL_NULL(geom->geometry_instance);
+
+ geom->geometry_instance->set_cast_double_sided_shadows(instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED);
}
_instance_queue_update(instance, false, true);
@@ -1222,7 +1227,8 @@ void RendererSceneCull::instance_geometry_set_material_override(RID p_instance,
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_material_override(geom->geometry_instance, p_material);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_material_override(p_material);
}
}
@@ -1235,7 +1241,8 @@ void RendererSceneCull::instance_geometry_set_material_overlay(RID p_instance, R
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_material_overlay(geom->geometry_instance, p_material);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_material_overlay(p_material);
}
}
@@ -1358,9 +1365,9 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
bool end_enabled = p_instance->visibility_range_end > 0.0f;
float end_min = p_instance->visibility_range_end - p_instance->visibility_range_end_margin;
float end_max = p_instance->visibility_range_end + p_instance->visibility_range_end_margin;
- scene_render->geometry_instance_set_fade_range(idata.instance_geometry, begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
+ idata.instance_geometry->set_fade_range(begin_enabled, begin_min, begin_max, end_enabled, end_min, end_max);
} else {
- scene_render->geometry_instance_set_fade_range(idata.instance_geometry, false, 0.0f, 0.0f, false, 0.0f, 0.0f);
+ idata.instance_geometry->set_fade_range(false, 0.0f, 0.0f, false, 0.0f, 0.0f);
}
}
@@ -1375,7 +1382,7 @@ void RendererSceneCull::_update_instance_visibility_dependencies(Instance *p_ins
} else {
idata.parent_array_index = -1;
if (is_geometry_instance) {
- scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, 1.0f);
+ idata.instance_geometry->set_parent_fade_alpha(1.0f);
}
}
}
@@ -1407,7 +1414,8 @@ void RendererSceneCull::instance_geometry_set_lightmap(RID p_instance, RID p_lig
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_use_lightmap(geom->geometry_instance, lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_use_lightmap(lightmap_instance_rid, p_lightmap_uv_scale, p_slice_index);
}
}
@@ -1419,7 +1427,8 @@ void RendererSceneCull::instance_geometry_set_lod_bias(RID p_instance, float p_l
if ((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK && instance->base_data) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
- scene_render->geometry_instance_set_lod_bias(geom->geometry_instance, p_lod_bias);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_lod_bias(p_lod_bias);
}
}
@@ -1429,19 +1438,34 @@ void RendererSceneCull::instance_geometry_set_shader_parameter(RID p_instance, c
ERR_FAIL_COND(p_value.get_type() == Variant::OBJECT);
- HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_parameters.find(p_parameter);
+ HashMap<StringName, Instance::InstanceShaderParameter>::Iterator E = instance->instance_shader_uniforms.find(p_parameter);
if (!E) {
Instance::InstanceShaderParameter isp;
isp.index = -1;
isp.info = PropertyInfo();
isp.value = p_value;
- instance->instance_shader_parameters[p_parameter] = isp;
+ instance->instance_shader_uniforms[p_parameter] = isp;
} else {
E->value.value = p_value;
- if (E->value.index >= 0 && instance->instance_allocated_shader_parameters) {
+ if (E->value.index >= 0 && instance->instance_allocated_shader_uniforms) {
+ int flags_count = 0;
+ if (E->value.info.hint == PROPERTY_HINT_FLAGS) {
+ // A small hack to detect boolean flags count and prevent overhead.
+ switch (E->value.info.hint_string.length()) {
+ case 3: // "x,y"
+ flags_count = 1;
+ break;
+ case 5: // "x,y,z"
+ flags_count = 2;
+ break;
+ case 7: // "x,y,z,w"
+ flags_count = 3;
+ break;
+ }
+ }
//update directly
- RSG::material_storage->global_variables_instance_update(p_instance, E->value.index, p_value);
+ RSG::material_storage->global_shader_parameters_instance_update(p_instance, E->value.index, p_value, flags_count);
}
}
}
@@ -1450,8 +1474,8 @@ Variant RendererSceneCull::instance_geometry_get_shader_parameter(RID p_instance
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
- if (instance->instance_shader_parameters.has(p_parameter)) {
- return instance->instance_shader_parameters[p_parameter].value;
+ if (instance->instance_shader_uniforms.has(p_parameter)) {
+ return instance->instance_shader_uniforms[p_parameter].value;
}
return Variant();
}
@@ -1460,8 +1484,8 @@ Variant RendererSceneCull::instance_geometry_get_shader_parameter_default_value(
const Instance *instance = const_cast<RendererSceneCull *>(this)->instance_owner.get_or_null(p_instance);
ERR_FAIL_COND_V(!instance, Variant());
- if (instance->instance_shader_parameters.has(p_parameter)) {
- return instance->instance_shader_parameters[p_parameter].default_value;
+ if (instance->instance_shader_uniforms.has(p_parameter)) {
+ return instance->instance_shader_uniforms[p_parameter].default_value;
}
return Variant();
}
@@ -1473,12 +1497,12 @@ void RendererSceneCull::instance_geometry_get_shader_parameter_list(RID p_instan
const_cast<RendererSceneCull *>(this)->update_dirty_instances();
Vector<StringName> names;
- for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_parameters) {
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : instance->instance_shader_uniforms) {
names.push_back(E.key);
}
names.sort_custom<StringName::AlphCompare>();
for (int i = 0; i < names.size(); i++) {
- PropertyInfo pinfo = instance->instance_shader_parameters[names[i]].info;
+ PropertyInfo pinfo = instance->instance_shader_uniforms[names[i]].info;
p_parameters->push_back(pinfo);
}
}
@@ -1489,8 +1513,8 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if (p_instance->base_type == RS::INSTANCE_LIGHT) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
- scene_render->light_instance_set_transform(light->instance, p_instance->transform);
- scene_render->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb));
+ RSG::light_storage->light_instance_set_transform(light->instance, p_instance->transform);
+ RSG::light_storage->light_instance_set_aabb(light->instance, p_instance->transform.xform(p_instance->aabb));
light->shadow_dirty = true;
RS::LightBakeMode bake_mode = RSG::light_storage->light_get_bake_mode(p_instance->base);
@@ -1513,7 +1537,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
} else if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(p_instance->base_data);
- scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
+ RSG::light_storage->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform);
if (p_instance->scenario && p_instance->array_index >= 0) {
InstanceData &idata = p_instance->scenario->instance_data[p_instance->array_index];
@@ -1522,11 +1546,11 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
} else if (p_instance->base_type == RS::INSTANCE_DECAL) {
InstanceDecalData *decal = static_cast<InstanceDecalData *>(p_instance->base_data);
- scene_render->decal_instance_set_transform(decal->instance, p_instance->transform);
+ RSG::texture_storage->decal_instance_set_transform(decal->instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_LIGHTMAP) {
InstanceLightmapData *lightmap = static_cast<InstanceLightmapData *>(p_instance->base_data);
- scene_render->lightmap_instance_set_transform(lightmap->instance, p_instance->transform);
+ RSG::light_storage->lightmap_instance_set_transform(lightmap->instance, p_instance->transform);
} else if (p_instance->base_type == RS::INSTANCE_VOXEL_GI) {
InstanceVoxelGIData *voxel_gi = static_cast<InstanceVoxelGIData *>(p_instance->base_data);
@@ -1550,7 +1574,7 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
}
}
- if (p_instance->aabb.has_no_surface()) {
+ if (!p_instance->aabb.has_surface()) {
return;
}
@@ -1587,11 +1611,13 @@ void RendererSceneCull::_update_instance(Instance *p_instance) {
if (!p_instance->lightmap_sh.is_empty()) {
p_instance->lightmap_sh.clear(); //don't need SH
p_instance->lightmap_target_sh.clear(); //don't need SH
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, nullptr);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_lightmap_capture(nullptr);
}
}
- scene_render->geometry_instance_set_transform(geom->geometry_instance, p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_transform(p_instance->transform, p_instance->aabb, p_instance->transformed_aabb);
}
// note: we had to remove is equal approx check here, it meant that det == 0.000004 won't work, which is the case for some of our scenes.
@@ -1817,11 +1843,12 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
// Clear these now because the InstanceData containing the dirty flags is gone
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, nullptr, 0);
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, nullptr, 0);
+ geom->geometry_instance->pair_light_instances(nullptr, 0);
+ geom->geometry_instance->pair_reflection_probe_instances(nullptr, 0);
+ geom->geometry_instance->pair_decal_instances(nullptr, 0);
+ geom->geometry_instance->pair_voxel_gi_instances(nullptr, 0);
}
for (Instance *E : p_instance->visibility_dependencies) {
@@ -1829,7 +1856,7 @@ void RendererSceneCull::_unpair_instance(Instance *p_instance) {
if (dep_instance->array_index != -1) {
dep_instance->scenario->instance_data[dep_instance->array_index].parent_array_index = -1;
if ((1 << dep_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
- scene_render->geometry_instance_set_parent_fade_alpha(dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry, 1.0f);
+ dep_instance->scenario->instance_data[dep_instance->array_index].instance_geometry->set_parent_fade_alpha(1.0f);
}
}
}
@@ -1876,10 +1903,10 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
} break;
case RenderingServer::INSTANCE_FOG_VOLUME: {
- new_aabb = RSG::storage->fog_volume_get_aabb(p_instance->base);
+ new_aabb = RSG::fog->fog_volume_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_VISIBLITY_NOTIFIER: {
- new_aabb = RSG::storage->visibility_notifier_get_aabb(p_instance->base);
+ new_aabb = RSG::utilities->visibility_notifier_get_aabb(p_instance->base);
} break;
case RenderingServer::INSTANCE_LIGHT: {
new_aabb = RSG::light_storage->light_get_aabb(p_instance->base);
@@ -1894,7 +1921,7 @@ void RendererSceneCull::_update_instance_aabb(Instance *p_instance) {
} break;
case RenderingServer::INSTANCE_VOXEL_GI: {
- new_aabb = RSG::storage->voxel_gi_get_bounds(p_instance->base);
+ new_aabb = RSG::gi->voxel_gi_get_bounds(p_instance->base);
} break;
case RenderingServer::INSTANCE_LIGHTMAP: {
@@ -1990,10 +2017,11 @@ void RendererSceneCull::_update_instance_lightmap_captures(Instance *p_instance)
}
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, p_instance->lightmap_sh.ptr());
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_lightmap_capture(p_instance->lightmap_sh.ptr());
}
-void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
+void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform;
@@ -2033,7 +2061,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
distances[splits] = max_distance;
- real_t texture_size = scene_render->get_directional_light_shadow_size(light->instance);
+ real_t texture_size = RSG::light_storage->get_directional_light_shadow_size(light->instance);
bool overlap = RSG::light_storage->light_directional_get_blend_splits(p_instance->base);
@@ -2045,7 +2073,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
RENDER_TIMESTAMP("Cull DirectionalLight3D, Split " + itos(i));
// setup a camera matrix for that range!
- CameraMatrix camera_matrix;
+ Projection camera_matrix;
real_t aspect = p_cam_projection.get_aspect();
@@ -2146,7 +2174,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
if (soft_shadow_angle > 0.0) {
float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam;
- soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range;
+ soft_shadow_expand = Math::tan(Math::deg_to_rad(soft_shadow_angle)) * z_range;
x_max += soft_shadow_expand;
y_max += soft_shadow_expand;
@@ -2185,7 +2213,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
z_max = z_vec.dot(center) + radius + pancake_size;
{
- CameraMatrix ortho_camera;
+ Projection ortho_camera;
real_t half_x = (x_max_cam - x_min_cam) * 0.5;
real_t half_y = (y_max_cam - y_min_cam) * 0.5;
@@ -2210,7 +2238,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in
}
}
-bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) {
+bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_screen_mesh_lod_threshold) {
InstanceLightData *light = static_cast<InstanceLightData *>(p_instance->base_data);
Transform3D light_transform = p_instance->transform;
@@ -2224,7 +2252,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
case RS::LIGHT_OMNI: {
RS::LightOmniShadowMode shadow_mode = RSG::light_storage->light_omni_get_shadow_mode(p_instance->base);
- if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !scene_render->light_instances_can_render_shadow_cube()) {
+ if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::light_storage->light_instances_can_render_shadow_cube()) {
if (max_shadows_used + 2 > MAX_UPDATE_SHADOWS) {
return true;
}
@@ -2283,7 +2311,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::mesh_storage->update_mesh_instances();
- scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i, 0);
+ RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, i, 0);
shadow_data.light = light->instance;
shadow_data.pass = i;
}
@@ -2294,7 +2322,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, radius * 0.005f, radius);
for (int i = 0; i < 6; i++) {
@@ -2359,14 +2387,14 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
}
RSG::mesh_storage->update_mesh_instances();
- scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
+ RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i, 0);
shadow_data.light = light->instance;
shadow_data.pass = i;
}
//restore the regular DP matrix
- //scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0, 0);
+ //RSG::light_storage->light_instance_set_shadow_transform(light->instance, Projection(), light_transform, radius, 0, 0, 0);
}
} break;
@@ -2380,7 +2408,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
real_t radius = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE);
real_t angle = RSG::light_storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE);
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(angle * 2.0, 1.0, 0.005f * radius, radius);
Vector<Plane> planes = cm.get_projection_planes(light_transform);
@@ -2423,7 +2451,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
RSG::mesh_storage->update_mesh_instances();
- scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
+ RSG::light_storage->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0, 0);
shadow_data.light = light->instance;
shadow_data.pass = 0;
@@ -2433,7 +2461,7 @@ bool RendererSceneCull::_light_instance_update_shadow(Instance *p_instance, cons
return animated_material_found;
}
-void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
+void RendererSceneCull::render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info) {
#ifndef _3D_DISABLED
Camera *camera = camera_owner.get_or_null(p_camera);
@@ -2450,7 +2478,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
if (p_xr_interface.is_null()) {
// Normal camera
Transform3D transform = camera->transform;
- CameraMatrix projection;
+ Projection projection;
bool vaspect = camera->vaspect;
bool is_orthogonal = false;
@@ -2489,7 +2517,7 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
// Setup our camera for our XR interface.
// We can support multiple views here each with their own camera
Transform3D transforms[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix projections[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection projections[RendererSceneRender::MAX_RENDER_VIEWS];
uint32_t view_count = p_xr_interface->get_view_count();
ERR_FAIL_COND_MSG(view_count > RendererSceneRender::MAX_RENDER_VIEWS, "Requested view count is not supported");
@@ -2518,14 +2546,14 @@ void RendererSceneCull::render_camera(RID p_render_buffers, RID p_camera, RID p_
RENDER_TIMESTAMP("Update Occlusion Buffer")
// For now just cull on the first camera
- RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal, RendererThreadPool::singleton->thread_work_pool);
+ RendererSceneOcclusionCull::get_singleton()->buffer_update(p_viewport, camera_data.main_transform, camera_data.main_projection, camera_data.is_orthogonal);
- _render_scene(&camera_data, p_render_buffers, environment, camera->effects, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info);
+ _render_scene(&camera_data, p_render_buffers, environment, camera->attributes, camera->visible_layers, p_scenario, p_viewport, p_shadow_atlas, RID(), -1, p_screen_mesh_lod_threshold, true, r_render_info);
#endif
}
void RendererSceneCull::_visibility_cull_threaded(uint32_t p_thread, VisibilityCullData *cull_data) {
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t bin_from = p_thread * cull_data->cull_count / total_threads;
uint32_t bin_to = (p_thread + 1 == total_threads) ? cull_data->cull_count : ((p_thread + 1) * cull_data->cull_count / total_threads);
@@ -2622,7 +2650,7 @@ bool RendererSceneCull::_visibility_parent_check(const CullData &p_cull_data, co
void RendererSceneCull::_scene_cull_threaded(uint32_t p_thread, CullData *cull_data) {
uint32_t cull_total = cull_data->scenario->instance_data.size();
- uint32_t total_threads = RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ uint32_t total_threads = WorkerThreadPool::get_singleton()->get_thread_count();
uint32_t cull_from = p_thread * cull_total / total_threads;
uint32_t cull_to = (p_thread + 1 == total_threads) ? cull_total : ((p_thread + 1) * cull_total / total_threads);
@@ -2663,14 +2691,14 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
cull_result.lights.push_back(idata.instance);
cull_result.light_instances.push_back(RID::from_uint64(idata.instance_data_rid));
if (cull_data.shadow_atlas.is_valid() && RSG::light_storage->light_has_shadow(idata.base_rid)) {
- scene_render->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
+ RSG::light_storage->light_instance_mark_visible(RID::from_uint64(idata.instance_data_rid)); //mark it visible for shadow allocation later
}
} else if (base_type == RS::INSTANCE_REFLECTION_PROBE) {
if (cull_data.render_reflection_probe != idata.instance) {
//avoid entering The Matrix
- if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || scene_render->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
+ if ((idata.flags & InstanceData::FLAG_REFLECTION_PROBE_DIRTY) || RSG::light_storage->reflection_probe_instance_needs_redraw(RID::from_uint64(idata.instance_data_rid))) {
InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData *>(idata.instance->base_data);
cull_data.cull->lock.lock();
if (!reflection_probe->update_list.in_list()) {
@@ -2682,7 +2710,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
idata.flags &= ~uint32_t(InstanceData::FLAG_REFLECTION_PROBE_DIRTY);
}
- if (scene_render->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
+ if (RSG::light_storage->reflection_probe_instance_has_reflection(RID::from_uint64(idata.instance_data_rid))) {
cull_result.reflections.push_back(RID::from_uint64(idata.instance_data_rid));
}
}
@@ -2742,7 +2770,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
const int32_t &parent_idx = cull_data.scenario->instance_data[idata.parent_array_index].visibility_index;
fade = cull_data.scenario->instance_visibility[parent_idx].children_fade_alpha;
}
- scene_render->geometry_instance_set_parent_fade_alpha(idata.instance_geometry, fade);
+ idata.instance_geometry->set_parent_fade_alpha(fade);
}
if (geometry_instance_pair_mask & (1 << RS::INSTANCE_LIGHT) && (idata.flags & InstanceData::FLAG_GEOM_LIGHTING_DIRTY)) {
@@ -2757,14 +2785,16 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_light_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->pair_light_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_LIGHTING_DIRTY);
}
if (idata.flags & InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(idata.instance->base_data);
- scene_render->geometry_instance_set_softshadow_projector_pairing(geom->geometry_instance, geom->softshadow_count > 0, geom->projector_count > 0);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_softshadow_projector_pairing(geom->softshadow_count > 0, geom->projector_count > 0);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_PROJECTOR_SOFTSHADOW_DIRTY);
}
@@ -2781,7 +2811,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_reflection_probe_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->pair_reflection_probe_instances(instance_pair_buffer, idx);
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_REFLECTION_DIRTY);
}
@@ -2797,7 +2828,10 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
break;
}
}
- scene_render->geometry_instance_pair_decal_instances(geom->geometry_instance, instance_pair_buffer, idx);
+
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->pair_decal_instances(instance_pair_buffer, idx);
+
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_DECAL_DIRTY);
}
@@ -2813,7 +2847,9 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);
+
idata.flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
@@ -2824,7 +2860,8 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
for (uint32_t j = 0; j < 9; j++) {
sh[j] = sh[j].lerp(target_sh[j], MIN(1.0, lightmap_probe_update_speed));
}
- scene_render->geometry_instance_set_lightmap_capture(geom->geometry_instance, sh);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_lightmap_capture(sh);
idata.instance->last_frame_pass = frame_number;
}
@@ -2884,7 +2921,7 @@ void RendererSceneCull::_scene_cull(CullData &cull_data, InstanceCullResult &cul
}
}
-void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RendererScene::RenderInfo *r_render_info) {
+void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows, RenderingMethod::RenderInfo *r_render_info) {
Instance *render_reflection_probe = instance_owner.get_or_null(p_reflection_probe); //if null, not rendering to it
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@@ -2919,7 +2956,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
if (visibility_cull_data.cull_count > thread_cull_threshold) {
- RendererThreadPool::singleton->thread_work_pool.do_work(RendererThreadPool::singleton->thread_work_pool.get_thread_count(), this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_visibility_cull_threaded, &visibility_cull_data, WorkerThreadPool::get_singleton()->get_thread_count(), -1, true, SNAME("VisibilityCullInstances"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
} else {
_visibility_cull(visibility_cull_data, visibility_cull_data.cull_offset, visibility_cull_data.cull_offset + visibility_cull_data.cull_count);
}
@@ -2964,7 +3002,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
}
- scene_render->set_directional_shadow_count(lights_with_shadow.size());
+ RSG::light_storage->set_directional_shadow_count(lights_with_shadow.size());
for (int i = 0; i < lights_with_shadow.size(); i++) {
_light_instance_setup_directional_shadow(i, lights_with_shadow[i], p_camera_data->main_transform, p_camera_data->main_projection, p_camera_data->is_orthogonal, p_camera_data->vaspect);
@@ -3024,7 +3062,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
scene_cull_result_threads[i].clear();
}
- RendererThreadPool::singleton->thread_work_pool.do_work(scene_cull_result_threads.size(), this, &RendererSceneCull::_scene_cull_threaded, &cull_data);
+ WorkerThreadPool::GroupID group_task = WorkerThreadPool::get_singleton()->add_template_group_task(this, &RendererSceneCull::_scene_cull_threaded, &cull_data, scene_cull_result_threads.size(), -1, true, SNAME("RenderCullInstances"));
+ WorkerThreadPool::get_singleton()->wait_for_group_task_completion(group_task);
for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
scene_cull_result.append_from(scene_cull_result_threads[i]);
@@ -3063,7 +3102,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
for (uint32_t j = 0; j < cull.shadows[i].cascade_count; j++) {
const Cull::Shadow::Cascade &c = cull.shadows[i].cascades[j];
// print_line("shadow " + itos(i) + " cascade " + itos(j) + " elements: " + itos(c.cull_result.size()));
- scene_render->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale);
+ RSG::light_storage->light_instance_set_shadow_transform(cull.shadows[i].light_instance, c.projection, c.transform, c.zfar, c.split, j, c.shadow_texel_size, c.bias_scale, c.range_begin, c.uv_scale);
if (max_shadows_used == MAX_UPDATE_SHADOWS) {
continue;
}
@@ -3123,8 +3162,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE);
float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE);
- float w = radius * Math::sin(Math::deg2rad(angle));
- float d = radius * Math::cos(Math::deg2rad(angle));
+ float w = radius * Math::sin(Math::deg_to_rad(angle));
+ float d = radius * Math::cos(Math::deg_to_rad(angle));
Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d;
@@ -3159,7 +3198,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
light->shadow_dirty = false;
}
- bool redraw = scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);
+ bool redraw = RSG::light_storage->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version);
if (redraw && max_shadows_used < MAX_UPDATE_SHADOWS) {
//must redraw!
@@ -3212,11 +3251,11 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
scene_cull_result.light_instances.push_back(directional_lights[i]);
}
- RID camera_effects;
- if (p_force_camera_effects.is_valid()) {
- camera_effects = p_force_camera_effects;
+ RID camera_attributes;
+ if (p_force_camera_attributes.is_valid()) {
+ camera_attributes = p_force_camera_attributes;
} else {
- camera_effects = scenario->camera_effects;
+ camera_attributes = scenario->camera_attributes;
}
/* PROCESS GEOMETRY AND DRAW SCENE */
@@ -3228,7 +3267,7 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
}
RENDER_TIMESTAMP("Render 3D Scene");
- scene_render->render_scene(p_render_buffers, p_camera_data, prev_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_effects, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
+ scene_render->render_scene(p_render_buffers, p_camera_data, prev_camera_data, scene_cull_result.geometry_instances, scene_cull_result.light_instances, scene_cull_result.reflections, scene_cull_result.voxel_gi_instances, scene_cull_result.decals, scene_cull_result.lightmaps, scene_cull_result.fog_volumes, p_environment, camera_attributes, p_shadow_atlas, occluders_tex, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass, p_screen_mesh_lod_threshold, render_shadow_data, max_shadows_used, render_sdfgi_data, cull.sdfgi.region_count, &sdfgi_update_data, r_render_info);
if (p_viewport.is_valid()) {
RSG::viewport->viewport_set_prev_camera_data(p_viewport, p_camera_data);
@@ -3242,8 +3281,6 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c
for (uint32_t i = 0; i < cull.sdfgi.region_count; i++) {
render_sdfgi_data[i].instances.clear();
}
-
- // virtual void render_scene(RID p_render_buffers, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold,const RenderShadowData *p_render_shadows,int p_render_shadow_count,const RenderSDFGIData *p_render_sdfgi_regions,int p_render_sdfgi_region_count,const RenderSDFGIStaticLightData *p_render_sdfgi_static_lights=nullptr) = 0;
}
RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
@@ -3267,7 +3304,7 @@ RID RendererSceneCull::_render_get_environment(RID p_camera, RID p_scenario) {
return RID();
}
-void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
+void RendererSceneCull::render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) {
#ifndef _3D_DISABLED
Scenario *scenario = scenario_owner.get_or_null(p_scenario);
@@ -3280,9 +3317,9 @@ void RendererSceneCull::render_empty_scene(RID p_render_buffers, RID p_scenario,
RENDER_TIMESTAMP("Render Empty 3D Scene");
RendererSceneRender::CameraData camera_data;
- camera_data.set_camera(Transform3D(), CameraMatrix(), true, false);
+ camera_data.set_camera(Transform3D(), Projection(), true, false);
- scene_render->render_scene(p_render_buffers, &camera_data, nullptr, PagedArray<RendererSceneRender::GeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
+ scene_render->render_scene(p_render_buffers, &camera_data, &camera_data, PagedArray<RenderGeometryInstance *>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), PagedArray<RID>(), RID(), RID(), p_shadow_atlas, RID(), scenario->reflection_atlas, RID(), 0, 0, nullptr, 0, nullptr, 0, nullptr);
#endif
}
@@ -3294,7 +3331,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RenderingServerDefault::redraw_request(); //update, so it updates in editor
if (p_step == 0) {
- if (!scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
+ if (!RSG::light_storage->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) {
return true; //all full
}
}
@@ -3320,7 +3357,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
Vector3 extents = RSG::light_storage->reflection_probe_get_extents(p_instance->base);
Vector3 origin_offset = RSG::light_storage->reflection_probe_get_origin_offset(p_instance->base);
float max_distance = RSG::light_storage->reflection_probe_get_origin_max_distance(p_instance->base);
- float size = scene_render->reflection_atlas_get_size(scenario->reflection_atlas);
+ float size = RSG::light_storage->reflection_atlas_get_size(scenario->reflection_atlas);
float mesh_lod_threshold = RSG::light_storage->reflection_probe_get_mesh_lod_threshold(p_instance->base) / size;
Vector3 edge = view_normals[p_step] * extents;
@@ -3329,7 +3366,7 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
max_distance = MAX(max_distance, distance);
//render cubemap side
- CameraMatrix cm;
+ Projection cm;
cm.set_perspective(90, 1, 0.01, max_distance);
Transform3D local_view;
@@ -3355,12 +3392,13 @@ bool RendererSceneCull::_render_reflection_probe_step(Instance *p_instance, int
RendererSceneRender::CameraData camera_data;
camera_data.set_camera(xform, cm, false, false);
- _render_scene(&camera_data, RID(), environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
+ Ref<RenderSceneBuffers> render_buffers;
+ _render_scene(&camera_data, render_buffers, environment, RID(), RSG::light_storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, RID(), shadow_atlas, reflection_probe->instance, p_step, mesh_lod_threshold, use_shadows);
} else {
//do roughness postprocess step until it believes it's done
RENDER_TIMESTAMP("Post-Process ReflectionProbe, Step " + itos(p_step));
- return scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance);
+ return RSG::light_storage->reflection_probe_instance_postprocess_step(reflection_probe->instance);
}
return false;
@@ -3451,6 +3489,7 @@ void RendererSceneCull::render_probes() {
cache->transform != instance->transform ||
cache->color != RSG::light_storage->light_get_color(instance->base) ||
cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+ cache->intensity != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY) ||
cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
@@ -3482,6 +3521,7 @@ void RendererSceneCull::render_probes() {
cache->transform != instance->transform ||
cache->color != RSG::light_storage->light_get_color(instance->base) ||
cache->energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) ||
+ cache->intensity != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY) ||
cache->bake_energy != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) ||
cache->radius != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) ||
cache->attenuation != RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) ||
@@ -3528,6 +3568,7 @@ void RendererSceneCull::render_probes() {
cache->transform = instance->transform;
cache->color = RSG::light_storage->light_get_color(instance->base);
cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+ cache->intensity = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY);
cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
@@ -3550,6 +3591,7 @@ void RendererSceneCull::render_probes() {
cache->transform = instance->transform;
cache->color = RSG::light_storage->light_get_color(instance->base);
cache->energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY);
+ cache->intensity = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INTENSITY);
cache->bake_energy = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY);
cache->radius = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE);
cache->attenuation = RSG::light_storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION);
@@ -3586,11 +3628,13 @@ void RendererSceneCull::render_probes() {
}
}
- scene_render->geometry_instance_pair_voxel_gi_instances(geom->geometry_instance, instance_pair_buffer, idx);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->pair_voxel_gi_instances(instance_pair_buffer, idx);
ins->scenario->instance_data[ins->array_index].flags &= ~uint32_t(InstanceData::FLAG_GEOM_VOXEL_GI_DIRTY);
}
+ ERR_FAIL_NULL(geom->geometry_instance);
scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
@@ -3631,6 +3675,7 @@ void RendererSceneCull::render_particle_colliders() {
continue;
}
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(instance->base_data);
+ ERR_FAIL_NULL(geom->geometry_instance);
scene_cull_result.geometry_instances.push_back(geom->geometry_instance);
}
@@ -3640,7 +3685,7 @@ void RendererSceneCull::render_particle_colliders() {
}
}
-void RendererSceneCull::_update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
+void RendererSceneCull::_update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material) {
List<RendererMaterialStorage::InstanceShaderParam> plist;
RSG::material_storage->material_get_instance_shader_parameters(p_material, &plist);
for (const RendererMaterialStorage::InstanceShaderParam &E : plist) {
@@ -3677,7 +3722,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
p_instance->dependency_tracker.update_begin();
if (p_instance->base.is_valid()) {
- RSG::storage->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);
+ RSG::utilities->base_update_dependency(p_instance->base, &p_instance->dependency_tracker);
}
if (p_instance->material_override.is_valid()) {
@@ -3722,7 +3767,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
can_cast_shadows = false;
}
is_animated = RSG::material_storage->material_is_animated(p_instance->material_override);
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_override);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_override);
} else {
if (p_instance->base_type == RS::INSTANCE_MESH) {
RID mesh = p_instance->base;
@@ -3744,7 +3789,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3775,7 +3820,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3785,7 +3830,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
can_cast_shadows = false;
}
- RSG::storage->base_update_dependency(mesh, &p_instance->dependency_tracker);
+ RSG::utilities->base_update_dependency(mesh, &p_instance->dependency_tracker);
}
} else if (p_instance->base_type == RS::INSTANCE_PARTICLES) {
bool cast_shadows = false;
@@ -3813,7 +3858,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
is_animated = true;
}
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, mat);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, mat);
RSG::material_storage->material_update_dependency(mat, &p_instance->dependency_tracker);
}
@@ -3827,9 +3872,9 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
if (p_instance->material_overlay.is_valid()) {
- can_cast_shadows = can_cast_shadows || RSG::material_storage->material_casts_shadows(p_instance->material_overlay);
+ can_cast_shadows = can_cast_shadows && RSG::material_storage->material_casts_shadows(p_instance->material_overlay);
is_animated = is_animated || RSG::material_storage->material_is_animated(p_instance->material_overlay);
- _update_instance_shader_parameters_from_material(isparams, p_instance->instance_shader_parameters, p_instance->material_overlay);
+ _update_instance_shader_uniforms_from_material(isparams, p_instance->instance_shader_uniforms, p_instance->material_overlay);
}
if (can_cast_shadows != geom->can_cast_shadows) {
@@ -3843,23 +3888,40 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
geom->material_is_animated = is_animated;
- p_instance->instance_shader_parameters = isparams;
+ p_instance->instance_shader_uniforms = isparams;
- if (p_instance->instance_allocated_shader_parameters != (p_instance->instance_shader_parameters.size() > 0)) {
- p_instance->instance_allocated_shader_parameters = (p_instance->instance_shader_parameters.size() > 0);
- if (p_instance->instance_allocated_shader_parameters) {
- p_instance->instance_allocated_shader_parameters_offset = RSG::material_storage->global_variables_instance_allocate(p_instance->self);
- scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, p_instance->instance_allocated_shader_parameters_offset);
+ if (p_instance->instance_allocated_shader_uniforms != (p_instance->instance_shader_uniforms.size() > 0)) {
+ p_instance->instance_allocated_shader_uniforms = (p_instance->instance_shader_uniforms.size() > 0);
+ if (p_instance->instance_allocated_shader_uniforms) {
+ p_instance->instance_allocated_shader_uniforms_offset = RSG::material_storage->global_shader_parameters_instance_allocate(p_instance->self);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_instance_shader_uniforms_offset(p_instance->instance_allocated_shader_uniforms_offset);
- for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_parameters) {
+ for (const KeyValue<StringName, Instance::InstanceShaderParameter> &E : p_instance->instance_shader_uniforms) {
if (E.value.value.get_type() != Variant::NIL) {
- RSG::material_storage->global_variables_instance_update(p_instance->self, E.value.index, E.value.value);
+ int flags_count = 0;
+ if (E.value.info.hint == PROPERTY_HINT_FLAGS) {
+ // A small hack to detect boolean flags count and prevent overhead.
+ switch (E.value.info.hint_string.length()) {
+ case 3: // "x,y"
+ flags_count = 1;
+ break;
+ case 5: // "x,y,z"
+ flags_count = 2;
+ break;
+ case 7: // "x,y,z,w"
+ flags_count = 3;
+ break;
+ }
+ }
+ RSG::material_storage->global_shader_parameters_instance_update(p_instance->self, E.value.index, E.value.value, flags_count);
}
}
} else {
- RSG::material_storage->global_variables_instance_free(p_instance->self);
- p_instance->instance_allocated_shader_parameters_offset = -1;
- scene_render->geometry_instance_set_instance_shader_parameters_offset(geom->geometry_instance, -1);
+ RSG::material_storage->global_shader_parameters_instance_free(p_instance->self);
+ p_instance->instance_allocated_shader_uniforms_offset = -1;
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_instance_shader_uniforms_offset(-1);
}
}
}
@@ -3872,7 +3934,8 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) {
InstanceGeometryData *geom = static_cast<InstanceGeometryData *>(p_instance->base_data);
- scene_render->geometry_instance_set_surface_materials(geom->geometry_instance, p_instance->materials);
+ ERR_FAIL_NULL(geom->geometry_instance);
+ geom->geometry_instance->set_surface_materials(p_instance->materials);
}
}
@@ -3885,7 +3948,7 @@ void RendererSceneCull::_update_dirty_instance(Instance *p_instance) {
}
void RendererSceneCull::update_dirty_instances() {
- RSG::storage->update_dirty_resources();
+ RSG::utilities->update_dirty_resources();
while (_instance_update_list.first()) {
_update_dirty_instance(_instance_update_list.first()->self());
@@ -3930,8 +3993,8 @@ bool RendererSceneCull::free(RID p_rid) {
scenario->instance_data.reset();
scenario->instance_visibility.reset();
- scene_render->free(scenario->reflection_probe_shadow_atlas);
- scene_render->free(scenario->reflection_atlas);
+ RSG::light_storage->shadow_atlas_free(scenario->reflection_probe_shadow_atlas);
+ RSG::light_storage->reflection_atlas_free(scenario->reflection_atlas);
scenario_owner.free(p_rid);
RendererSceneOcclusionCull::get_singleton()->remove_scenario(p_rid);
@@ -3951,9 +4014,9 @@ bool RendererSceneCull::free(RID p_rid) {
instance_geometry_set_material_overlay(p_rid, RID());
instance_attach_skeleton(p_rid, RID());
- if (instance->instance_allocated_shader_parameters) {
+ if (instance->instance_allocated_shader_uniforms) {
//free the used shader parameters
- RSG::material_storage->global_variables_instance_free(instance->self);
+ RSG::material_storage->global_shader_parameters_instance_free(instance->self);
}
update_dirty_instances(); //in case something changed this
@@ -3965,7 +4028,7 @@ bool RendererSceneCull::free(RID p_rid) {
return true;
}
-TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) {
+TypedArray<Image> RendererSceneCull::bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) {
return scene_render->bake_render_uv2(p_base, p_material_overrides, p_image_size);
}
@@ -3978,12 +4041,12 @@ void RendererSceneCull::update_visibility_notifiers() {
if (visibility_notifier->just_visible) {
visibility_notifier->just_visible = false;
- RSG::storage->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);
+ RSG::utilities->visibility_notifier_call(visibility_notifier->base, true, RSG::threaded);
} else {
if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) {
visible_notifier_list.remove(E);
- RSG::storage->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);
+ RSG::utilities->visibility_notifier_call(visibility_notifier->base, false, RSG::threaded);
}
}
@@ -4030,14 +4093,14 @@ RendererSceneCull::RendererSceneCull() {
}
scene_cull_result.init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
- scene_cull_result_threads.resize(RendererThreadPool::singleton->thread_work_pool.get_thread_count());
+ scene_cull_result_threads.resize(WorkerThreadPool::get_singleton()->get_thread_count());
for (uint32_t i = 0; i < scene_cull_result_threads.size(); i++) {
scene_cull_result_threads[i].init(&rid_cull_page_pool, &geometry_instance_cull_page_pool, &instance_cull_page_pool);
}
indexer_update_iterations = GLOBAL_GET("rendering/limits/spatial_indexer/update_iterations_per_frame");
thread_cull_threshold = GLOBAL_GET("rendering/limits/spatial_indexer/threaded_cull_minimum_instances");
- thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)RendererThreadPool::singleton->thread_work_pool.get_thread_count()); //make sure there is at least one thread per CPU
+ thread_cull_threshold = MAX(thread_cull_threshold, (uint32_t)WorkerThreadPool::get_singleton()->get_thread_count()); //make sure there is at least one thread per CPU
taa_jitter_array.resize(TAA_JITTER_COUNT);
for (int i = 0; i < TAA_JITTER_COUNT; i++) {
diff --git a/servers/rendering/renderer_scene_cull.h b/servers/rendering/renderer_scene_cull.h
index d1d3484871..d085b84a8c 100644
--- a/servers/rendering/renderer_scene_cull.h
+++ b/servers/rendering/renderer_scene_cull.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERING_SERVER_SCENE_CULL_H
-#define RENDERING_SERVER_SCENE_CULL_H
+#ifndef RENDERER_SCENE_CULL_H
+#define RENDERER_SCENE_CULL_H
#include "core/math/dynamic_bvh.h"
#include "core/templates/bin_sorted_array.h"
@@ -39,13 +39,13 @@
#include "core/templates/pass_func.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
-#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_occlusion_cull.h"
#include "servers/rendering/renderer_scene_render.h"
-#include "servers/rendering/renderer_storage.h"
+#include "servers/rendering/rendering_method.h"
+#include "servers/rendering/storage/utilities.h"
#include "servers/xr/xr_interface.h"
-class RendererSceneCull : public RendererScene {
+class RendererSceneCull : public RenderingMethod {
public:
RendererSceneRender *scene_render = nullptr;
@@ -76,7 +76,7 @@ public:
uint32_t visible_layers;
bool vaspect;
RID env;
- RID effects;
+ RID attributes;
Transform3D transform;
@@ -103,7 +103,7 @@ public:
virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform);
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers);
virtual void camera_set_environment(RID p_camera, RID p_env);
- virtual void camera_set_camera_effects(RID p_camera, RID p_fx);
+ virtual void camera_set_camera_attributes(RID p_camera, RID p_attributes);
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable);
virtual bool is_camera(RID p_camera) const;
@@ -272,7 +272,7 @@ public:
RID base_rid;
union {
uint64_t instance_data_rid;
- RendererSceneRender::GeometryInstance *instance_geometry;
+ RenderGeometryInstance *instance_geometry;
InstanceVisibilityNotifierData *visibility_notifier = nullptr;
};
Instance *instance = nullptr;
@@ -320,7 +320,7 @@ public:
List<Instance *> directional_lights;
RID environment;
RID fallback_environment;
- RID camera_effects;
+ RID camera_attributes;
RID reflection_probe_shadow_atlas;
RID reflection_atlas;
uint64_t used_viewport_visibility_bits;
@@ -354,7 +354,7 @@ public:
virtual void scenario_initialize(RID p_rid);
virtual void scenario_set_environment(RID p_scenario, RID p_environment);
- virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx);
+ virtual void scenario_set_camera_attributes(RID p_scenario, RID p_attributes);
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count);
virtual bool is_scenario(RID p_scenario) const;
@@ -426,9 +426,9 @@ public:
PropertyInfo info;
};
- HashMap<StringName, InstanceShaderParameter> instance_shader_parameters;
- bool instance_allocated_shader_parameters = false;
- int32_t instance_allocated_shader_parameters_offset = -1;
+ HashMap<StringName, InstanceShaderParameter> instance_shader_uniforms;
+ bool instance_allocated_shader_uniforms = false;
+ int32_t instance_allocated_shader_uniforms_offset = -1;
//
@@ -470,32 +470,32 @@ public:
SelfList<InstancePair>::List pairs;
uint64_t pair_check;
- RendererStorage::DependencyTracker dependency_tracker;
+ DependencyTracker dependency_tracker;
- static void dependency_changed(RendererStorage::DependencyChangedNotification p_notification, RendererStorage::DependencyTracker *tracker) {
+ static void dependency_changed(Dependency::DependencyChangedNotification p_notification, DependencyTracker *tracker) {
Instance *instance = (Instance *)tracker->userdata;
switch (p_notification) {
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_DATA:
- case RendererStorage::DEPENDENCY_CHANGED_AABB: {
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_DATA:
+ case Dependency::DEPENDENCY_CHANGED_AABB: {
singleton->_instance_queue_update(instance, true, false);
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MATERIAL: {
+ case Dependency::DEPENDENCY_CHANGED_MATERIAL: {
singleton->_instance_queue_update(instance, false, true);
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MESH:
- case RendererStorage::DEPENDENCY_CHANGED_PARTICLES:
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH:
- case RendererStorage::DEPENDENCY_CHANGED_DECAL:
- case RendererStorage::DEPENDENCY_CHANGED_LIGHT:
- case RendererStorage::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
+ case Dependency::DEPENDENCY_CHANGED_MESH:
+ case Dependency::DEPENDENCY_CHANGED_PARTICLES:
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH:
+ case Dependency::DEPENDENCY_CHANGED_DECAL:
+ case Dependency::DEPENDENCY_CHANGED_LIGHT:
+ case Dependency::DEPENDENCY_CHANGED_REFLECTION_PROBE: {
singleton->_instance_queue_update(instance, true, true);
} break;
- case RendererStorage::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES:
- case RendererStorage::DEPENDENCY_CHANGED_SKELETON_BONES: {
+ case Dependency::DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES:
+ case Dependency::DEPENDENCY_CHANGED_SKELETON_BONES: {
//ignored
} break;
- case RendererStorage::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
+ case Dependency::DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR: {
//requires repairing
if (instance->indexer_id.is_valid()) {
singleton->_unpair_instance(instance);
@@ -506,7 +506,7 @@ public:
}
}
- static void dependency_deleted(const RID &p_dependency, RendererStorage::DependencyTracker *tracker) {
+ static void dependency_deleted(const RID &p_dependency, DependencyTracker *tracker) {
Instance *instance = (Instance *)tracker->userdata;
if (p_dependency == instance->base) {
@@ -526,7 +526,7 @@ public:
receive_shadows = true;
visible = true;
layer_mask = 1;
- baked_light = false;
+ baked_light = true;
dynamic_gi = false;
redraw_if_visible = false;
lightmap_slice_index = 0;
@@ -578,7 +578,7 @@ public:
void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false);
struct InstanceGeometryData : public InstanceBaseData {
- RendererSceneRender::GeometryInstance *geometry_instance = nullptr;
+ RenderGeometryInstance *geometry_instance = nullptr;
HashSet<Instance *> lights;
bool can_cast_shadows;
bool material_is_animated;
@@ -683,6 +683,7 @@ public:
Transform3D transform;
Color color;
float energy;
+ float intensity;
float bake_energy;
float radius;
float attenuation;
@@ -782,14 +783,14 @@ public:
HashSet<Instance *> heightfield_particle_colliders_update_list;
PagedArrayPool<Instance *> instance_cull_page_pool;
- PagedArrayPool<RendererSceneRender::GeometryInstance *> geometry_instance_cull_page_pool;
+ PagedArrayPool<RenderGeometryInstance *> geometry_instance_cull_page_pool;
PagedArrayPool<RID> rid_cull_page_pool;
PagedArray<Instance *> instance_cull_result;
PagedArray<Instance *> instance_shadow_cull_result;
struct InstanceCullResult {
- PagedArray<RendererSceneRender::GeometryInstance *> geometry_instances;
+ PagedArray<RenderGeometryInstance *> geometry_instances;
PagedArray<Instance *> lights;
PagedArray<RID> light_instances;
PagedArray<RID> lightmaps;
@@ -800,10 +801,10 @@ public:
PagedArray<RID> fog_volumes;
struct DirectionalShadow {
- PagedArray<RendererSceneRender::GeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
+ PagedArray<RenderGeometryInstance *> cascade_geometry_instances[RendererSceneRender::MAX_DIRECTIONAL_LIGHT_CASCADES];
} directional_shadows[RendererSceneRender::MAX_DIRECTIONAL_LIGHTS];
- PagedArray<RendererSceneRender::GeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
+ PagedArray<RenderGeometryInstance *> sdfgi_region_geometry_instances[SDFGI_MAX_CASCADES * SDFGI_MAX_REGIONS_PER_CASCADE];
PagedArray<RID> sdfgi_cascade_lights[SDFGI_MAX_CASCADES];
void clear() {
@@ -882,7 +883,7 @@ public:
}
}
- void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RendererSceneRender::GeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) {
+ void init(PagedArrayPool<RID> *p_rid_pool, PagedArrayPool<RenderGeometryInstance *> *p_geometry_instance_pool, PagedArrayPool<Instance *> *p_instance_pool) {
geometry_instances.set_page_pool(p_geometry_instance_pool);
light_instances.set_page_pool(p_rid_pool);
lights.set_page_pool(p_instance_pool);
@@ -967,7 +968,7 @@ public:
virtual void instance_geometry_set_lightmap(RID p_instance, RID p_lightmap, const Rect2 &p_lightmap_uv_scale, int p_slice_index);
virtual void instance_geometry_set_lod_bias(RID p_instance, float p_lod_bias);
- void _update_instance_shader_parameters_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material);
+ void _update_instance_shader_uniforms_from_material(HashMap<StringName, Instance::InstanceShaderParameter> &isparams, const HashMap<StringName, Instance::InstanceShaderParameter> &existing_isparams, RID p_material);
virtual void instance_geometry_set_shader_parameter(RID p_instance, const StringName &p_parameter, const Variant &p_value);
virtual void instance_geometry_get_shader_parameter_list(RID p_instance, List<PropertyInfo> *p_parameters) const;
@@ -980,9 +981,9 @@ public:
_FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance);
void _unpair_instance(Instance *p_instance);
- void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
+ void _light_instance_setup_directional_shadow(int p_shadow_index, Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect);
- _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold);
+ _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform3D p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, bool p_cam_vaspect, RID p_shadow_atlas, Scenario *p_scenario, float p_scren_mesh_lod_threshold);
RID _render_get_environment(RID p_camera, RID p_scenario);
@@ -992,7 +993,7 @@ public:
struct Cascade {
Frustum frustum;
- CameraMatrix projection;
+ Projection projection;
Transform3D transform;
real_t zfar;
real_t split;
@@ -1045,7 +1046,7 @@ public:
uint32_t visible_layers;
Instance *render_reflection_probe = nullptr;
const RendererSceneOcclusionCull::HZBuffer *occlusion_buffer;
- const CameraMatrix *camera_matrix;
+ const Projection *camera_matrix;
uint64_t visibility_viewport_mask;
};
@@ -1054,16 +1055,16 @@ public:
_FORCE_INLINE_ bool _visibility_parent_check(const CullData &p_cull_data, const InstanceData &p_instance_data);
bool _render_reflection_probe_step(Instance *p_instance, int p_step);
- void _render_scene(const RendererSceneRender::CameraData *p_camera_data, RID p_render_buffers, RID p_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
- void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas);
+ void _render_scene(const RendererSceneRender::CameraData *p_camera_data, const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, RID p_force_camera_attributes, uint32_t p_visible_layers, RID p_scenario, RID p_viewport, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, bool p_using_shadows = true, RenderInfo *r_render_info = nullptr);
+ void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas);
- void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RendererScene::RenderInfo *r_render_info = nullptr);
+ void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_screen_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderingMethod::RenderInfo *r_render_info = nullptr);
void update_dirty_instances();
void render_particle_colliders();
virtual void render_probes();
- TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size);
+ TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size);
//pass to scene render
@@ -1075,7 +1076,6 @@ public:
#define PASSBASE scene_render
- PASS2(directional_shadow_atlas_set_size, int, bool)
PASS1(voxel_gi_set_quality, RS::VoxelGIQuality)
/* SKY API */
@@ -1093,45 +1093,153 @@ public:
PASS1RC(bool, is_environment, RID)
+ // Background
PASS2(environment_set_background, RID, RS::EnvironmentBG)
PASS2(environment_set_sky, RID, RID)
PASS2(environment_set_sky_custom_fov, RID, float)
PASS2(environment_set_sky_orientation, RID, const Basis &)
PASS2(environment_set_bg_color, RID, const Color &)
- PASS2(environment_set_bg_energy, RID, float)
+ PASS3(environment_set_bg_energy, RID, float, float)
PASS2(environment_set_canvas_max_layer, RID, int)
PASS6(environment_set_ambient_light, RID, const Color &, RS::EnvironmentAmbientSource, float, float, RS::EnvironmentReflectionSource)
+ PASS1RC(RS::EnvironmentBG, environment_get_background, RID)
+ PASS1RC(RID, environment_get_sky, RID)
+ PASS1RC(float, environment_get_sky_custom_fov, RID)
+ PASS1RC(Basis, environment_get_sky_orientation, RID)
+ PASS1RC(Color, environment_get_bg_color, RID)
+ PASS1RC(float, environment_get_bg_energy_multiplier, RID)
+ PASS1RC(float, environment_get_bg_intensity, RID)
+ PASS1RC(int, environment_get_canvas_max_layer, RID)
+ PASS1RC(RS::EnvironmentAmbientSource, environment_get_ambient_source, RID)
+ PASS1RC(Color, environment_get_ambient_light, RID)
+ PASS1RC(float, environment_get_ambient_light_energy, RID)
+ PASS1RC(float, environment_get_ambient_sky_contribution, RID)
+ PASS1RC(RS::EnvironmentReflectionSource, environment_get_reflection_source, RID)
+
+ // Tonemap
+ PASS4(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float)
+ PASS1RC(RS::EnvironmentToneMapper, environment_get_tone_mapper, RID)
+ PASS1RC(float, environment_get_exposure, RID)
+ PASS1RC(float, environment_get_white, RID)
+
+ // Fog
+ PASS10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float)
+
+ PASS1RC(bool, environment_get_fog_enabled, RID)
+ PASS1RC(Color, environment_get_fog_light_color, RID)
+ PASS1RC(float, environment_get_fog_light_energy, RID)
+ PASS1RC(float, environment_get_fog_sun_scatter, RID)
+ PASS1RC(float, environment_get_fog_density, RID)
+ PASS1RC(float, environment_get_fog_sky_affect, RID)
+ PASS1RC(float, environment_get_fog_height, RID)
+ PASS1RC(float, environment_get_fog_height_density, RID)
+ PASS1RC(float, environment_get_fog_aerial_perspective, RID)
+
+ PASS2(environment_set_volumetric_fog_volume_size, int, int)
+ PASS1(environment_set_volumetric_fog_filter_active, bool)
+
+ // Volumentric Fog
+ PASS14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float)
+
+ PASS1RC(bool, environment_get_volumetric_fog_enabled, RID)
+ PASS1RC(float, environment_get_volumetric_fog_density, RID)
+ PASS1RC(Color, environment_get_volumetric_fog_scattering, RID)
+ PASS1RC(Color, environment_get_volumetric_fog_emission, RID)
+ PASS1RC(float, environment_get_volumetric_fog_emission_energy, RID)
+ PASS1RC(float, environment_get_volumetric_fog_anisotropy, RID)
+ PASS1RC(float, environment_get_volumetric_fog_length, RID)
+ PASS1RC(float, environment_get_volumetric_fog_detail_spread, RID)
+ PASS1RC(float, environment_get_volumetric_fog_gi_inject, RID)
+ PASS1RC(float, environment_get_volumetric_fog_sky_affect, RID)
+ PASS1RC(bool, environment_get_volumetric_fog_temporal_reprojection, RID)
+ PASS1RC(float, environment_get_volumetric_fog_temporal_reprojection_amount, RID)
+ PASS1RC(float, environment_get_volumetric_fog_ambient_inject, RID)
+
+ // Glow
+ PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID)
+
+ PASS1RC(bool, environment_get_glow_enabled, RID)
+ PASS1RC(Vector<float>, environment_get_glow_levels, RID)
+ PASS1RC(float, environment_get_glow_intensity, RID)
+ PASS1RC(float, environment_get_glow_strength, RID)
+ PASS1RC(float, environment_get_glow_bloom, RID)
+ PASS1RC(float, environment_get_glow_mix, RID)
+ PASS1RC(RS::EnvironmentGlowBlendMode, environment_get_glow_blend_mode, RID)
+ PASS1RC(float, environment_get_glow_hdr_bleed_threshold, RID)
+ PASS1RC(float, environment_get_glow_hdr_luminance_cap, RID)
+ PASS1RC(float, environment_get_glow_hdr_bleed_scale, RID)
+ PASS1RC(float, environment_get_glow_map_strength, RID)
+ PASS1RC(RID, environment_get_glow_map, RID)
+
+ PASS1(environment_glow_set_use_bicubic_upscale, bool)
+ PASS1(environment_glow_set_use_high_quality, bool)
+
+ // SSR
PASS6(environment_set_ssr, RID, bool, int, float, float, float)
+
+ PASS1RC(bool, environment_get_ssr_enabled, RID)
+ PASS1RC(int, environment_get_ssr_max_steps, RID)
+ PASS1RC(float, environment_get_ssr_fade_in, RID)
+ PASS1RC(float, environment_get_ssr_fade_out, RID)
+ PASS1RC(float, environment_get_ssr_depth_tolerance, RID)
+
PASS1(environment_set_ssr_roughness_quality, RS::EnvironmentSSRRoughnessQuality)
+ // SSAO
PASS10(environment_set_ssao, RID, bool, float, float, float, float, float, float, float, float)
+
+ PASS1RC(bool, environment_get_ssao_enabled, RID)
+ PASS1RC(float, environment_get_ssao_radius, RID)
+ PASS1RC(float, environment_get_ssao_intensity, RID)
+ PASS1RC(float, environment_get_ssao_power, RID)
+ PASS1RC(float, environment_get_ssao_detail, RID)
+ PASS1RC(float, environment_get_ssao_horizon, RID)
+ PASS1RC(float, environment_get_ssao_sharpness, RID)
+ PASS1RC(float, environment_get_ssao_direct_light_affect, RID)
+ PASS1RC(float, environment_get_ssao_ao_channel_affect, RID)
+
PASS6(environment_set_ssao_quality, RS::EnvironmentSSAOQuality, bool, float, int, float, float)
+ // SSIL
PASS6(environment_set_ssil, RID, bool, float, float, float, float)
- PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float)
- PASS13(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, RS::EnvironmentGlowBlendMode, float, float, float, float, RID)
- PASS1(environment_glow_set_use_bicubic_upscale, bool)
- PASS1(environment_glow_set_use_high_quality, bool)
+ PASS1RC(bool, environment_get_ssil_enabled, RID)
+ PASS1RC(float, environment_get_ssil_radius, RID)
+ PASS1RC(float, environment_get_ssil_intensity, RID)
+ PASS1RC(float, environment_get_ssil_sharpness, RID)
+ PASS1RC(float, environment_get_ssil_normal_rejection, RID)
- PASS9(environment_set_tonemap, RID, RS::EnvironmentToneMapper, float, float, bool, float, float, float, float)
+ PASS6(environment_set_ssil_quality, RS::EnvironmentSSILQuality, bool, float, int, float, float)
- PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
+ // SDFGI
- PASS9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- PASS13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
+ PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
- PASS2(environment_set_volumetric_fog_volume_size, int, int)
- PASS1(environment_set_volumetric_fog_filter_active, bool)
+ PASS1RC(bool, environment_get_sdfgi_enabled, RID)
+ PASS1RC(int, environment_get_sdfgi_cascades, RID)
+ PASS1RC(float, environment_get_sdfgi_min_cell_size, RID)
+ PASS1RC(bool, environment_get_sdfgi_use_occlusion, RID)
+ PASS1RC(float, environment_get_sdfgi_bounce_feedback, RID)
+ PASS1RC(bool, environment_get_sdfgi_read_sky_light, RID)
+ PASS1RC(float, environment_get_sdfgi_energy, RID)
+ PASS1RC(float, environment_get_sdfgi_normal_bias, RID)
+ PASS1RC(float, environment_get_sdfgi_probe_bias, RID)
+ PASS1RC(RS::EnvironmentSDFGIYScale, environment_get_sdfgi_y_scale, RID)
- PASS11(environment_set_sdfgi, RID, bool, int, float, RS::EnvironmentSDFGIYScale, bool, float, bool, float, float, float)
PASS1(environment_set_sdfgi_ray_count, RS::EnvironmentSDFGIRayCount)
PASS1(environment_set_sdfgi_frames_to_converge, RS::EnvironmentSDFGIFramesToConverge)
PASS1(environment_set_sdfgi_frames_to_update_light, RS::EnvironmentSDFGIFramesToUpdateLight)
- PASS1RC(RS::EnvironmentBG, environment_get_background, RID)
- PASS1RC(int, environment_get_canvas_max_layer, RID)
+ // Adjustment
+ PASS7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
+
+ PASS1RC(bool, environment_get_adjustments_enabled, RID)
+ PASS1RC(float, environment_get_adjustments_brightness, RID)
+ PASS1RC(float, environment_get_adjustments_contrast, RID)
+ PASS1RC(float, environment_get_adjustments_saturation, RID)
+ PASS1RC(bool, environment_get_use_1d_color_correction, RID)
+ PASS1RC(RID, environment_get_color_correction, RID)
PASS3R(Ref<Image>, environment_bake_panorama, RID, bool, const Size2i &)
@@ -1139,33 +1247,17 @@ public:
PASS1(sub_surface_scattering_set_quality, RS::SubSurfaceScatteringQuality)
PASS2(sub_surface_scattering_set_scale, float, float)
- /* CAMERA EFFECTS */
-
- PASS0R(RID, camera_effects_allocate)
- PASS1(camera_effects_initialize, RID)
-
- PASS2(camera_effects_set_dof_blur_quality, RS::DOFBlurQuality, bool)
- PASS1(camera_effects_set_dof_blur_bokeh_shape, RS::DOFBokehShape)
-
- PASS8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
- PASS3(camera_effects_set_custom_exposure, RID, bool, float)
-
- PASS1(shadows_quality_set, RS::ShadowQuality)
- PASS1(directional_shadow_quality_set, RS::ShadowQuality)
+ PASS1(positional_soft_shadow_filter_set_quality, RS::ShadowQuality)
+ PASS1(directional_soft_shadow_filter_set_quality, RS::ShadowQuality)
PASS2(sdfgi_set_debug_probe_select, const Vector3 &, const Vector3 &)
/* Render Buffers */
- PASS0R(RID, render_buffers_create)
- PASS13(render_buffers_configure, RID, RID, int, int, int, int, float, float, RS::ViewportMSAA, RS::ViewportScreenSpaceAA, bool, bool, uint32_t)
+ PASS0R(Ref<RenderSceneBuffers>, render_buffers_create)
PASS1(gi_set_use_half_resolution, bool)
- /* Shadow Atlas */
- PASS0R(RID, shadow_atlas_create)
- PASS3(shadow_atlas_set_size, RID, int, bool)
- PASS3(shadow_atlas_set_quadrant_subdivision, RID, int, int)
-
+ /* Misc */
PASS1(set_debug_draw_mode, RS::ViewportDebugDraw)
PASS1(decals_set_filter, RS::DecalFilter)
@@ -1183,4 +1275,4 @@ public:
virtual ~RendererSceneCull();
};
-#endif // RENDERING_SERVER_SCENE_CULL_H
+#endif // RENDERER_SCENE_CULL_H
diff --git a/servers/rendering/renderer_scene_occlusion_cull.cpp b/servers/rendering/renderer_scene_occlusion_cull.cpp
index bda0950097..e1ca5a7103 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.cpp
+++ b/servers/rendering/renderer_scene_occlusion_cull.cpp
@@ -180,7 +180,7 @@ RID RendererSceneOcclusionCull::HZBuffer::get_debug_texture() {
ptrw[i] = MIN(mips[0][i] / debug_tex_range, 1.0) * 255;
}
- debug_image->create(sizes[0].x, sizes[0].y, false, Image::FORMAT_L8, debug_data);
+ debug_image->set_data(sizes[0].x, sizes[0].y, false, Image::FORMAT_L8, debug_data);
if (debug_texture.is_null()) {
debug_texture = RS::get_singleton()->texture_2d_create(debug_image);
diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h
index 7198379ade..0d466e8a32 100644
--- a/servers/rendering/renderer_scene_occlusion_cull.h
+++ b/servers/rendering/renderer_scene_occlusion_cull.h
@@ -31,7 +31,7 @@
#ifndef RENDERER_SCENE_OCCLUSION_CULL_H
#define RENDERER_SCENE_OCCLUSION_CULL_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/local_vector.h"
#include "servers/rendering_server.h"
@@ -60,7 +60,7 @@ public:
void update_mips();
- _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const CameraMatrix &p_cam_projection, real_t p_near) const {
+ _FORCE_INLINE_ bool is_occluded(const real_t p_bounds[6], const Vector3 &p_cam_position, const Transform3D &p_cam_inv_transform, const Projection &p_cam_projection, real_t p_near) const {
if (is_empty()) {
return false;
}
@@ -183,7 +183,8 @@ public:
}
virtual void buffer_set_scenario(RID p_buffer, RID p_scenario) { _print_warning(); }
virtual void buffer_set_size(RID p_buffer, const Vector2i &p_size) { _print_warning(); }
- virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_pool) {}
+ virtual void buffer_update(RID p_buffer, const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal) {}
+
virtual RID buffer_get_debug_texture(RID p_buffer) {
_print_warning();
return RID();
@@ -200,4 +201,4 @@ public:
};
};
-#endif //RENDERER_SCENE_OCCLUSION_CULL_H
+#endif // RENDERER_SCENE_OCCLUSION_CULL_H
diff --git a/servers/rendering/renderer_scene_render.cpp b/servers/rendering/renderer_scene_render.cpp
index 600908cf16..f085168df3 100644
--- a/servers/rendering/renderer_scene_render.cpp
+++ b/servers/rendering/renderer_scene_render.cpp
@@ -30,7 +30,10 @@
#include "renderer_scene_render.h"
-void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) {
+/////////////////////////////////////////////////////////////////////////////
+// CameraData
+
+void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter) {
view_count = 1;
is_orthogonal = p_is_orthogonal;
vaspect = p_vaspect;
@@ -43,7 +46,7 @@ void RendererSceneRender::CameraData::set_camera(const Transform3D p_transform,
taa_jitter = p_taa_jitter;
}
-void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect) {
+void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect) {
ERR_FAIL_COND_MSG(p_view_count != 2, "Incorrect view count for stereoscopic view");
view_count = p_view_count;
@@ -60,8 +63,8 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
}
// 2. average and normalize plane normals to obtain z vector, cross them to obtain y vector, and from there the x vector for combined camera basis.
- Vector3 n0 = planes[0][CameraMatrix::PLANE_LEFT].normal;
- Vector3 n1 = planes[1][CameraMatrix::PLANE_RIGHT].normal;
+ Vector3 n0 = planes[0][Projection::PLANE_LEFT].normal;
+ Vector3 n1 = planes[1][Projection::PLANE_RIGHT].normal;
Vector3 z = (n0 + n1).normalized();
Vector3 y = n0.cross(n1).normalized();
Vector3 x = y.cross(z).normalized();
@@ -73,13 +76,13 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 4. Intersect horizon, left and right to obtain the combined camera origin.
ERR_FAIL_COND_MSG(
- !horizon.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
+ !horizon.intersect_3(planes[0][Projection::PLANE_LEFT], planes[1][Projection::PLANE_RIGHT], &main_transform.origin), "Can't determine camera origin");
// handy to have the inverse of the transform we just build
Transform3D main_transform_inv = main_transform.inverse();
// 5. figure out far plane, this could use some improvement, we may have our far plane too close like this, not sure if this matters
- Vector3 far_center = (planes[0][CameraMatrix::PLANE_FAR].center() + planes[1][CameraMatrix::PLANE_FAR].center()) * 0.5;
+ Vector3 far_center = (planes[0][Projection::PLANE_FAR].center() + planes[1][Projection::PLANE_FAR].center()) * 0.5;
Plane far(-z, far_center);
/////////////////////////////////////////////////////////////////////////////
@@ -88,9 +91,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 6. Intersect far and left planes with top planes from both eyes, save the point with highest y as top_left.
Vector3 top_left, other;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
+ !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_TOP], &top_left), "Can't determine left camera far/left/top vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
+ !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/left/top vector");
if (y.dot(top_left) < y.dot(other)) {
top_left = other;
}
@@ -98,9 +101,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 7. Intersect far and left planes with bottom planes from both eyes, save the point with lowest y as bottom_left.
Vector3 bottom_left;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_LEFT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
+ !far.intersect_3(planes[0][Projection::PLANE_LEFT], planes[0][Projection::PLANE_BOTTOM], &bottom_left), "Can't determine left camera far/left/bottom vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_LEFT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
+ !far.intersect_3(planes[1][Projection::PLANE_LEFT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/left/bottom vector");
if (y.dot(other) < y.dot(bottom_left)) {
bottom_left = other;
}
@@ -108,9 +111,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 8. Intersect far and right planes with top planes from both eyes, save the point with highest y as top_right.
Vector3 top_right;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
+ !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_TOP], &top_right), "Can't determine left camera far/right/top vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
+ !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_TOP], &other), "Can't determine right camera far/right/top vector");
if (y.dot(top_right) < y.dot(other)) {
top_right = other;
}
@@ -118,9 +121,9 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 9. Intersect far and right planes with bottom planes from both eyes, save the point with lowest y as bottom_right.
Vector3 bottom_right;
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[0][CameraMatrix::PLANE_RIGHT], planes[0][CameraMatrix::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
+ !far.intersect_3(planes[0][Projection::PLANE_RIGHT], planes[0][Projection::PLANE_BOTTOM], &bottom_right), "Can't determine left camera far/right/bottom vector");
ERR_FAIL_COND_MSG(
- !far.intersect_3(planes[1][CameraMatrix::PLANE_RIGHT], planes[1][CameraMatrix::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
+ !far.intersect_3(planes[1][Projection::PLANE_RIGHT], planes[1][Projection::PLANE_BOTTOM], &other), "Can't determine right camera far/right/bottom vector");
if (y.dot(other) < y.dot(bottom_right)) {
bottom_right = other;
}
@@ -146,18 +149,18 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 13. Intersect near plane with bottm/left planes, to obtain min_vec then top/right to obtain max_vec
Vector3 min_vec;
ERR_FAIL_COND_MSG(
- !near.intersect_3(bottom, planes[0][CameraMatrix::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
+ !near.intersect_3(bottom, planes[0][Projection::PLANE_LEFT], &min_vec), "Can't determine left camera near/left/bottom vector");
ERR_FAIL_COND_MSG(
- !near.intersect_3(bottom, planes[1][CameraMatrix::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
+ !near.intersect_3(bottom, planes[1][Projection::PLANE_LEFT], &other), "Can't determine right camera near/left/bottom vector");
if (x.dot(other) < x.dot(min_vec)) {
min_vec = other;
}
Vector3 max_vec;
ERR_FAIL_COND_MSG(
- !near.intersect_3(top, planes[0][CameraMatrix::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
+ !near.intersect_3(top, planes[0][Projection::PLANE_RIGHT], &max_vec), "Can't determine left camera near/right/top vector");
ERR_FAIL_COND_MSG(
- !near.intersect_3(top, planes[1][CameraMatrix::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
+ !near.intersect_3(top, planes[1][Projection::PLANE_RIGHT], &other), "Can't determine right camera near/right/top vector");
if (x.dot(max_vec) < x.dot(other)) {
max_vec = other;
}
@@ -177,6 +180,452 @@ void RendererSceneRender::CameraData::set_multiview_camera(uint32_t p_view_count
// 3. Copy our view data
for (uint32_t v = 0; v < view_count; v++) {
view_offset[v] = main_transform_inv * p_transforms[v];
- view_projection[v] = p_projections[v] * CameraMatrix(view_offset[v].inverse());
+ view_projection[v] = p_projections[v] * Projection(view_offset[v].inverse());
}
}
+
+/* Environment API */
+
+RID RendererSceneRender::environment_allocate() {
+ return environment_storage.environment_allocate();
+}
+
+void RendererSceneRender::environment_initialize(RID p_rid) {
+ environment_storage.environment_initialize(p_rid);
+}
+
+void RendererSceneRender::environment_free(RID p_rid) {
+ environment_storage.environment_free(p_rid);
+}
+
+bool RendererSceneRender::is_environment(RID p_rid) const {
+ return environment_storage.is_environment(p_rid);
+}
+
+// background
+
+void RendererSceneRender::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
+ environment_storage.environment_set_background(p_env, p_bg);
+}
+
+void RendererSceneRender::environment_set_sky(RID p_env, RID p_sky) {
+ environment_storage.environment_set_sky(p_env, p_sky);
+}
+
+void RendererSceneRender::environment_set_sky_custom_fov(RID p_env, float p_scale) {
+ environment_storage.environment_set_sky_custom_fov(p_env, p_scale);
+}
+
+void RendererSceneRender::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
+ environment_storage.environment_set_sky_orientation(p_env, p_orientation);
+}
+
+void RendererSceneRender::environment_set_bg_color(RID p_env, const Color &p_color) {
+ environment_storage.environment_set_bg_color(p_env, p_color);
+}
+
+void RendererSceneRender::environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value) {
+ environment_storage.environment_set_bg_energy(p_env, p_multiplier, p_exposure_value);
+}
+
+void RendererSceneRender::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
+ environment_storage.environment_set_canvas_max_layer(p_env, p_max_layer);
+}
+
+void RendererSceneRender::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
+ environment_storage.environment_set_ambient_light(p_env, p_color, p_ambient, p_energy, p_sky_contribution, p_reflection_source);
+}
+
+RS::EnvironmentBG RendererSceneRender::environment_get_background(RID p_env) const {
+ return environment_storage.environment_get_background(p_env);
+}
+
+RID RendererSceneRender::environment_get_sky(RID p_env) const {
+ return environment_storage.environment_get_sky(p_env);
+}
+
+float RendererSceneRender::environment_get_sky_custom_fov(RID p_env) const {
+ return environment_storage.environment_get_sky_custom_fov(p_env);
+}
+
+Basis RendererSceneRender::environment_get_sky_orientation(RID p_env) const {
+ return environment_storage.environment_get_sky_orientation(p_env);
+}
+
+Color RendererSceneRender::environment_get_bg_color(RID p_env) const {
+ return environment_storage.environment_get_bg_color(p_env);
+}
+
+float RendererSceneRender::environment_get_bg_energy_multiplier(RID p_env) const {
+ return environment_storage.environment_get_bg_energy_multiplier(p_env);
+}
+
+float RendererSceneRender::environment_get_bg_intensity(RID p_env) const {
+ return environment_storage.environment_get_bg_intensity(p_env);
+}
+
+int RendererSceneRender::environment_get_canvas_max_layer(RID p_env) const {
+ return environment_storage.environment_get_canvas_max_layer(p_env);
+}
+
+RS::EnvironmentAmbientSource RendererSceneRender::environment_get_ambient_source(RID p_env) const {
+ return environment_storage.environment_get_ambient_source(p_env);
+}
+
+Color RendererSceneRender::environment_get_ambient_light(RID p_env) const {
+ return environment_storage.environment_get_ambient_light(p_env);
+}
+
+float RendererSceneRender::environment_get_ambient_light_energy(RID p_env) const {
+ return environment_storage.environment_get_ambient_light_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_ambient_sky_contribution(RID p_env) const {
+ return environment_storage.environment_get_ambient_sky_contribution(p_env);
+}
+
+RS::EnvironmentReflectionSource RendererSceneRender::environment_get_reflection_source(RID p_env) const {
+ return environment_storage.environment_get_reflection_source(p_env);
+}
+
+// Tonemap
+
+void RendererSceneRender::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) {
+ environment_storage.environment_set_tonemap(p_env, p_tone_mapper, p_exposure, p_white);
+}
+
+RS::EnvironmentToneMapper RendererSceneRender::environment_get_tone_mapper(RID p_env) const {
+ return environment_storage.environment_get_tone_mapper(p_env);
+}
+
+float RendererSceneRender::environment_get_exposure(RID p_env) const {
+ return environment_storage.environment_get_exposure(p_env);
+}
+
+float RendererSceneRender::environment_get_white(RID p_env) const {
+ return environment_storage.environment_get_white(p_env);
+}
+
+// Fog
+
+void RendererSceneRender::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) {
+ environment_storage.environment_set_fog(p_env, p_enable, p_light_color, p_light_energy, p_sun_scatter, p_density, p_height, p_height_density, p_aerial_perspective, p_sky_affect);
+}
+
+bool RendererSceneRender::environment_get_fog_enabled(RID p_env) const {
+ return environment_storage.environment_get_fog_enabled(p_env);
+}
+
+Color RendererSceneRender::environment_get_fog_light_color(RID p_env) const {
+ return environment_storage.environment_get_fog_light_color(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_light_energy(RID p_env) const {
+ return environment_storage.environment_get_fog_light_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_sun_scatter(RID p_env) const {
+ return environment_storage.environment_get_fog_sun_scatter(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_density(RID p_env) const {
+ return environment_storage.environment_get_fog_density(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_sky_affect(RID p_env) const {
+ return environment_storage.environment_get_fog_sky_affect(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_height(RID p_env) const {
+ return environment_storage.environment_get_fog_height(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_height_density(RID p_env) const {
+ return environment_storage.environment_get_fog_height_density(p_env);
+}
+
+float RendererSceneRender::environment_get_fog_aerial_perspective(RID p_env) const {
+ return environment_storage.environment_get_fog_aerial_perspective(p_env);
+}
+
+// Volumetric Fog
+
+void RendererSceneRender::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) {
+ environment_storage.environment_set_volumetric_fog(p_env, p_enable, p_density, p_albedo, p_emission, p_emission_energy, p_anisotropy, p_length, p_detail_spread, p_gi_inject, p_temporal_reprojection, p_temporal_reprojection_amount, p_ambient_inject, p_sky_affect);
+}
+
+bool RendererSceneRender::environment_get_volumetric_fog_enabled(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_density(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_density(p_env);
+}
+
+Color RendererSceneRender::environment_get_volumetric_fog_scattering(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_scattering(p_env);
+}
+
+Color RendererSceneRender::environment_get_volumetric_fog_emission(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_emission(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_emission_energy(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_emission_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_anisotropy(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_anisotropy(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_length(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_length(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_detail_spread(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_detail_spread(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_gi_inject(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_gi_inject(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_sky_affect(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_sky_affect(p_env);
+}
+
+bool RendererSceneRender::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_temporal_reprojection(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_temporal_reprojection_amount(p_env);
+}
+
+float RendererSceneRender::environment_get_volumetric_fog_ambient_inject(RID p_env) const {
+ return environment_storage.environment_get_volumetric_fog_ambient_inject(p_env);
+}
+
+// GLOW
+
+void RendererSceneRender::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
+ environment_storage.environment_set_glow(p_env, p_enable, p_levels, p_intensity, p_strength, p_mix, p_bloom_threshold, p_blend_mode, p_hdr_bleed_threshold, p_hdr_bleed_scale, p_hdr_luminance_cap, p_glow_map_strength, p_glow_map);
+}
+
+bool RendererSceneRender::environment_get_glow_enabled(RID p_env) const {
+ return environment_storage.environment_get_glow_enabled(p_env);
+}
+
+Vector<float> RendererSceneRender::environment_get_glow_levels(RID p_env) const {
+ return environment_storage.environment_get_glow_levels(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_intensity(RID p_env) const {
+ return environment_storage.environment_get_glow_intensity(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_strength(RID p_env) const {
+ return environment_storage.environment_get_glow_strength(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_bloom(RID p_env) const {
+ return environment_storage.environment_get_glow_bloom(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_mix(RID p_env) const {
+ return environment_storage.environment_get_glow_mix(p_env);
+}
+
+RS::EnvironmentGlowBlendMode RendererSceneRender::environment_get_glow_blend_mode(RID p_env) const {
+ return environment_storage.environment_get_glow_blend_mode(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_hdr_bleed_threshold(RID p_env) const {
+ return environment_storage.environment_get_glow_hdr_bleed_threshold(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_hdr_luminance_cap(RID p_env) const {
+ return environment_storage.environment_get_glow_hdr_luminance_cap(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_hdr_bleed_scale(RID p_env) const {
+ return environment_storage.environment_get_glow_hdr_bleed_scale(p_env);
+}
+
+float RendererSceneRender::environment_get_glow_map_strength(RID p_env) const {
+ return environment_storage.environment_get_glow_map_strength(p_env);
+}
+
+RID RendererSceneRender::environment_get_glow_map(RID p_env) const {
+ return environment_storage.environment_get_glow_map(p_env);
+}
+
+// SSR
+
+void RendererSceneRender::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
+ environment_storage.environment_set_ssr(p_env, p_enable, p_max_steps, p_fade_int, p_fade_out, p_depth_tolerance);
+}
+
+bool RendererSceneRender::environment_get_ssr_enabled(RID p_env) const {
+ return environment_storage.environment_get_ssr_enabled(p_env);
+}
+
+int RendererSceneRender::environment_get_ssr_max_steps(RID p_env) const {
+ return environment_storage.environment_get_ssr_max_steps(p_env);
+}
+
+float RendererSceneRender::environment_get_ssr_fade_in(RID p_env) const {
+ return environment_storage.environment_get_ssr_fade_in(p_env);
+}
+
+float RendererSceneRender::environment_get_ssr_fade_out(RID p_env) const {
+ return environment_storage.environment_get_ssr_fade_out(p_env);
+}
+
+float RendererSceneRender::environment_get_ssr_depth_tolerance(RID p_env) const {
+ return environment_storage.environment_get_ssr_depth_tolerance(p_env);
+}
+
+// SSAO
+
+void RendererSceneRender::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
+ environment_storage.environment_set_ssao(p_env, p_enable, p_radius, p_intensity, p_power, p_detail, p_horizon, p_sharpness, p_light_affect, p_ao_channel_affect);
+}
+
+bool RendererSceneRender::environment_get_ssao_enabled(RID p_env) const {
+ return environment_storage.environment_get_ssao_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_radius(RID p_env) const {
+ return environment_storage.environment_get_ssao_radius(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_intensity(RID p_env) const {
+ return environment_storage.environment_get_ssao_intensity(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_power(RID p_env) const {
+ return environment_storage.environment_get_ssao_power(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_detail(RID p_env) const {
+ return environment_storage.environment_get_ssao_detail(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_horizon(RID p_env) const {
+ return environment_storage.environment_get_ssao_horizon(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_sharpness(RID p_env) const {
+ return environment_storage.environment_get_ssao_sharpness(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_direct_light_affect(RID p_env) const {
+ return environment_storage.environment_get_ssao_direct_light_affect(p_env);
+}
+
+float RendererSceneRender::environment_get_ssao_ao_channel_affect(RID p_env) const {
+ return environment_storage.environment_get_ssao_ao_channel_affect(p_env);
+}
+
+// SSIL
+
+void RendererSceneRender::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
+ environment_storage.environment_set_ssil(p_env, p_enable, p_radius, p_intensity, p_sharpness, p_normal_rejection);
+}
+
+bool RendererSceneRender::environment_get_ssil_enabled(RID p_env) const {
+ return environment_storage.environment_get_ssil_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_radius(RID p_env) const {
+ return environment_storage.environment_get_ssil_radius(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_intensity(RID p_env) const {
+ return environment_storage.environment_get_ssil_intensity(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_sharpness(RID p_env) const {
+ return environment_storage.environment_get_ssil_sharpness(p_env);
+}
+
+float RendererSceneRender::environment_get_ssil_normal_rejection(RID p_env) const {
+ return environment_storage.environment_get_ssil_normal_rejection(p_env);
+}
+
+// SDFGI
+
+void RendererSceneRender::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+ environment_storage.environment_set_sdfgi(p_env, p_enable, p_cascades, p_min_cell_size, p_y_scale, p_use_occlusion, p_bounce_feedback, p_read_sky, p_energy, p_normal_bias, p_probe_bias);
+}
+
+bool RendererSceneRender::environment_get_sdfgi_enabled(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_enabled(p_env);
+}
+
+int RendererSceneRender::environment_get_sdfgi_cascades(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_cascades(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_min_cell_size(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_min_cell_size(p_env);
+}
+
+bool RendererSceneRender::environment_get_sdfgi_use_occlusion(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_use_occlusion(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_bounce_feedback(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_bounce_feedback(p_env);
+}
+
+bool RendererSceneRender::environment_get_sdfgi_read_sky_light(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_read_sky_light(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_energy(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_energy(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_normal_bias(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_normal_bias(p_env);
+}
+
+float RendererSceneRender::environment_get_sdfgi_probe_bias(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_probe_bias(p_env);
+}
+
+RS::EnvironmentSDFGIYScale RendererSceneRender::environment_get_sdfgi_y_scale(RID p_env) const {
+ return environment_storage.environment_get_sdfgi_y_scale(p_env);
+}
+
+// Adjustments
+
+void RendererSceneRender::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
+ environment_storage.environment_set_adjustment(p_env, p_enable, p_brightness, p_contrast, p_saturation, p_use_1d_color_correction, p_color_correction);
+}
+
+bool RendererSceneRender::environment_get_adjustments_enabled(RID p_env) const {
+ return environment_storage.environment_get_adjustments_enabled(p_env);
+}
+
+float RendererSceneRender::environment_get_adjustments_brightness(RID p_env) const {
+ return environment_storage.environment_get_adjustments_brightness(p_env);
+}
+
+float RendererSceneRender::environment_get_adjustments_contrast(RID p_env) const {
+ return environment_storage.environment_get_adjustments_contrast(p_env);
+}
+
+float RendererSceneRender::environment_get_adjustments_saturation(RID p_env) const {
+ return environment_storage.environment_get_adjustments_saturation(p_env);
+}
+
+bool RendererSceneRender::environment_get_use_1d_color_correction(RID p_env) const {
+ return environment_storage.environment_get_use_1d_color_correction(p_env);
+}
+
+RID RendererSceneRender::environment_get_color_correction(RID p_env) const {
+ return environment_storage.environment_get_color_correction(p_env);
+}
diff --git a/servers/rendering/renderer_scene_render.h b/servers/rendering/renderer_scene_render.h
index 280277c6d8..a8df897077 100644
--- a/servers/rendering/renderer_scene_render.h
+++ b/servers/rendering/renderer_scene_render.h
@@ -28,14 +28,21 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERSCENERENDER_H
-#define RENDERINGSERVERSCENERENDER_H
+#ifndef RENDERER_SCENE_RENDER_H
+#define RENDERER_SCENE_RENDER_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/templates/paged_array.h"
-#include "servers/rendering/renderer_scene.h"
+#include "servers/rendering/renderer_geometry_instance.h"
+#include "servers/rendering/rendering_method.h"
+#include "servers/rendering/storage/environment_storage.h"
+#include "storage/render_scene_buffers.h"
+#include "storage/utilities.h"
class RendererSceneRender {
+private:
+ RendererEnvironmentStorage environment_storage;
+
public:
enum {
MAX_DIRECTIONAL_LIGHTS = 8,
@@ -43,56 +50,18 @@ public:
MAX_RENDER_VIEWS = 2
};
- struct GeometryInstance {
- virtual ~GeometryInstance() {}
- };
-
- virtual GeometryInstance *geometry_instance_create(RID p_base) = 0;
- virtual void geometry_instance_set_skeleton(GeometryInstance *p_geometry_instance, RID p_skeleton) = 0;
- virtual void geometry_instance_set_material_override(GeometryInstance *p_geometry_instance, RID p_override) = 0;
- virtual void geometry_instance_set_material_overlay(GeometryInstance *p_geometry_instance, RID p_override) = 0;
- virtual void geometry_instance_set_surface_materials(GeometryInstance *p_geometry_instance, const Vector<RID> &p_material) = 0;
- virtual void geometry_instance_set_mesh_instance(GeometryInstance *p_geometry_instance, RID p_mesh_instance) = 0;
- virtual void geometry_instance_set_transform(GeometryInstance *p_geometry_instance, const Transform3D &p_transform, const AABB &p_aabb, const AABB &p_transformed_aabbb) = 0;
- virtual void geometry_instance_set_layer_mask(GeometryInstance *p_geometry_instance, uint32_t p_layer_mask) = 0;
- virtual void geometry_instance_set_lod_bias(GeometryInstance *p_geometry_instance, float p_lod_bias) = 0;
- virtual void geometry_instance_set_transparency(GeometryInstance *p_geometry_instance, float p_transparency) = 0;
- virtual void geometry_instance_set_fade_range(GeometryInstance *p_geometry_instance, bool p_enable_near, float p_near_begin, float p_near_end, bool p_enable_far, float p_far_begin, float p_far_end) = 0;
- virtual void geometry_instance_set_parent_fade_alpha(GeometryInstance *p_geometry_instance, float p_alpha) = 0;
- virtual void geometry_instance_set_use_baked_light(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
- virtual void geometry_instance_set_use_dynamic_gi(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
- virtual void geometry_instance_set_use_lightmap(GeometryInstance *p_geometry_instance, RID p_lightmap_instance, const Rect2 &p_lightmap_uv_scale, int p_lightmap_slice_index) = 0;
- virtual void geometry_instance_set_lightmap_capture(GeometryInstance *p_geometry_instance, const Color *p_sh9) = 0;
- virtual void geometry_instance_set_instance_shader_parameters_offset(GeometryInstance *p_geometry_instance, int32_t p_offset) = 0;
- virtual void geometry_instance_set_cast_double_sided_shadows(GeometryInstance *p_geometry_instance, bool p_enable) = 0;
+ /* Geometry Instance */
+ virtual RenderGeometryInstance *geometry_instance_create(RID p_base) = 0;
+ virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) = 0;
virtual uint32_t geometry_instance_get_pair_mask() = 0;
- virtual void geometry_instance_pair_light_instances(GeometryInstance *p_geometry_instance, const RID *p_light_instances, uint32_t p_light_instance_count) = 0;
- virtual void geometry_instance_pair_reflection_probe_instances(GeometryInstance *p_geometry_instance, const RID *p_reflection_probe_instances, uint32_t p_reflection_probe_instance_count) = 0;
- virtual void geometry_instance_pair_decal_instances(GeometryInstance *p_geometry_instance, const RID *p_decal_instances, uint32_t p_decal_instance_count) = 0;
- virtual void geometry_instance_pair_voxel_gi_instances(GeometryInstance *p_geometry_instance, const RID *p_voxel_gi_instances, uint32_t p_voxel_gi_instance_count) = 0;
-
- virtual void geometry_instance_set_softshadow_projector_pairing(GeometryInstance *p_geometry_instance, bool p_softshadow, bool p_projector) = 0;
-
- virtual void geometry_instance_free(GeometryInstance *p_geometry_instance) = 0;
-
- /* SHADOW ATLAS API */
-
- virtual RID shadow_atlas_create() = 0;
- virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_16_bits = true) = 0;
- virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
- virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
-
- virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
- virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
- virtual void set_directional_shadow_count(int p_count) = 0;
/* SDFGI UPDATE */
- virtual void sdfgi_update(RID p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
- virtual int sdfgi_get_pending_region_count(RID p_render_buffers) const = 0;
- virtual AABB sdfgi_get_pending_region_bounds(RID p_render_buffers, int p_region) const = 0;
- virtual uint32_t sdfgi_get_pending_region_cascade(RID p_render_buffers, int p_region) const = 0;
+ virtual void sdfgi_update(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_environment, const Vector3 &p_world_position) = 0;
+ virtual int sdfgi_get_pending_region_count(const Ref<RenderSceneBuffers> &p_render_buffers) const = 0;
+ virtual AABB sdfgi_get_pending_region_bounds(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
+ virtual uint32_t sdfgi_get_pending_region_cascade(const Ref<RenderSceneBuffers> &p_render_buffers, int p_region) const = 0;
/* SKY API */
@@ -106,77 +75,159 @@ public:
/* ENVIRONMENT API */
- virtual RID environment_allocate() = 0;
- virtual void environment_initialize(RID p_rid) = 0;
-
- virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
- virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
- virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
- virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
- virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
- virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
- virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
- virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
+ RID environment_allocate();
+ void environment_initialize(RID p_rid);
+ void environment_free(RID p_rid);
+
+ bool is_environment(RID p_env) const;
+
+ // Background
+ void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
+ void environment_set_sky(RID p_env, RID p_sky);
+ void environment_set_sky_custom_fov(RID p_env, float p_scale);
+ void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
+ void environment_set_bg_color(RID p_env, const Color &p_color);
+ void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value);
+ void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
+ void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG);
// FIXME: Disabled during Vulkan refactoring, should be ported.
#if 0
- virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0;
+ void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
#endif
- virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
- virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
- virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
+ RS::EnvironmentBG environment_get_background(RID p_env) const;
+ RID environment_get_sky(RID p_env) const;
+ float environment_get_sky_custom_fov(RID p_env) const;
+ Basis environment_get_sky_orientation(RID p_env) const;
+ Color environment_get_bg_color(RID p_env) const;
+ float environment_get_bg_energy_multiplier(RID p_env) const;
+ float environment_get_bg_intensity(RID p_env) const;
+ int environment_get_canvas_max_layer(RID p_env) const;
+ RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
+ Color environment_get_ambient_light(RID p_env) const;
+ float environment_get_ambient_light_energy(RID p_env) const;
+ float environment_get_ambient_sky_contribution(RID p_env) const;
+ RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
+
+ // Tonemap
+ void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white);
+ RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const;
+ float environment_get_exposure(RID p_env) const;
+ float environment_get_white(RID p_env) const;
+
+ // Fog
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ bool environment_get_fog_enabled(RID p_env) const;
+ Color environment_get_fog_light_color(RID p_env) const;
+ float environment_get_fog_light_energy(RID p_env) const;
+ float environment_get_fog_sun_scatter(RID p_env) const;
+ float environment_get_fog_density(RID p_env) const;
+ float environment_get_fog_sky_affect(RID p_env) const;
+ float environment_get_fog_height(RID p_env) const;
+ float environment_get_fog_height_density(RID p_env) const;
+ float environment_get_fog_aerial_perspective(RID p_env) const;
+
+ // Volumetric Fog
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect);
+ bool environment_get_volumetric_fog_enabled(RID p_env) const;
+ float environment_get_volumetric_fog_density(RID p_env) const;
+ Color environment_get_volumetric_fog_scattering(RID p_env) const;
+ Color environment_get_volumetric_fog_emission(RID p_env) const;
+ float environment_get_volumetric_fog_emission_energy(RID p_env) const;
+ float environment_get_volumetric_fog_anisotropy(RID p_env) const;
+ float environment_get_volumetric_fog_length(RID p_env) const;
+ float environment_get_volumetric_fog_detail_spread(RID p_env) const;
+ float environment_get_volumetric_fog_gi_inject(RID p_env) const;
+ float environment_get_volumetric_fog_sky_affect(RID p_env) const;
+ bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const;
+ float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const;
+ float environment_get_volumetric_fog_ambient_inject(RID p_env) const;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
- virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
+ // GLOW
+ void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
+ bool environment_get_glow_enabled(RID p_env) const;
+ Vector<float> environment_get_glow_levels(RID p_env) const;
+ float environment_get_glow_intensity(RID p_env) const;
+ float environment_get_glow_strength(RID p_env) const;
+ float environment_get_glow_bloom(RID p_env) const;
+ float environment_get_glow_mix(RID p_env) const;
+ RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const;
+ float environment_get_glow_hdr_bleed_threshold(RID p_env) const;
+ float environment_get_glow_hdr_luminance_cap(RID p_env) const;
+ float environment_get_glow_hdr_bleed_scale(RID p_env) const;
+ float environment_get_glow_map_strength(RID p_env) const;
+ RID environment_get_glow_map(RID p_env) const;
+
+ virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
+ virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
+
+ // SSR
+ void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
+ bool environment_get_ssr_enabled(RID p_env) const;
+ int environment_get_ssr_max_steps(RID p_env) const;
+ float environment_get_ssr_fade_in(RID p_env) const;
+ float environment_get_ssr_fade_out(RID p_env) const;
+ float environment_get_ssr_depth_tolerance(RID p_env) const;
+
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
- virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0;
+ // SSAO
+ void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
+ bool environment_get_ssao_enabled(RID p_env) const;
+ float environment_get_ssao_radius(RID p_env) const;
+ float environment_get_ssao_intensity(RID p_env) const;
+ float environment_get_ssao_power(RID p_env) const;
+ float environment_get_ssao_detail(RID p_env) const;
+ float environment_get_ssao_horizon(RID p_env) const;
+ float environment_get_ssao_sharpness(RID p_env) const;
+ float environment_get_ssao_direct_light_affect(RID p_env) const;
+ float environment_get_ssao_ao_channel_affect(RID p_env) const;
+
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0;
+ // SSIL
+ void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection);
+ bool environment_get_ssil_enabled(RID p_env) const;
+ float environment_get_ssil_radius(RID p_env) const;
+ float environment_get_ssil_intensity(RID p_env) const;
+ float environment_get_ssil_sharpness(RID p_env) const;
+ float environment_get_ssil_normal_rejection(RID p_env) const;
+
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
- virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ // SDFGI
+ void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
+ bool environment_get_sdfgi_enabled(RID p_env) const;
+ int environment_get_sdfgi_cascades(RID p_env) const;
+ float environment_get_sdfgi_min_cell_size(RID p_env) const;
+ bool environment_get_sdfgi_use_occlusion(RID p_env) const;
+ float environment_get_sdfgi_bounce_feedback(RID p_env) const;
+ bool environment_get_sdfgi_read_sky_light(RID p_env) const;
+ float environment_get_sdfgi_energy(RID p_env) const;
+ float environment_get_sdfgi_normal_bias(RID p_env) const;
+ float environment_get_sdfgi_probe_bias(RID p_env) const;
+ RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const;
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
- virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
-
- virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
-
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
+ // Adjustment
+ void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
+ bool environment_get_adjustments_enabled(RID p_env) const;
+ float environment_get_adjustments_brightness(RID p_env) const;
+ float environment_get_adjustments_contrast(RID p_env) const;
+ float environment_get_adjustments_saturation(RID p_env) const;
+ bool environment_get_use_1d_color_correction(RID p_env) const;
+ RID environment_get_color_correction(RID p_env) const;
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
- virtual bool is_environment(RID p_env) const = 0;
- virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0;
- virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
-
- virtual RID camera_effects_allocate() = 0;
- virtual void camera_effects_initialize(RID p_rid) = 0;
-
- virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0;
- virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0;
-
- virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
- virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
-
- virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
-
- virtual RID light_instance_create(RID p_light) = 0;
- virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0;
- virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
- virtual void light_instance_mark_visible(RID p_light_instance) = 0;
- virtual bool light_instances_can_render_shadow_cube() const {
- return true;
- }
+ virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
+ virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
virtual RID fog_volume_instance_create(RID p_fog_volume) = 0;
virtual void fog_volume_instance_set_transform(RID p_fog_volume_instance, const Transform3D &p_transform) = 0;
@@ -184,40 +235,22 @@ public:
virtual RID fog_volume_instance_get_volume(RID p_fog_volume_instance) const = 0;
virtual Vector3 fog_volume_instance_get_position(RID p_fog_volume_instance) const = 0;
- virtual RID reflection_atlas_create() = 0;
- virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
- virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0;
-
- virtual RID reflection_probe_instance_create(RID p_probe) = 0;
- virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
- virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
- virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
- virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
- virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
- virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
-
- virtual RID decal_instance_create(RID p_decal) = 0;
- virtual void decal_instance_set_transform(RID p_decal, const Transform3D &p_transform) = 0;
-
- virtual RID lightmap_instance_create(RID p_lightmap) = 0;
- virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) = 0;
-
virtual RID voxel_gi_instance_create(RID p_voxel_gi) = 0;
virtual void voxel_gi_instance_set_transform_to_data(RID p_probe, const Transform3D &p_xform) = 0;
virtual bool voxel_gi_needs_update(RID p_probe) const = 0;
- virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<GeometryInstance *> &p_dynamic_objects) = 0;
+ virtual void voxel_gi_update(RID p_probe, bool p_update_light_instances, const Vector<RID> &p_light_instances, const PagedArray<RenderGeometryInstance *> &p_dynamic_objects) = 0;
virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0;
struct RenderShadowData {
RID light;
int pass = 0;
- PagedArray<GeometryInstance *> instances;
+ PagedArray<RenderGeometryInstance *> instances;
};
struct RenderSDFGIData {
int region = 0;
- PagedArray<GeometryInstance *> instances;
+ PagedArray<RenderGeometryInstance *> instances;
};
struct RenderSDFGIUpdateData {
@@ -239,27 +272,26 @@ public:
// Main/center projection
Transform3D main_transform;
- CameraMatrix main_projection;
+ Projection main_projection;
Transform3D view_offset[RendererSceneRender::MAX_RENDER_VIEWS];
- CameraMatrix view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
+ Projection view_projection[RendererSceneRender::MAX_RENDER_VIEWS];
Vector2 taa_jitter;
- void set_camera(const Transform3D p_transform, const CameraMatrix p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2());
- void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const CameraMatrix *p_projections, bool p_is_orthogonal, bool p_vaspect);
+ void set_camera(const Transform3D p_transform, const Projection p_projection, bool p_is_orthogonal, bool p_vaspect, const Vector2 &p_taa_jitter = Vector2());
+ void set_multiview_camera(uint32_t p_view_count, const Transform3D *p_transforms, const Projection *p_projections, bool p_is_orthogonal, bool p_vaspect);
};
- virtual void render_scene(RID p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<GeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RendererScene::RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_scene(const Ref<RenderSceneBuffers> &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray<RenderGeometryInstance *> &p_instances, const PagedArray<RID> &p_lights, const PagedArray<RID> &p_reflection_probes, const PagedArray<RID> &p_voxel_gi_instances, const PagedArray<RID> &p_decals, const PagedArray<RID> &p_lightmaps, const PagedArray<RID> &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RenderingMethod::RenderInfo *r_render_info = nullptr) = 0;
- virtual void render_material(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, const PagedArray<GeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
- virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<GeometryInstance *> &p_instances) = 0;
+ virtual void render_material(const Transform3D &p_cam_transform, const Projection &p_cam_projection, bool p_cam_orthogonal, const PagedArray<RenderGeometryInstance *> &p_instances, RID p_framebuffer, const Rect2i &p_region) = 0;
+ virtual void render_particle_collider_heightfield(RID p_collider, const Transform3D &p_transform, const PagedArray<RenderGeometryInstance *> &p_instances) = 0;
virtual void set_scene_pass(uint64_t p_pass) = 0;
virtual void set_time(double p_time, double p_step) = 0;
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
- virtual RID render_buffers_create() = 0;
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
@@ -268,7 +300,7 @@ public:
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0;
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0;
- virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
virtual bool free(RID p_rid) = 0;
@@ -281,4 +313,4 @@ public:
virtual ~RendererSceneRender() {}
};
-#endif // RENDERINGSERVERSCENERENDER_H
+#endif // RENDERER_SCENE_RENDER_H
diff --git a/servers/rendering/renderer_storage.h b/servers/rendering/renderer_storage.h
deleted file mode 100644
index bb4acab582..0000000000
--- a/servers/rendering/renderer_storage.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/*************************************************************************/
-/* renderer_storage.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* 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. */
-/*************************************************************************/
-
-#ifndef RENDERINGSERVERSTORAGE_H
-#define RENDERINGSERVERSTORAGE_H
-
-#include "servers/rendering_server.h"
-
-class RendererStorage {
- Color default_clear_color;
-
-public:
- enum DependencyChangedNotification {
- DEPENDENCY_CHANGED_AABB,
- DEPENDENCY_CHANGED_MATERIAL,
- DEPENDENCY_CHANGED_MESH,
- DEPENDENCY_CHANGED_MULTIMESH,
- DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES,
- DEPENDENCY_CHANGED_PARTICLES,
- DEPENDENCY_CHANGED_DECAL,
- DEPENDENCY_CHANGED_SKELETON_DATA,
- DEPENDENCY_CHANGED_SKELETON_BONES,
- DEPENDENCY_CHANGED_LIGHT,
- DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR,
- DEPENDENCY_CHANGED_REFLECTION_PROBE,
- };
-
- struct DependencyTracker;
-
- struct Dependency {
- void changed_notify(DependencyChangedNotification p_notification);
- void deleted_notify(const RID &p_rid);
-
- ~Dependency();
-
- private:
- friend struct DependencyTracker;
- HashMap<DependencyTracker *, uint32_t> instances;
- };
-
- struct DependencyTracker {
- void *userdata = nullptr;
- typedef void (*ChangedCallback)(DependencyChangedNotification, DependencyTracker *);
- typedef void (*DeletedCallback)(const RID &, DependencyTracker *);
-
- ChangedCallback changed_callback = nullptr;
- DeletedCallback deleted_callback = nullptr;
-
- void update_begin() { // call before updating dependencies
- instance_version++;
- }
-
- void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage
- dependencies.insert(p_dependency);
- p_dependency->instances[this] = instance_version;
- }
-
- void update_end() { //call after updating dependencies
- List<Pair<Dependency *, DependencyTracker *>> to_clean_up;
-
- for (Dependency *E : dependencies) {
- Dependency *dep = E;
- HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this);
- ERR_CONTINUE(!F);
- if (F->value != instance_version) {
- Pair<Dependency *, DependencyTracker *> p;
- p.first = dep;
- p.second = F->key;
- to_clean_up.push_back(p);
- }
- }
-
- while (to_clean_up.size()) {
- to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second);
- dependencies.erase(to_clean_up.front()->get().first);
- to_clean_up.pop_front();
- }
- }
-
- void clear() { // clear all dependencies
- for (Dependency *E : dependencies) {
- Dependency *dep = E;
- dep->instances.erase(this);
- }
- dependencies.clear();
- }
-
- ~DependencyTracker() { clear(); }
-
- private:
- friend struct Dependency;
- uint32_t instance_version = 0;
- HashSet<Dependency *> dependencies;
- };
-
- virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
-
- /* VOXEL GI API */
-
- virtual RID voxel_gi_allocate() = 0;
- virtual void voxel_gi_initialize(RID p_rid) = 0;
-
- virtual void voxel_gi_allocate_data(RID p_voxel_gi, const Transform3D &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector<uint8_t> &p_octree_cells, const Vector<uint8_t> &p_data_cells, const Vector<uint8_t> &p_distance_field, const Vector<int> &p_level_counts) = 0;
-
- virtual AABB voxel_gi_get_bounds(RID p_voxel_gi) const = 0;
- virtual Vector3i voxel_gi_get_octree_size(RID p_voxel_gi) const = 0;
- virtual Vector<uint8_t> voxel_gi_get_octree_cells(RID p_voxel_gi) const = 0;
- virtual Vector<uint8_t> voxel_gi_get_data_cells(RID p_voxel_gi) const = 0;
- virtual Vector<uint8_t> voxel_gi_get_distance_field(RID p_voxel_gi) const = 0;
-
- virtual Vector<int> voxel_gi_get_level_counts(RID p_voxel_gi) const = 0;
- virtual Transform3D voxel_gi_get_to_cell_xform(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0;
- virtual float voxel_gi_get_dynamic_range(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0;
- virtual float voxel_gi_get_propagation(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
- virtual float voxel_gi_get_energy(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
- virtual float voxel_gi_get_bias(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0;
- virtual float voxel_gi_get_normal_bias(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0;
- virtual bool voxel_gi_is_interior(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_use_two_bounces(RID p_voxel_gi, bool p_enable) = 0;
- virtual bool voxel_gi_is_using_two_bounces(RID p_voxel_gi) const = 0;
-
- virtual void voxel_gi_set_anisotropy_strength(RID p_voxel_gi, float p_strength) = 0;
- virtual float voxel_gi_get_anisotropy_strength(RID p_voxel_gi) const = 0;
-
- virtual uint32_t voxel_gi_get_version(RID p_probe) = 0;
-
- /* FOG VOLUMES */
-
- virtual RID fog_volume_allocate() = 0;
- virtual void fog_volume_initialize(RID p_rid) = 0;
-
- virtual void fog_volume_set_shape(RID p_fog_volume, RS::FogVolumeShape p_shape) = 0;
- virtual void fog_volume_set_extents(RID p_fog_volume, const Vector3 &p_extents) = 0;
- virtual void fog_volume_set_material(RID p_fog_volume, RID p_material) = 0;
- virtual AABB fog_volume_get_aabb(RID p_fog_volume) const = 0;
- virtual RS::FogVolumeShape fog_volume_get_shape(RID p_fog_volume) const = 0;
-
- /* VISIBILITY NOTIFIER */
-
- virtual RID visibility_notifier_allocate() = 0;
- virtual void visibility_notifier_initialize(RID p_notifier) = 0;
- virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
- virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
-
- virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
- virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
-
- virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
- virtual bool free(RID p_rid) = 0;
-
- virtual bool has_os_feature(const String &p_feature) const = 0;
-
- virtual void update_dirty_resources() = 0;
-
- virtual void set_debug_generate_wireframes(bool p_generate) = 0;
-
- virtual void update_memory_info() = 0;
-
- virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
- virtual String get_video_adapter_name() const = 0;
- virtual String get_video_adapter_vendor() const = 0;
- virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
- virtual String get_video_adapter_api_version() const = 0;
-
- static RendererStorage *base_singleton;
-
- void set_default_clear_color(const Color &p_color) {
- default_clear_color = p_color;
- }
-
- Color get_default_clear_color() const {
- return default_clear_color;
- }
-#define TIMESTAMP_BEGIN() \
- { \
- if (RSG::storage->capturing_timestamps) \
- RSG::storage->capture_timestamps_begin(); \
- }
-
-#define RENDER_TIMESTAMP(m_text) \
- { \
- if (RSG::storage->capturing_timestamps) \
- RSG::storage->capture_timestamp(m_text); \
- }
-
- bool capturing_timestamps = false;
-
- virtual void capture_timestamps_begin() = 0;
- virtual void capture_timestamp(const String &p_name) = 0;
- virtual uint32_t get_captured_timestamps_count() const = 0;
- virtual uint64_t get_captured_timestamps_frame() const = 0;
- virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0;
- virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0;
- virtual String get_captured_timestamp_name(uint32_t p_index) const = 0;
-
- RendererStorage();
- virtual ~RendererStorage() {}
-};
-
-#endif // RENDERINGSERVERSTORAGE_H
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp
index 2e0c4e0f79..2836889de5 100644
--- a/servers/rendering/renderer_viewport.cpp
+++ b/servers/rendering/renderer_viewport.cpp
@@ -72,11 +72,48 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,
return xf;
}
+Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() {
+ // 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.
+
+ Vector<Viewport *> result;
+ List<Viewport *> nodes;
+
+ for (int i = active_viewports.size() - 1; i >= 0; --i) {
+ Viewport *viewport = active_viewports[i];
+ if (viewport->parent.is_valid()) {
+ continue;
+ }
+
+ nodes.push_back(viewport);
+ result.insert(0, viewport);
+ }
+
+ while (!nodes.is_empty()) {
+ const Viewport *node = nodes[0];
+ nodes.pop_front();
+
+ for (int i = active_viewports.size() - 1; i >= 0; --i) {
+ Viewport *child = active_viewports[i];
+ if (child->parent != node->self) {
+ continue;
+ }
+
+ if (!nodes.find(child)) {
+ nodes.push_back(child);
+ result.insert(0, child);
+ }
+ }
+ }
+
+ return result;
+}
+
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) {
- RSG::scene->free(p_viewport->render_buffers);
- p_viewport->render_buffers = RID();
+ p_viewport->render_buffers.unref();
} else {
const float scaling_3d_scale = p_viewport->scaling_3d_scale;
RS::ViewportScaling3DMode scaling_3d_mode = p_viewport->scaling_3d_mode;
@@ -138,7 +175,11 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
p_viewport->internal_size = Size2(render_width, render_height);
- RSG::scene->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, render_width, render_height, width, height, p_viewport->fsr_sharpness, p_viewport->fsr_mipmap_bias, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
+ // 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;
+
+ p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), 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);
}
}
}
@@ -154,7 +195,7 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
if (p_viewport->use_occlusion_culling) {
if (p_viewport->occlusion_buffer_dirty) {
float aspect = p_viewport->size.aspect();
- int max_size = occlusion_rays_per_thread * RendererThreadPool::singleton->thread_work_pool.get_thread_count();
+ int max_size = occlusion_rays_per_thread * WorkerThreadPool::get_singleton()->get_thread_count();
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.
@@ -175,11 +216,11 @@ void RendererViewport::_draw_3d(Viewport *p_viewport) {
void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_begin_" + itos(p_viewport->self.get_id());
- RSG::storage->capture_timestamp(rt_id);
+ RSG::utilities->capture_timestamp(rt_id);
timestamp_vp_map[rt_id] = p_viewport->self;
}
- if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") {
+ if (OS::get_singleton()->get_current_rendering_method() == "gl_compatibility") {
// 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);
}
@@ -212,7 +253,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
_configure_3d_render_buffers(p_viewport);
}
- Color bgcolor = p_viewport->transparent_bg ? Color(0, 0, 0, 0) : RSG::storage->get_default_clear_color();
+ Color bgcolor = p_viewport->transparent_bg ? Color(0, 0, 0, 0) : RSG::texture_storage->get_default_clear_color();
if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) {
RSG::texture_storage->render_target_request_clear(p_viewport->render_target, bgcolor);
@@ -489,7 +530,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
ptr = ptr->filter_next_ptr;
}
- 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);
+ 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);
if (RSG::canvas->was_sdf_used()) {
p_viewport->sdf_active = true;
}
@@ -521,7 +562,7 @@ void RendererViewport::_draw_viewport(Viewport *p_viewport) {
if (p_viewport->measure_render_time) {
String rt_id = "vp_end_" + itos(p_viewport->self.get_id());
- RSG::storage->capture_timestamp(rt_id);
+ RSG::utilities->capture_timestamp(rt_id);
timestamp_vp_map[rt_id] = p_viewport->self;
}
}
@@ -544,8 +585,10 @@ void RendererViewport::draw_viewports() {
set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));
}
- //sort viewports
- active_viewports.sort_custom<ViewportSort>();
+ if (sorted_active_viewports_dirty) {
+ sorted_active_viewports = _sort_active_viewports();
+ sorted_active_viewports_dirty = false;
+ }
HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;
//draw viewports
@@ -554,9 +597,9 @@ void RendererViewport::draw_viewports() {
//determine what is visible
draw_viewports_pass++;
- for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
+ for (int i = sorted_active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
- Viewport *vp = active_viewports[i];
+ Viewport *vp = sorted_active_viewports[i];
if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) {
continue;
@@ -571,39 +614,32 @@ void RendererViewport::draw_viewports() {
if (vp->use_xr) {
if (xr_interface.is_valid()) {
+ // Ignore update mode we have to commit frames to our XR interface
+ visible = true;
+
// 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();
-
- // Would have been nice if we could call viewport_set_size here,
- // but alas that takes our RID and we now have our pointer,
- // also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change
- vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
- vp->size = xr_size;
- uint32_t view_count = xr_interface->get_view_count();
- RSG::texture_storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
-
- // Inform xr interface we're about to render its viewport, if this returns false we don't render
- visible = xr_interface->pre_draw_viewport(vp->render_target);
+ _viewport_set_size(vp, xr_size.width, xr_size.height, xr_interface->get_view_count());
} else {
// don't render anything
visible = false;
vp->size = Size2();
}
- }
-
- if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) {
- visible = true;
- }
-
- if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::texture_storage->render_target_was_used(vp->render_target)) {
- visible = true;
- }
+ } else {
+ if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) {
+ visible = true;
+ }
- 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) {
+ if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::texture_storage->render_target_was_used(vp->render_target)) {
visible = true;
}
+
+ 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;
+ }
+ }
}
visible = visible && vp->size.x > 1 && vp->size.y > 1;
@@ -617,8 +653,8 @@ void RendererViewport::draw_viewports() {
int objects_drawn = 0;
int draw_calls_used = 0;
- for (int i = 0; i < active_viewports.size(); i++) {
- Viewport *vp = active_viewports[i];
+ for (int i = 0; i < sorted_active_viewports.size(); i++) {
+ Viewport *vp = sorted_active_viewports[i];
if (vp->last_pass != draw_viewports_pass) {
continue; //should not draw
@@ -628,31 +664,43 @@ void RendererViewport::draw_viewports() {
RSG::texture_storage->render_target_set_as_unused(vp->render_target);
if (vp->use_xr && xr_interface.is_valid()) {
- // check for an external texture destination (disabled for now, not yet supported)
- // RSG::texture_storage->render_target_set_external_texture(vp->render_target, xr_interface->get_external_texture_for_eye(leftOrMono));
- RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
-
- // render...
- RSG::scene->set_debug_draw_mode(vp->debug_draw);
-
- // and draw viewport
- _draw_viewport(vp);
-
- // measure
-
- // 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 && blits.size() > 0) {
- if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
- blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
- }
+ // 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)) {
+ 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());
+
+ // 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>();
+ }
- for (int b = 0; b < blits.size(); b++) {
- blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
+ for (int b = 0; b < blits.size(); b++) {
+ blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
+ }
+ }
}
}
} else {
- RSG::texture_storage->render_target_set_external_texture(vp->render_target, 0);
+ RSG::texture_storage->render_target_set_override(vp->render_target, RID(), RID(), RID());
RSG::scene->set_debug_draw_mode(vp->debug_draw);
@@ -674,7 +722,14 @@ void RendererViewport::draw_viewports() {
blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
}
- blit_to_screen_list[vp->viewport_to_screen].push_back(blit);
+ 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);
+ }
}
}
@@ -712,7 +767,7 @@ void RendererViewport::viewport_initialize(RID p_rid) {
Viewport *viewport = viewport_owner.get_or_null(p_rid);
viewport->self = p_rid;
viewport->render_target = RSG::texture_storage->render_target_create();
- viewport->shadow_atlas = RSG::scene->shadow_atlas_create();
+ viewport->shadow_atlas = RSG::light_storage->shadow_atlas_create();
viewport->viewport_render_direct_to_screen = false;
viewport->fsr_enabled = !RSG::rasterizer->is_low_end() && !viewport->disable_3d;
@@ -727,7 +782,13 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
}
viewport->use_xr = p_use_xr;
- _configure_3d_render_buffers(viewport);
+
+ // 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);
+ }
}
void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) {
@@ -743,15 +804,19 @@ void RendererViewport::viewport_set_fsr_sharpness(RID p_viewport, float p_sharpn
ERR_FAIL_COND(!viewport);
viewport->fsr_sharpness = p_sharpness;
- _configure_3d_render_buffers(viewport);
+ if (viewport->render_buffers.is_valid()) {
+ viewport->render_buffers->set_fsr_sharpness(p_sharpness);
+ }
}
-void RendererViewport::viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
+void RendererViewport::viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- viewport->fsr_mipmap_bias = p_mipmap_bias;
- _configure_3d_render_buffers(viewport);
+ viewport->texture_mipmap_bias = p_mipmap_bias;
+ if (viewport->render_buffers.is_valid()) {
+ viewport->render_buffers->set_texture_mipmap_bias(p_mipmap_bias);
+ }
}
void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) {
@@ -769,34 +834,27 @@ void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_sca
_configure_3d_render_buffers(viewport);
}
-uint32_t RendererViewport::Viewport::get_view_count() {
- uint32_t view_count = 1;
-
- if (use_xr && XRServer::get_singleton() != nullptr) {
- Ref<XRInterface> xr_interface;
-
- xr_interface = XRServer::get_singleton()->get_primary_interface();
- if (xr_interface.is_valid()) {
- view_count = xr_interface->get_view_count();
- }
- }
-
- return view_count;
-}
-
void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
ERR_FAIL_COND(p_width < 0 && p_height < 0);
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
+ ERR_FAIL_COND_MSG(viewport->use_xr, "Cannot set viewport size when using XR");
- viewport->size = Size2(p_width, p_height);
+ _viewport_set_size(viewport, p_width, p_height, 1);
+}
- uint32_t view_count = viewport->get_view_count();
- RSG::texture_storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
- _configure_3d_render_buffers(viewport);
+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;
- viewport->occlusion_buffer_dirty = true;
+ 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;
+ }
}
void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
@@ -810,6 +868,8 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
} else {
active_viewports.erase(viewport);
}
+
+ sorted_active_viewports_dirty = true;
}
void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) {
@@ -834,7 +894,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
- RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->view_count);
RSG::texture_storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
@@ -844,7 +904,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->view_count);
}
viewport->viewport_to_screen_rect = Rect2();
@@ -863,7 +923,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if disabled, reset render_target size and position
if (!p_enable) {
RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
- RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
+ RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->view_count);
}
RSG::texture_storage->render_target_set_direct_to_screen(viewport->render_target, p_enable);
@@ -871,7 +931,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
- 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->get_view_count());
+ 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);
RSG::texture_storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}
@@ -1016,31 +1076,42 @@ void RendererViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas
viewport->canvas_map[p_canvas].sublayer = p_sublayer;
}
-void RendererViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) {
+void RendererViewport::viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
viewport->shadow_atlas_size = p_size;
viewport->shadow_atlas_16_bits = p_16_bits;
- RSG::scene->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size, viewport->shadow_atlas_16_bits);
+ RSG::light_storage->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size, viewport->shadow_atlas_16_bits);
+}
+
+void RendererViewport::viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
+ Viewport *viewport = viewport_owner.get_or_null(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ RSG::light_storage->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
}
-void RendererViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) {
+void RendererViewport::viewport_set_msaa_2d(RID p_viewport, RS::ViewportMSAA p_msaa) {
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
- RSG::scene->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv);
+ if (viewport->msaa_2d == p_msaa) {
+ return;
+ }
+ viewport->msaa_2d = p_msaa;
+ RSG::texture_storage->render_target_set_msaa(viewport->render_target, p_msaa);
}
-void RendererViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA 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 == p_msaa) {
+ if (viewport->msaa_3d == p_msaa) {
return;
}
- viewport->msaa = p_msaa;
+ viewport->msaa_3d = p_msaa;
_configure_3d_render_buffers(viewport);
}
@@ -1074,7 +1145,9 @@ void RendererViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_deb
return;
}
viewport->use_debanding = p_use_debanding;
- _configure_3d_render_buffers(viewport);
+ if (viewport->render_buffers.is_valid()) {
+ viewport->render_buffers->set_use_debanding(p_use_debanding);
+ }
}
void RendererViewport::viewport_set_use_occlusion_culling(RID p_viewport, bool p_use_occlusion_culling) {
@@ -1193,14 +1266,44 @@ void RendererViewport::viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::V
RSG::texture_storage->render_target_set_sdf_size_and_scale(viewport->render_target, p_size, p_scale);
}
+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();
+}
+
+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);
+}
+
bool RendererViewport::free(RID p_rid) {
if (viewport_owner.owns(p_rid)) {
Viewport *viewport = viewport_owner.get_or_null(p_rid);
RSG::texture_storage->render_target_free(viewport->render_target);
- RSG::scene->free(viewport->shadow_atlas);
+ RSG::light_storage->shadow_atlas_free(viewport->shadow_atlas);
if (viewport->render_buffers.is_valid()) {
- RSG::scene->free(viewport->render_buffers);
+ viewport->render_buffers.unref();
}
while (viewport->canvas_map.begin()) {
@@ -1209,6 +1312,7 @@ bool RendererViewport::free(RID p_rid) {
viewport_set_scenario(p_rid, RID());
active_viewports.erase(viewport);
+ sorted_active_viewports_dirty = true;
if (viewport->use_occlusion_culling) {
RendererSceneOcclusionCull::get_singleton()->remove_buffer(p_rid);
@@ -1245,7 +1349,13 @@ void RendererViewport::handle_timestamp(String p_timestamp, uint64_t p_cpu_time,
}
void RendererViewport::set_default_clear_color(const Color &p_color) {
- RSG::storage->set_default_clear_color(p_color);
+ RSG::texture_storage->set_default_clear_color(p_color);
+}
+
+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;
}
// Workaround for setting this on thread.
diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h
index 18385d1613..5e0c090ec0 100644
--- a/servers/rendering/renderer_viewport.h
+++ b/servers/rendering/renderer_viewport.h
@@ -34,10 +34,11 @@
#include "core/templates/local_vector.h"
#include "core/templates/rid_owner.h"
#include "core/templates/self_list.h"
-#include "servers/rendering/renderer_scene.h"
#include "servers/rendering/renderer_scene_render.h"
+#include "servers/rendering/rendering_method.h"
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
+#include "storage/render_scene_buffers.h"
class RendererViewport {
public:
@@ -48,33 +49,36 @@ public:
RID self;
RID parent;
- bool use_xr; /* use xr interface to override camera positioning and projection matrices and control output */
+ // use xr interface to override camera positioning and projection matrices and control output
+ bool use_xr = false;
Size2i internal_size;
Size2i size;
+ uint32_t view_count;
RID camera;
RID scenario;
- RS::ViewportScaling3DMode scaling_3d_mode;
+ RS::ViewportScaling3DMode scaling_3d_mode = RenderingServer::VIEWPORT_SCALING_3D_MODE_BILINEAR;
float scaling_3d_scale = 1.0;
float fsr_sharpness = 0.2f;
- float fsr_mipmap_bias = 0.0f;
- bool fsr_enabled;
- RS::ViewportUpdateMode update_mode;
+ float texture_mipmap_bias = 0.0f;
+ bool fsr_enabled = false;
+ RS::ViewportUpdateMode update_mode = RenderingServer::VIEWPORT_UPDATE_WHEN_VISIBLE;
RID render_target;
RID render_target_texture;
- RID render_buffers;
+ Ref<RenderSceneBuffers> render_buffers;
- RS::ViewportMSAA msaa;
- RS::ViewportScreenSpaceAA screen_space_aa;
- bool use_taa;
- bool use_debanding;
+ RS::ViewportMSAA msaa_2d = RenderingServer::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportMSAA msaa_3d = RenderingServer::VIEWPORT_MSAA_DISABLED;
+ RS::ViewportScreenSpaceAA screen_space_aa = RenderingServer::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
+ bool use_taa = false;
+ bool use_debanding = false;
RendererSceneRender::CameraData prev_camera_data;
uint64_t prev_camera_data_frame = 0;
- bool use_occlusion_culling;
- bool occlusion_buffer_dirty;
+ bool use_occlusion_culling = false;
+ bool occlusion_buffer_dirty = false;
DisplayServer::WindowID viewport_to_screen;
Rect2 viewport_to_screen_rect;
@@ -83,10 +87,10 @@ public:
bool disable_2d = false;
bool disable_environment = false;
bool disable_3d = false;
- bool measure_render_time;
+ bool measure_render_time = false;
- bool snap_2d_transforms_to_pixel;
- bool snap_2d_vertices_to_pixel;
+ bool snap_2d_transforms_to_pixel = false;
+ bool snap_2d_vertices_to_pixel = false;
uint64_t time_cpu_begin;
uint64_t time_cpu_end;
@@ -95,23 +99,25 @@ public:
uint64_t time_gpu_end;
RID shadow_atlas;
- int shadow_atlas_size;
+ int shadow_atlas_size = 2048;
bool shadow_atlas_16_bits = true;
- bool sdf_active;
+ bool sdf_active = false;
float mesh_lod_threshold = 1.0;
uint64_t last_pass = 0;
- RS::ViewportDebugDraw debug_draw;
+ RS::ViewportDebugDraw debug_draw = RenderingServer::VIEWPORT_DEBUG_DRAW_DISABLED;
- RS::ViewportClearMode clear_mode;
+ RS::ViewportClearMode clear_mode = RenderingServer::VIEWPORT_CLEAR_ALWAYS;
RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
- bool transparent_bg;
+ bool transparent_bg = false;
+
+ uint32_t canvas_cull_mask = 0xffffffff;
struct CanvasKey {
int64_t stacking;
@@ -144,9 +150,10 @@ public:
HashMap<RID, CanvasData> canvas_map;
- RendererScene::RenderInfo render_info;
+ RenderingMethod::RenderInfo render_info;
Viewport() {
+ view_count = 1;
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
transparent_bg = false;
@@ -156,7 +163,6 @@ public:
measure_render_time = false;
debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED;
- msaa = RS::VIEWPORT_MSAA_DISABLED;
screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED;
use_debanding = false;
use_occlusion_culling = false;
@@ -174,8 +180,6 @@ public:
time_gpu_begin = 0;
time_gpu_end = 0;
}
-
- uint32_t get_view_count();
};
HashMap<String, RID> timestamp_vp_map;
@@ -184,25 +188,17 @@ public:
mutable RID_Owner<Viewport, true> viewport_owner;
- struct ViewportSort {
- _FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const {
- bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2();
- bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2();
-
- if (left_to_screen == right_to_screen) {
- return p_right->parent == p_left->self;
- }
- return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1);
- }
- };
-
Vector<Viewport *> active_viewports;
+ Vector<Viewport *> sorted_active_viewports;
+ bool sorted_active_viewports_dirty = false;
int total_objects_drawn = 0;
int total_vertices_drawn = 0;
int total_draw_calls_used = 0;
private:
+ Vector<Viewport *> _sort_active_viewports();
+ void _viewport_set_size(Viewport *p_viewport, int p_width, int p_height, uint32_t p_view_count);
void _configure_3d_render_buffers(Viewport *p_viewport);
void _draw_3d(Viewport *p_viewport);
void _draw_viewport(Viewport *p_viewport);
@@ -228,7 +224,7 @@ public:
void viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode);
void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale);
void viewport_set_fsr_sharpness(RID p_viewport, float p_sharpness);
- void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_mipmap_bias);
+ void viewport_set_texture_mipmap_bias(RID p_viewport, float p_mipmap_bias);
void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode);
void viewport_set_vflip(RID p_viewport, bool p_enable);
@@ -255,10 +251,13 @@ public:
void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform);
void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer);
- void viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true);
- void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
+ void viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask);
+
+ void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true);
+ void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv);
- void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa);
+ void viewport_set_msaa_2d(RID p_viewport, RS::ViewportMSAA p_msaa);
+ void viewport_set_msaa_3d(RID p_viewport, RS::ViewportMSAA p_msaa);
void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode);
void viewport_set_use_taa(RID p_viewport, bool p_use_taa);
void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding);
@@ -282,6 +281,11 @@ public:
void viewport_set_sdf_oversize_and_scale(RID p_viewport, RS::ViewportSDFOversize p_over_size, RS::ViewportSDFScale p_scale);
+ virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const;
+
+ void viewport_set_vrs_mode(RID p_viewport, RS::ViewportVRSMode p_mode);
+ void viewport_set_vrs_texture(RID p_viewport, RID p_texture);
+
void handle_timestamp(String p_timestamp, uint64_t p_cpu_time, uint64_t p_gpu_time);
void set_default_clear_color(const Color &p_color);
diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp
index 6fc5d0b3e8..bb4c41df52 100644
--- a/servers/rendering/rendering_device.cpp
+++ b/servers/rendering/rendering_device.cpp
@@ -64,12 +64,12 @@ Vector<uint8_t> RenderingDevice::shader_compile_spirv_from_source(ShaderStage p_
ERR_FAIL_COND_V(!compile_to_spirv_function, Vector<uint8_t>());
- return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, &device_capabilities);
+ return compile_to_spirv_function(p_stage, p_source_code, p_language, r_error, this);
}
String RenderingDevice::shader_get_spirv_cache_key() const {
if (get_spirv_cache_key_function) {
- return get_spirv_cache_key_function(&device_capabilities);
+ return get_spirv_cache_key_function(this);
}
return String();
}
@@ -235,7 +235,7 @@ RID RenderingDevice::_shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv
return shader_create_from_spirv(stage_data);
}
-RID RenderingDevice::_uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set) {
+RID RenderingDevice::_uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) {
Vector<Uniform> uniforms;
uniforms.resize(p_uniforms.size());
for (int i = 0; i < p_uniforms.size(); i++) {
@@ -279,6 +279,7 @@ static Vector<RenderingDevice::PipelineSpecializationConstant> _get_spec_constan
}
return ret;
}
+
RID RenderingDevice::_render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const Ref<RDPipelineRasterizationState> &p_rasterization_state, const Ref<RDPipelineMultisampleState> &p_multisample_state, const Ref<RDPipelineDepthStencilState> &p_depth_stencil_state, const Ref<RDPipelineColorBlendState> &p_blend_state, int p_dynamic_state_flags, uint32_t p_for_render_pass, const TypedArray<RDPipelineSpecializationConstant> &p_specialization_constants) {
PipelineRasterizationState rasterization_state;
if (p_rasterization_state.is_valid()) {
@@ -386,11 +387,13 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("framebuffer_create_multipass", "textures", "passes", "validate_with_format", "view_count"), &RenderingDevice::_framebuffer_create_multipass, DEFVAL(INVALID_FORMAT_ID), DEFVAL(1));
ClassDB::bind_method(D_METHOD("framebuffer_create_empty", "size", "samples", "validate_with_format"), &RenderingDevice::framebuffer_create_empty, DEFVAL(TEXTURE_SAMPLES_1), DEFVAL(INVALID_FORMAT_ID));
ClassDB::bind_method(D_METHOD("framebuffer_get_format", "framebuffer"), &RenderingDevice::framebuffer_get_format);
+ ClassDB::bind_method(D_METHOD("framebuffer_is_valid", "framebuffer"), &RenderingDevice::framebuffer_is_valid);
ClassDB::bind_method(D_METHOD("sampler_create", "state"), &RenderingDevice::_sampler_create);
ClassDB::bind_method(D_METHOD("vertex_buffer_create", "size_bytes", "data", "use_as_storage"), &RenderingDevice::vertex_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("vertex_format_create", "vertex_descriptions"), &RenderingDevice::_vertex_format_create);
+ ClassDB::bind_method(D_METHOD("vertex_array_create", "vertex_count", "vertex_format", "src_buffers"), &RenderingDevice::_vertex_array_create);
ClassDB::bind_method(D_METHOD("index_buffer_create", "size_indices", "format", "data", "use_restart_indices"), &RenderingDevice::index_buffer_create, DEFVAL(Vector<uint8_t>()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("index_array_create", "index_buffer", "index_offset", "index_count"), &RenderingDevice::index_array_create);
@@ -427,6 +430,7 @@ void RenderingDevice::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>()));
+ ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants);
ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline);
ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set);
ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array);
@@ -971,6 +975,8 @@ void RenderingDevice::_bind_methods() {
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X);
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y);
BIND_ENUM_CONSTANT(LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_VIEWPORT_DIMENSIONS_X);
+ BIND_ENUM_CONSTANT(LIMIT_MAX_VIEWPORT_DIMENSIONS_Y);
BIND_ENUM_CONSTANT(MEMORY_TEXTURES);
BIND_ENUM_CONSTANT(MEMORY_BUFFERS);
diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h
index 0973e29974..d0b85d8220 100644
--- a/servers/rendering/rendering_device.h
+++ b/servers/rendering/rendering_device.h
@@ -42,7 +42,7 @@ class RDSamplerState;
class RDVertexAttribute;
class RDShaderSource;
class RDShaderSPIRV;
-class RDUniforms;
+class RDUniform;
class RDPipelineRasterizationState;
class RDPipelineMultisampleState;
class RDPipelineDepthStencilState;
@@ -123,21 +123,14 @@ public:
DeviceFamily device_family = DEVICE_UNKNOWN;
uint32_t version_major = 1.0;
uint32_t version_minor = 0.0;
-
- // subgroup capabilities
- uint32_t subgroup_size = 0;
- uint32_t subgroup_in_shaders = 0; // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
- uint32_t subgroup_operations = 0; // Set flags, using SubgroupOperations
-
- // features
- bool supports_multiview = false; // If true this device supports multiview options
- bool supports_fsr_half_float = false; // If true this device supports FSR scaling 3D in half float mode, otherwise use the fallback mode
};
- typedef String (*ShaderSPIRVGetCacheKeyFunction)(const Capabilities *p_capabilities);
- typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const Capabilities *p_capabilities);
+ typedef String (*ShaderSPIRVGetCacheKeyFunction)(const RenderingDevice *p_render_device);
+ typedef Vector<uint8_t> (*ShaderCompileToSPIRVFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, const RenderingDevice *p_render_device);
typedef Vector<uint8_t> (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language);
+ typedef void (*InvalidationCallback)(void *);
+
private:
static ShaderCompileToSPIRVFunction compile_to_spirv_function;
static ShaderCacheFunction cache_function;
@@ -444,6 +437,7 @@ public:
TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7),
TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8),
TEXTURE_USAGE_INPUT_ATTACHMENT_BIT = (1 << 9),
+ TEXTURE_USAGE_VRS_ATTACHMENT_BIT = (1 << 10),
};
enum TextureSwizzle {
@@ -468,6 +462,33 @@ public:
TextureSamples samples;
uint32_t usage_bits;
Vector<DataFormat> shareable_formats;
+ bool is_resolve_buffer = false;
+
+ bool operator==(const TextureFormat &b) const {
+ if (format != b.format) {
+ return false;
+ } else if (width != b.width) {
+ return false;
+ } else if (height != b.height) {
+ return false;
+ } else if (depth != b.depth) {
+ return false;
+ } else if (array_layers != b.array_layers) {
+ return false;
+ } else if (mipmaps != b.mipmaps) {
+ return false;
+ } else if (texture_type != b.texture_type) {
+ return false;
+ } else if (samples != b.samples) {
+ return false;
+ } else if (usage_bits != b.usage_bits) {
+ return false;
+ } else if (shareable_formats != b.shareable_formats) {
+ return false;
+ } else {
+ return true;
+ }
+ }
TextureFormat() {
format = DATA_FORMAT_R8_UNORM;
@@ -552,15 +573,18 @@ public:
Vector<int32_t> resolve_attachments;
Vector<int32_t> preserve_attachments;
int32_t depth_attachment = ATTACHMENT_UNUSED;
+ int32_t vrs_attachment = ATTACHMENT_UNUSED; // density map for VRS, only used if supported
};
- virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
+ virtual FramebufferFormatID framebuffer_format_create_multipass(const Vector<AttachmentFormat> &p_attachments, const Vector<FramebufferPass> &p_passes, uint32_t p_view_count = 1) = 0;
virtual FramebufferFormatID framebuffer_format_create_empty(TextureSamples p_samples = TEXTURE_SAMPLES_1) = 0;
virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format, uint32_t p_pass = 0) = 0;
virtual RID framebuffer_create(const Vector<RID> &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
- virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
+ virtual RID framebuffer_create_multipass(const Vector<RID> &p_texture_attachments, const Vector<FramebufferPass> &p_passes, FramebufferFormatID p_format_check = INVALID_ID, uint32_t p_view_count = 1) = 0;
virtual RID framebuffer_create_empty(const Size2i &p_size, TextureSamples p_samples = TEXTURE_SAMPLES_1, FramebufferFormatID p_format_check = INVALID_ID) = 0;
+ virtual bool framebuffer_is_valid(RID p_framebuffer) const = 0;
+ virtual void framebuffer_set_invalidation_callback(RID p_framebuffer, InvalidationCallback p_callback, void *p_userdata) = 0;
virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0;
@@ -675,6 +699,13 @@ public:
const Capabilities *get_device_capabilities() const { return &device_capabilities; };
+ enum Features {
+ SUPPORTS_MULTIVIEW,
+ SUPPORTS_FSR_HALF_FLOAT,
+ SUPPORTS_ATTACHMENT_VRS,
+ };
+ virtual bool has_feature(const Features p_feature) const = 0;
+
virtual Vector<uint8_t> shader_compile_spirv_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = nullptr, bool p_allow_cache = true);
virtual String shader_get_spirv_cache_key() const;
@@ -793,8 +824,7 @@ public:
virtual RID uniform_set_create(const Vector<Uniform> &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0;
virtual bool uniform_set_is_valid(RID p_uniform_set) = 0;
- typedef void (*UniformSetInvalidatedCallback)(void *);
- virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, UniformSetInvalidatedCallback p_callback, void *p_userdata) = 0;
+ virtual void uniform_set_set_invalidation_callback(RID p_uniform_set, InvalidationCallback p_callback, void *p_userdata) = 0;
virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
virtual Error buffer_clear(RID p_buffer, uint32_t p_offset, uint32_t p_size, uint32_t p_post_barrier = BARRIER_MASK_ALL) = 0;
@@ -928,7 +958,7 @@ public:
bool wireframe;
PolygonCullMode cull_mode;
PolygonFrontFace front_face;
- bool depth_bias_enable;
+ bool depth_bias_enabled;
float depth_bias_constant_factor;
float depth_bias_clamp;
float depth_bias_slope_factor;
@@ -940,7 +970,7 @@ public:
wireframe = false;
cull_mode = POLYGON_CULL_DISABLED;
front_face = POLYGON_FRONT_FACE_CLOCKWISE;
- depth_bias_enable = false;
+ depth_bias_enabled = false;
depth_bias_constant_factor = 0;
depth_bias_clamp = 0;
depth_bias_slope_factor = 0;
@@ -1126,6 +1156,7 @@ public:
virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0;
+ virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) = 0;
virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0;
virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0;
virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0;
@@ -1221,9 +1252,14 @@ public:
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X,
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y,
LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z,
+ LIMIT_MAX_VIEWPORT_DIMENSIONS_X,
+ LIMIT_MAX_VIEWPORT_DIMENSIONS_Y,
+ LIMIT_SUBGROUP_SIZE,
+ LIMIT_SUBGROUP_IN_SHADERS, // Set flags using SHADER_STAGE_VERTEX_BIT, SHADER_STAGE_FRAGMENT_BIT, etc.
+ LIMIT_SUBGROUP_OPERATIONS,
};
- virtual uint64_t limit_get(Limit p_limit) = 0;
+ virtual uint64_t limit_get(Limit p_limit) const = 0;
//methods below not exposed, used by RenderingDeviceRD
virtual void prepare_screen_for_drawing() = 0;
@@ -1280,7 +1316,7 @@ protected:
Vector<uint8_t> _shader_compile_binary_from_spirv(const Ref<RDShaderSPIRV> &p_bytecode, const String &p_shader_name = "");
RID _shader_create_from_spirv(const Ref<RDShaderSPIRV> &p_spirv, const String &p_shader_name = "");
- RID _uniform_set_create(const Array &p_uniforms, RID p_shader, uint32_t p_shader_set);
+ RID _uniform_set_create(const TypedArray<RDUniform> &p_uniforms, RID p_shader, uint32_t p_shader_set);
Error _buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const Vector<uint8_t> &p_data, uint32_t p_post_barrier = BARRIER_MASK_ALL);
@@ -1324,6 +1360,7 @@ VARIANT_ENUM_CAST(RenderingDevice::InitialAction)
VARIANT_ENUM_CAST(RenderingDevice::FinalAction)
VARIANT_ENUM_CAST(RenderingDevice::Limit)
VARIANT_ENUM_CAST(RenderingDevice::MemoryType)
+VARIANT_ENUM_CAST(RenderingDevice::Features)
typedef RenderingDevice RD;
diff --git a/servers/rendering/rendering_device_binds.h b/servers/rendering/rendering_device_binds.h
index 8bdd3deea1..c710bd0a10 100644
--- a/servers/rendering/rendering_device_binds.h
+++ b/servers/rendering/rendering_device_binds.h
@@ -407,10 +407,10 @@ protected:
List<Variant> keys;
p_versions.get_key_list(&keys);
for (const Variant &E : keys) {
- StringName name = E;
+ StringName vname = E;
Ref<RDShaderSPIRV> bc = p_versions[E];
ERR_CONTINUE(bc.is_null());
- versions[name] = bc;
+ versions[vname] = bc;
}
emit_changed();
@@ -443,8 +443,8 @@ public:
void add_id(const RID &p_id) { base.append_id(p_id); }
void clear_ids() { base.clear_ids(); }
- Array get_ids() const {
- Array ids;
+ TypedArray<RID> get_ids() const {
+ TypedArray<RID> ids;
for (uint32_t i = 0; i < base.get_id_count(); i++) {
ids.push_back(base.get_id(i));
}
@@ -452,7 +452,7 @@ public:
}
protected:
- void _set_ids(const Array &p_ids) {
+ void _set_ids(const TypedArray<RID> &p_ids) {
base.clear_ids();
for (int i = 0; i < p_ids.size(); i++) {
RID id = p_ids[i];
@@ -517,7 +517,7 @@ public:
RD_SETGET(bool, wireframe)
RD_SETGET(RD::PolygonCullMode, cull_mode)
RD_SETGET(RD::PolygonFrontFace, front_face)
- RD_SETGET(bool, depth_bias_enable)
+ RD_SETGET(bool, depth_bias_enabled)
RD_SETGET(float, depth_bias_constant_factor)
RD_SETGET(float, depth_bias_clamp)
RD_SETGET(float, depth_bias_slope_factor)
@@ -531,7 +531,7 @@ protected:
RD_BIND(Variant::BOOL, RDPipelineRasterizationState, wireframe);
RD_BIND(Variant::INT, RDPipelineRasterizationState, cull_mode);
RD_BIND(Variant::INT, RDPipelineRasterizationState, front_face);
- RD_BIND(Variant::BOOL, RDPipelineRasterizationState, depth_bias_enable);
+ RD_BIND(Variant::BOOL, RDPipelineRasterizationState, depth_bias_enabled);
RD_BIND(Variant::FLOAT, RDPipelineRasterizationState, depth_bias_constant_factor);
RD_BIND(Variant::FLOAT, RDPipelineRasterizationState, depth_bias_clamp);
RD_BIND(Variant::FLOAT, RDPipelineRasterizationState, depth_bias_slope_factor);
diff --git a/servers/rendering/renderer_scene.cpp b/servers/rendering/rendering_method.cpp
index b3fdd88626..16a4e35ad3 100644
--- a/servers/rendering/renderer_scene.cpp
+++ b/servers/rendering/rendering_method.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene.cpp */
+/* rendering_method.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,10 +28,10 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_scene.h"
+#include "rendering_method.h"
-RendererScene::RendererScene() {
+RenderingMethod::RenderingMethod() {
}
-RendererScene::~RendererScene() {
+RenderingMethod::~RenderingMethod() {
}
diff --git a/servers/rendering/renderer_scene.h b/servers/rendering/rendering_method.h
index b773ed61f4..c4d9e25ecd 100644
--- a/servers/rendering/renderer_scene.h
+++ b/servers/rendering/rendering_method.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_scene.h */
+/* rendering_method.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,13 +28,14 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef RENDERINGSERVERSCENE_H
-#define RENDERINGSERVERSCENE_H
+#ifndef RENDERING_METHOD_H
+#define RENDERING_METHOD_H
+#include "servers/rendering/storage/render_scene_buffers.h"
#include "servers/rendering_server.h"
#include "servers/xr/xr_interface.h"
-class RendererScene {
+class RenderingMethod {
public:
virtual RID camera_allocate() = 0;
virtual void camera_initialize(RID p_rid) = 0;
@@ -45,7 +46,7 @@ public:
virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
- virtual void camera_set_camera_effects(RID p_camera, RID p_fx) = 0;
+ virtual void camera_set_camera_attributes(RID p_camera, RID p_attributes) = 0;
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
virtual bool is_camera(RID p_camera) const = 0;
@@ -57,7 +58,7 @@ public:
virtual void scenario_initialize(RID p_rid) = 0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
- virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx) = 0;
+ virtual void scenario_set_camera_attributes(RID p_scenario, RID p_attributes) = 0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) = 0;
virtual bool is_scenario(RID p_scenario) const = 0;
@@ -105,8 +106,6 @@ public:
virtual Variant instance_geometry_get_shader_parameter(RID p_instance, const StringName &p_parameter) const = 0;
virtual Variant instance_geometry_get_shader_parameter_default_value(RID p_instance, const StringName &p_parameter) const = 0;
- virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
-
/* SKY API */
virtual RID sky_allocate() = 0;
@@ -122,96 +121,187 @@ public:
virtual RID environment_allocate() = 0;
virtual void environment_initialize(RID p_rid) = 0;
+ // Background
virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0;
virtual void environment_set_sky(RID p_env, RID p_sky) = 0;
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
- virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
+ virtual void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG) = 0;
+ virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0;
+ virtual RID environment_get_sky(RID p_env) const = 0;
+ virtual float environment_get_sky_custom_fov(RID p_env) const = 0;
+ virtual Basis environment_get_sky_orientation(RID p_env) const = 0;
+ virtual Color environment_get_bg_color(RID p_env) const = 0;
+ virtual float environment_get_bg_energy_multiplier(RID p_env) const = 0;
+ virtual float environment_get_bg_intensity(RID p_env) const = 0;
+ virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
+ virtual RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const = 0;
+ virtual Color environment_get_ambient_light(RID p_env) const = 0;
+ virtual float environment_get_ambient_light_energy(RID p_env) const = 0;
+ virtual float environment_get_ambient_sky_contribution(RID p_env) const = 0;
+ virtual RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const = 0;
+
+ // Tonemap
+ virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) = 0;
+
+ virtual RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const = 0;
+ virtual float environment_get_exposure(RID p_env) const = 0;
+ virtual float environment_get_white(RID p_env) const = 0;
+
+ // Fog
+ virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) = 0;
+
+ virtual bool environment_get_fog_enabled(RID p_env) const = 0;
+ virtual Color environment_get_fog_light_color(RID p_env) const = 0;
+ virtual float environment_get_fog_light_energy(RID p_env) const = 0;
+ virtual float environment_get_fog_sun_scatter(RID p_env) const = 0;
+ virtual float environment_get_fog_density(RID p_env) const = 0;
+ virtual float environment_get_fog_height(RID p_env) const = 0;
+ virtual float environment_get_fog_height_density(RID p_env) const = 0;
+ virtual float environment_get_fog_aerial_perspective(RID p_env) const = 0;
+ virtual float environment_get_fog_sky_affect(RID p_env) const = 0;
+
+ // Volumetric Fog
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0;
+
+ virtual bool environment_get_volumetric_fog_enabled(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_density(RID p_env) const = 0;
+ virtual Color environment_get_volumetric_fog_scattering(RID p_env) const = 0;
+ virtual Color environment_get_volumetric_fog_emission(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_emission_energy(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_anisotropy(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_length(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_detail_spread(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_gi_inject(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_sky_affect(RID p_env) const = 0;
+ virtual bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const = 0;
+ virtual float environment_get_volumetric_fog_ambient_inject(RID p_env) const = 0;
+
+ virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
+ virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
+
+ // Glow
+
virtual void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) = 0;
+
+ virtual bool environment_get_glow_enabled(RID p_env) const = 0;
+ virtual Vector<float> environment_get_glow_levels(RID p_env) const = 0;
+ virtual float environment_get_glow_intensity(RID p_env) const = 0;
+ virtual float environment_get_glow_strength(RID p_env) const = 0;
+ virtual float environment_get_glow_bloom(RID p_env) const = 0;
+ virtual float environment_get_glow_mix(RID p_env) const = 0;
+ virtual RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const = 0;
+ virtual float environment_get_glow_hdr_bleed_threshold(RID p_env) const = 0;
+ virtual float environment_get_glow_hdr_luminance_cap(RID p_env) const = 0;
+ virtual float environment_get_glow_hdr_bleed_scale(RID p_env) const = 0;
+ virtual float environment_get_glow_map_strength(RID p_env) const = 0;
+ virtual RID environment_get_glow_map(RID p_env) const = 0;
+
virtual void environment_glow_set_use_bicubic_upscale(bool p_enable) = 0;
virtual void environment_glow_set_use_high_quality(bool p_enable) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
-
- virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
- virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
+ // SSR
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) = 0;
+
+ virtual bool environment_get_ssr_enabled(RID p_env) const = 0;
+ virtual int environment_get_ssr_max_steps(RID p_env) const = 0;
+ virtual float environment_get_ssr_fade_in(RID p_env) const = 0;
+ virtual float environment_get_ssr_fade_out(RID p_env) const = 0;
+ virtual float environment_get_ssr_depth_tolerance(RID p_env) const = 0;
+
virtual void environment_set_ssr_roughness_quality(RS::EnvironmentSSRRoughnessQuality p_quality) = 0;
+ // SSAO
virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) = 0;
+
+ virtual bool environment_get_ssao_enabled(RID p_env) const = 0;
+ virtual float environment_get_ssao_radius(RID p_env) const = 0;
+ virtual float environment_get_ssao_intensity(RID p_env) const = 0;
+ virtual float environment_get_ssao_power(RID p_env) const = 0;
+ virtual float environment_get_ssao_detail(RID p_env) const = 0;
+ virtual float environment_get_ssao_horizon(RID p_env) const = 0;
+ virtual float environment_get_ssao_sharpness(RID p_env) const = 0;
+ virtual float environment_get_ssao_direct_light_affect(RID p_env) const = 0;
+ virtual float environment_get_ssao_ao_channel_affect(RID p_env) const = 0;
+
virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
+ // SSIL
+
virtual void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) = 0;
+
+ virtual bool environment_get_ssil_enabled(RID p_env) const = 0;
+ virtual float environment_get_ssil_radius(RID p_env) const = 0;
+ virtual float environment_get_ssil_intensity(RID p_env) const = 0;
+ virtual float environment_get_ssil_sharpness(RID p_env) const = 0;
+ virtual float environment_get_ssil_normal_rejection(RID p_env) const = 0;
+
virtual void environment_set_ssil_quality(RS::EnvironmentSSILQuality p_quality, bool p_half_size, float p_adaptive_target, int p_blur_passes, float p_fadeout_from, float p_fadeout_to) = 0;
+ // SDFGI
virtual void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) = 0;
+ virtual bool environment_get_sdfgi_enabled(RID p_env) const = 0;
+ virtual int environment_get_sdfgi_cascades(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_min_cell_size(RID p_env) const = 0;
+ virtual bool environment_get_sdfgi_use_occlusion(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_bounce_feedback(RID p_env) const = 0;
+ virtual bool environment_get_sdfgi_read_sky_light(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_energy(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_normal_bias(RID p_env) const = 0;
+ virtual float environment_get_sdfgi_probe_bias(RID p_env) const = 0;
+ virtual RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const = 0;
+
virtual void environment_set_sdfgi_ray_count(RS::EnvironmentSDFGIRayCount p_ray_count) = 0;
virtual void environment_set_sdfgi_frames_to_converge(RS::EnvironmentSDFGIFramesToConverge p_frames) = 0;
virtual void environment_set_sdfgi_frames_to_update_light(RS::EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
- virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0;
-
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
+ virtual bool environment_get_adjustments_enabled(RID p_env) const = 0;
+ virtual float environment_get_adjustments_brightness(RID p_env) const = 0;
+ virtual float environment_get_adjustments_contrast(RID p_env) const = 0;
+ virtual float environment_get_adjustments_saturation(RID p_env) const = 0;
+ virtual bool environment_get_use_1d_color_correction(RID p_env) const = 0;
+ virtual RID environment_get_color_correction(RID p_env) const = 0;
virtual Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0;
- virtual RS::EnvironmentBG environment_get_background(RID p_Env) const = 0;
- virtual int environment_get_canvas_max_layer(RID p_env) const = 0;
-
virtual bool is_environment(RID p_environment) const = 0;
virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0;
virtual void sub_surface_scattering_set_quality(RS::SubSurfaceScatteringQuality p_quality) = 0;
virtual void sub_surface_scattering_set_scale(float p_scale, float p_depth_scale) = 0;
- /* Camera Effects */
-
- virtual RID camera_effects_allocate() = 0;
- virtual void camera_effects_initialize(RID p_rid) = 0;
-
- virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0;
- virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0;
-
- virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
- virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
-
- virtual void shadows_quality_set(RS::ShadowQuality p_quality) = 0;
- virtual void directional_shadow_quality_set(RS::ShadowQuality p_quality) = 0;
-
- virtual RID shadow_atlas_create() = 0;
- virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0;
- virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
+ virtual void positional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
+ virtual void directional_soft_shadow_filter_set_quality(RS::ShadowQuality p_quality) = 0;
/* Render Buffers */
- virtual RID render_buffers_create() = 0;
-
- virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_internal_width, int p_internal_height, int p_width, int p_height, float p_fsr_sharpness, float p_fsr_mipmap_bias, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) = 0;
+ virtual Ref<RenderSceneBuffers> render_buffers_create() = 0;
virtual void gi_set_use_half_resolution(bool p_enable) = 0;
virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0;
- virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
virtual void voxel_gi_set_quality(RS::VoxelGIQuality) = 0;
virtual void sdfgi_set_debug_probe_select(const Vector3 &p_position, const Vector3 &p_dir) = 0;
- virtual void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
+ virtual void render_empty_scene(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_scenario, RID p_shadow_atlas) = 0;
struct RenderInfo {
int info[RS::VIEWPORT_RENDER_INFO_TYPE_MAX][RS::VIEWPORT_RENDER_INFO_MAX] = {};
};
- virtual void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
+ virtual void render_camera(const Ref<RenderSceneBuffers> &p_render_buffers, RID p_camera, RID p_scenario, RID p_viewport, Size2 p_viewport_size, bool p_use_taa, float p_mesh_lod_threshold, RID p_shadow_atlas, Ref<XRInterface> &p_xr_interface, RenderInfo *r_render_info = nullptr) = 0;
virtual void update() = 0;
virtual void render_probes() = 0;
@@ -222,8 +312,8 @@ public:
virtual bool free(RID p_rid) = 0;
- RendererScene();
- virtual ~RendererScene();
+ RenderingMethod();
+ virtual ~RenderingMethod();
};
-#endif // RENDERINGSERVERSCENE_H
+#endif // RENDERING_METHOD_H
diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp
index 718f20f80a..c0cd564308 100644
--- a/servers/rendering/rendering_server_default.cpp
+++ b/servers/rendering/rendering_server_default.cpp
@@ -48,7 +48,7 @@ void RenderingServerDefault::_free(RID p_rid) {
if (unlikely(p_rid.is_null())) {
return;
}
- if (RSG::storage->free(p_rid)) {
+ if (RSG::utilities->free(p_rid)) {
return;
}
if (RSG::canvas->free(p_rid)) {
@@ -91,7 +91,10 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::viewport->draw_viewports();
RSG::canvas_render->update();
- RSG::rasterizer->end_frame(p_swap_buffers);
+ if (OS::get_singleton()->get_current_rendering_driver_name() != "opengl3") {
+ // Already called for gl_compatibility renderer.
+ RSG::rasterizer->end_frame(p_swap_buffers);
+ }
XRServer *xr_server = XRServer::get_singleton();
if (xr_server != nullptr) {
@@ -106,7 +109,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
Callable c = frame_drawn_callbacks.front()->get();
Variant result;
Callable::CallError ce;
- c.call(nullptr, 0, result, ce);
+ c.callp(nullptr, 0, result, ce);
if (ce.error != Callable::CallError::CALL_OK) {
String err = Variant::get_callable_error_text(c, nullptr, 0, ce);
ERR_PRINT("Error calling frame drawn function: " + err);
@@ -116,35 +119,35 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
}
RS::get_singleton()->emit_signal(SNAME("frame_post_draw"));
- if (RSG::storage->get_captured_timestamps_count()) {
+ if (RSG::utilities->get_captured_timestamps_count()) {
Vector<FrameProfileArea> new_profile;
- if (RSG::storage->capturing_timestamps) {
- new_profile.resize(RSG::storage->get_captured_timestamps_count());
+ if (RSG::utilities->capturing_timestamps) {
+ new_profile.resize(RSG::utilities->get_captured_timestamps_count());
}
- uint64_t base_cpu = RSG::storage->get_captured_timestamp_cpu_time(0);
- uint64_t base_gpu = RSG::storage->get_captured_timestamp_gpu_time(0);
- for (uint32_t i = 0; i < RSG::storage->get_captured_timestamps_count(); i++) {
- uint64_t time_cpu = RSG::storage->get_captured_timestamp_cpu_time(i);
- uint64_t time_gpu = RSG::storage->get_captured_timestamp_gpu_time(i);
+ uint64_t base_cpu = RSG::utilities->get_captured_timestamp_cpu_time(0);
+ uint64_t base_gpu = RSG::utilities->get_captured_timestamp_gpu_time(0);
+ for (uint32_t i = 0; i < RSG::utilities->get_captured_timestamps_count(); i++) {
+ uint64_t time_cpu = RSG::utilities->get_captured_timestamp_cpu_time(i);
+ uint64_t time_gpu = RSG::utilities->get_captured_timestamp_gpu_time(i);
- String name = RSG::storage->get_captured_timestamp_name(i);
+ String name = RSG::utilities->get_captured_timestamp_name(i);
if (name.begins_with("vp_")) {
RSG::viewport->handle_timestamp(name, time_cpu, time_gpu);
}
- if (RSG::storage->capturing_timestamps) {
+ if (RSG::utilities->capturing_timestamps) {
new_profile.write[i].gpu_msec = double((time_gpu - base_gpu) / 1000) / 1000.0;
new_profile.write[i].cpu_msec = double(time_cpu - base_cpu) / 1000.0;
- new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i);
+ new_profile.write[i].name = RSG::utilities->get_captured_timestamp_name(i);
}
}
frame_profile = new_profile;
}
- frame_profile_frame = RSG::storage->get_captured_timestamps_frame();
+ frame_profile_frame = RSG::utilities->get_captured_timestamps_frame();
if (print_gpu_profile) {
if (print_frame_profile_ticks_from == 0) {
@@ -191,7 +194,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
}
}
- RSG::storage->update_memory_info();
+ RSG::utilities->update_memory_info();
}
double RenderingServerDefault::get_frame_setup_time_cpu() const {
@@ -250,27 +253,27 @@ uint64_t RenderingServerDefault::get_rendering_info(RenderingInfo p_info) {
} else if (p_info == RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME) {
return RSG::viewport->get_total_draw_calls_used();
}
- return RSG::storage->get_rendering_info(p_info);
+ return RSG::utilities->get_rendering_info(p_info);
}
String RenderingServerDefault::get_video_adapter_name() const {
- return RSG::storage->get_video_adapter_name();
+ return RSG::utilities->get_video_adapter_name();
}
String RenderingServerDefault::get_video_adapter_vendor() const {
- return RSG::storage->get_video_adapter_vendor();
+ return RSG::utilities->get_video_adapter_vendor();
}
RenderingDevice::DeviceType RenderingServerDefault::get_video_adapter_type() const {
- return RSG::storage->get_video_adapter_type();
+ return RSG::utilities->get_video_adapter_type();
}
String RenderingServerDefault::get_video_adapter_api_version() const {
- return RSG::storage->get_video_adapter_api_version();
+ return RSG::utilities->get_video_adapter_api_version();
}
void RenderingServerDefault::set_frame_profiling_enabled(bool p_enable) {
- RSG::storage->capturing_timestamps = p_enable;
+ RSG::utilities->capturing_timestamps = p_enable;
}
uint64_t RenderingServerDefault::get_frame_profile_frame() {
@@ -301,7 +304,7 @@ void RenderingServerDefault::sdfgi_set_debug_probe_select(const Vector3 &p_posit
}
void RenderingServerDefault::set_print_gpu_profile(bool p_enable) {
- RSG::storage->capturing_timestamps = p_enable;
+ RSG::utilities->capturing_timestamps = p_enable;
print_gpu_profile = p_enable;
}
@@ -313,33 +316,38 @@ RID RenderingServerDefault::get_test_cube() {
}
bool RenderingServerDefault::has_os_feature(const String &p_feature) const {
- if (RSG::storage) {
- return RSG::storage->has_os_feature(p_feature);
+ if (RSG::utilities) {
+ return RSG::utilities->has_os_feature(p_feature);
} else {
return false;
}
}
void RenderingServerDefault::set_debug_generate_wireframes(bool p_generate) {
- RSG::storage->set_debug_generate_wireframes(p_generate);
+ RSG::utilities->set_debug_generate_wireframes(p_generate);
}
bool RenderingServerDefault::is_low_end() const {
return RendererCompositor::is_low_end();
}
+Size2i RenderingServerDefault::get_maximum_viewport_size() const {
+ if (RSG::utilities) {
+ return RSG::utilities->get_maximum_viewport_size();
+ } else {
+ return Size2i();
+ }
+}
+
void RenderingServerDefault::_thread_exit() {
exit.set();
}
void RenderingServerDefault::_thread_draw(bool p_swap_buffers, double frame_step) {
- if (!draw_pending.decrement()) {
- _draw(p_swap_buffers, frame_step);
- }
+ _draw(p_swap_buffers, frame_step);
}
void RenderingServerDefault::_thread_flush() {
- draw_pending.decrement();
}
void RenderingServerDefault::_thread_callback(void *_instance) {
@@ -370,7 +378,6 @@ void RenderingServerDefault::_thread_loop() {
void RenderingServerDefault::sync() {
if (create_thread) {
- draw_pending.increment();
command_queue.push_and_sync(this, &RenderingServerDefault::_thread_flush);
} else {
command_queue.flush_all(); //flush all pending from other threads
@@ -379,7 +386,6 @@ void RenderingServerDefault::sync() {
void RenderingServerDefault::draw(bool p_swap_buffers, double frame_step) {
if (create_thread) {
- draw_pending.increment();
command_queue.push(this, &RenderingServerDefault::_thread_draw, p_swap_buffers, frame_step);
} else {
_draw(p_swap_buffers, frame_step);
@@ -402,14 +408,17 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) :
RSG::canvas = memnew(RendererCanvasCull);
RSG::viewport = memnew(RendererViewport);
RendererSceneCull *sr = memnew(RendererSceneCull);
+ RSG::camera_attributes = memnew(RendererCameraAttributes);
RSG::scene = sr;
RSG::rasterizer = RendererCompositor::create();
+ RSG::utilities = RSG::rasterizer->get_utilities();
RSG::light_storage = RSG::rasterizer->get_light_storage();
RSG::material_storage = RSG::rasterizer->get_material_storage();
RSG::mesh_storage = RSG::rasterizer->get_mesh_storage();
RSG::particles_storage = RSG::rasterizer->get_particles_storage();
RSG::texture_storage = RSG::rasterizer->get_texture_storage();
- RSG::storage = RSG::rasterizer->get_storage();
+ RSG::gi = RSG::rasterizer->get_gi();
+ RSG::fog = RSG::rasterizer->get_fog();
RSG::canvas_render = RSG::rasterizer->get_canvas();
sr->set_scene_render(RSG::rasterizer->get_scene());
@@ -421,4 +430,5 @@ RenderingServerDefault::~RenderingServerDefault() {
memdelete(RSG::viewport);
memdelete(RSG::rasterizer);
memdelete(RSG::scene);
+ memdelete(RSG::camera_attributes);
}
diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h
index 6008f2b00e..b77b95bb62 100644
--- a/servers/rendering/rendering_server_default.h
+++ b/servers/rendering/rendering_server_default.h
@@ -31,7 +31,6 @@
#ifndef RENDERING_SERVER_DEFAULT_H
#define RENDERING_SERVER_DEFAULT_H
-#include "core/math/octree.h"
#include "core/templates/command_queue_mt.h"
#include "core/templates/hash_map.h"
#include "renderer_canvas_cull.h"
@@ -84,7 +83,6 @@ class RenderingServerDefault : public RenderingServer {
SafeFlag draw_thread_up;
bool create_thread;
- SafeNumeric<uint64_t> draw_pending;
void _thread_draw(bool p_swap_buffers, double frame_step);
void _thread_flush();
@@ -214,6 +212,7 @@ public:
FUNC1(texture_debug_usage, List<TextureInfo> *)
FUNC2(texture_set_force_redraw_if_visible, RID, bool)
+ FUNC2RC(RID, texture_get_rd_texture_rid, RID, bool)
/* SHADER API */
@@ -226,13 +225,14 @@ public:
FUNCRIDSPLIT(shader)
FUNC2(shader_set_code, RID, const String &)
+ FUNC2(shader_set_path_hint, RID, const String &)
FUNC1RC(String, shader_get_code, RID)
- FUNC2SC(shader_get_param_list, RID, List<PropertyInfo> *)
+ FUNC2SC(get_shader_parameter_list, RID, List<PropertyInfo> *)
- FUNC4(shader_set_default_texture_param, RID, const StringName &, RID, int)
- FUNC3RC(RID, shader_get_default_texture_param, RID, const StringName &, int)
- FUNC2RC(Variant, shader_get_param_default, RID, const StringName &)
+ FUNC4(shader_set_default_texture_parameter, RID, const StringName &, RID, int)
+ FUNC3RC(RID, shader_get_default_texture_parameter, RID, const StringName &, int)
+ FUNC2RC(Variant, shader_get_parameter_default, RID, const StringName &)
FUNC1RC(ShaderNativeSourceCode, shader_get_native_source_code, RID)
@@ -404,12 +404,20 @@ public:
FUNC2(lightmap_set_probe_bounds, RID, const AABB &)
FUNC2(lightmap_set_probe_interior, RID, bool)
FUNC5(lightmap_set_probe_capture_data, RID, const PackedVector3Array &, const PackedColorArray &, const PackedInt32Array &, const PackedInt32Array &)
+ FUNC2(lightmap_set_baked_exposure_normalization, RID, float)
FUNC1RC(PackedVector3Array, lightmap_get_probe_capture_points, RID)
FUNC1RC(PackedColorArray, lightmap_get_probe_capture_sh, RID)
FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_tetrahedra, RID)
FUNC1RC(PackedInt32Array, lightmap_get_probe_capture_bsp_tree, RID)
FUNC1(lightmap_set_probe_capture_update_speed, float)
+ /* Shadow Atlas */
+ FUNC0R(RID, shadow_atlas_create)
+ FUNC3(shadow_atlas_set_size, RID, int, bool)
+ FUNC3(shadow_atlas_set_quadrant_subdivision, RID, int, int)
+
+ FUNC2(directional_shadow_atlas_set_size, int, bool)
+
/* DECAL API */
#undef ServerName
@@ -436,8 +444,8 @@ public:
#undef ServerName
#undef server_name
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererGI
+#define server_name RSG::gi
FUNCRIDSPLIT(voxel_gi)
@@ -454,6 +462,7 @@ public:
FUNC2(voxel_gi_set_dynamic_range, RID, float)
FUNC2(voxel_gi_set_propagation, RID, float)
FUNC2(voxel_gi_set_energy, RID, float)
+ FUNC2(voxel_gi_set_baked_exposure_normalization, RID, float)
FUNC2(voxel_gi_set_bias, RID, float)
FUNC2(voxel_gi_set_normal_bias, RID, float)
FUNC2(voxel_gi_set_interior, RID, bool)
@@ -525,8 +534,8 @@ public:
#undef ServerName
#undef server_name
-#define ServerName RendererStorage
-#define server_name RSG::storage
+#define ServerName RendererFog
+#define server_name RSG::fog
FUNCRIDSPLIT(fog_volume)
@@ -536,6 +545,12 @@ public:
/* VISIBILITY_NOTIFIER */
+#undef ServerName
+#undef server_name
+
+#define ServerName RendererUtilities
+#define server_name RSG::utilities
+
FUNCRIDSPLIT(visibility_notifier)
FUNC2(visibility_notifier_set_aabb, RID, const AABB &)
FUNC3(visibility_notifier_set_callbacks, RID, const Callable &, const Callable &)
@@ -543,7 +558,7 @@ public:
#undef server_name
#undef ServerName
//from now on, calls forwarded to this singleton
-#define ServerName RendererScene
+#define ServerName RenderingMethod
#define server_name RSG::scene
/* CAMERA API */
@@ -555,7 +570,7 @@ public:
FUNC2(camera_set_transform, RID, const Transform3D &)
FUNC2(camera_set_cull_mask, RID, uint32_t)
FUNC2(camera_set_environment, RID, RID)
- FUNC2(camera_set_camera_effects, RID, RID)
+ FUNC2(camera_set_camera_attributes, RID, RID)
FUNC2(camera_set_use_vertical_aspect, RID, bool)
/* OCCLUDER */
@@ -586,7 +601,7 @@ public:
FUNC2(viewport_set_scaling_3d_mode, RID, ViewportScaling3DMode)
FUNC2(viewport_set_scaling_3d_scale, RID, float)
FUNC2(viewport_set_fsr_sharpness, RID, float)
- FUNC2(viewport_set_fsr_mipmap_bias, RID, float)
+ FUNC2(viewport_set_texture_mipmap_bias, RID, float)
FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode)
@@ -596,6 +611,8 @@ public:
FUNC2(viewport_set_disable_environment, RID, bool)
FUNC2(viewport_set_disable_3d, RID, bool)
+ FUNC2(viewport_set_canvas_cull_mask, RID, uint32_t)
+
FUNC2(viewport_attach_camera, RID, RID)
FUNC2(viewport_set_scenario, RID, RID)
FUNC2(viewport_attach_canvas, RID, RID)
@@ -611,10 +628,11 @@ public:
FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &)
FUNC4(viewport_set_canvas_stacking, RID, RID, int, int)
- FUNC3(viewport_set_shadow_atlas_size, RID, int, bool)
+ FUNC3(viewport_set_positional_shadow_atlas_size, RID, int, bool)
FUNC3(viewport_set_sdf_oversize_and_scale, RID, ViewportSDFOversize, ViewportSDFScale)
- FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int)
- FUNC2(viewport_set_msaa, RID, ViewportMSAA)
+ FUNC3(viewport_set_positional_shadow_atlas_quadrant_subdivision, RID, int, int)
+ FUNC2(viewport_set_msaa_2d, RID, ViewportMSAA)
+ FUNC2(viewport_set_msaa_3d, RID, ViewportMSAA)
FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA)
FUNC2(viewport_set_use_taa, RID, bool)
FUNC2(viewport_set_use_debanding, RID, bool)
@@ -629,18 +647,21 @@ public:
FUNC2(viewport_set_measure_render_time, RID, bool)
FUNC1RC(double, viewport_get_measured_render_time_cpu, RID)
FUNC1RC(double, viewport_get_measured_render_time_gpu, RID)
+ FUNC1RC(RID, viewport_find_from_screen_attachment, DisplayServer::WindowID)
FUNC2(call_set_vsync_mode, DisplayServer::VSyncMode, DisplayServer::WindowID)
+ FUNC2(viewport_set_vrs_mode, RID, ViewportVRSMode)
+ FUNC2(viewport_set_vrs_texture, RID, RID)
+
/* ENVIRONMENT API */
#undef server_name
#undef ServerName
//from now on, calls forwarded to this singleton
-#define ServerName RendererScene
+#define ServerName RenderingMethod
#define server_name RSG::scene
- FUNC2(directional_shadow_atlas_set_size, int, bool)
FUNC1(voxel_gi_set_quality, VoxelGIQuality)
/* SKY API */
@@ -658,7 +679,7 @@ public:
FUNC2(environment_set_sky_custom_fov, RID, float)
FUNC2(environment_set_sky_orientation, RID, const Basis &)
FUNC2(environment_set_bg_color, RID, const Color &)
- FUNC2(environment_set_bg_energy, RID, float)
+ FUNC3(environment_set_bg_energy, RID, float, float)
FUNC2(environment_set_canvas_max_layer, RID, int)
FUNC6(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource)
@@ -679,12 +700,12 @@ public:
FUNC1(environment_glow_set_use_bicubic_upscale, bool)
FUNC1(environment_glow_set_use_high_quality, bool)
- FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float)
+ FUNC4(environment_set_tonemap, RID, EnvironmentToneMapper, float, float)
FUNC7(environment_set_adjustment, RID, bool, float, float, float, bool, RID)
- FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float)
- FUNC13(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float)
+ FUNC10(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float, float)
+ FUNC14(environment_set_volumetric_fog, RID, bool, float, const Color &, const Color &, float, float, float, float, float, bool, float, float, float)
FUNC2(environment_set_volumetric_fog_volume_size, int, int)
FUNC1(environment_set_volumetric_fog_filter_active, bool)
@@ -700,33 +721,40 @@ public:
FUNC1(sub_surface_scattering_set_quality, SubSurfaceScatteringQuality)
FUNC2(sub_surface_scattering_set_scale, float, float)
- /* CAMERA EFFECTS */
+ FUNC1(positional_soft_shadow_filter_set_quality, ShadowQuality);
+ FUNC1(directional_soft_shadow_filter_set_quality, ShadowQuality);
+ FUNC1(decals_set_filter, RS::DecalFilter);
+ FUNC1(light_projectors_set_filter, RS::LightProjectorFilter);
- FUNCRIDSPLIT(camera_effects)
+ /* CAMERA ATTRIBUTES */
- FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool)
- FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape)
+#undef server_name
+#undef ServerName
+//from now on, calls forwarded to this singleton
+#define ServerName RendererCameraAttributes
+#define server_name RSG::camera_attributes
- FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float)
- FUNC3(camera_effects_set_custom_exposure, RID, bool, float)
+ FUNCRIDSPLIT(camera_attributes)
- FUNC1(shadows_quality_set, ShadowQuality);
- FUNC1(directional_shadow_quality_set, ShadowQuality);
- FUNC1(decals_set_filter, RS::DecalFilter);
- FUNC1(light_projectors_set_filter, RS::LightProjectorFilter);
+ FUNC2(camera_attributes_set_dof_blur_quality, DOFBlurQuality, bool)
+ FUNC1(camera_attributes_set_dof_blur_bokeh_shape, DOFBokehShape)
+
+ FUNC8(camera_attributes_set_dof_blur, RID, bool, float, float, bool, float, float, float)
+ FUNC3(camera_attributes_set_exposure, RID, float, float)
+ FUNC6(camera_attributes_set_auto_exposure, RID, bool, float, float, float, float)
/* SCENARIO API */
#undef server_name
#undef ServerName
-#define ServerName RendererScene
+#define ServerName RenderingMethod
#define server_name RSG::scene
FUNCRIDSPLIT(scenario)
FUNC2(scenario_set_environment, RID, RID)
- FUNC2(scenario_set_camera_effects, RID, RID)
+ FUNC2(scenario_set_camera_attributes, RID, RID)
FUNC2(scenario_set_fallback_environment, RID, RID)
/* INSTANCING API */
@@ -769,7 +797,7 @@ public:
FUNC2RC(Variant, instance_geometry_get_shader_parameter_default_value, RID, const StringName &)
FUNC2C(instance_geometry_get_shader_parameter_list, RID, List<PropertyInfo> *)
- FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const Vector<RID> &, const Size2i &)
+ FUNC3R(TypedArray<Image>, bake_render_uv2, RID, const TypedArray<RID> &, const Size2i &)
FUNC1(gi_set_use_half_resolution, bool)
@@ -803,6 +831,8 @@ public:
FUNC2(canvas_item_set_visible, RID, bool)
FUNC2(canvas_item_set_light_mask, RID, int)
+ FUNC2(canvas_item_set_visibility_layer, RID, uint32_t)
+
FUNC2(canvas_item_set_update_when_visible, RID, bool)
FUNC2(canvas_item_set_transform, RID, const Transform2D &)
@@ -822,6 +852,7 @@ public:
FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool)
FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool)
FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float)
+ FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &)
FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &)
FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float)
FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID)
@@ -891,7 +922,7 @@ public:
FUNC1(canvas_set_shadow_texture_size, int)
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
#undef server_name
#undef ServerName
@@ -899,16 +930,16 @@ public:
#define ServerName RendererMaterialStorage
#define server_name RSG::material_storage
- FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &)
- FUNC1(global_variable_remove, const StringName &)
- FUNC0RC(Vector<StringName>, global_variable_get_list)
- FUNC2(global_variable_set, const StringName &, const Variant &)
- FUNC2(global_variable_set_override, const StringName &, const Variant &)
- FUNC1RC(GlobalVariableType, global_variable_get_type, const StringName &)
- FUNC1RC(Variant, global_variable_get, const StringName &)
+ FUNC3(global_shader_parameter_add, const StringName &, GlobalShaderParameterType, const Variant &)
+ FUNC1(global_shader_parameter_remove, const StringName &)
+ FUNC0RC(Vector<StringName>, global_shader_parameter_get_list)
+ FUNC2(global_shader_parameter_set, const StringName &, const Variant &)
+ FUNC2(global_shader_parameter_set_override, const StringName &, const Variant &)
+ FUNC1RC(GlobalShaderParameterType, global_shader_parameter_get_type, const StringName &)
+ FUNC1RC(Variant, global_shader_parameter_get, const StringName &)
- FUNC1(global_variables_load_settings, bool)
- FUNC0(global_variables_clear)
+ FUNC1(global_shader_parameters_load_settings, bool)
+ FUNC0(global_shader_parameters_clear)
#undef server_name
#undef ServerName
@@ -968,8 +999,10 @@ public:
virtual void set_print_gpu_profile(bool p_enable) override;
+ virtual Size2i get_maximum_viewport_size() const override;
+
RenderingServerDefault(bool p_create_thread = false);
~RenderingServerDefault();
};
-#endif
+#endif // RENDERING_SERVER_DEFAULT_H
diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp
index 4d24dbf3b4..ca24042ef9 100644
--- a/servers/rendering/rendering_server_globals.cpp
+++ b/servers/rendering/rendering_server_globals.cpp
@@ -32,15 +32,18 @@
bool RenderingServerGlobals::threaded = false;
+RendererUtilities *RenderingServerGlobals::utilities = nullptr;
RendererLightStorage *RenderingServerGlobals::light_storage = nullptr;
RendererMaterialStorage *RenderingServerGlobals::material_storage = nullptr;
RendererMeshStorage *RenderingServerGlobals::mesh_storage = nullptr;
RendererParticlesStorage *RenderingServerGlobals::particles_storage = nullptr;
RendererTextureStorage *RenderingServerGlobals::texture_storage = nullptr;
-RendererStorage *RenderingServerGlobals::storage = nullptr;
+RendererGI *RenderingServerGlobals::gi = nullptr;
+RendererFog *RenderingServerGlobals::fog = nullptr;
+RendererCameraAttributes *RenderingServerGlobals::camera_attributes = nullptr;
RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr;
RendererCompositor *RenderingServerGlobals::rasterizer = nullptr;
RendererCanvasCull *RenderingServerGlobals::canvas = nullptr;
RendererViewport *RenderingServerGlobals::viewport = nullptr;
-RendererScene *RenderingServerGlobals::scene = nullptr;
+RenderingMethod *RenderingServerGlobals::scene = nullptr;
diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h
index ce11fae9e8..23f3810ce8 100644
--- a/servers/rendering/rendering_server_globals.h
+++ b/servers/rendering/rendering_server_globals.h
@@ -31,35 +31,42 @@
#ifndef RENDERING_SERVER_GLOBALS_H
#define RENDERING_SERVER_GLOBALS_H
+#include "servers/rendering/environment/renderer_fog.h"
+#include "servers/rendering/environment/renderer_gi.h"
#include "servers/rendering/renderer_canvas_cull.h"
#include "servers/rendering/renderer_canvas_render.h"
-#include "servers/rendering/renderer_scene.h"
+#include "servers/rendering/rendering_method.h"
+#include "servers/rendering/storage/camera_attributes_storage.h"
#include "servers/rendering/storage/light_storage.h"
#include "servers/rendering/storage/material_storage.h"
#include "servers/rendering/storage/mesh_storage.h"
#include "servers/rendering/storage/particles_storage.h"
#include "servers/rendering/storage/texture_storage.h"
+#include "servers/rendering/storage/utilities.h"
class RendererCanvasCull;
class RendererViewport;
-class RendererScene;
+class RenderingMethod;
class RenderingServerGlobals {
public:
static bool threaded;
+ static RendererUtilities *utilities;
static RendererLightStorage *light_storage;
static RendererMaterialStorage *material_storage;
static RendererMeshStorage *mesh_storage;
static RendererParticlesStorage *particles_storage;
static RendererTextureStorage *texture_storage;
- static RendererStorage *storage;
+ static RendererGI *gi;
+ static RendererFog *fog;
+ static RendererCameraAttributes *camera_attributes;
static RendererCanvasRender *canvas_render;
static RendererCompositor *rasterizer;
static RendererCanvasCull *canvas;
static RendererViewport *viewport;
- static RendererScene *scene;
+ static RenderingMethod *scene;
};
#define RSG RenderingServerGlobals
diff --git a/servers/rendering/shader_compiler.cpp b/servers/rendering/shader_compiler.cpp
index 463b67033d..fc644fcae6 100644
--- a/servers/rendering/shader_compiler.cpp
+++ b/servers/rendering/shader_compiler.cpp
@@ -32,8 +32,8 @@
#include "core/config/project_settings.h"
#include "core/os/os.h"
+#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_types.h"
-#include "servers/rendering_server.h"
#define SL ShaderLanguage
@@ -370,19 +370,19 @@ void ShaderCompiler::_dump_function_deps(const SL::ShaderNode *p_node, const Str
}
}
-static String _get_global_variable_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
+static String _get_global_shader_uniform_from_type_and_index(const String &p_buffer, const String &p_index, ShaderLanguage::DataType p_type) {
switch (p_type) {
case ShaderLanguage::TYPE_BOOL: {
- return "(" + p_buffer + "[" + p_index + "].x != 0.0)";
+ return "bool(floatBitsToUint(" + p_buffer + "[" + p_index + "].x))";
}
case ShaderLanguage::TYPE_BVEC2: {
- return "(notEqual(" + p_buffer + "[" + p_index + "].xy, vec2(0.0)))";
+ return "bvec2(floatBitsToUint(" + p_buffer + "[" + p_index + "].xy))";
}
case ShaderLanguage::TYPE_BVEC3: {
- return "(notEqual(" + p_buffer + "[" + p_index + "].xyz, vec3(0.0)))";
+ return "bvec3(floatBitsToUint(" + p_buffer + "[" + p_index + "].xyz))";
}
case ShaderLanguage::TYPE_BVEC4: {
- return "(notEqual(" + p_buffer + "[" + p_index + "].xyzw, vec4(0.0)))";
+ return "bvec4(floatBitsToUint(" + p_buffer + "[" + p_index + "].xyzw))";
}
case ShaderLanguage::TYPE_INT: {
return "floatBitsToInt(" + p_buffer + "[" + p_index + "].x)";
@@ -498,6 +498,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
for (const KeyValue<StringName, SL::ShaderNode::Uniform> &E : pnode->uniforms) {
if (SL::is_sampler_type(E.value.type)) {
+ if (E.value.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ E.value.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
max_texture_uniforms++;
} else {
if (E.value.scope == SL::ShaderNode::Uniform::SCOPE_INSTANCE) {
@@ -537,6 +542,13 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
p_actions.uniforms->insert(uniform_name, uniform);
continue; // Instances are indexed directly, don't need index uniforms.
}
+
+ if (uniform.hint == SL::ShaderNode::Uniform::HINT_SCREEN_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE ||
+ uniform.hint == SL::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ continue; // Don't create uniforms in the generated code for these.
+ }
+
if (SL::is_sampler_type(uniform.type)) {
// Texture layouts are different for OpenGL GLSL and Vulkan GLSL
if (!RS::get_singleton()->is_low_end()) {
@@ -892,22 +904,49 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (p_default_actions.renames.has(vnode->name)) {
code = p_default_actions.renames[vnode->name];
+ if (vnode->name == "SCREEN_TEXTURE") {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
} else {
if (shader->uniforms.has(vnode->name)) {
//its a uniform!
const ShaderLanguage::ShaderNode::Uniform &u = shader->uniforms[vnode->name];
if (u.texture_order >= 0) {
- code = _mkid(vnode->name); //texture, use as is
+ StringName name = vnode->name;
+ if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SCREEN_TEXTURE) {
+ name = "SCREEN_TEXTURE";
+ if (u.filter >= ShaderLanguage::FILTER_NEAREST_MIPMAP) {
+ r_gen_code.uses_screen_texture_mipmaps = true;
+ }
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE) {
+ name = "NORMAL_ROUGHNESS_TEXTURE";
+ } else if (u.hint == ShaderLanguage::ShaderNode::Uniform::HINT_DEPTH_TEXTURE) {
+ name = "DEPTH_TEXTURE";
+ } else {
+ name = _mkid(vnode->name); //texture, use as is
+ }
+
+ if (p_default_actions.renames.has(name)) {
+ code = p_default_actions.renames[name];
+ } else {
+ code = name;
+ }
+
+ if (p_actions.usage_flag_pointers.has(name) && !used_flag_pointers.has(name)) {
+ *p_actions.usage_flag_pointers[name] = true;
+ used_flag_pointers.insert(name);
+ }
+
} else {
//a scalar or vector
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(vnode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(vnode->name);
@@ -1003,11 +1042,11 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_GLOBAL) {
code = actions.base_uniform_string + _mkid(anode->name); //texture, use as is
//global variable, this means the code points to an index to the global table
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else if (u.scope == ShaderLanguage::ShaderNode::Uniform::SCOPE_INSTANCE) {
//instance variable, index it as such
code = "(" + p_default_actions.instance_uniform_index_variable + "+" + itos(u.instance_index) + ")";
- code = _get_global_variable_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
+ code = _get_global_shader_uniform_from_type_and_index(p_default_actions.global_buffer_array_variable, code, u.type);
} else {
//regular uniform, index from UBO
code = actions.base_uniform_string + _mkid(anode->name);
@@ -1155,6 +1194,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
if (correct_texture_uniform) {
+ //TODO Needs to detect screen_texture hint as well
is_screen_texture = (texture_uniform == "SCREEN_TEXTURE");
String sampler_name;
@@ -1199,7 +1239,7 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
}
code += ")";
if (is_screen_texture && actions.apply_luminance_multiplier) {
- code = "(" + code + " * vec4(vec3(sc_luminance_multiplier), 1.0))";
+ code = "(" + code + " / vec4(vec3(sc_luminance_multiplier), 1.0))";
}
} break;
case SL::OP_INDEX: {
@@ -1308,9 +1348,9 @@ String ShaderCompiler::_dump_node_code(const SL::Node *p_node, int p_level, Gene
return code;
}
-ShaderLanguage::DataType ShaderCompiler::_get_variable_type(const StringName &p_type) {
- RS::GlobalVariableType gvt = RS::get_singleton()->global_variable_get_type(p_type);
- return (ShaderLanguage::DataType)RS::global_variable_type_get_shader_datatype(gvt);
+ShaderLanguage::DataType ShaderCompiler::_get_global_shader_uniform_type(const StringName &p_name) {
+ RS::GlobalShaderParameterType gvt = RSG::material_storage->global_shader_parameter_get_type(p_name);
+ return (ShaderLanguage::DataType)RS::global_shader_uniform_type_get_shader_datatype(gvt);
}
Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) {
@@ -1318,23 +1358,81 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
info.functions = ShaderTypes::get_singleton()->get_functions(p_mode);
info.render_modes = ShaderTypes::get_singleton()->get_modes(p_mode);
info.shader_types = ShaderTypes::get_singleton()->get_types();
- info.global_variable_type_func = _get_variable_type;
+ info.global_shader_uniform_type_func = _get_global_shader_uniform_type;
Error err = parser.compile(p_code, info);
if (err != OK) {
- Vector<String> shader = p_code.split("\n");
- for (int i = 0; i < shader.size(); i++) {
- if (i + 1 == parser.get_error_line()) {
- // Mark the error line to be visible without having to look at
- // the trace at the end.
- print_line(vformat("E%4d-> %s", i + 1, shader[i]));
+ Vector<ShaderLanguage::FilePosition> include_positions = parser.get_include_positions();
+
+ String current;
+ HashMap<String, Vector<String>> includes;
+ includes[""] = Vector<String>();
+ Vector<String> include_stack;
+ Vector<String> shader_lines = p_code.split("\n");
+
+ // Reconstruct the files.
+ for (int i = 0; i < shader_lines.size(); i++) {
+ String l = shader_lines[i];
+ if (l.begins_with("@@>")) {
+ String inc_path = l.replace_first("@@>", "");
+
+ l = "#include \"" + inc_path + "\"";
+ includes[current].append("#include \"" + inc_path + "\""); // Restore the include directive
+ include_stack.push_back(current);
+ current = inc_path;
+ includes[inc_path] = Vector<String>();
+
+ } else if (l.begins_with("@@<")) {
+ if (include_stack.size()) {
+ current = include_stack[include_stack.size() - 1];
+ include_stack.resize(include_stack.size() - 1);
+ }
} else {
- print_line(vformat("%5d | %s", i + 1, shader[i]));
+ includes[current].push_back(l);
}
}
- _err_print_error(nullptr, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
+ // Print the files.
+ for (const KeyValue<String, Vector<String>> &E : includes) {
+ if (E.key.is_empty()) {
+ if (p_path == "") {
+ print_line("--Main Shader--");
+ } else {
+ print_line("--" + p_path + "--");
+ }
+ } else {
+ print_line("--" + E.key + "--");
+ }
+ int err_line = -1;
+ for (int i = 0; i < include_positions.size(); i++) {
+ if (include_positions[i].file == E.key) {
+ err_line = include_positions[i].line;
+ }
+ }
+ const Vector<String> &V = E.value;
+ for (int i = 0; i < V.size(); i++) {
+ if (i == err_line - 1) {
+ // Mark the error line to be visible without having to look at
+ // the trace at the end.
+ print_line(vformat("E%4d-> %s", i + 1, V[i]));
+ } else {
+ print_line(vformat("%5d | %s", i + 1, V[i]));
+ }
+ }
+ }
+
+ String file;
+ int line;
+ if (include_positions.size() > 1) {
+ file = include_positions[include_positions.size() - 1].file;
+ line = include_positions[include_positions.size() - 1].line;
+ } else {
+ file = p_path;
+ line = parser.get_error_line();
+ }
+
+ _err_print_error(nullptr, file.utf8().get_data(), line, parser.get_error_text().utf8().get_data(), false, ERR_HANDLER_SHADER);
return err;
}
@@ -1346,6 +1444,7 @@ Error ShaderCompiler::compile(RS::ShaderMode p_mode, const String &p_code, Ident
r_gen_code.uses_fragment_time = false;
r_gen_code.uses_vertex_time = false;
r_gen_code.uses_global_textures = false;
+ r_gen_code.uses_screen_texture_mipmaps = false;
used_name_defines.clear();
used_rmode_defines.clear();
@@ -1376,8 +1475,11 @@ void ShaderCompiler::initialize(DefaultIdentifierActions p_actions) {
texture_functions.insert("textureLod");
texture_functions.insert("textureProjLod");
texture_functions.insert("textureGrad");
+ texture_functions.insert("textureProjGrad");
texture_functions.insert("textureGather");
texture_functions.insert("textureSize");
+ texture_functions.insert("textureQueryLod");
+ texture_functions.insert("textureQueryLevels");
texture_functions.insert("texelFetch");
}
diff --git a/servers/rendering/shader_compiler.h b/servers/rendering/shader_compiler.h
index 06f42e9f0f..4cbe93afb2 100644
--- a/servers/rendering/shader_compiler.h
+++ b/servers/rendering/shader_compiler.h
@@ -80,6 +80,7 @@ public:
bool uses_global_textures;
bool uses_fragment_time;
bool uses_vertex_time;
+ bool uses_screen_texture_mipmaps;
};
struct DefaultIdentifierActions {
@@ -121,7 +122,7 @@ private:
DefaultIdentifierActions actions;
- static ShaderLanguage::DataType _get_variable_type(const StringName &p_type);
+ static ShaderLanguage::DataType _get_global_shader_uniform_type(const StringName &p_name);
public:
Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code);
diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp
index fe3d1e03b6..14c09c1512 100644
--- a/servers/rendering/shader_language.cpp
+++ b/servers/rendering/shader_language.cpp
@@ -32,7 +32,9 @@
#include "core/os/os.h"
#include "core/string/print_string.h"
+#include "core/templates/local_vector.h"
#include "servers/rendering_server.h"
+#include "shader_types.h"
#define HAS_WARNING(flag) (warning_flags & flag)
@@ -193,10 +195,14 @@ const char *ShaderLanguage::token_names[TK_MAX] = {
"SOURCE_COLOR",
"HINT_DEFAULT_WHITE_TEXTURE",
"HINT_DEFAULT_BLACK_TEXTURE",
+ "HINT_DEFAULT_TRANSPARENT_TEXTURE",
"HINT_NORMAL_TEXTURE",
"HINT_ANISOTROPY_TEXTURE",
"HINT_RANGE",
"HINT_INSTANCE_INDEX",
+ "HINT_SCREEN_TEXTURE",
+ "HINT_NORMAL_ROUGHNESS_TEXTURE",
+ "HINT_DEPTH_TEXTURE",
"FILTER_NEAREST",
"FILTER_LINEAR",
"FILTER_NEAREST_MIPMAP",
@@ -251,6 +257,7 @@ enum ContextFlag : uint32_t {
CF_UNIFORM_KEYWORD = 2048U, // "uniform"
CF_CONST_KEYWORD = 4096U, // "const"
CF_UNIFORM_QUALIFIER = 8192U, // "<x> uniform float t;"
+ CF_SHADER_TYPE = 16384U, // "shader_type"
};
const uint32_t KCF_DATATYPE = CF_BLOCK | CF_GLOBAL_SPACE | CF_DATATYPE | CF_FUNC_DECL_PARAM_TYPE | CF_UNIFORM_TYPE;
@@ -308,10 +315,11 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
// global space keywords
{ TK_UNIFORM, "uniform", CF_GLOBAL_SPACE | CF_UNIFORM_KEYWORD, {}, {} },
+ { TK_UNIFORM_GROUP, "group_uniforms", CF_GLOBAL_SPACE, {}, {} },
{ TK_VARYING, "varying", CF_GLOBAL_SPACE, { "particles", "sky", "fog" }, {} },
{ TK_CONST, "const", CF_BLOCK | CF_GLOBAL_SPACE | CF_CONST_KEYWORD, {}, {} },
{ TK_STRUCT, "struct", CF_GLOBAL_SPACE, {}, {} },
- { TK_SHADER_TYPE, "shader_type", CF_GLOBAL_SPACE, {}, {} },
+ { TK_SHADER_TYPE, "shader_type", CF_SHADER_TYPE, {}, {} },
{ TK_RENDER_MODE, "render_mode", CF_GLOBAL_SPACE, {}, {} },
// uniform qualifiers
@@ -351,6 +359,7 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_NORMAL_TEXTURE, "hint_normal", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_DEFAULT_WHITE_TEXTURE, "hint_default_white", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_DEFAULT_BLACK_TEXTURE, "hint_default_black", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEFAULT_TRANSPARENT_TEXTURE, "hint_default_transparent", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ANISOTROPY_TEXTURE, "hint_anisotropy", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_R, "hint_roughness_r", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_G, "hint_roughness_g", CF_UNSPECIFIED, {}, {} },
@@ -358,6 +367,10 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = {
{ TK_HINT_ROUGHNESS_A, "hint_roughness_a", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal", CF_UNSPECIFIED, {}, {} },
{ TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_SCREEN_TEXTURE, "hint_screen_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_NORMAL_ROUGHNESS_TEXTURE, "hint_normal_roughness_texture", CF_UNSPECIFIED, {}, {} },
+ { TK_HINT_DEPTH_TEXTURE, "hint_depth_texture", CF_UNSPECIFIED, {}, {} },
+
{ TK_FILTER_NEAREST, "filter_nearest", CF_UNSPECIFIED, {}, {} },
{ TK_FILTER_LINEAR, "filter_linear", CF_UNSPECIFIED, {}, {} },
{ TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap", CF_UNSPECIFIED, {}, {} },
@@ -574,6 +587,37 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_OP_MOD);
} break;
+ case '@': {
+ if (GETCHAR(0) == '@' && GETCHAR(1) == '>') {
+ char_idx += 2;
+
+ LocalVector<char32_t> incp;
+ while (GETCHAR(0) != '\n') {
+ incp.push_back(GETCHAR(0));
+ char_idx++;
+ }
+ incp.push_back(0); // Zero end it.
+ String include_path(incp.ptr());
+ include_positions.write[include_positions.size() - 1].line = tk_line;
+ FilePosition fp;
+ fp.file = include_path;
+ fp.line = 0;
+ tk_line = 0;
+ include_positions.push_back(fp);
+
+ } else if (GETCHAR(0) == '@' && GETCHAR(1) == '<') {
+ if (include_positions.size() == 1) {
+ return _make_token(TK_ERROR, "Invalid include exit hint @@< without matching enter hint.");
+ }
+ char_idx += 2;
+
+ include_positions.resize(include_positions.size() - 1); // Pop back.
+ tk_line = include_positions[include_positions.size() - 1].line; // Restore line.
+
+ } else {
+ return _make_token(TK_ERROR, "Invalid include enter/exit hint token (@@> and @@<)");
+ }
+ } break;
default: {
char_idx--; //go back one, since we have no idea what this is
@@ -613,12 +657,16 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
String str;
int i = 0;
+ bool digit_after_exp = false;
while (true) {
const char32_t symbol = String::char_lowercase(GETCHAR(i));
bool error = false;
if (is_digit(symbol)) {
+ if (exponent_found) {
+ digit_after_exp = true;
+ }
if (end_suffix_found) {
error = true;
}
@@ -683,7 +731,7 @@ ShaderLanguage::Token ShaderLanguage::_get_token() {
return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant");
}
} else if (period_found || exponent_found || float_suffix_found) { // Float
- if (exponent_found && (!is_digit(last_char) && last_char != 'f')) { // checks for eg: "2E", "2E-", "2E+"
+ if (exponent_found && (!digit_after_exp || (!is_digit(last_char) && last_char != 'f'))) { // Checks for eg: "2E", "2E-", "2E+" and 0ef, 0e+f, 0.0ef, 0.0e-f (exponent without digit after it).
return _make_token(TK_ERROR, "Invalid (float) numeric constant");
}
if (period_found) {
@@ -1021,7 +1069,7 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
result = "hint_range";
} break;
case ShaderNode::Uniform::HINT_SOURCE_COLOR: {
- result = "hint_color";
+ result = "source_color";
} break;
case ShaderNode::Uniform::HINT_NORMAL: {
result = "hint_normal";
@@ -1050,9 +1098,21 @@ String ShaderLanguage::get_uniform_hint_name(ShaderNode::Uniform::Hint p_hint) {
case ShaderNode::Uniform::HINT_DEFAULT_WHITE: {
result = "hint_default_white";
} break;
+ case ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT: {
+ result = "hint_default_transparent";
+ } break;
case ShaderNode::Uniform::HINT_ANISOTROPY: {
result = "hint_anisotropy";
} break;
+ case ShaderNode::Uniform::HINT_SCREEN_TEXTURE: {
+ result = "hint_screen_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ result = "hint_normal_roughness_texture";
+ } break;
+ case ShaderNode::Uniform::HINT_DEPTH_TEXTURE: {
+ result = "hint_depth_texture";
+ } break;
default:
break;
}
@@ -1109,6 +1169,12 @@ void ShaderLanguage::clear() {
current_function = StringName();
last_name = StringName();
last_type = IDENTIFIER_MAX;
+ current_uniform_group_name = "";
+ current_uniform_subgroup_name = "";
+ current_uniform_hint = ShaderNode::Uniform::HINT_NONE;
+ current_uniform_filter = FILTER_DEFAULT;
+ current_uniform_repeat = REPEAT_DEFAULT;
+ current_uniform_instance_index_defined = false;
completion_type = COMPLETION_NONE;
completion_block = nullptr;
@@ -1118,8 +1184,11 @@ void ShaderLanguage::clear() {
completion_base = TYPE_VOID;
completion_base_array = false;
+ include_positions.clear();
+ include_positions.push_back(FilePosition());
+
#ifdef DEBUG_ENABLED
- keyword_completion_context = CF_GLOBAL_SPACE;
+ keyword_completion_context = CF_UNSPECIFIED;
used_constants.clear();
used_varyings.clear();
used_uniforms.clear();
@@ -1179,17 +1248,36 @@ void ShaderLanguage::_parse_used_identifier(const StringName &p_identifier, Iden
#endif // DEBUG_ENABLED
bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const FunctionInfo &p_function_info, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name, ConstantNode::Value *r_constant_value) {
- if (p_function_info.built_ins.has(p_identifier)) {
- if (r_data_type) {
- *r_data_type = p_function_info.built_ins[p_identifier].type;
- }
- if (r_is_const) {
- *r_is_const = p_function_info.built_ins[p_identifier].constant;
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ for (const KeyValue<StringName, FunctionInfo> &E : ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i))) {
+ if ((current_function == E.key || E.key == "global" || E.key == "constants") && E.value.built_ins.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type = E.value.built_ins[p_identifier].type;
+ }
+ if (r_is_const) {
+ *r_is_const = E.value.built_ins[p_identifier].constant;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_BUILTIN_VAR;
+ }
+ return true;
+ }
+ }
}
- if (r_type) {
- *r_type = IDENTIFIER_BUILTIN_VAR;
+ } else {
+ if (p_function_info.built_ins.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type = p_function_info.built_ins[p_identifier].type;
+ }
+ if (r_is_const) {
+ *r_is_const = p_function_info.built_ins[p_identifier].constant;
+ }
+ if (r_type) {
+ *r_type = IDENTIFIER_BUILTIN_VAR;
+ }
+ return true;
}
- return true;
}
if (p_function_info.stage_functions.has(p_identifier)) {
@@ -1854,21 +1942,21 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
@@ -1882,22 +1970,22 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
// Conversion vectors.
@@ -1909,57 +1997,57 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
- { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
+ { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
- { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, true },
+ { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
{ "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, { "" }, TAG_GLOBAL, false },
// Conversion between matrixes.
@@ -2203,10 +2291,10 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// modf
- { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
- { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, true },
+ { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
+ { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "x", "i" }, TAG_GLOBAL, false },
// min
@@ -2226,13 +2314,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// max
@@ -2252,13 +2340,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// clamp
@@ -2278,13 +2366,13 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
{ "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
- { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
- { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, true },
+ { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
+ { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, { "x", "minVal", "maxVal" }, TAG_GLOBAL, false },
// mix
@@ -2335,31 +2423,31 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// floatBitsToInt
- { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// floatBitsToUint
- { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// intBitsToFloat
- { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// uintBitsToFloat
- { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
- { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, true },
+ { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
+ { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, { "x" }, TAG_GLOBAL, false },
// Built-ins - geometric functions.
// length
@@ -2396,11 +2484,15 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// reflect
+ { "reflect", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
{ "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
+ { "reflect", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, { "I", "N" }, TAG_GLOBAL, false },
// refract
+ { "refract", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
{ "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
+ { "refract", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "I", "N", "eta" }, TAG_GLOBAL, false },
// faceforward
@@ -2448,9 +2540,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// greaterThan
@@ -2462,9 +2554,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// lessThanEqual
@@ -2476,9 +2568,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// greaterThanEqual
@@ -2490,9 +2582,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
// equal
@@ -2504,9 +2596,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2522,9 +2614,9 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
{ "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
- { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
- { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, true },
+ { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
+ { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
{ "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, { "a", "b" }, TAG_GLOBAL, false },
@@ -2551,38 +2643,38 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// Built-ins: texture functions.
// textureSize
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
- { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, true },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
+ { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBEARRAY, TYPE_INT, TYPE_VOID }, { "sampler", "lod" }, TAG_GLOBAL, false },
// texture
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
{ "texture", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
@@ -2590,119 +2682,157 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// textureProj
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, true },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "bias" }, TAG_GLOBAL, false },
// textureLod
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
- { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
{ "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// texelFetch
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// textureProjLod
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
- { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, true },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
+ { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, { "sampler", "coords", "lod" }, TAG_GLOBAL, false },
// textureGrad
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
- { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, true },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBEARRAY, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+
+ // textureProjGrad
+
+ { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
+ { "textureProjGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords", "dPdx", "dPdy" }, TAG_GLOBAL, false },
// textureGather
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, true },
- { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, true },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, { "sampler", "coords" }, TAG_GLOBAL, false },
+ { "textureGather", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_INT, TYPE_VOID }, { "sampler", "coords", "comp" }, TAG_GLOBAL, false },
+
+ // textureQueryLod
+
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER2D, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER2DARRAY, TYPE_VEC2 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_ISAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_USAMPLER3D, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+ { "textureQueryLod", TYPE_VEC2, { TYPE_SAMPLERCUBE, TYPE_VEC3 }, { "sampler", "coords" }, TAG_GLOBAL, true },
+
+ // textureQueryLevels
+
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER2D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER2D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER2D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER2DARRAY }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLER3D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_ISAMPLER3D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_USAMPLER3D }, { "sampler" }, TAG_GLOBAL, true },
+ { "textureQueryLevels", TYPE_INT, { TYPE_SAMPLERCUBE }, { "sampler" }, TAG_GLOBAL, true },
// dFdx
- { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// dFdy
- { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// fwidth
- { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
- { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, true },
+ { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
+ { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, { "p" }, TAG_GLOBAL, false },
// Sub-functions.
// array
- { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, true },
+ { "length", TYPE_INT, { TYPE_VOID }, { "" }, TAG_ARRAY, false },
// Modern functions.
// fma
@@ -2714,17 +2844,17 @@ const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = {
// Packing/Unpacking functions.
- { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "packHalf2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packUnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packSnorm2x16", TYPE_UINT, { TYPE_VEC2, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packUnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "packSnorm4x8", TYPE_UINT, { TYPE_VEC4, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
- { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
- { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, true },
+ { "unpackHalf2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackUnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackSnorm2x16", TYPE_VEC2, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackUnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
+ { "unpackSnorm4x8", TYPE_VEC4, { TYPE_UINT, TYPE_VOID }, { "v" }, TAG_GLOBAL, false },
// bitfieldExtract
@@ -3794,18 +3924,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C
}
value = Variant(array);
} else {
- Basis p;
- p[0][0] = p_value[0].real;
- p[0][1] = p_value[1].real;
- p[0][2] = p_value[2].real;
- p[1][0] = p_value[4].real;
- p[1][1] = p_value[5].real;
- p[1][2] = p_value[6].real;
- p[2][0] = p_value[8].real;
- p[2][1] = p_value[9].real;
- p[2][2] = p_value[10].real;
- Transform3D t = Transform3D(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real));
- value = Variant(t);
+ Projection p = Projection(Vector4(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real),
+ Vector4(p_value[4].real, p_value[5].real, p_value[6].real, p_value[7].real),
+ Vector4(p_value[8].real, p_value[9].real, p_value[10].real, p_value[11].real),
+ Vector4(p_value[12].real, p_value[13].real, p_value[14].real, p_value[15].real));
+ value = Variant(p);
}
break;
}
@@ -3887,13 +4010,29 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
}
}
} break;
- case ShaderLanguage::TYPE_IVEC2:
- case ShaderLanguage::TYPE_IVEC3:
- case ShaderLanguage::TYPE_IVEC4:
case ShaderLanguage::TYPE_UVEC2:
+ case ShaderLanguage::TYPE_IVEC2: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR2I;
+ }
+ } break;
case ShaderLanguage::TYPE_UVEC3:
- case ShaderLanguage::TYPE_UVEC4: {
- pi.type = Variant::PACKED_INT32_ARRAY;
+ case ShaderLanguage::TYPE_IVEC3: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR3I;
+ }
+ } break;
+ case ShaderLanguage::TYPE_UVEC4:
+ case ShaderLanguage::TYPE_IVEC4: {
+ if (p_uniform.array_size > 0) {
+ pi.type = Variant::PACKED_INT32_ARRAY;
+ } else {
+ pi.type = Variant::VECTOR4I;
+ }
} break;
case ShaderLanguage::TYPE_FLOAT: {
if (p_uniform.array_size > 0) {
@@ -3941,7 +4080,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_SOURCE_COLOR) {
pi.type = Variant::COLOR;
} else {
- pi.type = Variant::QUATERNION;
+ pi.type = Variant::VECTOR4;
}
}
} break;
@@ -3963,7 +4102,7 @@ PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform
if (p_uniform.array_size > 0) {
pi.type = Variant::PACKED_FLOAT32_ARRAY;
} else {
- pi.type = Variant::TRANSFORM3D;
+ pi.type = Variant::PROJECTION;
}
break;
case ShaderLanguage::TYPE_SAMPLER2D:
@@ -4257,8 +4396,6 @@ bool ShaderLanguage::_is_operator_assign(Operator p_op) const {
default:
return false;
}
-
- return false;
}
bool ShaderLanguage::_validate_varying_assign(ShaderNode::Varying &p_varying, String *r_message) {
@@ -5205,8 +5342,8 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
last_type = IDENTIFIER_MAX;
_set_tkpos(pos);
- DataType data_type;
- IdentifierType ident_type;
+ DataType data_type = TYPE_MAX;
+ IdentifierType ident_type = IDENTIFIER_MAX;
int array_size = 0;
StringName struct_name;
bool is_local = false;
@@ -5243,6 +5380,7 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
}
_set_tkpos(prev_pos);
+ ShaderNode::Varying &var = shader->varyings[identifier];
String error;
if (is_token_operator_assign(next_token.type)) {
if (!_validate_varying_assign(shader->varyings[identifier], &error)) {
@@ -5250,8 +5388,6 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
return nullptr;
}
} else {
- ShaderNode::Varying &var = shader->varyings[identifier];
-
switch (var.stage) {
case ShaderNode::Varying::STAGE_VERTEX:
if (current_function == varying_function_names.fragment || current_function == varying_function_names.light) {
@@ -5267,6 +5403,12 @@ ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, cons
break;
}
}
+
+ if ((var.stage != ShaderNode::Varying::STAGE_FRAGMENT && var.stage != ShaderNode::Varying::STAGE_FRAGMENT_TO_LIGHT) && var.type < TYPE_FLOAT && var.interpolation != INTERPOLATION_FLAT) {
+ _set_tkpos(var.tkpos);
+ _set_error(RTR("Varying with integer data type must be declared with `flat` interpolation qualifier."));
+ return nullptr;
+ }
}
if (ident_type == IDENTIFIER_FUNCTION) {
@@ -6649,10 +6791,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
DataType type = is_struct ? TYPE_STRUCT : get_token_datatype(tk.type);
- if (_validate_datatype(type) != OK) {
- return ERR_PARSE_ERROR;
- }
-
if (precision != PRECISION_DEFAULT && _validate_precision(type, precision) != OK) {
return ERR_PARSE_ERROR;
}
@@ -6749,11 +6887,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
- if (RenderingServer::get_singleton()->is_low_end() && is_const) {
- _set_error(RTR("Local const arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
-
Error error = _parse_array_size(p_block, p_function_info, false, &decl.size_expression, &var.array_size, &unknown_size);
if (error != OK) {
return error;
@@ -6773,11 +6906,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
bool full_def = false;
if (tk.type == TK_OP_ASSIGN) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Array initialization is only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
-
TkPos prev_pos = _get_tkpos();
tk = _get_token();
@@ -7084,11 +7212,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
_set_tkpos(pos); //rollback
}
} else if (tk.type == TK_CF_SWITCH) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(vformat(RTR("The '%s' operator is only supported on high-end platforms."), "switch"));
- return ERR_PARSE_ERROR;
- }
-
// switch() {}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_OPEN) {
@@ -7101,9 +7224,12 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const FunctionInfo &p_fun
if (!n) {
return ERR_PARSE_ERROR;
}
- if (n->get_datatype() != TYPE_INT) {
- _set_error(RTR("Expected an integer expression."));
- return ERR_PARSE_ERROR;
+ {
+ const ShaderLanguage::DataType switch_type = n->get_datatype();
+ if (switch_type != TYPE_INT && switch_type != TYPE_UINT) {
+ _set_error(RTR("Expected an integer expression."));
+ return ERR_PARSE_ERROR;
+ }
}
tk = _get_token();
if (tk.type != TK_PARENTHESIS_CLOSE) {
@@ -7692,64 +7818,42 @@ Error ShaderLanguage::_validate_precision(DataType p_type, DataPrecision p_preci
return OK;
}
-Error ShaderLanguage::_validate_datatype(DataType p_type) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- bool invalid_type = false;
-
- switch (p_type) {
- case TYPE_UINT:
- case TYPE_UVEC2:
- case TYPE_UVEC3:
- case TYPE_UVEC4:
- case TYPE_ISAMPLER2D:
- case TYPE_USAMPLER2D:
- case TYPE_ISAMPLER3D:
- case TYPE_USAMPLER3D:
- case TYPE_USAMPLER2DARRAY:
- case TYPE_ISAMPLER2DARRAY:
- invalid_type = true;
- break;
- default:
- break;
- }
-
- if (invalid_type) {
- _set_error(vformat(RTR("The \"%s\" type is only supported on high-end platforms."), get_datatype_name(p_type)));
- return ERR_UNAVAILABLE;
- }
- }
- return OK;
-}
-
Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_functions, const Vector<ModeInfo> &p_render_modes, const HashSet<String> &p_shader_types) {
- Token tk = _get_token();
+ Token tk;
TkPos prev_pos;
Token next;
- if (tk.type != TK_SHADER_TYPE) {
- _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
+ if (!is_shader_inc) {
#ifdef DEBUG_ENABLED
- keyword_completion_context = CF_UNSPECIFIED;
+ keyword_completion_context = CF_SHADER_TYPE;
#endif // DEBUG_ENABLED
+ tk = _get_token();
- _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
- if (shader_type_identifier == StringName()) {
- _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
- if (!p_shader_types.has(shader_type_identifier)) {
- _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types)));
- return ERR_PARSE_ERROR;
- }
- prev_pos = _get_tkpos();
- tk = _get_token();
+ if (tk.type != TK_SHADER_TYPE) {
+ _set_error(vformat(RTR("Expected '%s' at the beginning of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
+#ifdef DEBUG_ENABLED
+ keyword_completion_context = CF_UNSPECIFIED;
+#endif // DEBUG_ENABLED
- if (tk.type != TK_SEMICOLON) {
- _set_tkpos(prev_pos);
- _set_expected_after_error(";", "shader_type " + String(shader_type_identifier));
- return ERR_PARSE_ERROR;
+ _get_completable_identifier(nullptr, COMPLETION_SHADER_TYPE, shader_type_identifier);
+ if (shader_type_identifier == StringName()) {
+ _set_error(vformat(RTR("Expected an identifier after '%s', indicating the type of shader. Valid types are: %s."), "shader_type", _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
+ if (!p_shader_types.has(shader_type_identifier)) {
+ _set_error(vformat(RTR("Invalid shader type. Valid types are: %s"), _get_shader_type_list(p_shader_types)));
+ return ERR_PARSE_ERROR;
+ }
+ prev_pos = _get_tkpos();
+ tk = _get_token();
+
+ if (tk.type != TK_SEMICOLON) {
+ _set_tkpos(prev_pos);
+ _set_expected_after_error(";", "shader_type " + String(shader_type_identifier));
+ return ERR_PARSE_ERROR;
+ }
}
#ifdef DEBUG_ENABLED
@@ -7804,25 +7908,54 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
bool found = false;
- for (int i = 0; i < p_render_modes.size(); i++) {
- const ModeInfo &info = p_render_modes[i];
- const String name = String(info.name);
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
- if (smode.begins_with(name)) {
- if (!info.options.is_empty()) {
- if (info.options.has(smode.substr(name.length() + 1))) {
- found = true;
+ for (int j = 0; j < modes.size(); j++) {
+ const ModeInfo &info = modes[j];
+ const String name = String(info.name);
- if (defined_modes.has(name)) {
- _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
- return ERR_PARSE_ERROR;
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.has(smode.substr(name.length() + 1))) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
+ }
+ } else {
+ found = true;
+ break;
}
- defined_modes.insert(name, smode);
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < p_render_modes.size(); i++) {
+ const ModeInfo &info = p_render_modes[i];
+ const String name = String(info.name);
+
+ if (smode.begins_with(name)) {
+ if (!info.options.is_empty()) {
+ if (info.options.has(smode.substr(name.length() + 1))) {
+ found = true;
+
+ if (defined_modes.has(name)) {
+ _set_error(vformat(RTR("Redefinition of render mode: '%s'. The '%s' mode has already been set to '%s'."), smode, name, defined_modes[name]));
+ return ERR_PARSE_ERROR;
+ }
+ defined_modes.insert(name, smode);
+ break;
+ }
+ } else {
+ found = true;
break;
}
- } else {
- found = true;
- break;
}
}
}
@@ -8045,6 +8178,10 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
}
}
#endif // DEBUG_ENABLED
+ if (String(shader_type_identifier) != "spatial") {
+ _set_error(vformat(RTR("Uniform instances are not yet implemented for '%s' shaders."), shader_type_identifier));
+ return ERR_PARSE_ERROR;
+ }
if (uniform_scope == ShaderNode::Uniform::SCOPE_LOCAL) {
tk = _get_token();
if (tk.type != TK_UNIFORM) {
@@ -8177,8 +8314,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
- if (!is_uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) {
- _set_error(RTR("Invalid type for varying, only 'float', 'vec2', 'vec3', 'vec4', 'mat2', 'mat3', 'mat4', or arrays of these types are allowed."));
+ if (!is_uniform && type > TYPE_MAT4) {
+ _set_error(RTR("Invalid data type for varying."));
return ERR_PARSE_ERROR;
}
@@ -8221,7 +8358,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
if (is_uniform) {
if (uniform_scope == ShaderNode::Uniform::SCOPE_GLOBAL && Engine::get_singleton()->is_editor_hint()) { // Type checking for global uniforms is not allowed outside the editor.
//validate global uniform
- DataType gvtype = global_var_get_type_func(name);
+ DataType gvtype = global_shader_uniform_get_type_func(name);
if (gvtype == TYPE_MAX) {
_set_error(vformat(RTR("Global uniform '%s' does not exist. Create it in Project Settings."), String(name)));
return ERR_PARSE_ERROR;
@@ -8238,6 +8375,8 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
uniform.scope = uniform_scope;
uniform.precision = precision;
uniform.array_size = array_size;
+ uniform.group = current_uniform_group_name;
+ uniform.subgroup = current_uniform_subgroup_name;
tk = _get_token();
if (tk.type == TK_BRACKET_OPEN) {
@@ -8261,9 +8400,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
++texture_binding;
}
uniform.order = -1;
- if (_validate_datatype(type) != OK) {
- return ERR_PARSE_ERROR;
- }
} else {
if (uniform_scope == ShaderNode::Uniform::SCOPE_INSTANCE && (type == TYPE_MAT2 || type == TYPE_MAT3 || type == TYPE_MAT4)) {
_set_error(vformat(RTR("The '%s' qualifier is not supported for matrix types."), "SCOPE_INSTANCE"));
@@ -8355,6 +8491,9 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_HINT_DEFAULT_WHITE_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_DEFAULT_WHITE;
} break;
+ case TK_HINT_DEFAULT_TRANSPARENT_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEFAULT_TRANSPARENT;
+ } break;
case TK_HINT_NORMAL_TEXTURE: {
new_hint = ShaderNode::Uniform::HINT_NORMAL;
} break;
@@ -8484,6 +8623,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
}
custom_instance_index = tk.constant;
+ current_uniform_instance_index_defined = true;
if (custom_instance_index >= MAX_INSTANCE_UNIFORM_INDICES) {
_set_error(vformat(RTR("Allowed instance uniform indices must be within [0..%d] range."), MAX_INSTANCE_UNIFORM_INDICES - 1));
@@ -8497,6 +8637,18 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
}
} break;
+ case TK_HINT_SCREEN_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_SCREEN_TEXTURE;
+ --texture_uniforms;
+ } break;
+ case TK_HINT_NORMAL_ROUGHNESS_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_NORMAL_ROUGHNESS_TEXTURE;
+ --texture_uniforms;
+ } break;
+ case TK_HINT_DEPTH_TEXTURE: {
+ new_hint = ShaderNode::Uniform::HINT_DEPTH_TEXTURE;
+ --texture_uniforms;
+ } break;
case TK_FILTER_NEAREST: {
new_filter = FILTER_NEAREST;
} break;
@@ -8521,6 +8673,7 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
case TK_REPEAT_ENABLE: {
new_repeat = REPEAT_ENABLE;
} break;
+
default:
break;
}
@@ -8539,32 +8692,35 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
return ERR_PARSE_ERROR;
} else {
uniform.hint = new_hint;
+ current_uniform_hint = new_hint;
}
}
if (new_filter != FILTER_DEFAULT) {
if (uniform.filter != FILTER_DEFAULT) {
if (uniform.filter == new_filter) {
- _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_filter_name(new_filter)));
+ _set_error(vformat(RTR("Duplicated filter mode: '%s'."), get_texture_filter_name(new_filter)));
} else {
- _set_error(vformat(RTR("Redefinition of hint: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter)));
+ _set_error(vformat(RTR("Redefinition of filter mode: '%s'. The filter mode has already been set to '%s'."), get_texture_filter_name(new_filter), get_texture_filter_name(uniform.filter)));
}
return ERR_PARSE_ERROR;
} else {
uniform.filter = new_filter;
+ current_uniform_filter = new_filter;
}
}
if (new_repeat != REPEAT_DEFAULT) {
if (uniform.repeat != REPEAT_DEFAULT) {
if (uniform.repeat == new_repeat) {
- _set_error(vformat(RTR("Duplicated hint: '%s'."), get_texture_repeat_name(new_repeat)));
+ _set_error(vformat(RTR("Duplicated repeat mode: '%s'."), get_texture_repeat_name(new_repeat)));
} else {
- _set_error(vformat(RTR("Redefinition of hint: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat)));
+ _set_error(vformat(RTR("Redefinition of repeat mode: '%s'. The repeat mode has already been set to '%s'."), get_texture_repeat_name(new_repeat), get_texture_repeat_name(uniform.repeat)));
}
return ERR_PARSE_ERROR;
} else {
uniform.repeat = new_repeat;
+ current_uniform_repeat = new_repeat;
}
}
@@ -8632,6 +8788,11 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
keyword_completion_context = CF_GLOBAL_SPACE;
#endif // DEBUG_ENABLED
completion_type = COMPLETION_NONE;
+
+ current_uniform_hint = ShaderNode::Uniform::HINT_NONE;
+ current_uniform_filter = FILTER_DEFAULT;
+ current_uniform_repeat = REPEAT_DEFAULT;
+ current_uniform_instance_index_defined = false;
} else { // varying
ShaderNode::Varying varying;
varying.type = type;
@@ -8667,6 +8828,45 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
}
} break;
+ case TK_UNIFORM_GROUP: {
+ tk = _get_token();
+ if (tk.type == TK_IDENTIFIER) {
+ current_uniform_group_name = tk.text;
+ tk = _get_token();
+ if (tk.type == TK_PERIOD) {
+ tk = _get_token();
+ if (tk.type == TK_IDENTIFIER) {
+ current_uniform_subgroup_name = tk.text;
+ tk = _get_token();
+ if (tk.type != TK_SEMICOLON) {
+ _set_expected_error(";");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ _set_error(RTR("Expected an uniform subgroup identifier."));
+ return ERR_PARSE_ERROR;
+ }
+ } else if (tk.type != TK_SEMICOLON) {
+ _set_expected_error(";", ".");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
+ if (tk.type != TK_SEMICOLON) {
+ if (current_uniform_group_name.is_empty()) {
+ _set_error(RTR("Expected an uniform group identifier."));
+ } else {
+ _set_error(RTR("Expected an uniform group identifier or `;`."));
+ }
+ return ERR_PARSE_ERROR;
+ } else if (tk.type == TK_SEMICOLON && current_uniform_group_name.is_empty()) {
+ _set_error(RTR("Group needs to be opened before."));
+ return ERR_PARSE_ERROR;
+ } else {
+ current_uniform_group_name = "";
+ current_uniform_subgroup_name = "";
+ }
+ }
+ } break;
case TK_SHADER_TYPE: {
_set_error(RTR("Shader type is already defined."));
return ERR_PARSE_ERROR;
@@ -8739,10 +8939,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
bool fixed_array_size = false;
if (tk.type == TK_BRACKET_OPEN) {
- if (is_constant && RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Global constant arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
Error error = _parse_array_size(nullptr, constants, !is_constant, nullptr, &array_size, &unknown_size);
if (error != OK) {
return error;
@@ -8787,10 +8983,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
constant.array_size = array_size;
if (tk.type == TK_BRACKET_OPEN) {
- if (RenderingServer::get_singleton()->is_low_end()) {
- _set_error(RTR("Global const arrays are only supported on high-end platforms."));
- return ERR_PARSE_ERROR;
- }
Error error = _parse_array_size(nullptr, constants, false, nullptr, &constant.array_size, &unknown_size);
if (error != OK) {
return error;
@@ -9258,9 +9450,6 @@ Error ShaderLanguage::_parse_shader(const HashMap<StringName, FunctionInfo> &p_f
param_type = TYPE_STRUCT;
} else {
param_type = get_token_datatype(tk.type);
- if (_validate_datatype(param_type) != OK) {
- return ERR_PARSE_ERROR;
- }
if (param_type == TYPE_VOID) {
_set_error(RTR("Void type not allowed as argument."));
return ERR_PARSE_ERROR;
@@ -9566,9 +9755,11 @@ uint32_t ShaderLanguage::get_warning_flags() const {
Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_info) {
clear();
+ is_shader_inc = p_info.is_include;
code = p_code;
- global_var_get_type_func = p_info.global_variable_type_func;
+ global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
+
varying_function_names = p_info.varying_function_names;
nodes = nullptr;
@@ -9590,12 +9781,13 @@ Error ShaderLanguage::compile(const String &p_code, const ShaderCompileInfo &p_i
Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint) {
clear();
+ is_shader_inc = p_info.is_include;
code = p_code;
varying_function_names = p_info.varying_function_names;
nodes = nullptr;
- global_var_get_type_func = p_info.global_variable_type_func;
+ global_shader_uniform_get_type_func = p_info.global_shader_uniform_type_func;
shader = alloc_node<ShaderNode>();
_parse_shader(p_info.functions, p_info.render_modes, p_info.shader_types);
@@ -9635,30 +9827,64 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
return OK;
} break;
case COMPLETION_RENDER_MODE: {
- for (int i = 0; i < p_info.render_modes.size(); i++) {
- const ModeInfo &info = p_info.render_modes[i];
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const Vector<ModeInfo> modes = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(i));
- if (!info.options.is_empty()) {
- bool found = false;
+ for (int j = 0; j < modes.size(); j++) {
+ const ModeInfo &info = modes[j];
- for (int j = 0; j < info.options.size(); j++) {
- if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
- found = true;
+ if (!info.options.is_empty()) {
+ bool found = false;
+
+ for (int k = 0; k < info.options.size(); k++) {
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[k]))) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ for (int k = 0; k < info.options.size(); k++) {
+ ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[k]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
}
}
+ }
+ } else {
+ for (int i = 0; i < p_info.render_modes.size(); i++) {
+ const ModeInfo &info = p_info.render_modes[i];
+
+ if (!info.options.is_empty()) {
+ bool found = false;
- if (!found) {
for (int j = 0; j < info.options.size(); j++) {
- ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- r_options->push_back(option);
+ if (shader->render_modes.has(String(info.name) + "_" + String(info.options[j]))) {
+ found = true;
+ }
}
- }
- } else {
- const String name = String(info.name);
- if (!shader->render_modes.has(name)) {
- ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- r_options->push_back(option);
+ if (!found) {
+ for (int j = 0; j < info.options.size(); j++) {
+ ScriptLanguage::CodeCompletionOption option(String(info.name) + "_" + String(info.options[j]), ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
+ }
+ } else {
+ const String name = String(info.name);
+
+ if (!shader->render_modes.has(name)) {
+ ScriptLanguage::CodeCompletionOption option(name, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
}
}
}
@@ -9726,33 +9952,69 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
}
if (comp_ident) {
- if (p_info.functions.has("global")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (is_shader_inc) {
+ for (int i = 0; i < RenderingServer::SHADER_MAX; i++) {
+ const HashMap<StringName, ShaderLanguage::FunctionInfo> info = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(i));
+
+ if (info.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info["global"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (info.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info["constants"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+
+ if (skip_function != StringName() && info.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : info[skip_function].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
+ }
+ }
+ }
+ } else {
+ if (p_info.functions.has("global")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["global"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
- }
- if (p_info.functions.has("constants")) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (p_info.functions.has("constants")) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions["constants"].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
- }
- if (skip_function != StringName() && p_info.functions.has(skip_function)) {
- for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
- ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
- if (E.value.constant) {
- kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ if (skip_function != StringName() && p_info.functions.has(skip_function)) {
+ for (const KeyValue<StringName, BuiltInInfo> &E : p_info.functions[skip_function].built_ins) {
+ ScriptLanguage::CodeCompletionKind kind = ScriptLanguage::CODE_COMPLETION_KIND_MEMBER;
+ if (E.value.constant) {
+ kind = ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT;
+ }
+ matches.insert(E.key, kind);
}
- matches.insert(E.key, kind);
}
}
@@ -10067,31 +10329,37 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
} break;
case COMPLETION_HINT: {
if (completion_base == DataType::TYPE_VEC3 || completion_base == DataType::TYPE_VEC4) {
- ScriptLanguage::CodeCompletionOption option("source_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- r_options->push_back(option);
+ if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) {
+ ScriptLanguage::CodeCompletionOption option("source_color", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_options->push_back(option);
+ }
} else if ((completion_base == DataType::TYPE_INT || completion_base == DataType::TYPE_FLOAT) && !completion_base_array) {
- ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) {
+ ScriptLanguage::CodeCompletionOption option("hint_range", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
- if (completion_base == DataType::TYPE_INT) {
- option.insert_text = "hint_range(0, 100, 1)";
- } else {
- option.insert_text = "hint_range(0.0, 1.0, 0.1)";
- }
+ if (completion_base == DataType::TYPE_INT) {
+ option.insert_text = "hint_range(0, 100, 1)";
+ } else {
+ option.insert_text = "hint_range(0.0, 1.0, 0.1)";
+ }
- r_options->push_back(option);
+ r_options->push_back(option);
+ }
} else if ((int(completion_base) > int(TYPE_MAT4) && int(completion_base) < int(TYPE_STRUCT)) && !completion_base_array) {
- static Vector<String> options;
-
- if (options.is_empty()) {
+ Vector<String> options;
+ if (current_uniform_filter == FILTER_DEFAULT) {
options.push_back("filter_linear");
options.push_back("filter_linear_mipmap");
options.push_back("filter_linear_mipmap_anisotropic");
options.push_back("filter_nearest");
options.push_back("filter_nearest_mipmap");
options.push_back("filter_nearest_mipmap_anisotropic");
+ }
+ if (current_uniform_hint == ShaderNode::Uniform::HINT_NONE) {
options.push_back("hint_anisotropy");
options.push_back("hint_default_black");
options.push_back("hint_default_white");
+ options.push_back("hint_default_transparent");
options.push_back("hint_normal");
options.push_back("hint_roughness_a");
options.push_back("hint_roughness_b");
@@ -10099,7 +10367,12 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
options.push_back("hint_roughness_gray");
options.push_back("hint_roughness_normal");
options.push_back("hint_roughness_r");
+ options.push_back("hint_screen_texture");
+ options.push_back("hint_normal_roughness_texture");
+ options.push_back("hint_depth_texture");
options.push_back("source_color");
+ }
+ if (current_uniform_repeat == REPEAT_DEFAULT) {
options.push_back("repeat_enable");
options.push_back("repeat_disable");
}
@@ -10109,7 +10382,7 @@ Error ShaderLanguage::complete(const String &p_code, const ShaderCompileInfo &p_
r_options->push_back(option);
}
}
- if (!completion_base_array) {
+ if (!completion_base_array && !current_uniform_instance_index_defined) {
ScriptLanguage::CodeCompletionOption option("instance_index", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
option.insert_text = "instance_index(0)";
r_options->push_back(option);
@@ -10124,6 +10397,10 @@ String ShaderLanguage::get_error_text() {
return error_str;
}
+Vector<ShaderLanguage::FilePosition> ShaderLanguage::get_include_positions() {
+ return include_positions;
+}
+
int ShaderLanguage::get_error_line() {
return error_line;
}
diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h
index a4226a9764..1e302f5805 100644
--- a/servers/rendering/shader_language.h
+++ b/servers/rendering/shader_language.h
@@ -38,6 +38,7 @@
#include "core/templates/rb_map.h"
#include "core/typedefs.h"
#include "core/variant/variant.h"
+#include "scene/resources/shader_include.h"
#ifdef DEBUG_ENABLED
#include "shader_warnings.h"
@@ -153,6 +154,7 @@ public:
TK_SEMICOLON,
TK_PERIOD,
TK_UNIFORM,
+ TK_UNIFORM_GROUP,
TK_INSTANCE,
TK_GLOBAL,
TK_VARYING,
@@ -162,6 +164,7 @@ public:
TK_RENDER_MODE,
TK_HINT_DEFAULT_WHITE_TEXTURE,
TK_HINT_DEFAULT_BLACK_TEXTURE,
+ TK_HINT_DEFAULT_TRANSPARENT_TEXTURE,
TK_HINT_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_NORMAL_TEXTURE,
TK_HINT_ROUGHNESS_R,
@@ -173,6 +176,9 @@ public:
TK_HINT_SOURCE_COLOR,
TK_HINT_RANGE,
TK_HINT_INSTANCE_INDEX,
+ TK_HINT_SCREEN_TEXTURE,
+ TK_HINT_NORMAL_ROUGHNESS_TEXTURE,
+ TK_HINT_DEPTH_TEXTURE,
TK_FILTER_NEAREST,
TK_FILTER_LINEAR,
TK_FILTER_NEAREST_MIPMAP,
@@ -477,7 +483,7 @@ public:
int array_size = 0;
union Value {
- bool boolean;
+ bool boolean = false;
float real;
int32_t sint;
uint32_t uint;
@@ -662,7 +668,11 @@ public:
HINT_ROUGHNESS_GRAY,
HINT_DEFAULT_BLACK,
HINT_DEFAULT_WHITE,
+ HINT_DEFAULT_TRANSPARENT,
HINT_ANISOTROPY,
+ HINT_SCREEN_TEXTURE,
+ HINT_NORMAL_ROUGHNESS_TEXTURE,
+ HINT_DEPTH_TEXTURE,
HINT_MAX
};
@@ -686,6 +696,8 @@ public:
TextureRepeat repeat = REPEAT_DEFAULT;
float hint_range[3];
int instance_index = 0;
+ String group;
+ String subgroup;
Uniform() {
hint_range[0] = 0.0f;
@@ -865,7 +877,12 @@ public:
};
static bool has_builtin(const HashMap<StringName, ShaderLanguage::FunctionInfo> &p_functions, const StringName &p_name);
- typedef DataType (*GlobalVariableGetTypeFunc)(const StringName &p_name);
+ typedef DataType (*GlobalShaderUniformGetTypeFunc)(const StringName &p_name);
+
+ struct FilePosition {
+ String file;
+ int line = 0;
+ };
private:
struct KeyWord {
@@ -878,12 +895,14 @@ private:
static const KeyWord keyword_list[];
- GlobalVariableGetTypeFunc global_var_get_type_func = nullptr;
+ GlobalShaderUniformGetTypeFunc global_shader_uniform_get_type_func = nullptr;
bool error_set = false;
String error_str;
int error_line = 0;
+ Vector<FilePosition> include_positions;
+
#ifdef DEBUG_ENABLED
struct Usage {
int decl_line;
@@ -928,6 +947,10 @@ private:
StringName current_function;
bool last_const = false;
StringName last_name;
+ bool is_shader_inc = false;
+
+ String current_uniform_group_name;
+ String current_uniform_subgroup_name;
VaryingFunctionNames varying_function_names;
@@ -951,6 +974,7 @@ private:
error_line = tk_line;
error_set = true;
error_str = p_str;
+ include_positions.write[include_positions.size() - 1].line = tk_line;
}
void _set_expected_error(const String &p_what) {
@@ -1026,6 +1050,10 @@ private:
};
CompletionType completion_type;
+ ShaderNode::Uniform::Hint current_uniform_hint = ShaderNode::Uniform::HINT_NONE;
+ TextureFilter current_uniform_filter = FILTER_DEFAULT;
+ TextureRepeat current_uniform_repeat = REPEAT_DEFAULT;
+ bool current_uniform_instance_index_defined = false;
int completion_line = 0;
BlockNode *completion_block = nullptr;
DataType completion_base;
@@ -1049,7 +1077,6 @@ private:
static bool is_const_suffix_lut_initialized;
Error _validate_precision(DataType p_type, DataPrecision p_precision);
- Error _validate_datatype(DataType p_type);
bool _compare_datatypes(DataType p_datatype_a, String p_datatype_name_a, int p_array_size_a, DataType p_datatype_b, String p_datatype_name_b, int p_array_size_b);
bool _compare_datatypes_in_nodes(Node *a, Node *b);
@@ -1098,13 +1125,15 @@ public:
Vector<ModeInfo> render_modes;
VaryingFunctionNames varying_function_names = VaryingFunctionNames();
HashSet<String> shader_types;
- GlobalVariableGetTypeFunc global_variable_type_func = nullptr;
+ GlobalShaderUniformGetTypeFunc global_shader_uniform_type_func = nullptr;
+ bool is_include = false;
};
Error compile(const String &p_code, const ShaderCompileInfo &p_info);
Error complete(const String &p_code, const ShaderCompileInfo &p_info, List<ScriptLanguage::CodeCompletionOption> *r_options, String &r_call_hint);
String get_error_text();
+ Vector<FilePosition> get_include_positions();
int get_error_line();
ShaderNode *get_shader();
diff --git a/servers/rendering/shader_preprocessor.cpp b/servers/rendering/shader_preprocessor.cpp
new file mode 100644
index 0000000000..46e76fbe92
--- /dev/null
+++ b/servers/rendering/shader_preprocessor.cpp
@@ -0,0 +1,1277 @@
+/*************************************************************************/
+/* shader_preprocessor.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "shader_preprocessor.h"
+#include "core/math/expression.h"
+
+const char32_t CURSOR = 0xFFFF;
+
+// Tokenizer
+
+void ShaderPreprocessor::Tokenizer::add_generated(const ShaderPreprocessor::Token &p_t) {
+ generated.push_back(p_t);
+}
+
+char32_t ShaderPreprocessor::Tokenizer::next() {
+ if (index < size) {
+ return code[index++];
+ }
+ return 0;
+}
+
+int ShaderPreprocessor::Tokenizer::get_line() const {
+ return line;
+}
+
+int ShaderPreprocessor::Tokenizer::get_index() const {
+ return index;
+}
+
+void ShaderPreprocessor::Tokenizer::get_and_clear_generated(Vector<ShaderPreprocessor::Token> *r_out) {
+ for (int i = 0; i < generated.size(); i++) {
+ r_out->push_back(generated[i]);
+ }
+ generated.clear();
+}
+
+void ShaderPreprocessor::Tokenizer::backtrack(char32_t p_what) {
+ while (index >= 0) {
+ char32_t c = code[index];
+ if (c == p_what) {
+ break;
+ }
+ index--;
+ }
+}
+
+char32_t ShaderPreprocessor::Tokenizer::peek() {
+ if (index < size) {
+ return code[index];
+ }
+ return 0;
+}
+
+LocalVector<ShaderPreprocessor::Token> ShaderPreprocessor::Tokenizer::advance(char32_t p_what) {
+ LocalVector<ShaderPreprocessor::Token> tokens;
+
+ while (index < size) {
+ char32_t c = code[index++];
+
+ tokens.push_back(ShaderPreprocessor::Token(c, line));
+
+ if (c == '\n') {
+ add_generated(ShaderPreprocessor::Token('\n', line));
+ line++;
+ }
+
+ if (c == p_what || c == 0) {
+ return tokens;
+ }
+ }
+ return LocalVector<ShaderPreprocessor::Token>();
+}
+
+void ShaderPreprocessor::Tokenizer::skip_whitespace() {
+ while (is_char_space(peek())) {
+ next();
+ }
+}
+
+String ShaderPreprocessor::Tokenizer::get_identifier(bool *r_is_cursor, bool p_started) {
+ if (r_is_cursor != nullptr) {
+ *r_is_cursor = false;
+ }
+
+ LocalVector<char32_t> text;
+
+ while (true) {
+ char32_t c = peek();
+ if (is_char_end(c) || c == '(' || c == ')' || c == ',' || c == ';') {
+ break;
+ }
+
+ if (is_whitespace(c) && p_started) {
+ break;
+ }
+ if (!is_whitespace(c)) {
+ p_started = true;
+ }
+
+ char32_t n = next();
+ if (n == CURSOR) {
+ if (r_is_cursor != nullptr) {
+ *r_is_cursor = true;
+ }
+ } else {
+ if (p_started) {
+ text.push_back(n);
+ }
+ }
+ }
+
+ String id = vector_to_string(text);
+ if (!id.is_valid_identifier()) {
+ return "";
+ }
+
+ return id;
+}
+
+String ShaderPreprocessor::Tokenizer::peek_identifier() {
+ const int original = index;
+ String id = get_identifier();
+ index = original;
+ return id;
+}
+
+ShaderPreprocessor::Token ShaderPreprocessor::Tokenizer::get_token() {
+ while (index < size) {
+ const char32_t c = code[index++];
+ const Token t = ShaderPreprocessor::Token(c, line);
+
+ switch (c) {
+ case ' ':
+ case '\t':
+ skip_whitespace();
+ return ShaderPreprocessor::Token(' ', line);
+ case '\n':
+ line++;
+ return t;
+ default:
+ return t;
+ }
+ }
+ return ShaderPreprocessor::Token(char32_t(0), line);
+}
+
+ShaderPreprocessor::Tokenizer::Tokenizer(const String &p_code) {
+ code = p_code;
+ line = 0;
+ index = 0;
+ size = code.size();
+}
+
+// ShaderPreprocessor::CommentRemover
+
+String ShaderPreprocessor::CommentRemover::get_error() const {
+ if (comments_open != 0) {
+ return "Block comment mismatch";
+ }
+ return "";
+}
+
+int ShaderPreprocessor::CommentRemover::get_error_line() const {
+ if (comments_open != 0) {
+ return comment_line_open;
+ }
+ return -1;
+}
+
+char32_t ShaderPreprocessor::CommentRemover::peek() const {
+ if (index < code.size()) {
+ return code[index];
+ }
+ return 0;
+}
+
+bool ShaderPreprocessor::CommentRemover::advance(char32_t p_what) {
+ while (index < code.size()) {
+ char32_t c = code[index++];
+
+ if (c == '\n') {
+ line++;
+ stripped.push_back('\n');
+ }
+
+ if (c == p_what) {
+ return true;
+ }
+ }
+ return false;
+}
+
+String ShaderPreprocessor::CommentRemover::strip() {
+ stripped.clear();
+ index = 0;
+ line = 0;
+ comment_line_open = 0;
+ comments_open = 0;
+ strings_open = 0;
+
+ while (index < code.size()) {
+ char32_t c = code[index++];
+
+ if (c == CURSOR) {
+ // Cursor. Maintain.
+ stripped.push_back(c);
+ } else if (c == '"') {
+ if (strings_open <= 0) {
+ strings_open++;
+ } else {
+ strings_open--;
+ }
+ stripped.push_back(c);
+ } else if (c == '/' && strings_open == 0) {
+ char32_t p = peek();
+ if (p == '/') { // Single line comment.
+ advance('\n');
+ } else if (p == '*') { // Start of a block comment.
+ index++;
+ comment_line_open = line;
+ comments_open++;
+ while (advance('*')) {
+ if (peek() == '/') { // End of a block comment.
+ comments_open--;
+ index++;
+ break;
+ }
+ }
+ } else {
+ stripped.push_back(c);
+ }
+ } else if (c == '*' && strings_open == 0) {
+ if (peek() == '/') { // Unmatched end of a block comment.
+ comment_line_open = line;
+ comments_open--;
+ } else {
+ stripped.push_back(c);
+ }
+ } else if (c == '\n') {
+ line++;
+ stripped.push_back(c);
+ } else {
+ stripped.push_back(c);
+ }
+ }
+ return vector_to_string(stripped);
+}
+
+ShaderPreprocessor::CommentRemover::CommentRemover(const String &p_code) {
+ code = p_code;
+ index = 0;
+ line = 0;
+ comment_line_open = 0;
+ comments_open = 0;
+ strings_open = 0;
+}
+
+// ShaderPreprocessor::Token
+
+ShaderPreprocessor::Token::Token() {
+ text = 0;
+ line = -1;
+}
+
+ShaderPreprocessor::Token::Token(char32_t p_text, int p_line) {
+ text = p_text;
+ line = p_line;
+}
+
+// ShaderPreprocessor
+
+bool ShaderPreprocessor::is_char_word(char32_t p_char) {
+ if ((p_char >= '0' && p_char <= '9') ||
+ (p_char >= 'a' && p_char <= 'z') ||
+ (p_char >= 'A' && p_char <= 'Z') ||
+ p_char == '_') {
+ return true;
+ }
+
+ return false;
+}
+
+bool ShaderPreprocessor::is_char_space(char32_t p_char) {
+ return p_char == ' ' || p_char == '\t';
+}
+
+bool ShaderPreprocessor::is_char_end(char32_t p_char) {
+ return p_char == '\n' || p_char == 0;
+}
+
+String ShaderPreprocessor::vector_to_string(const LocalVector<char32_t> &p_v, int p_start, int p_end) {
+ const int stop = (p_end == -1) ? p_v.size() : p_end;
+ const int count = stop - p_start;
+
+ String result;
+ result.resize(count + 1);
+ for (int i = 0; i < count; i++) {
+ result[i] = p_v[p_start + i];
+ }
+ result[count] = 0; // Ensure string is null terminated for length() to work.
+ return result;
+}
+
+String ShaderPreprocessor::tokens_to_string(const LocalVector<Token> &p_tokens) {
+ LocalVector<char32_t> result;
+ for (uint32_t i = 0; i < p_tokens.size(); i++) {
+ result.push_back(p_tokens[i].text);
+ }
+ return vector_to_string(result);
+}
+
+void ShaderPreprocessor::process_directive(Tokenizer *p_tokenizer) {
+ bool is_cursor;
+ String directive = p_tokenizer->get_identifier(&is_cursor, true);
+ if (is_cursor) {
+ state->completion_type = COMPLETION_TYPE_DIRECTIVE;
+ }
+
+ if (directive == "if") {
+ process_if(p_tokenizer);
+ } else if (directive == "ifdef") {
+ process_ifdef(p_tokenizer);
+ } else if (directive == "ifndef") {
+ process_ifndef(p_tokenizer);
+ } else if (directive == "elif") {
+ process_elif(p_tokenizer);
+ } else if (directive == "else") {
+ process_else(p_tokenizer);
+ } else if (directive == "endif") {
+ process_endif(p_tokenizer);
+ } else if (directive == "define") {
+ process_define(p_tokenizer);
+ } else if (directive == "undef") {
+ process_undef(p_tokenizer);
+ } else if (directive == "include") {
+ process_include(p_tokenizer);
+ } else if (directive == "pragma") {
+ process_pragma(p_tokenizer);
+ } else {
+ set_error(RTR("Unknown directive."), p_tokenizer->get_line());
+ }
+}
+
+void ShaderPreprocessor::process_define(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ if (state->defines.has(label)) {
+ set_error(RTR("Macro redefinition."), line);
+ return;
+ }
+
+ if (p_tokenizer->peek() == '(') {
+ // Macro has arguments.
+ p_tokenizer->get_token();
+
+ Vector<String> args;
+ while (true) {
+ String name = p_tokenizer->get_identifier();
+ if (name.is_empty()) {
+ set_error(RTR("Invalid argument name."), line);
+ return;
+ }
+ args.push_back(name);
+
+ p_tokenizer->skip_whitespace();
+ char32_t next = p_tokenizer->get_token().text;
+ if (next == ')') {
+ break;
+ } else if (next != ',') {
+ set_error(RTR("Expected a comma in the macro argument list."), line);
+ return;
+ }
+ }
+
+ Define *define = memnew(Define);
+ define->arguments = args;
+ define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ state->defines[label] = define;
+ } else {
+ // Simple substitution macro.
+ Define *define = memnew(Define);
+ define->body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ state->defines[label] = define;
+ }
+}
+
+void ShaderPreprocessor::process_elif(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ if (state->current_branch == nullptr || state->current_branch->else_defined) {
+ set_error(RTR("Unmatched elif."), line);
+ return;
+ }
+ if (state->previous_region != nullptr) {
+ state->previous_region->to_line = line - 1;
+ }
+
+ String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ if (body.is_empty()) {
+ set_error(RTR("Missing condition."), line);
+ return;
+ }
+
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ Expression expression;
+ Vector<String> names;
+ error = expression.parse(body, names);
+ if (error != OK) {
+ set_error(expression.get_error_text(), line);
+ return;
+ }
+
+ Variant v = expression.execute(Array(), nullptr, false);
+ if (v.get_type() == Variant::NIL) {
+ set_error(RTR("Condition evaluation error."), line);
+ return;
+ }
+
+ bool skip = false;
+ for (int i = 0; i < state->current_branch->conditions.size(); i++) {
+ if (state->current_branch->conditions[i]) {
+ skip = true;
+ break;
+ }
+ }
+
+ bool success = !skip && v.booleanize();
+ start_branch_condition(p_tokenizer, success, true);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region->parent);
+ }
+}
+
+void ShaderPreprocessor::process_else(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ if (state->current_branch == nullptr || state->current_branch->else_defined) {
+ set_error(RTR("Unmatched else."), line);
+ return;
+ }
+ if (state->previous_region != nullptr) {
+ state->previous_region->to_line = line - 1;
+ }
+
+ p_tokenizer->advance('\n');
+
+ bool skip = false;
+ for (int i = 0; i < state->current_branch->conditions.size(); i++) {
+ if (state->current_branch->conditions[i]) {
+ skip = true;
+ break;
+ }
+ }
+ state->current_branch->else_defined = true;
+
+ if (state->save_regions) {
+ add_region(line + 1, !skip, state->previous_region->parent);
+ }
+
+ if (skip) {
+ Vector<String> ends;
+ ends.push_back("endif");
+ next_directive(p_tokenizer, ends);
+ }
+}
+
+void ShaderPreprocessor::process_endif(Tokenizer *p_tokenizer) {
+ state->condition_depth--;
+ if (state->condition_depth < 0) {
+ set_error(RTR("Unmatched endif."), p_tokenizer->get_line());
+ return;
+ }
+ if (state->previous_region != nullptr) {
+ state->previous_region->to_line = p_tokenizer->get_line() - 1;
+ state->previous_region = state->previous_region->parent;
+ }
+
+ p_tokenizer->advance('\n');
+
+ state->current_branch = state->current_branch->parent;
+ state->branches.pop_back();
+}
+
+void ShaderPreprocessor::process_if(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String body = tokens_to_string(p_tokenizer->advance('\n')).strip_edges();
+ if (body.is_empty()) {
+ set_error(RTR("Missing condition."), line);
+ return;
+ }
+
+ Error error = expand_condition(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ error = expand_macros(body, line, body);
+ if (error != OK) {
+ return;
+ }
+
+ Expression expression;
+ Vector<String> names;
+ error = expression.parse(body, names);
+ if (error != OK) {
+ set_error(expression.get_error_text(), line);
+ return;
+ }
+
+ Variant v = expression.execute(Array(), nullptr, false);
+ if (v.get_type() == Variant::NIL) {
+ set_error(RTR("Condition evaluation error."), line);
+ return;
+ }
+
+ bool success = v.booleanize();
+ start_branch_condition(p_tokenizer, success);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region);
+ }
+}
+
+void ShaderPreprocessor::process_ifdef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid ifdef."), line);
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool success = state->defines.has(label);
+ start_branch_condition(p_tokenizer, success);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region);
+ }
+}
+
+void ShaderPreprocessor::process_ifndef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ String label = p_tokenizer->get_identifier();
+ if (label.is_empty()) {
+ set_error(RTR("Invalid macro name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid ifndef."), line);
+ return;
+ }
+ p_tokenizer->advance('\n');
+
+ bool success = !state->defines.has(label);
+ start_branch_condition(p_tokenizer, success);
+
+ if (state->save_regions) {
+ add_region(line + 1, success, state->previous_region);
+ }
+}
+
+void ShaderPreprocessor::process_include(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ p_tokenizer->advance('"');
+ String path = tokens_to_string(p_tokenizer->advance('"'));
+ for (int i = 0; i < path.length(); i++) {
+ if (path[i] == '\n') {
+ break; //stop parsing
+ }
+ if (path[i] == CURSOR) {
+ state->completion_type = COMPLETION_TYPE_INCLUDE_PATH;
+ break;
+ }
+ }
+ path = path.substr(0, path.length() - 1);
+ p_tokenizer->skip_whitespace();
+
+ if (path.is_empty() || !is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid path."), line);
+ return;
+ }
+
+ Ref<Resource> res = ResourceLoader::load(path);
+ if (res.is_null()) {
+ set_error(RTR("Shader include load failed. Does the shader include exist? Is there a cyclic dependency?"), line);
+ return;
+ }
+
+ Ref<ShaderInclude> shader_inc = res;
+ if (shader_inc.is_null()) {
+ set_error(RTR("Shader include resource type is wrong."), line);
+ return;
+ }
+
+ String included = shader_inc->get_code();
+ if (!included.is_empty()) {
+ uint64_t code_hash = included.hash64();
+ if (state->cyclic_include_hashes.find(code_hash)) {
+ set_error(RTR("Cyclic include found."), line);
+ return;
+ }
+ }
+
+ state->shader_includes.insert(shader_inc);
+
+ const String real_path = shader_inc->get_path();
+ if (state->includes.has(real_path)) {
+ // Already included, skip.
+ // This is a valid check because 2 separate include paths could use some
+ // of the same shared functions from a common shader include.
+ return;
+ }
+
+ // Mark as included.
+ state->includes.insert(real_path);
+
+ state->include_depth++;
+ if (state->include_depth > 25) {
+ set_error(RTR("Shader max include depth exceeded."), line);
+ return;
+ }
+
+ String old_filename = state->current_filename;
+ state->current_filename = real_path;
+ ShaderPreprocessor processor;
+
+ int prev_condition_depth = state->condition_depth;
+ state->condition_depth = 0;
+
+ FilePosition fp;
+ fp.file = state->current_filename;
+ fp.line = line;
+ state->include_positions.push_back(fp);
+
+ String result;
+ processor.preprocess(state, included, result);
+ add_to_output("@@>" + real_path + "\n"); // Add token for enter include path
+ add_to_output(result);
+ add_to_output("\n@@<\n"); // Add token for exit include path
+
+ // Reset to last include if there are no errors. We want to use this as context.
+ if (state->error.is_empty()) {
+ state->current_filename = old_filename;
+ state->include_positions.pop_back();
+ } else {
+ return;
+ }
+
+ state->include_depth--;
+ state->condition_depth = prev_condition_depth;
+}
+
+void ShaderPreprocessor::process_pragma(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+
+ bool is_cursor;
+ const String label = p_tokenizer->get_identifier(&is_cursor);
+ if (is_cursor) {
+ state->completion_type = COMPLETION_TYPE_PRAGMA;
+ }
+
+ if (label.is_empty()) {
+ set_error(RTR("Invalid pragma directive."), line);
+ return;
+ }
+
+ // Rxplicitly handle pragma values here.
+ // If more pragma options are created, then refactor into a more defined structure.
+ if (label == "disable_preprocessor") {
+ state->disabled = true;
+ } else {
+ set_error(RTR("Invalid pragma directive."), line);
+ return;
+ }
+
+ p_tokenizer->advance('\n');
+}
+
+void ShaderPreprocessor::process_undef(Tokenizer *p_tokenizer) {
+ const int line = p_tokenizer->get_line();
+ const String label = p_tokenizer->get_identifier();
+ if (label.is_empty() || !state->defines.has(label)) {
+ set_error(RTR("Invalid name."), line);
+ return;
+ }
+
+ p_tokenizer->skip_whitespace();
+ if (!is_char_end(p_tokenizer->peek())) {
+ set_error(RTR("Invalid undef."), line);
+ return;
+ }
+
+ memdelete(state->defines[label]);
+ state->defines.erase(label);
+}
+
+void ShaderPreprocessor::add_region(int p_line, bool p_enabled, Region *p_parent_region) {
+ Region region;
+ region.file = state->current_filename;
+ region.enabled = p_enabled;
+ region.from_line = p_line;
+ region.parent = p_parent_region;
+ state->previous_region = &state->regions[region.file].push_back(region)->get();
+}
+
+void ShaderPreprocessor::start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue) {
+ if (!p_continue) {
+ state->condition_depth++;
+ state->current_branch = &state->branches.push_back(Branch(p_success, state->current_branch))->get();
+ } else {
+ state->current_branch->conditions.push_back(p_success);
+ }
+ if (!p_success) {
+ Vector<String> ends;
+ ends.push_back("elif");
+ ends.push_back("else");
+ ends.push_back("endif");
+ next_directive(p_tokenizer, ends);
+ }
+}
+
+void ShaderPreprocessor::expand_output_macros(int p_start, int p_line_number) {
+ String line = vector_to_string(output, p_start, output.size());
+
+ Error error = expand_macros(line, p_line_number - 1, line); // We are already on next line, so -1.
+ if (error != OK) {
+ return;
+ }
+
+ output.resize(p_start);
+
+ add_to_output(line);
+}
+
+Error ShaderPreprocessor::expand_condition(const String &p_string, int p_line, String &r_expanded) {
+ // Checks bracket count to be even + check the cursor position.
+ {
+ int bracket_start_count = 0;
+ int bracket_end_count = 0;
+
+ for (int i = 0; i < p_string.size(); i++) {
+ switch (p_string[i]) {
+ case CURSOR:
+ state->completion_type = COMPLETION_TYPE_CONDITION;
+ break;
+ case '(':
+ bracket_start_count++;
+ break;
+ case ')':
+ bracket_end_count++;
+ break;
+ }
+ }
+ if (bracket_start_count > bracket_end_count) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (bracket_end_count > bracket_start_count) {
+ _set_expected_error("(", p_line);
+ return FAILED;
+ }
+ }
+
+ String result = p_string;
+
+ int index = 0;
+ int index_start = 0;
+ int index_end = 0;
+
+ while (find_match(result, "defined", index, index_start)) {
+ bool open_bracket = false;
+ bool found_word = false;
+ bool word_completed = false;
+
+ LocalVector<char32_t> text;
+ int post_bracket_index = -1;
+ int size = result.size();
+
+ for (int i = (index_start - 1); i < size; i++) {
+ char32_t c = result[i];
+ if (c == 0) {
+ if (found_word) {
+ word_completed = true;
+ }
+ break;
+ }
+ char32_t cs[] = { c, '\0' };
+ String s = String(cs);
+ bool is_space = is_char_space(c);
+
+ if (word_completed) {
+ if (c == ')') {
+ continue;
+ }
+ if (c == '|' || c == '&') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ break;
+ } else if (!is_space) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ } else if (is_space) {
+ if (found_word && !open_bracket) {
+ index_end = i;
+ word_completed = true;
+ }
+ } else if (c == '(') {
+ if (open_bracket) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = true;
+ } else if (c == ')') {
+ if (open_bracket) {
+ if (!found_word) {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ open_bracket = false;
+ post_bracket_index = i + 1;
+ } else {
+ index_end = i;
+ }
+ word_completed = true;
+ } else if (is_char_word(c)) {
+ text.push_back(c);
+ found_word = true;
+ } else {
+ _set_unexpected_token_error(s, p_line);
+ return FAILED;
+ }
+ }
+
+ if (word_completed) {
+ if (open_bracket) {
+ _set_expected_error(")", p_line);
+ return FAILED;
+ }
+ if (post_bracket_index != -1) {
+ index_end = post_bracket_index;
+ }
+
+ String body = state->defines.has(vector_to_string(text)) ? "true" : "false";
+ String temp = result;
+
+ result = result.substr(0, index) + body;
+ index_start = result.length();
+ if (index_end > 0) {
+ result += temp.substr(index_end);
+ }
+ } else {
+ set_error(RTR("Invalid macro name."), p_line);
+ return FAILED;
+ }
+ }
+ r_expanded = result;
+ return OK;
+}
+
+Error ShaderPreprocessor::expand_macros(const String &p_string, int p_line, String &r_expanded) {
+ String iterative = p_string;
+ int pass_count = 0;
+ bool expanded = true;
+
+ while (expanded) {
+ expanded = false;
+
+ // As long as we find something to expand, keep going.
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ if (expand_macros_once(iterative, p_line, E, iterative)) {
+ expanded = true;
+ }
+ }
+
+ pass_count++;
+ if (pass_count > 50) {
+ set_error(RTR("Macro expansion limit exceeded."), p_line);
+ break;
+ }
+ }
+
+ r_expanded = iterative;
+
+ if (!state->error.is_empty()) {
+ return FAILED;
+ }
+ return OK;
+}
+
+bool ShaderPreprocessor::expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded) {
+ String result = p_line;
+
+ const String &key = p_define_pair->key();
+ const Define *define = p_define_pair->value();
+
+ int index_start = 0;
+ int index = 0;
+ if (find_match(result, key, index, index_start)) {
+ String body = define->body;
+ if (define->arguments.size() > 0) {
+ // Complex macro with arguments.
+ int args_start = index + key.length();
+ int args_end = p_line.find(")", args_start);
+ if (args_start == -1 || args_end == -1) {
+ set_error(RTR("Missing macro argument parenthesis."), p_line_number);
+ return false;
+ }
+
+ String values = result.substr(args_start + 1, args_end - (args_start + 1));
+ Vector<String> args = values.split(",");
+ if (args.size() != define->arguments.size()) {
+ set_error(RTR("Invalid macro argument count."), p_line_number);
+ return false;
+ }
+
+ // Insert macro arguments into the body.
+ for (int i = 0; i < args.size(); i++) {
+ String arg_name = define->arguments[i];
+ int arg_index_start = 0;
+ int arg_index = 0;
+ while (find_match(body, arg_name, arg_index, arg_index_start)) {
+ body = body.substr(0, arg_index) + args[i] + body.substr(arg_index + arg_name.length(), body.length() - (arg_index + arg_name.length()));
+ // Manually reset arg_index_start to where the arg value of the define finishes.
+ // This ensures we don't skip the other args of this macro in the string.
+ arg_index_start = arg_index + args[i].length() + 1;
+ }
+ }
+
+ result = result.substr(0, index) + " " + body + " " + result.substr(args_end + 1, result.length());
+ } else {
+ result = result.substr(0, index) + body + result.substr(index + key.length(), result.length() - (index + key.length()));
+ // Manually reset index_start to where the body value of the define finishes.
+ // This ensures we don't skip another instance of this macro in the string.
+ index_start = index + body.length() + 1;
+ }
+
+ r_expanded = result;
+ return true;
+ }
+
+ return false;
+}
+
+bool ShaderPreprocessor::find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start) {
+ // Looks for value in string and then determines if the boundaries
+ // are non-word characters. This method semi-emulates \b in regex.
+ r_index = p_string.find(p_value, r_index_start);
+ while (r_index > -1) {
+ if (r_index > 0) {
+ if (is_char_word(p_string[r_index - 1])) {
+ r_index_start = r_index + 1;
+ r_index = p_string.find(p_value, r_index_start);
+ continue;
+ }
+ }
+
+ if (r_index + p_value.length() < p_string.length()) {
+ if (is_char_word(p_string[r_index + p_value.length()])) {
+ r_index_start = r_index + p_value.length() + 1;
+ r_index = p_string.find(p_value, r_index_start);
+ continue;
+ }
+ }
+
+ // Return and shift index start automatically for next call.
+ r_index_start = r_index + p_value.length() + 1;
+ return true;
+ }
+
+ return false;
+}
+
+String ShaderPreprocessor::next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives) {
+ const int line = p_tokenizer->get_line();
+ int nesting = 0;
+
+ while (true) {
+ p_tokenizer->advance('#');
+
+ String id = p_tokenizer->peek_identifier();
+ if (id.is_empty()) {
+ break;
+ }
+
+ if (nesting == 0) {
+ for (int i = 0; i < p_directives.size(); i++) {
+ if (p_directives[i] == id) {
+ p_tokenizer->backtrack('#');
+ return id;
+ }
+ }
+ }
+
+ if (id == "ifdef" || id == "ifndef" || id == "if") {
+ nesting++;
+ } else if (id == "endif") {
+ nesting--;
+ }
+ }
+
+ set_error(RTR("Can't find matching branch directive."), line);
+ return "";
+}
+
+void ShaderPreprocessor::add_to_output(const String &p_str) {
+ for (int i = 0; i < p_str.length(); i++) {
+ output.push_back(p_str[i]);
+ }
+}
+
+void ShaderPreprocessor::set_error(const String &p_error, int p_line) {
+ if (state->error.is_empty()) {
+ state->error = p_error;
+ FilePosition fp;
+ fp.line = p_line + 1;
+ state->include_positions.push_back(fp);
+ }
+}
+
+ShaderPreprocessor::Define *ShaderPreprocessor::create_define(const String &p_body) {
+ ShaderPreprocessor::Define *define = memnew(Define);
+ define->body = p_body;
+ return define;
+}
+
+void ShaderPreprocessor::clear() {
+ if (state_owner && state != nullptr) {
+ for (const RBMap<String, Define *>::Element *E = state->defines.front(); E; E = E->next()) {
+ memdelete(E->get());
+ }
+
+ memdelete(state);
+ }
+ state_owner = false;
+ state = nullptr;
+}
+
+Error ShaderPreprocessor::preprocess(State *p_state, const String &p_code, String &r_result) {
+ clear();
+
+ output.clear();
+
+ state = p_state;
+
+ CommentRemover remover(p_code);
+ String stripped = remover.strip();
+ String error = remover.get_error();
+ if (!error.is_empty()) {
+ set_error(error, remover.get_error_line());
+ return FAILED;
+ }
+
+ // Track code hashes to prevent cyclic include.
+ uint64_t code_hash = p_code.hash64();
+ state->cyclic_include_hashes.push_back(code_hash);
+
+ Tokenizer p_tokenizer(stripped);
+ int last_size = 0;
+ bool has_symbols_before_directive = false;
+
+ while (true) {
+ const Token &t = p_tokenizer.get_token();
+
+ if (t.text == 0) {
+ break;
+ }
+
+ if (state->disabled) {
+ // Preprocessor was disabled.
+ // Read the rest of the file into the output.
+ output.push_back(t.text);
+ continue;
+ } else {
+ // Add autogenerated tokens.
+ Vector<Token> generated;
+ p_tokenizer.get_and_clear_generated(&generated);
+ for (int i = 0; i < generated.size(); i++) {
+ output.push_back(generated[i].text);
+ }
+ }
+
+ if (t.text == '#') {
+ if (has_symbols_before_directive) {
+ set_error(RTR("Invalid symbols placed before directive."), p_tokenizer.get_line());
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+ return FAILED;
+ }
+ process_directive(&p_tokenizer);
+ } else {
+ if (is_char_end(t.text)) {
+ expand_output_macros(last_size, p_tokenizer.get_line());
+ last_size = output.size();
+ has_symbols_before_directive = false;
+ } else if (!is_char_space(t.text)) {
+ has_symbols_before_directive = true;
+ }
+ output.push_back(t.text);
+ }
+
+ if (!state->error.is_empty()) {
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+ return FAILED;
+ }
+ }
+ state->cyclic_include_hashes.erase(code_hash); // Remove this hash.
+
+ if (!state->disabled) {
+ if (state->condition_depth != 0) {
+ set_error(RTR("Unmatched conditional statement."), p_tokenizer.line);
+ return FAILED;
+ }
+
+ expand_output_macros(last_size, p_tokenizer.get_line());
+ }
+
+ r_result = vector_to_string(output);
+
+ return OK;
+}
+
+Error ShaderPreprocessor::preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text, List<FilePosition> *r_error_position, List<Region> *r_regions, HashSet<Ref<ShaderInclude>> *r_includes, List<ScriptLanguage::CodeCompletionOption> *r_completion_options, List<ScriptLanguage::CodeCompletionOption> *r_completion_defines, IncludeCompletionFunction p_include_completion_func) {
+ State pp_state;
+ if (!p_filename.is_empty()) {
+ pp_state.current_filename = p_filename;
+ pp_state.save_regions = r_regions != nullptr;
+ }
+ Error err = preprocess(&pp_state, p_code, r_result);
+ if (err != OK) {
+ if (r_error_text) {
+ *r_error_text = pp_state.error;
+ }
+ if (r_error_position) {
+ *r_error_position = pp_state.include_positions;
+ }
+ }
+ if (r_regions) {
+ *r_regions = pp_state.regions[p_filename];
+ }
+ if (r_includes) {
+ *r_includes = pp_state.shader_includes;
+ }
+
+ if (r_completion_defines) {
+ for (const KeyValue<String, Define *> &E : state->defines) {
+ ScriptLanguage::CodeCompletionOption option(E.key, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT);
+ r_completion_defines->push_back(option);
+ }
+ }
+
+ if (r_completion_options) {
+ switch (pp_state.completion_type) {
+ case COMPLETION_TYPE_DIRECTIVE: {
+ List<String> options;
+ get_keyword_list(&options, true, true);
+
+ for (const String &E : options) {
+ ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+ }
+
+ } break;
+ case COMPLETION_TYPE_PRAGMA: {
+ List<String> options;
+ ShaderPreprocessor::get_pragma_list(&options);
+
+ for (const String &E : options) {
+ ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+ }
+
+ } break;
+ case COMPLETION_TYPE_CONDITION: {
+ ScriptLanguage::CodeCompletionOption option("defined", ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT);
+ r_completion_options->push_back(option);
+
+ } break;
+ case COMPLETION_TYPE_INCLUDE_PATH: {
+ if (p_include_completion_func && r_completion_options) {
+ p_include_completion_func(r_completion_options);
+ }
+
+ } break;
+ default: {
+ }
+ }
+ }
+ return err;
+}
+
+void ShaderPreprocessor::get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords) {
+ r_keywords->push_back("define");
+ if (!p_ignore_context_keywords) {
+ r_keywords->push_back("defined");
+ }
+ r_keywords->push_back("elif");
+ if (p_include_shader_keywords) {
+ r_keywords->push_back("else");
+ }
+ r_keywords->push_back("endif");
+ if (p_include_shader_keywords) {
+ r_keywords->push_back("if");
+ }
+ r_keywords->push_back("ifdef");
+ r_keywords->push_back("ifndef");
+ r_keywords->push_back("include");
+ r_keywords->push_back("pragma");
+ r_keywords->push_back("undef");
+}
+
+void ShaderPreprocessor::get_pragma_list(List<String> *r_pragmas) {
+ r_pragmas->push_back("disable_preprocessor");
+}
+
+ShaderPreprocessor::ShaderPreprocessor() {
+}
+
+ShaderPreprocessor::~ShaderPreprocessor() {
+ clear();
+}
diff --git a/servers/rendering/shader_preprocessor.h b/servers/rendering/shader_preprocessor.h
new file mode 100644
index 0000000000..f1b2876891
--- /dev/null
+++ b/servers/rendering/shader_preprocessor.h
@@ -0,0 +1,230 @@
+/*************************************************************************/
+/* shader_preprocessor.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef SHADER_PREPROCESSOR_H
+#define SHADER_PREPROCESSOR_H
+
+#include "core/string/ustring.h"
+#include "core/templates/list.h"
+#include "core/templates/local_vector.h"
+#include "core/templates/rb_map.h"
+#include "core/templates/rb_set.h"
+#include "core/typedefs.h"
+
+#include "core/io/resource_loader.h"
+#include "core/os/os.h"
+#include "scene/resources/shader.h"
+#include "scene/resources/shader_include.h"
+
+class ShaderPreprocessor {
+public:
+ enum CompletionType {
+ COMPLETION_TYPE_NONE,
+ COMPLETION_TYPE_DIRECTIVE,
+ COMPLETION_TYPE_PRAGMA_DIRECTIVE,
+ COMPLETION_TYPE_PRAGMA,
+ COMPLETION_TYPE_CONDITION,
+ COMPLETION_TYPE_INCLUDE_PATH,
+ };
+
+ struct FilePosition {
+ String file;
+ int line = 0;
+ };
+
+ struct Region {
+ String file;
+ int from_line = -1;
+ int to_line = -1;
+ bool enabled = false;
+ Region *parent = nullptr;
+ };
+
+private:
+ struct Token {
+ char32_t text;
+ int line;
+
+ Token();
+ Token(char32_t p_text, int p_line);
+ };
+
+ // The real preprocessor that understands basic shader and preprocessor language syntax.
+ class Tokenizer {
+ public:
+ String code;
+ int line;
+ int index;
+ int size;
+ Vector<Token> generated;
+
+ private:
+ void add_generated(const Token &p_t);
+ char32_t next();
+
+ public:
+ int get_line() const;
+ int get_index() const;
+ char32_t peek();
+
+ void get_and_clear_generated(Vector<Token> *r_out);
+ void backtrack(char32_t p_what);
+ LocalVector<Token> advance(char32_t p_what);
+ void skip_whitespace();
+ String get_identifier(bool *r_is_cursor = nullptr, bool p_started = false);
+ String peek_identifier();
+ Token get_token();
+
+ Tokenizer(const String &p_code);
+ };
+
+ class CommentRemover {
+ private:
+ LocalVector<char32_t> stripped;
+ String code;
+ int index;
+ int line;
+ int comment_line_open;
+ int comments_open;
+ int strings_open;
+
+ public:
+ String get_error() const;
+ int get_error_line() const;
+ char32_t peek() const;
+
+ bool advance(char32_t p_what);
+ String strip();
+
+ CommentRemover(const String &p_code);
+ };
+
+ struct Define {
+ Vector<String> arguments;
+ String body;
+ };
+
+ struct Branch {
+ Vector<bool> conditions;
+ Branch *parent = nullptr;
+ bool else_defined = false;
+
+ Branch() {}
+
+ Branch(bool p_condition, Branch *p_parent) :
+ parent(p_parent) {
+ conditions.push_back(p_condition);
+ }
+ };
+
+ struct State {
+ RBMap<String, Define *> defines;
+ List<Branch> branches;
+ Branch *current_branch = nullptr;
+ int condition_depth = 0;
+ RBSet<String> includes;
+ List<uint64_t> cyclic_include_hashes; // Holds code hash of includes.
+ int include_depth = 0;
+ String current_filename;
+ String current_shader_type;
+ String error;
+ List<FilePosition> include_positions;
+ bool save_regions = false;
+ RBMap<String, List<Region>> regions;
+ Region *previous_region = nullptr;
+ bool disabled = false;
+ CompletionType completion_type = COMPLETION_TYPE_NONE;
+ HashSet<Ref<ShaderInclude>> shader_includes;
+ };
+
+private:
+ LocalVector<char32_t> output;
+ State *state = nullptr;
+ bool state_owner = false;
+
+private:
+ static bool is_char_word(char32_t p_char);
+ static bool is_char_space(char32_t p_char);
+ static bool is_char_end(char32_t p_char);
+ static String vector_to_string(const LocalVector<char32_t> &p_v, int p_start = 0, int p_end = -1);
+ static String tokens_to_string(const LocalVector<Token> &p_tokens);
+
+ void _set_expected_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Expected a '%s'."), p_what), p_line);
+ }
+
+ void _set_unexpected_token_error(const String &p_what, int p_line) {
+ set_error(vformat(RTR("Unexpected token '%s'."), p_what), p_line);
+ }
+
+ void process_directive(Tokenizer *p_tokenizer);
+ void process_define(Tokenizer *p_tokenizer);
+ void process_elif(Tokenizer *p_tokenizer);
+ void process_else(Tokenizer *p_tokenizer);
+ void process_endif(Tokenizer *p_tokenizer);
+ void process_if(Tokenizer *p_tokenizer);
+ void process_ifdef(Tokenizer *p_tokenizer);
+ void process_ifndef(Tokenizer *p_tokenizer);
+ void process_include(Tokenizer *p_tokenizer);
+ void process_pragma(Tokenizer *p_tokenizer);
+ void process_undef(Tokenizer *p_tokenizer);
+
+ void add_region(int p_line, bool p_enabled, Region *p_parent_region);
+ void start_branch_condition(Tokenizer *p_tokenizer, bool p_success, bool p_continue = false);
+
+ Error expand_condition(const String &p_string, int p_line, String &r_result);
+ void expand_output_macros(int p_start, int p_line);
+ Error expand_macros(const String &p_string, int p_line, String &r_result);
+ bool expand_macros_once(const String &p_line, int p_line_number, const RBMap<String, Define *>::Element *p_define_pair, String &r_expanded);
+ bool find_match(const String &p_string, const String &p_value, int &r_index, int &r_index_start);
+
+ String next_directive(Tokenizer *p_tokenizer, const Vector<String> &p_directives);
+ void add_to_output(const String &p_str);
+ void set_error(const String &p_error, int p_line);
+
+ static Define *create_define(const String &p_body);
+
+ void clear();
+
+ Error preprocess(State *p_state, const String &p_code, String &r_result);
+
+public:
+ typedef void (*IncludeCompletionFunction)(List<ScriptLanguage::CodeCompletionOption> *);
+
+ Error preprocess(const String &p_code, const String &p_filename, String &r_result, String *r_error_text = nullptr, List<FilePosition> *r_error_position = nullptr, List<Region> *r_regions = nullptr, HashSet<Ref<ShaderInclude>> *r_includes = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_options = nullptr, List<ScriptLanguage::CodeCompletionOption> *r_completion_defines = nullptr, IncludeCompletionFunction p_include_completion_func = nullptr);
+
+ static void get_keyword_list(List<String> *r_keywords, bool p_include_shader_keywords, bool p_ignore_context_keywords = false);
+ static void get_pragma_list(List<String> *r_pragmas);
+
+ ShaderPreprocessor();
+ ~ShaderPreprocessor();
+};
+
+#endif // SHADER_PREPROCESSOR_H
diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp
index 5772179d68..5e1da7c15d 100644
--- a/servers/rendering/shader_types.cpp
+++ b/servers/rendering/shader_types.cpp
@@ -86,8 +86,8 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].main_function = true;
//builtins
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_MATRIX"] = ShaderLanguage::TYPE_MAT4;
- shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODEL_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_VIEW_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4;
@@ -97,6 +97,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL);
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3;
+
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
@@ -139,6 +144,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2);
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_POSITION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_DIRECTION_WORLD"] = ShaderLanguage::TYPE_VEC3;
+ shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NODE_POSITION_VIEW"] = ShaderLanguage::TYPE_VEC3;
+
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_INDEX"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_MONO_LEFT"] = constt(ShaderLanguage::TYPE_INT);
shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW_RIGHT"] = constt(ShaderLanguage::TYPE_INT);
@@ -287,6 +297,9 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC4);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT);
+ shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_IS_DIRECTIONAL"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VERTEX"] = constt(ShaderLanguage::TYPE_VEC3);
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4;
shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_MODULATE"] = ShaderLanguage::TYPE_VEC4;
@@ -330,6 +343,11 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_POSITION"] = constt(ShaderLanguage::TYPE_UINT);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_ROT_SCALE"] = constt(ShaderLanguage::TYPE_UINT);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_VELOCITY"] = constt(ShaderLanguage::TYPE_UINT);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_COLOR"] = constt(ShaderLanguage::TYPE_UINT);
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["FLAG_EMIT_CUSTOM"] = constt(ShaderLanguage::TYPE_UINT);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_POSITION"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_ROT_SCALE"] = constt(ShaderLanguage::TYPE_BOOL);
shader_modes[RS::SHADER_PARTICLES].functions["start"].built_ins["RESTART_VELOCITY"] = constt(ShaderLanguage::TYPE_BOOL);
@@ -375,6 +393,7 @@ ShaderTypes::ShaderTypes() {
emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("custom", ShaderLanguage::TYPE_VEC4));
emit_vertex_func.arguments.push_back(ShaderLanguage::StageFunctionInfo::Argument("flags", ShaderLanguage::TYPE_UINT));
emit_vertex_func.return_type = ShaderLanguage::TYPE_BOOL; //whether it could emit
+ shader_modes[RS::SHADER_PARTICLES].functions["start"].stage_functions["emit_subparticle"] = emit_vertex_func;
shader_modes[RS::SHADER_PARTICLES].functions["process"].stage_functions["emit_subparticle"] = emit_vertex_func;
}
@@ -434,6 +453,7 @@ ShaderTypes::ShaderTypes() {
shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_half_res_pass") });
shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_quarter_res_pass") });
shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("disable_fog") });
+ shader_modes[RS::SHADER_SKY].modes.push_back({ PNAME("use_debanding") });
}
/************ FOG **************************/
diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h
index 107525cd15..dfec3a7111 100644
--- a/servers/rendering/shader_types.h
+++ b/servers/rendering/shader_types.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADERTYPES_H
-#define SHADERTYPES_H
+#ifndef SHADER_TYPES_H
+#define SHADER_TYPES_H
#include "core/templates/rb_map.h"
#include "servers/rendering_server.h"
@@ -59,4 +59,4 @@ public:
ShaderTypes();
};
-#endif // SHADERTYPES_H
+#endif // SHADER_TYPES_H
diff --git a/servers/rendering/shader_warnings.h b/servers/rendering/shader_warnings.h
index 8edf85842f..d5c6a4b1a6 100644
--- a/servers/rendering/shader_warnings.h
+++ b/servers/rendering/shader_warnings.h
@@ -28,8 +28,8 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef SHADER_WARNINGS
-#define SHADER_WARNINGS
+#ifndef SHADER_WARNINGS_H
+#define SHADER_WARNINGS_H
#ifdef DEBUG_ENABLED
@@ -90,4 +90,4 @@ public:
#endif // DEBUG_ENABLED
-#endif // SHADER_WARNINGS
+#endif // SHADER_WARNINGS_H
diff --git a/servers/rendering/storage/camera_attributes_storage.cpp b/servers/rendering/storage/camera_attributes_storage.cpp
new file mode 100644
index 0000000000..570fefb9de
--- /dev/null
+++ b/servers/rendering/storage/camera_attributes_storage.cpp
@@ -0,0 +1,177 @@
+/*************************************************************************/
+/* camera_attributes_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "camera_attributes_storage.h"
+
+RendererCameraAttributes *RendererCameraAttributes::singleton = nullptr;
+uint64_t RendererCameraAttributes::auto_exposure_counter = 2;
+
+RendererCameraAttributes::RendererCameraAttributes() {
+ singleton = this;
+}
+
+RendererCameraAttributes::~RendererCameraAttributes() {
+ singleton = nullptr;
+}
+
+RID RendererCameraAttributes::camera_attributes_allocate() {
+ return camera_attributes_owner.allocate_rid();
+}
+
+void RendererCameraAttributes::camera_attributes_initialize(RID p_rid) {
+ camera_attributes_owner.initialize_rid(p_rid, CameraAttributes());
+}
+
+void RendererCameraAttributes::camera_attributes_free(RID p_rid) {
+ camera_attributes_owner.free(p_rid);
+}
+
+void RendererCameraAttributes::camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {
+ dof_blur_quality = p_quality;
+ dof_blur_use_jitter = p_use_jitter;
+}
+
+void RendererCameraAttributes::camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {
+ dof_blur_bokeh_shape = p_shape;
+}
+
+void RendererCameraAttributes::camera_attributes_set_dof_blur(RID p_camera_attributes, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND(!cam_attributes);
+
+ cam_attributes->dof_blur_far_enabled = p_far_enable;
+ cam_attributes->dof_blur_far_distance = p_far_distance;
+ cam_attributes->dof_blur_far_transition = p_far_transition;
+
+ cam_attributes->dof_blur_near_enabled = p_near_enable;
+ cam_attributes->dof_blur_near_distance = p_near_distance;
+ cam_attributes->dof_blur_near_transition = p_near_transition;
+
+ cam_attributes->dof_blur_amount = p_amount;
+}
+
+bool RendererCameraAttributes::camera_attributes_get_dof_far_enabled(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, false);
+ return cam_attributes->dof_blur_far_enabled;
+}
+
+float RendererCameraAttributes::camera_attributes_get_dof_far_distance(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->dof_blur_far_distance;
+}
+
+float RendererCameraAttributes::camera_attributes_get_dof_far_transition(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->dof_blur_far_transition;
+}
+
+bool RendererCameraAttributes::camera_attributes_get_dof_near_enabled(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, false);
+ return cam_attributes->dof_blur_near_enabled;
+}
+
+float RendererCameraAttributes::camera_attributes_get_dof_near_distance(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->dof_blur_near_distance;
+}
+
+float RendererCameraAttributes::camera_attributes_get_dof_near_transition(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->dof_blur_near_transition;
+}
+
+float RendererCameraAttributes::camera_attributes_get_dof_blur_amount(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->dof_blur_amount;
+}
+
+void RendererCameraAttributes::camera_attributes_set_exposure(RID p_camera_attributes, float p_multiplier, float p_exposure_normalization) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND(!cam_attributes);
+ cam_attributes->exposure_multiplier = p_multiplier;
+ cam_attributes->exposure_normalization = p_exposure_normalization;
+}
+
+float RendererCameraAttributes::camera_attributes_get_exposure_normalization_factor(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 1.0);
+
+ return cam_attributes->exposure_multiplier * cam_attributes->exposure_normalization;
+}
+
+void RendererCameraAttributes::camera_attributes_set_auto_exposure(RID p_camera_attributes, bool p_enable, float p_min_sensitivity, float p_max_sensitivity, float p_speed, float p_scale) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND(!cam_attributes);
+ if (!cam_attributes->use_auto_exposure && p_enable) {
+ cam_attributes->auto_exposure_version = ++auto_exposure_counter;
+ }
+ cam_attributes->use_auto_exposure = p_enable;
+ cam_attributes->auto_exposure_min_sensitivity = p_min_sensitivity;
+ cam_attributes->auto_exposure_max_sensitivity = p_max_sensitivity;
+ cam_attributes->auto_exposure_adjust_speed = p_speed;
+ cam_attributes->auto_exposure_scale = p_scale;
+}
+
+float RendererCameraAttributes::camera_attributes_get_auto_exposure_min_sensitivity(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->auto_exposure_min_sensitivity;
+}
+
+float RendererCameraAttributes::camera_attributes_get_auto_exposure_max_sensitivity(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->auto_exposure_max_sensitivity;
+}
+
+float RendererCameraAttributes::camera_attributes_get_auto_exposure_adjust_speed(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->auto_exposure_adjust_speed;
+}
+
+float RendererCameraAttributes::camera_attributes_get_auto_exposure_scale(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0.0);
+ return cam_attributes->auto_exposure_scale;
+}
+
+uint64_t RendererCameraAttributes::camera_attributes_get_auto_exposure_version(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+ ERR_FAIL_COND_V(!cam_attributes, 0);
+ return cam_attributes->auto_exposure_version;
+}
diff --git a/servers/rendering/storage/camera_attributes_storage.h b/servers/rendering/storage/camera_attributes_storage.h
new file mode 100644
index 0000000000..6c7b364b10
--- /dev/null
+++ b/servers/rendering/storage/camera_attributes_storage.h
@@ -0,0 +1,129 @@
+/*************************************************************************/
+/* camera_attributes_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef CAMERA_ATTRIBUTES_STORAGE_H
+#define CAMERA_ATTRIBUTES_STORAGE_H
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering_server.h"
+
+class RendererCameraAttributes {
+private:
+ static RendererCameraAttributes *singleton;
+
+ struct CameraAttributes {
+ float exposure_multiplier = 1.0;
+ float exposure_normalization = 1.0;
+ float exposure_sensitivity = 100.0; // In ISO.
+
+ bool use_auto_exposure = false;
+ float auto_exposure_min_sensitivity = 50.0;
+ float auto_exposure_max_sensitivity = 800.0;
+ float auto_exposure_adjust_speed = 1.0;
+ float auto_exposure_scale = 1.0;
+ uint64_t auto_exposure_version = 0;
+
+ bool dof_blur_far_enabled = false;
+ float dof_blur_far_distance = 10;
+ float dof_blur_far_transition = 5;
+ bool dof_blur_near_enabled = false;
+ float dof_blur_near_distance = 2;
+ float dof_blur_near_transition = 1;
+ float dof_blur_amount = 0.1;
+ };
+
+ RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM;
+ RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON;
+ bool dof_blur_use_jitter = false;
+ static uint64_t auto_exposure_counter;
+
+ mutable RID_Owner<CameraAttributes, true> camera_attributes_owner;
+
+public:
+ static RendererCameraAttributes *get_singleton() { return singleton; }
+
+ RendererCameraAttributes();
+ ~RendererCameraAttributes();
+
+ CameraAttributes *get_camera_attributes(RID p_rid) { return camera_attributes_owner.get_or_null(p_rid); };
+ bool owns_camera_attributes(RID p_rid) { return camera_attributes_owner.owns(p_rid); };
+
+ RID camera_attributes_allocate();
+ void camera_attributes_initialize(RID p_rid);
+ void camera_attributes_free(RID p_rid);
+
+ void camera_attributes_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter);
+ void camera_attributes_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape);
+
+ void camera_attributes_set_dof_blur(RID p_camera_attributes, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount);
+ bool camera_attributes_get_dof_far_enabled(RID p_camera_attributes);
+ float camera_attributes_get_dof_far_distance(RID p_camera_attributes);
+ float camera_attributes_get_dof_far_transition(RID p_camera_attributes);
+ bool camera_attributes_get_dof_near_enabled(RID p_camera_attributes);
+ float camera_attributes_get_dof_near_distance(RID p_camera_attributes);
+ float camera_attributes_get_dof_near_transition(RID p_camera_attributes);
+ float camera_attributes_get_dof_blur_amount(RID p_camera_attributes);
+
+ _FORCE_INLINE_ bool camera_attributes_uses_dof(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+
+ return cam_attributes && (cam_attributes->dof_blur_near_enabled || cam_attributes->dof_blur_far_enabled) && cam_attributes->dof_blur_amount > 0.0;
+ }
+
+ void camera_attributes_set_exposure(RID p_camera_attributes, float p_multiplier, float p_exposure_normalization);
+ float camera_attributes_get_exposure_normalization_factor(RID p_camera_attributes);
+
+ void camera_attributes_set_auto_exposure(RID p_camera_attributes, bool p_enable, float p_min_sensitivity, float p_max_sensitivity, float p_speed, float p_scale);
+ float camera_attributes_get_auto_exposure_min_sensitivity(RID p_camera_attributes);
+ float camera_attributes_get_auto_exposure_max_sensitivity(RID p_camera_attributes);
+ float camera_attributes_get_auto_exposure_adjust_speed(RID p_camera_attributes);
+ float camera_attributes_get_auto_exposure_scale(RID p_camera_attributes);
+ uint64_t camera_attributes_get_auto_exposure_version(RID p_camera_attributes);
+
+ _FORCE_INLINE_ bool camera_attributes_uses_auto_exposure(RID p_camera_attributes) {
+ CameraAttributes *cam_attributes = camera_attributes_owner.get_or_null(p_camera_attributes);
+
+ return cam_attributes && cam_attributes->use_auto_exposure;
+ }
+
+ _FORCE_INLINE_ RS::DOFBlurQuality camera_attributes_get_dof_blur_quality() {
+ return dof_blur_quality;
+ }
+
+ _FORCE_INLINE_ RS::DOFBokehShape camera_attributes_get_dof_blur_bokeh_shape() {
+ return dof_blur_bokeh_shape;
+ }
+
+ _FORCE_INLINE_ bool camera_attributes_get_dof_blur_use_jitter() {
+ return dof_blur_use_jitter;
+ }
+};
+
+#endif // CAMERA_ATTRIBUTES_STORAGE_H
diff --git a/servers/rendering/storage/environment_storage.cpp b/servers/rendering/storage/environment_storage.cpp
new file mode 100644
index 0000000000..9b1842f1d9
--- /dev/null
+++ b/servers/rendering/storage/environment_storage.cpp
@@ -0,0 +1,744 @@
+/*************************************************************************/
+/* environment_storage.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "environment_storage.h"
+
+RID RendererEnvironmentStorage::environment_allocate() {
+ return environment_owner.allocate_rid();
+}
+
+void RendererEnvironmentStorage::environment_initialize(RID p_rid) {
+ environment_owner.initialize_rid(p_rid, Environment());
+}
+
+void RendererEnvironmentStorage::environment_free(RID p_rid) {
+ environment_owner.free(p_rid);
+}
+
+// Background
+
+void RendererEnvironmentStorage::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->background = p_bg;
+}
+
+void RendererEnvironmentStorage::environment_set_sky(RID p_env, RID p_sky) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sky = p_sky;
+}
+
+void RendererEnvironmentStorage::environment_set_sky_custom_fov(RID p_env, float p_scale) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sky_custom_fov = p_scale;
+}
+
+void RendererEnvironmentStorage::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sky_orientation = p_orientation;
+}
+
+void RendererEnvironmentStorage::environment_set_bg_color(RID p_env, const Color &p_color) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->bg_color = p_color;
+}
+
+void RendererEnvironmentStorage::environment_set_bg_energy(RID p_env, float p_multiplier, float p_intensity) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->bg_energy_multiplier = p_multiplier;
+ env->bg_intensity = p_intensity;
+}
+
+void RendererEnvironmentStorage::environment_set_canvas_max_layer(RID p_env, int p_max_layer) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->canvas_max_layer = p_max_layer;
+}
+
+void RendererEnvironmentStorage::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ambient_light = p_color;
+ env->ambient_source = p_ambient;
+ env->ambient_light_energy = p_energy;
+ env->ambient_sky_contribution = p_sky_contribution;
+ env->reflection_source = p_reflection_source;
+}
+
+RS::EnvironmentBG RendererEnvironmentStorage::environment_get_background(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_BG_CLEAR_COLOR);
+ return env->background;
+}
+
+RID RendererEnvironmentStorage::environment_get_sky(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RID());
+ return env->sky;
+}
+
+float RendererEnvironmentStorage::environment_get_sky_custom_fov(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->sky_custom_fov;
+}
+
+Basis RendererEnvironmentStorage::environment_get_sky_orientation(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Basis());
+ return env->sky_orientation;
+}
+
+Color RendererEnvironmentStorage::environment_get_bg_color(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color());
+ return env->bg_color;
+}
+
+float RendererEnvironmentStorage::environment_get_bg_energy_multiplier(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->bg_energy_multiplier;
+}
+
+float RendererEnvironmentStorage::environment_get_bg_intensity(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->bg_intensity;
+}
+
+int RendererEnvironmentStorage::environment_get_canvas_max_layer(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0);
+ return env->canvas_max_layer;
+}
+
+RS::EnvironmentAmbientSource RendererEnvironmentStorage::environment_get_ambient_source(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG);
+ return env->ambient_source;
+}
+
+Color RendererEnvironmentStorage::environment_get_ambient_light(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color());
+ return env->ambient_light;
+}
+
+float RendererEnvironmentStorage::environment_get_ambient_light_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ambient_light_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_ambient_sky_contribution(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ambient_sky_contribution;
+}
+
+RS::EnvironmentReflectionSource RendererEnvironmentStorage::environment_get_reflection_source(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_BG);
+ return env->reflection_source;
+}
+
+// Tonemap
+
+void RendererEnvironmentStorage::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->exposure = p_exposure;
+ env->tone_mapper = p_tone_mapper;
+ env->white = p_white;
+}
+
+RS::EnvironmentToneMapper RendererEnvironmentStorage::environment_get_tone_mapper(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_TONE_MAPPER_LINEAR);
+ return env->tone_mapper;
+}
+
+float RendererEnvironmentStorage::environment_get_exposure(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->exposure;
+}
+
+float RendererEnvironmentStorage::environment_get_white(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->white;
+}
+
+// Fog
+
+void RendererEnvironmentStorage::environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_fog_aerial_perspective, float p_sky_affect) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->fog_enabled = p_enable;
+ env->fog_light_color = p_light_color;
+ env->fog_light_energy = p_light_energy;
+ env->fog_sun_scatter = p_sun_scatter;
+ env->fog_density = p_density;
+ env->fog_height = p_height;
+ env->fog_height_density = p_height_density;
+ env->fog_aerial_perspective = p_fog_aerial_perspective;
+ env->fog_sky_affect = p_sky_affect;
+}
+
+bool RendererEnvironmentStorage::environment_get_fog_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->fog_enabled;
+}
+
+Color RendererEnvironmentStorage::environment_get_fog_light_color(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color(0.5, 0.6, 0.7));
+ return env->fog_light_color;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_light_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->fog_light_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_sun_scatter(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_sun_scatter;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_density(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.001);
+ return env->fog_density;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_height(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_height;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_height_density(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_height_density;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_aerial_perspective(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_aerial_perspective;
+}
+
+float RendererEnvironmentStorage::environment_get_fog_sky_affect(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->fog_sky_affect;
+}
+
+// Volumetric Fog
+
+void RendererEnvironmentStorage::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->volumetric_fog_enabled = p_enable;
+ env->volumetric_fog_density = p_density;
+ env->volumetric_fog_scattering = p_albedo;
+ env->volumetric_fog_emission = p_emission;
+ env->volumetric_fog_emission_energy = p_emission_energy;
+ env->volumetric_fog_anisotropy = p_anisotropy,
+ env->volumetric_fog_length = p_length;
+ env->volumetric_fog_detail_spread = p_detail_spread;
+ env->volumetric_fog_gi_inject = p_gi_inject;
+ env->volumetric_fog_temporal_reprojection = p_temporal_reprojection;
+ env->volumetric_fog_temporal_reprojection_amount = p_temporal_reprojection_amount;
+ env->volumetric_fog_ambient_inject = p_ambient_inject;
+ env->volumetric_fog_sky_affect = p_sky_affect;
+}
+
+bool RendererEnvironmentStorage::environment_get_volumetric_fog_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->volumetric_fog_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_density(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.01);
+ return env->volumetric_fog_density;
+}
+
+Color RendererEnvironmentStorage::environment_get_volumetric_fog_scattering(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color(1, 1, 1));
+ return env->volumetric_fog_scattering;
+}
+
+Color RendererEnvironmentStorage::environment_get_volumetric_fog_emission(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Color(0, 0, 0));
+ return env->volumetric_fog_emission;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_emission_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->volumetric_fog_emission_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_anisotropy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->volumetric_fog_anisotropy;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_length(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 64.0);
+ return env->volumetric_fog_length;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_detail_spread(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->volumetric_fog_detail_spread;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_gi_inject(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->volumetric_fog_gi_inject;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_sky_affect(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->volumetric_fog_sky_affect;
+}
+
+bool RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, true);
+ return env->volumetric_fog_temporal_reprojection;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.9);
+ return env->volumetric_fog_temporal_reprojection_amount;
+}
+
+float RendererEnvironmentStorage::environment_get_volumetric_fog_ambient_inject(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->volumetric_fog_ambient_inject;
+}
+
+// GLOW
+
+void RendererEnvironmentStorage::environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ ERR_FAIL_COND_MSG(p_levels.size() != 7, "Size of array of glow levels must be 7");
+ env->glow_enabled = p_enable;
+ env->glow_levels = p_levels;
+ env->glow_intensity = p_intensity;
+ env->glow_strength = p_strength;
+ env->glow_mix = p_mix;
+ env->glow_bloom = p_bloom_threshold;
+ env->glow_blend_mode = p_blend_mode;
+ env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold;
+ env->glow_hdr_bleed_scale = p_hdr_bleed_scale;
+ env->glow_hdr_luminance_cap = p_hdr_luminance_cap;
+ env->glow_map_strength = p_glow_map_strength;
+ env->glow_map = p_glow_map;
+}
+
+bool RendererEnvironmentStorage::environment_get_glow_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->glow_enabled;
+}
+
+Vector<float> RendererEnvironmentStorage::environment_get_glow_levels(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, Vector<float>());
+ return env->glow_levels;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_intensity(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.8);
+ return env->glow_intensity;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_strength(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->glow_strength;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_bloom(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->glow_bloom;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_mix(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.01);
+ return env->glow_mix;
+}
+
+RS::EnvironmentGlowBlendMode RendererEnvironmentStorage::environment_get_glow_blend_mode(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT);
+ return env->glow_blend_mode;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_threshold(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->glow_hdr_bleed_threshold;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_hdr_luminance_cap(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 12.0);
+ return env->glow_hdr_luminance_cap;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_hdr_bleed_scale(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->glow_hdr_bleed_scale;
+}
+
+float RendererEnvironmentStorage::environment_get_glow_map_strength(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->glow_map_strength;
+}
+
+RID RendererEnvironmentStorage::environment_get_glow_map(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RID());
+ return env->glow_map;
+}
+
+// SSR
+
+void RendererEnvironmentStorage::environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ssr_enabled = p_enable;
+ env->ssr_max_steps = p_max_steps;
+ env->ssr_fade_in = p_fade_int;
+ env->ssr_fade_out = p_fade_out;
+ env->ssr_depth_tolerance = p_depth_tolerance;
+}
+
+bool RendererEnvironmentStorage::environment_get_ssr_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->ssr_enabled;
+}
+
+int RendererEnvironmentStorage::environment_get_ssr_max_steps(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 64);
+ return env->ssr_max_steps;
+}
+
+float RendererEnvironmentStorage::environment_get_ssr_fade_in(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.15);
+ return env->ssr_fade_in;
+}
+
+float RendererEnvironmentStorage::environment_get_ssr_fade_out(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->ssr_fade_out;
+}
+
+float RendererEnvironmentStorage::environment_get_ssr_depth_tolerance(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->ssr_depth_tolerance;
+}
+
+// SSAO
+
+void RendererEnvironmentStorage::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ssao_enabled = p_enable;
+ env->ssao_radius = p_radius;
+ env->ssao_intensity = p_intensity;
+ env->ssao_power = p_power;
+ env->ssao_detail = p_detail;
+ env->ssao_horizon = p_horizon;
+ env->ssao_sharpness = p_sharpness;
+ env->ssao_direct_light_affect = p_light_affect;
+ env->ssao_ao_channel_affect = p_ao_channel_affect;
+}
+
+bool RendererEnvironmentStorage::environment_get_ssao_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->ssao_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_radius(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ssao_radius;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_intensity(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 2.0);
+ return env->ssao_intensity;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_power(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.5);
+ return env->ssao_power;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_detail(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.5);
+ return env->ssao_detail;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_horizon(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.06);
+ return env->ssao_horizon;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_sharpness(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.98);
+ return env->ssao_sharpness;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_direct_light_affect(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->ssao_direct_light_affect;
+}
+
+float RendererEnvironmentStorage::environment_get_ssao_ao_channel_affect(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.0);
+ return env->ssao_ao_channel_affect;
+}
+
+// SSIL
+
+void RendererEnvironmentStorage::environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->ssil_enabled = p_enable;
+ env->ssil_radius = p_radius;
+ env->ssil_intensity = p_intensity;
+ env->ssil_sharpness = p_sharpness;
+ env->ssil_normal_rejection = p_normal_rejection;
+}
+
+bool RendererEnvironmentStorage::environment_get_ssil_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->ssil_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_radius(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 5.0);
+ return env->ssil_radius;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_intensity(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ssil_intensity;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_sharpness(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.98);
+ return env->ssil_sharpness;
+}
+
+float RendererEnvironmentStorage::environment_get_ssil_normal_rejection(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->ssil_normal_rejection;
+}
+
+// SDFGI
+
+void RendererEnvironmentStorage::environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->sdfgi_enabled = p_enable;
+ env->sdfgi_cascades = p_cascades;
+ env->sdfgi_min_cell_size = p_min_cell_size;
+ env->sdfgi_use_occlusion = p_use_occlusion;
+ env->sdfgi_bounce_feedback = p_bounce_feedback;
+ env->sdfgi_read_sky_light = p_read_sky;
+ env->sdfgi_energy = p_energy;
+ env->sdfgi_normal_bias = p_normal_bias;
+ env->sdfgi_probe_bias = p_probe_bias;
+ env->sdfgi_y_scale = p_y_scale;
+}
+
+bool RendererEnvironmentStorage::environment_get_sdfgi_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->sdfgi_enabled;
+}
+
+int RendererEnvironmentStorage::environment_get_sdfgi_cascades(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 4);
+ return env->sdfgi_cascades;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_min_cell_size(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.2);
+ return env->sdfgi_min_cell_size;
+}
+
+bool RendererEnvironmentStorage::environment_get_sdfgi_use_occlusion(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->sdfgi_use_occlusion;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_bounce_feedback(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 0.5);
+ return env->sdfgi_bounce_feedback;
+}
+
+bool RendererEnvironmentStorage::environment_get_sdfgi_read_sky_light(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, true);
+ return env->sdfgi_read_sky_light;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_energy(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->sdfgi_energy;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_normal_bias(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.1);
+ return env->sdfgi_normal_bias;
+}
+
+float RendererEnvironmentStorage::environment_get_sdfgi_probe_bias(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.1);
+ return env->sdfgi_probe_bias;
+}
+
+RS::EnvironmentSDFGIYScale RendererEnvironmentStorage::environment_get_sdfgi_y_scale(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RS::ENV_SDFGI_Y_SCALE_75_PERCENT);
+ return env->sdfgi_y_scale;
+}
+
+// Adjustments
+
+void RendererEnvironmentStorage::environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND(!env);
+ env->adjustments_enabled = p_enable;
+ env->adjustments_brightness = p_brightness;
+ env->adjustments_contrast = p_contrast;
+ env->adjustments_saturation = p_saturation;
+ env->use_1d_color_correction = p_use_1d_color_correction;
+ env->color_correction = p_color_correction;
+}
+
+bool RendererEnvironmentStorage::environment_get_adjustments_enabled(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->adjustments_enabled;
+}
+
+float RendererEnvironmentStorage::environment_get_adjustments_brightness(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->adjustments_brightness;
+}
+
+float RendererEnvironmentStorage::environment_get_adjustments_contrast(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->adjustments_contrast;
+}
+
+float RendererEnvironmentStorage::environment_get_adjustments_saturation(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, 1.0);
+ return env->adjustments_saturation;
+}
+
+bool RendererEnvironmentStorage::environment_get_use_1d_color_correction(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, false);
+ return env->use_1d_color_correction;
+}
+
+RID RendererEnvironmentStorage::environment_get_color_correction(RID p_env) const {
+ Environment *env = environment_owner.get_or_null(p_env);
+ ERR_FAIL_COND_V(!env, RID());
+ return env->color_correction;
+}
diff --git a/servers/rendering/storage/environment_storage.h b/servers/rendering/storage/environment_storage.h
new file mode 100644
index 0000000000..17bde94902
--- /dev/null
+++ b/servers/rendering/storage/environment_storage.h
@@ -0,0 +1,288 @@
+/*************************************************************************/
+/* environment_storage.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef ENVIRONMENT_STORAGE_H
+#define ENVIRONMENT_STORAGE_H
+
+#include "core/templates/rid_owner.h"
+#include "servers/rendering_server.h"
+
+class RendererEnvironmentStorage {
+private:
+ struct Environment {
+ // Note, we capture and store all environment parameters received from Godot here.
+ // Not all renderers support all effects and should just ignore the bits they don't support.
+
+ // Background
+ RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR;
+ RID sky;
+ float sky_custom_fov = 0.0;
+ Basis sky_orientation;
+ Color bg_color;
+ float bg_energy_multiplier = 1.0;
+ float bg_intensity = 1.0; // Measured in nits or candela/m^2. Default to 1.0 so this doesn't impact rendering when Physical Light Units disabled.
+ int canvas_max_layer = 0;
+ RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG;
+ Color ambient_light;
+ float ambient_light_energy = 1.0;
+ float ambient_sky_contribution = 1.0;
+ RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG;
+
+ // Tonemap
+ RS::EnvironmentToneMapper tone_mapper;
+ float exposure = 1.0;
+ float white = 1.0;
+
+ // Fog
+ bool fog_enabled = false;
+ Color fog_light_color = Color(0.518, 0.553, 0.608);
+ float fog_light_energy = 1.0;
+ float fog_sun_scatter = 0.0;
+ float fog_density = 0.01;
+ float fog_sky_affect = 1.0;
+ float fog_height = 0.0;
+ float fog_height_density = 0.0; //can be negative to invert effect
+ float fog_aerial_perspective = 0.0;
+
+ // Volumetric Fog
+ bool volumetric_fog_enabled = false;
+ float volumetric_fog_density = 0.01;
+ Color volumetric_fog_scattering = Color(1, 1, 1);
+ Color volumetric_fog_emission = Color(0, 0, 0);
+ float volumetric_fog_emission_energy = 0.0;
+ float volumetric_fog_anisotropy = 0.2;
+ float volumetric_fog_length = 64.0;
+ float volumetric_fog_detail_spread = 2.0;
+ float volumetric_fog_gi_inject = 1.0;
+ float volumetric_fog_ambient_inject = 0.0;
+ float volumetric_fog_sky_affect = 1.0;
+ bool volumetric_fog_temporal_reprojection = true;
+ float volumetric_fog_temporal_reprojection_amount = 0.9;
+
+ // Glow
+ bool glow_enabled = false;
+ Vector<float> glow_levels;
+ float glow_intensity = 0.8;
+ float glow_strength = 1.0;
+ float glow_bloom = 0.0;
+ float glow_mix = 0.01;
+ RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT;
+ float glow_hdr_bleed_threshold = 1.0;
+ float glow_hdr_luminance_cap = 12.0;
+ float glow_hdr_bleed_scale = 2.0;
+ float glow_map_strength = 0.0f; // 1.0f in GLES3 ??
+ RID glow_map = RID();
+
+ // SSR
+ bool ssr_enabled = false;
+ int ssr_max_steps = 64;
+ float ssr_fade_in = 0.15;
+ float ssr_fade_out = 2.0;
+ float ssr_depth_tolerance = 0.2;
+
+ // SSAO
+ bool ssao_enabled = false;
+ float ssao_radius = 1.0;
+ float ssao_intensity = 2.0;
+ float ssao_power = 1.5;
+ float ssao_detail = 0.5;
+ float ssao_horizon = 0.06;
+ float ssao_sharpness = 0.98;
+ float ssao_direct_light_affect = 0.0;
+ float ssao_ao_channel_affect = 0.0;
+
+ // SSIL
+ bool ssil_enabled = false;
+ float ssil_radius = 5.0;
+ float ssil_intensity = 1.0;
+ float ssil_sharpness = 0.98;
+ float ssil_normal_rejection = 1.0;
+
+ // SDFGI
+ bool sdfgi_enabled = false;
+ int sdfgi_cascades = 4;
+ float sdfgi_min_cell_size = 0.2;
+ bool sdfgi_use_occlusion = false;
+ float sdfgi_bounce_feedback = 0.5;
+ bool sdfgi_read_sky_light = true;
+ float sdfgi_energy = 1.0;
+ float sdfgi_normal_bias = 1.1;
+ float sdfgi_probe_bias = 1.1;
+ RS::EnvironmentSDFGIYScale sdfgi_y_scale = RS::ENV_SDFGI_Y_SCALE_75_PERCENT;
+
+ // Adjustments
+ bool adjustments_enabled = false;
+ float adjustments_brightness = 1.0f;
+ float adjustments_contrast = 1.0f;
+ float adjustments_saturation = 1.0f;
+ bool use_1d_color_correction = false;
+ RID color_correction = RID();
+ };
+
+ mutable RID_Owner<Environment, true> environment_owner;
+
+public:
+ RID environment_allocate();
+ void environment_initialize(RID p_rid);
+ void environment_free(RID p_rid);
+
+ bool is_environment(RID p_environment) const {
+ return environment_owner.owns(p_environment);
+ }
+
+ // Background
+ void environment_set_background(RID p_env, RS::EnvironmentBG p_bg);
+ void environment_set_sky(RID p_env, RID p_sky);
+ void environment_set_sky_custom_fov(RID p_env, float p_scale);
+ void environment_set_sky_orientation(RID p_env, const Basis &p_orientation);
+ void environment_set_bg_color(RID p_env, const Color &p_color);
+ void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value);
+ void environment_set_canvas_max_layer(RID p_env, int p_max_layer);
+ void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG);
+// FIXME: Disabled during Vulkan refactoring, should be ported.
+#if 0
+ void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id);
+#endif
+
+ RS::EnvironmentBG environment_get_background(RID p_env) const;
+ RID environment_get_sky(RID p_env) const;
+ float environment_get_sky_custom_fov(RID p_env) const;
+ Basis environment_get_sky_orientation(RID p_env) const;
+ Color environment_get_bg_color(RID p_env) const;
+ float environment_get_bg_energy_multiplier(RID p_env) const;
+ float environment_get_bg_intensity(RID p_env) const;
+ int environment_get_canvas_max_layer(RID p_env) const;
+ RS::EnvironmentAmbientSource environment_get_ambient_source(RID p_env) const;
+ Color environment_get_ambient_light(RID p_env) const;
+ float environment_get_ambient_light_energy(RID p_env) const;
+ float environment_get_ambient_sky_contribution(RID p_env) const;
+ RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const;
+
+ // Tonemap
+ void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white);
+ RS::EnvironmentToneMapper environment_get_tone_mapper(RID p_env) const;
+ float environment_get_exposure(RID p_env) const;
+ float environment_get_white(RID p_env) const;
+
+ // Fog
+ void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect);
+ bool environment_get_fog_enabled(RID p_env) const;
+ Color environment_get_fog_light_color(RID p_env) const;
+ float environment_get_fog_light_energy(RID p_env) const;
+ float environment_get_fog_sun_scatter(RID p_env) const;
+ float environment_get_fog_density(RID p_env) const;
+ float environment_get_fog_sky_affect(RID p_env) const;
+ float environment_get_fog_height(RID p_env) const;
+ float environment_get_fog_height_density(RID p_env) const;
+ float environment_get_fog_aerial_perspective(RID p_env) const;
+
+ // Volumetric Fog
+ void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect);
+ bool environment_get_volumetric_fog_enabled(RID p_env) const;
+ float environment_get_volumetric_fog_density(RID p_env) const;
+ Color environment_get_volumetric_fog_scattering(RID p_env) const;
+ Color environment_get_volumetric_fog_emission(RID p_env) const;
+ float environment_get_volumetric_fog_emission_energy(RID p_env) const;
+ float environment_get_volumetric_fog_anisotropy(RID p_env) const;
+ float environment_get_volumetric_fog_length(RID p_env) const;
+ float environment_get_volumetric_fog_detail_spread(RID p_env) const;
+ float environment_get_volumetric_fog_gi_inject(RID p_env) const;
+ float environment_get_volumetric_fog_sky_affect(RID p_env) const;
+ bool environment_get_volumetric_fog_temporal_reprojection(RID p_env) const;
+ float environment_get_volumetric_fog_temporal_reprojection_amount(RID p_env) const;
+ float environment_get_volumetric_fog_ambient_inject(RID p_env) const;
+
+ // GLOW
+ void environment_set_glow(RID p_env, bool p_enable, Vector<float> p_levels, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, float p_glow_map_strength, RID p_glow_map);
+ bool environment_get_glow_enabled(RID p_env) const;
+ Vector<float> environment_get_glow_levels(RID p_env) const;
+ float environment_get_glow_intensity(RID p_env) const;
+ float environment_get_glow_strength(RID p_env) const;
+ float environment_get_glow_bloom(RID p_env) const;
+ float environment_get_glow_mix(RID p_env) const;
+ RS::EnvironmentGlowBlendMode environment_get_glow_blend_mode(RID p_env) const;
+ float environment_get_glow_hdr_bleed_threshold(RID p_env) const;
+ float environment_get_glow_hdr_luminance_cap(RID p_env) const;
+ float environment_get_glow_hdr_bleed_scale(RID p_env) const;
+ float environment_get_glow_map_strength(RID p_env) const;
+ RID environment_get_glow_map(RID p_env) const;
+
+ // SSR
+ void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance);
+ bool environment_get_ssr_enabled(RID p_env) const;
+ int environment_get_ssr_max_steps(RID p_env) const;
+ float environment_get_ssr_fade_in(RID p_env) const;
+ float environment_get_ssr_fade_out(RID p_env) const;
+ float environment_get_ssr_depth_tolerance(RID p_env) const;
+
+ // SSAO
+ void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_power, float p_detail, float p_horizon, float p_sharpness, float p_light_affect, float p_ao_channel_affect);
+ bool environment_get_ssao_enabled(RID p_env) const;
+ float environment_get_ssao_radius(RID p_env) const;
+ float environment_get_ssao_intensity(RID p_env) const;
+ float environment_get_ssao_power(RID p_env) const;
+ float environment_get_ssao_detail(RID p_env) const;
+ float environment_get_ssao_horizon(RID p_env) const;
+ float environment_get_ssao_sharpness(RID p_env) const;
+ float environment_get_ssao_direct_light_affect(RID p_env) const;
+ float environment_get_ssao_ao_channel_affect(RID p_env) const;
+
+ // SSIL
+ void environment_set_ssil(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_sharpness, float p_normal_rejection);
+ bool environment_get_ssil_enabled(RID p_env) const;
+ float environment_get_ssil_radius(RID p_env) const;
+ float environment_get_ssil_intensity(RID p_env) const;
+ float environment_get_ssil_sharpness(RID p_env) const;
+ float environment_get_ssil_normal_rejection(RID p_env) const;
+
+ // SDFGI
+ void environment_set_sdfgi(RID p_env, bool p_enable, int p_cascades, float p_min_cell_size, RS::EnvironmentSDFGIYScale p_y_scale, bool p_use_occlusion, float p_bounce_feedback, bool p_read_sky, float p_energy, float p_normal_bias, float p_probe_bias);
+ bool environment_get_sdfgi_enabled(RID p_env) const;
+ int environment_get_sdfgi_cascades(RID p_env) const;
+ float environment_get_sdfgi_min_cell_size(RID p_env) const;
+ bool environment_get_sdfgi_use_occlusion(RID p_env) const;
+ float environment_get_sdfgi_bounce_feedback(RID p_env) const;
+ bool environment_get_sdfgi_read_sky_light(RID p_env) const;
+ float environment_get_sdfgi_energy(RID p_env) const;
+ float environment_get_sdfgi_normal_bias(RID p_env) const;
+ float environment_get_sdfgi_probe_bias(RID p_env) const;
+ RS::EnvironmentSDFGIYScale environment_get_sdfgi_y_scale(RID p_env) const;
+
+ // Adjustment
+ void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction);
+ bool environment_get_adjustments_enabled(RID p_env) const;
+ float environment_get_adjustments_brightness(RID p_env) const;
+ float environment_get_adjustments_contrast(RID p_env) const;
+ float environment_get_adjustments_saturation(RID p_env) const;
+ bool environment_get_use_1d_color_correction(RID p_env) const;
+ RID environment_get_color_correction(RID p_env) const;
+};
+
+#endif // ENVIRONMENT_STORAGE_H
diff --git a/servers/rendering/storage/light_storage.h b/servers/rendering/storage/light_storage.h
index 0cb0f35570..df5b893cd5 100644
--- a/servers/rendering/storage/light_storage.h
+++ b/servers/rendering/storage/light_storage.h
@@ -31,7 +31,6 @@
#ifndef LIGHT_STORAGE_H
#define LIGHT_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
class RendererLightStorage {
@@ -85,6 +84,18 @@ public:
virtual uint32_t light_get_max_sdfgi_cascade(RID p_light) = 0;
virtual uint64_t light_get_version(RID p_light) const = 0;
+ /* LIGHT INSTANCE API */
+
+ virtual RID light_instance_create(RID p_light) = 0;
+ virtual void light_instance_free(RID p_light_instance) = 0;
+ virtual void light_instance_set_transform(RID p_light_instance, const Transform3D &p_transform) = 0;
+ virtual void light_instance_set_aabb(RID p_light_instance, const AABB &p_aabb) = 0;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance, const Projection &p_projection, const Transform3D &p_transform, float p_far, float p_split, int p_pass, float p_shadow_texel_size, float p_bias_scale = 1.0, float p_range_begin = 0, const Vector2 &p_uv_scale = Vector2()) = 0;
+ virtual void light_instance_mark_visible(RID p_light_instance) = 0;
+ virtual bool light_instances_can_render_shadow_cube() const {
+ return true;
+ }
+
/* PROBE API */
virtual RID reflection_probe_allocate() = 0;
@@ -115,6 +126,24 @@ public:
virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0;
virtual float reflection_probe_get_mesh_lod_threshold(RID p_probe) const = 0;
+ /* REFLECTION ATLAS */
+
+ virtual RID reflection_atlas_create() = 0;
+ virtual void reflection_atlas_free(RID p_ref_atlas) = 0;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0;
+ virtual int reflection_atlas_get_size(RID p_ref_atlas) const = 0;
+
+ /* REFLECTION PROBE INSTANCE */
+
+ virtual RID reflection_probe_instance_create(RID p_probe) = 0;
+ virtual void reflection_probe_instance_free(RID p_instance) = 0;
+ virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform3D &p_transform) = 0;
+ virtual void reflection_probe_release_atlas_index(RID p_instance) = 0;
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0;
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0;
+
/* LIGHTMAP */
virtual RID lightmap_allocate() = 0;
@@ -125,6 +154,7 @@ public:
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
+ virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) = 0;
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
@@ -134,6 +164,27 @@ public:
virtual bool lightmap_is_interior(RID p_lightmap) const = 0;
virtual void lightmap_set_probe_capture_update_speed(float p_speed) = 0;
virtual float lightmap_get_probe_capture_update_speed() const = 0;
+
+ /* LIGHTMAP INSTANCE */
+
+ virtual RID lightmap_instance_create(RID p_lightmap) = 0;
+ virtual void lightmap_instance_free(RID p_lightmap) = 0;
+ virtual void lightmap_instance_set_transform(RID p_lightmap, const Transform3D &p_transform) = 0;
+
+ /* SHADOW ATLAS */
+
+ virtual RID shadow_atlas_create() = 0;
+ virtual void shadow_atlas_free(RID p_atlas) = 0;
+
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0;
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
+ virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0;
+
+ virtual void shadow_atlas_update(RID p_atlas) = 0;
+
+ virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
+ virtual int get_directional_light_shadow_size(RID p_light_intance) = 0;
+ virtual void set_directional_shadow_count(int p_count) = 0;
};
-#endif // !LIGHT_STORAGE_H
+#endif // LIGHT_STORAGE_H
diff --git a/servers/rendering/storage/material_storage.h b/servers/rendering/storage/material_storage.h
index f0363f129a..a3de6343e5 100644
--- a/servers/rendering/storage/material_storage.h
+++ b/servers/rendering/storage/material_storage.h
@@ -31,29 +31,29 @@
#ifndef MATERIAL_STORAGE_H
#define MATERIAL_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
+#include "utilities.h"
class RendererMaterialStorage {
public:
virtual ~RendererMaterialStorage(){};
- /* GLOBAL VARIABLE API */
- virtual void global_variable_add(const StringName &p_name, RS::GlobalVariableType p_type, const Variant &p_value) = 0;
- virtual void global_variable_remove(const StringName &p_name) = 0;
- virtual Vector<StringName> global_variable_get_list() const = 0;
+ /* GLOBAL SHADER UNIFORM API */
+ virtual void global_shader_parameter_add(const StringName &p_name, RS::GlobalShaderParameterType p_type, const Variant &p_value) = 0;
+ virtual void global_shader_parameter_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_shader_parameter_get_list() const = 0;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
- virtual Variant global_variable_get(const StringName &p_name) const = 0;
- virtual RS::GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+ virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual Variant global_shader_parameter_get(const StringName &p_name) const = 0;
+ virtual RS::GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const = 0;
- virtual void global_variables_load_settings(bool p_load_textures = true) = 0;
- virtual void global_variables_clear() = 0;
+ virtual void global_shader_parameters_load_settings(bool p_load_textures = true) = 0;
+ virtual void global_shader_parameters_clear() = 0;
- virtual int32_t global_variables_instance_allocate(RID p_instance) = 0;
- virtual void global_variables_instance_free(RID p_instance) = 0;
- virtual void global_variables_instance_update(RID p_instance, int p_index, const Variant &p_value) = 0;
+ virtual int32_t global_shader_parameters_instance_allocate(RID p_instance) = 0;
+ virtual void global_shader_parameters_instance_free(RID p_instance) = 0;
+ virtual void global_shader_parameters_instance_update(RID p_instance, int p_index, const Variant &p_value, int p_flags_count = 0) = 0;
/* SHADER API */
virtual RID shader_allocate() = 0;
@@ -61,12 +61,13 @@ public:
virtual void shader_free(RID p_rid) = 0;
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
+ virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
+ virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index) const = 0;
- virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0;
+ virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index) = 0;
+ virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index) const = 0;
+ virtual Variant shader_get_parameter_default(RID p_material, const StringName &p_param) const = 0;
virtual RS::ShaderNativeSourceCode shader_get_native_source_code(RID p_shader) const = 0;
@@ -95,7 +96,7 @@ public:
virtual void material_get_instance_shader_parameters(RID p_material, List<InstanceShaderParam> *r_parameters) = 0;
- virtual void material_update_dependency(RID p_material, RendererStorage::DependencyTracker *p_instance) = 0;
+ virtual void material_update_dependency(RID p_material, DependencyTracker *p_instance) = 0;
};
-#endif // !MATERIAL_STORAGE_H
+#endif // MATERIAL_STORAGE_H
diff --git a/servers/rendering/storage/mesh_storage.h b/servers/rendering/storage/mesh_storage.h
index 1dac51319c..5b3738dfd7 100644
--- a/servers/rendering/storage/mesh_storage.h
+++ b/servers/rendering/storage/mesh_storage.h
@@ -31,8 +31,8 @@
#ifndef MESH_STORAGE_H
#define MESH_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
+#include "utilities.h"
class RendererMeshStorage {
public:
@@ -130,7 +130,7 @@ public:
virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0;
virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0;
- virtual void skeleton_update_dependency(RID p_base, RendererStorage::DependencyTracker *p_instance) = 0;
+ virtual void skeleton_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
};
-#endif // !MESH_STORAGE_H
+#endif // MESH_STORAGE_H
diff --git a/servers/rendering/storage/particles_storage.h b/servers/rendering/storage/particles_storage.h
index 268b5473e2..ee4b8679b3 100644
--- a/servers/rendering/storage/particles_storage.h
+++ b/servers/rendering/storage/particles_storage.h
@@ -31,7 +31,6 @@
#ifndef PARTICLES_STORAGE_H
#define PARTICLES_STORAGE_H
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering_server.h"
class RendererParticlesStorage {
@@ -126,4 +125,4 @@ public:
virtual void particles_collision_instance_set_active(RID p_collision_instance, bool p_active) = 0;
};
-#endif // !PARTICLES_STORAGE_H
+#endif // PARTICLES_STORAGE_H
diff --git a/servers/rendering/storage/render_scene_buffers.cpp b/servers/rendering/storage/render_scene_buffers.cpp
new file mode 100644
index 0000000000..104700090f
--- /dev/null
+++ b/servers/rendering/storage/render_scene_buffers.cpp
@@ -0,0 +1,51 @@
+/*************************************************************************/
+/* render_scene_buffers.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#include "render_scene_buffers.h"
+
+void RenderSceneBuffers::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("configure", "render_target", "internal_size", "target_size", "fsr_sharpness", "texture_mipmap_bias", "msaa", "screen_space_aa", "use_taa", "use_debanding", "view_count"), &RenderSceneBuffers::configure);
+}
+
+void RenderSceneBuffers::configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count) {
+ GDVIRTUAL_CALL(_configure, p_render_target, p_internal_size, p_target_size, p_fsr_sharpness, p_texture_mipmap_bias, p_msaa, p_screen_space_aa, p_use_taa, p_use_debanding, p_view_count);
+};
+
+void RenderSceneBuffers::set_fsr_sharpness(float p_fsr_sharpness) {
+ GDVIRTUAL_CALL(_set_fsr_sharpness, p_fsr_sharpness);
+}
+
+void RenderSceneBuffers::set_texture_mipmap_bias(float p_texture_mipmap_bias) {
+ GDVIRTUAL_CALL(_set_texture_mipmap_bias, p_texture_mipmap_bias);
+}
+
+void RenderSceneBuffers::set_use_debanding(bool p_use_debanding) {
+ GDVIRTUAL_CALL(_set_use_debanding, p_use_debanding);
+}
diff --git a/servers/rendering/storage/render_scene_buffers.h b/servers/rendering/storage/render_scene_buffers.h
new file mode 100644
index 0000000000..e28e3201ae
--- /dev/null
+++ b/servers/rendering/storage/render_scene_buffers.h
@@ -0,0 +1,60 @@
+/*************************************************************************/
+/* render_scene_buffers.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDER_SCENE_BUFFERS_H
+#define RENDER_SCENE_BUFFERS_H
+
+#include "core/object/ref_counted.h"
+#include "servers/rendering_server.h"
+
+class RenderSceneBuffers : public RefCounted {
+ GDCLASS(RenderSceneBuffers, RefCounted);
+
+protected:
+ static void _bind_methods();
+
+ GDVIRTUAL10(_configure, RID, Size2i, Size2i, float, float, RS::ViewportMSAA, RenderingServer::ViewportScreenSpaceAA, bool, bool, uint32_t)
+ GDVIRTUAL1(_set_fsr_sharpness, float)
+ GDVIRTUAL1(_set_texture_mipmap_bias, float)
+ GDVIRTUAL1(_set_use_debanding, bool)
+
+public:
+ RenderSceneBuffers(){};
+ virtual ~RenderSceneBuffers(){};
+
+ virtual void configure(RID p_render_target, const Size2i p_internal_size, const Size2i p_target_size, float p_fsr_sharpness, float p_texture_mipmap_bias, RS::ViewportMSAA p_msaa_3d, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_taa, bool p_use_debanding, uint32_t p_view_count);
+
+ // for those settings that are unlikely to require buffers to be recreated, we'll add setters
+ virtual void set_fsr_sharpness(float p_fsr_sharpness);
+ virtual void set_texture_mipmap_bias(float p_texture_mipmap_bias);
+ virtual void set_use_debanding(bool p_use_debanding);
+};
+
+#endif // RENDER_SCENE_BUFFERS_H
diff --git a/servers/rendering/storage/texture_storage.h b/servers/rendering/storage/texture_storage.h
index e3a969d032..31fb5e8791 100644
--- a/servers/rendering/storage/texture_storage.h
+++ b/servers/rendering/storage/texture_storage.h
@@ -34,7 +34,18 @@
#include "servers/rendering_server.h"
class RendererTextureStorage {
+private:
+ Color default_clear_color;
+
public:
+ void set_default_clear_color(const Color &p_color) {
+ default_clear_color = p_color;
+ }
+
+ Color get_default_clear_color() const {
+ return default_clear_color;
+ }
+
/* Canvas Texture API */
virtual RID canvas_texture_allocate() = 0;
@@ -89,6 +100,8 @@ public:
virtual Size2 texture_size_with_proxy(RID p_proxy) = 0;
+ virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const = 0;
+
/* Decal API */
virtual RID decal_allocate() = 0;
virtual void decal_initialize(RID p_rid) = 0;
@@ -109,19 +122,29 @@ public:
virtual void texture_add_to_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
virtual void texture_remove_from_decal_atlas(RID p_texture, bool p_panorama_to_dp = false) = 0;
+ /* DECAL INSTANCE */
+
+ virtual RID decal_instance_create(RID p_decal) = 0;
+ virtual void decal_instance_free(RID p_decal_instance) = 0;
+ virtual void decal_instance_set_transform(RID p_decal_instance, const Transform3D &p_transform) = 0;
+
/* RENDER TARGET */
virtual RID render_target_create() = 0;
virtual void render_target_free(RID p_rid) = 0;
- virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0;
- virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0;
- virtual RID render_target_get_texture(RID p_render_target) = 0;
- virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0;
+ virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; // Q change input to const Point2i &p_position ?
+ virtual Point2i render_target_get_position(RID p_render_target) const = 0;
+ virtual void render_target_set_size(RID p_render_target, int p_width, int p_height, uint32_t p_view_count) = 0; // Q change input to const Size2i &p_size ?
+ virtual Size2i render_target_get_size(RID p_render_target) const = 0;
virtual void render_target_set_transparent(RID p_render_target, bool p_is_transparent) = 0;
+ virtual bool render_target_get_transparent(RID p_render_target) const = 0;
virtual void render_target_set_direct_to_screen(RID p_render_target, bool p_direct_to_screen) = 0;
- virtual bool render_target_was_used(RID p_render_target) = 0;
+ virtual bool render_target_get_direct_to_screen(RID p_render_target) const = 0;
+ virtual bool render_target_was_used(RID p_render_target) const = 0;
virtual void render_target_set_as_unused(RID p_render_target) = 0;
+ virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) = 0;
+ virtual RS::ViewportMSAA render_target_get_msaa(RID p_render_target) const = 0;
virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0;
virtual bool render_target_is_clear_requested(RID p_render_target) = 0;
@@ -132,6 +155,20 @@ public:
virtual void render_target_set_sdf_size_and_scale(RID p_render_target, RS::ViewportSDFOversize p_size, RS::ViewportSDFScale p_scale) = 0;
virtual Rect2i render_target_get_sdf_rect(RID p_render_target) const = 0;
virtual void render_target_mark_sdf_enabled(RID p_render_target, bool p_enabled) = 0;
+
+ virtual void render_target_set_vrs_mode(RID p_render_target, RS::ViewportVRSMode p_mode) = 0;
+ virtual RS::ViewportVRSMode render_target_get_vrs_mode(RID p_render_target) const = 0;
+ virtual void render_target_set_vrs_texture(RID p_render_target, RID p_texture) = 0;
+ virtual RID render_target_get_vrs_texture(RID p_render_target) const = 0;
+
+ // override color, depth and velocity buffers (depth and velocity only for 3D)
+ virtual void render_target_set_override(RID p_render_target, RID p_color_texture, RID p_depth_texture, RID p_velocity_texture) = 0;
+ virtual RID render_target_get_override_color(RID p_render_target) const = 0;
+ virtual RID render_target_get_override_depth(RID p_render_target) const = 0;
+ virtual RID render_target_get_override_velocity(RID p_render_target) const = 0;
+
+ // get textures
+ virtual RID render_target_get_texture(RID p_render_target) = 0;
};
-#endif // !TEXTURE_STORAGE_H
+#endif // TEXTURE_STORAGE_H
diff --git a/servers/rendering/renderer_storage.cpp b/servers/rendering/storage/utilities.cpp
index 56409ae187..7cc6417a25 100644
--- a/servers/rendering/renderer_storage.cpp
+++ b/servers/rendering/storage/utilities.cpp
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* renderer_storage.cpp */
+/* utilities.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,11 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "renderer_storage.h"
+#include "utilities.h"
-RendererStorage *RendererStorage::base_singleton = nullptr;
-
-void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p_notification) {
+void Dependency::changed_notify(DependencyChangedNotification p_notification) {
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
if (E.key->changed_callback) {
E.key->changed_callback(p_notification, E.key);
@@ -40,7 +38,7 @@ void RendererStorage::Dependency::changed_notify(DependencyChangedNotification p
}
}
-void RendererStorage::Dependency::deleted_notify(const RID &p_rid) {
+void Dependency::deleted_notify(const RID &p_rid) {
for (const KeyValue<DependencyTracker *, uint32_t> &E : instances) {
if (E.key->deleted_callback) {
E.key->deleted_callback(p_rid, E.key);
@@ -52,7 +50,7 @@ void RendererStorage::Dependency::deleted_notify(const RID &p_rid) {
instances.clear();
}
-RendererStorage::Dependency::~Dependency() {
+Dependency::~Dependency() {
#ifdef DEBUG_ENABLED
if (instances.size()) {
WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing.");
@@ -62,7 +60,3 @@ RendererStorage::Dependency::~Dependency() {
}
#endif
}
-
-RendererStorage::RendererStorage() {
- base_singleton = this;
-}
diff --git a/servers/rendering/storage/utilities.h b/servers/rendering/storage/utilities.h
new file mode 100644
index 0000000000..23a782c14a
--- /dev/null
+++ b/servers/rendering/storage/utilities.h
@@ -0,0 +1,188 @@
+/*************************************************************************/
+/* utilities.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* 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. */
+/*************************************************************************/
+
+#ifndef RENDERER_UTILITIES_H
+#define RENDERER_UTILITIES_H
+
+#include "servers/rendering_server.h"
+
+class DependencyTracker;
+
+class Dependency {
+public:
+ enum DependencyChangedNotification {
+ DEPENDENCY_CHANGED_AABB,
+ DEPENDENCY_CHANGED_MATERIAL,
+ DEPENDENCY_CHANGED_MESH,
+ DEPENDENCY_CHANGED_MULTIMESH,
+ DEPENDENCY_CHANGED_MULTIMESH_VISIBLE_INSTANCES,
+ DEPENDENCY_CHANGED_PARTICLES,
+ DEPENDENCY_CHANGED_DECAL,
+ DEPENDENCY_CHANGED_SKELETON_DATA,
+ DEPENDENCY_CHANGED_SKELETON_BONES,
+ DEPENDENCY_CHANGED_LIGHT,
+ DEPENDENCY_CHANGED_LIGHT_SOFT_SHADOW_AND_PROJECTOR,
+ DEPENDENCY_CHANGED_REFLECTION_PROBE,
+ };
+
+ void changed_notify(DependencyChangedNotification p_notification);
+ void deleted_notify(const RID &p_rid);
+
+ ~Dependency();
+
+private:
+ friend class DependencyTracker;
+ HashMap<DependencyTracker *, uint32_t> instances;
+};
+
+class DependencyTracker {
+public:
+ void *userdata = nullptr;
+ typedef void (*ChangedCallback)(Dependency::DependencyChangedNotification, DependencyTracker *);
+ typedef void (*DeletedCallback)(const RID &, DependencyTracker *);
+
+ ChangedCallback changed_callback = nullptr;
+ DeletedCallback deleted_callback = nullptr;
+
+ void update_begin() { // call before updating dependencies
+ instance_version++;
+ }
+
+ void update_dependency(Dependency *p_dependency) { //called internally, can't be used directly, use update functions in Storage
+ dependencies.insert(p_dependency);
+ p_dependency->instances[this] = instance_version;
+ }
+
+ void update_end() { //call after updating dependencies
+ List<Pair<Dependency *, DependencyTracker *>> to_clean_up;
+
+ for (Dependency *E : dependencies) {
+ Dependency *dep = E;
+ HashMap<DependencyTracker *, uint32_t>::Iterator F = dep->instances.find(this);
+ ERR_CONTINUE(!F);
+ if (F->value != instance_version) {
+ Pair<Dependency *, DependencyTracker *> p;
+ p.first = dep;
+ p.second = F->key;
+ to_clean_up.push_back(p);
+ }
+ }
+
+ while (to_clean_up.size()) {
+ to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second);
+ dependencies.erase(to_clean_up.front()->get().first);
+ to_clean_up.pop_front();
+ }
+ }
+
+ void clear() { // clear all dependencies
+ for (Dependency *E : dependencies) {
+ Dependency *dep = E;
+ dep->instances.erase(this);
+ }
+ dependencies.clear();
+ }
+
+ ~DependencyTracker() { clear(); }
+
+private:
+ friend class Dependency;
+ uint32_t instance_version = 0;
+ HashSet<Dependency *> dependencies;
+};
+
+class RendererUtilities {
+public:
+ virtual ~RendererUtilities() {}
+
+ /* INSTANCES */
+
+ virtual RS::InstanceType get_base_type(RID p_rid) const = 0;
+ virtual bool free(RID p_rid) = 0;
+
+ /* DEPENDENCIES */
+
+ virtual void base_update_dependency(RID p_base, DependencyTracker *p_instance) = 0;
+
+ /* VISIBILITY NOTIFIER */
+
+ virtual RID visibility_notifier_allocate() = 0;
+ virtual void visibility_notifier_initialize(RID p_notifier) = 0;
+ virtual void visibility_notifier_free(RID p_notifier) = 0;
+
+ virtual void visibility_notifier_set_aabb(RID p_notifier, const AABB &p_aabb) = 0;
+ virtual void visibility_notifier_set_callbacks(RID p_notifier, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0;
+
+ virtual AABB visibility_notifier_get_aabb(RID p_notifier) const = 0;
+ virtual void visibility_notifier_call(RID p_notifier, bool p_enter, bool p_deferred) = 0;
+
+ /* TIMING */
+
+ bool capturing_timestamps = false;
+
+#define TIMESTAMP_BEGIN() \
+ { \
+ if (RSG::utilities->capturing_timestamps) \
+ RSG::utilities->capture_timestamps_begin(); \
+ }
+
+#define RENDER_TIMESTAMP(m_text) \
+ { \
+ if (RSG::utilities->capturing_timestamps) \
+ RSG::utilities->capture_timestamp(m_text); \
+ }
+
+ virtual void capture_timestamps_begin() = 0;
+ virtual void capture_timestamp(const String &p_name) = 0;
+ virtual uint32_t get_captured_timestamps_count() const = 0;
+ virtual uint64_t get_captured_timestamps_frame() const = 0;
+ virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0;
+ virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0;
+ virtual String get_captured_timestamp_name(uint32_t p_index) const = 0;
+
+ /* MISC */
+
+ virtual void update_dirty_resources() = 0;
+ virtual void set_debug_generate_wireframes(bool p_generate) = 0;
+
+ virtual bool has_os_feature(const String &p_feature) const = 0;
+
+ virtual void update_memory_info() = 0;
+
+ virtual uint64_t get_rendering_info(RS::RenderingInfo p_info) = 0;
+ virtual String get_video_adapter_name() const = 0;
+ virtual String get_video_adapter_vendor() const = 0;
+ virtual RenderingDevice::DeviceType get_video_adapter_type() const = 0;
+ virtual String get_video_adapter_api_version() const = 0;
+
+ virtual Size2i get_maximum_viewport_size() const = 0;
+};
+
+#endif // RENDERER_UTILITIES_H
diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp
index 26ab8b659e..7691bede07 100644
--- a/servers/rendering_server.cpp
+++ b/servers/rendering_server.cpp
@@ -31,6 +31,7 @@
#include "rendering_server.h"
#include "core/config/project_settings.h"
+#include "core/variant/typed_array.h"
#include "servers/rendering/rendering_server_globals.h"
#include "servers/rendering/shader_language.h"
@@ -69,44 +70,44 @@ Array RenderingServer::_texture_debug_usage_bind() {
return arr;
}
-static Array to_array(const Vector<ObjectID> &ids) {
- Array a;
+static PackedInt64Array to_int_array(const Vector<ObjectID> &ids) {
+ PackedInt64Array a;
a.resize(ids.size());
for (int i = 0; i < ids.size(); ++i) {
- a[i] = ids[i];
+ a.write[i] = ids[i];
}
return a;
}
-Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const {
+PackedInt64Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const {
if (RSG::threaded) {
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
}
Vector<ObjectID> ids = instances_cull_aabb(p_aabb, p_scenario);
- return to_array(ids);
+ return to_int_array(ids);
}
-Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
+PackedInt64Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const {
if (RSG::threaded) {
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
}
Vector<ObjectID> ids = instances_cull_ray(p_from, p_to, p_scenario);
- return to_array(ids);
+ return to_int_array(ids);
}
-Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const {
+PackedInt64Array RenderingServer::_instances_cull_convex_bind(const TypedArray<Plane> &p_convex, RID p_scenario) const {
if (RSG::threaded) {
WARN_PRINT_ONCE("Using this function with a threaded renderer hurts performance, as it causes a server stall.");
}
Vector<Plane> planes;
for (int i = 0; i < p_convex.size(); ++i) {
Variant v = p_convex[i];
- ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, Array());
+ ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, PackedInt64Array());
planes.push_back(v);
}
Vector<ObjectID> ids = instances_cull_convex(planes, p_scenario);
- return to_array(ids);
+ return to_int_array(ids);
}
RID RenderingServer::get_test_texture() {
@@ -398,16 +399,14 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const Vector3 *src = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- Vector3 n = src[i] * Vector3(0.5, 0.5, 0.5) + Vector3(0.5, 0.5, 0.5);
-
- uint32_t value = 0;
- value |= CLAMP(int(n.x * 1023.0), 0, 1023);
- value |= CLAMP(int(n.y * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int(n.z * 1023.0), 0, 1023) << 20;
+ Vector2 res = src[i].octahedron_encode();
+ int16_t vector[2] = {
+ (int16_t)CLAMP(res.x * 65535, 0, 65535),
+ (int16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4);
}
-
} break;
case RS::ARRAY_TANGENT: {
@@ -416,33 +415,32 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
if (type == Variant::PACKED_FLOAT32_ARRAY) {
Vector<float> array = p_arrays[ai];
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
- const float *src = array.ptr();
+ const float *src_ptr = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- uint32_t value = 0;
- value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
- value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
- if (src[i * 4 + 3] > 0) {
- value |= 3UL << 30;
- }
-
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]);
+ Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]);
+ int16_t vector[2] = {
+ (int16_t)CLAMP(res.x * 65535, 0, 65535),
+ (int16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
+
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4);
}
} else { // PACKED_FLOAT64_ARRAY
Vector<double> array = p_arrays[ai];
ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER);
- const double *src = array.ptr();
+ const double *src_ptr = array.ptr();
for (int i = 0; i < p_vertex_array_len; i++) {
- uint32_t value = 0;
- value |= CLAMP(int((src[i * 4 + 0] * 0.5 + 0.5) * 1023.0), 0, 1023);
- value |= CLAMP(int((src[i * 4 + 1] * 0.5 + 0.5) * 1023.0), 0, 1023) << 10;
- value |= CLAMP(int((src[i * 4 + 2] * 0.5 + 0.5) * 1023.0), 0, 1023) << 20;
- if (src[i * 4 + 3] > 0) {
- value |= 3UL << 30;
- }
- memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], &value, 4);
+ const Vector3 src(src_ptr[i * 4 + 0], src_ptr[i * 4 + 1], src_ptr[i * 4 + 2]);
+ Vector2 res = src.octahedron_tangent_encode(src_ptr[i * 4 + 3]);
+ int16_t vector[2] = {
+ (int16_t)CLAMP(res.x * 65535, 0, 65535),
+ (int16_t)CLAMP(res.y * 65535, 0, 65535),
+ };
+
+ memcpy(&vw[p_offsets[ai] + i * p_vertex_stride], vector, 4);
}
}
} break;
@@ -627,7 +625,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
const int *src = indices.ptr();
for (int i = 0; i < p_index_array_len; i++) {
- if (p_vertex_array_len < (1 << 16)) {
+ if (p_vertex_array_len < (1 << 16) && p_vertex_array_len > 0) {
uint16_t v = src[i];
memcpy(&iw[i * 2], &v, 2);
@@ -703,6 +701,7 @@ Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint
}
uint32_t RenderingServer::mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_array_index) const {
+ ERR_FAIL_INDEX_V(p_array_index, ARRAY_MAX, 0);
p_format &= ~ARRAY_FORMAT_INDEX;
uint32_t offsets[ARRAY_MAX];
uint32_t vstr;
@@ -745,7 +744,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
r_attrib_element_size = 0;
r_skin_element_size = 0;
- uint32_t *size_accum;
+ uint32_t *size_accum = nullptr;
for (int i = 0; i < RS::ARRAY_MAX; i++) {
r_offsets[i] = 0; // Reset
@@ -772,19 +771,11 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
elem_size = 3;
}
- {
- elem_size *= sizeof(float);
- }
-
- if (elem_size == 6) {
- elem_size = 8;
- }
-
+ elem_size *= sizeof(float);
} break;
case RS::ARRAY_NORMAL: {
elem_size = 4;
} break;
-
case RS::ARRAY_TANGENT: {
elem_size = 4;
} break;
@@ -793,12 +784,9 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
} break;
case RS::ARRAY_TEX_UV: {
elem_size = 8;
-
} break;
-
case RS::ARRAY_TEX_UV2: {
elem_size = 8;
-
} break;
case RS::ARRAY_CUSTOM0:
case RS::ARRAY_CUSTOM1:
@@ -847,9 +835,8 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
break;
}
/* determine whether using 16 or 32 bits indices */
- if (p_vertex_len >= (1 << 16)) {
+ if (p_vertex_len >= (1 << 16) || p_vertex_len == 0) {
elem_size = 4;
-
} else {
elem_size = 2;
}
@@ -861,8 +848,12 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i
}
}
- r_offsets[i] = (*size_accum);
- (*size_accum) += elem_size;
+ if (size_accum != nullptr) {
+ r_offsets[i] = (*size_accum);
+ (*size_accum) += elem_size;
+ } else {
+ r_offsets[i] = 0;
+ }
}
}
@@ -920,8 +911,6 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
}
}
- ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // Mandatory
-
if (p_blend_shapes.size()) {
// Validate format for morphs.
for (int i = 0; i < p_blend_shapes.size(); i++) {
@@ -955,6 +944,12 @@ Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surfa
uint32_t mask = (1 << ARRAY_MAX) - 1;
format |= (~mask) & p_compress_format; // Make the full format.
+ if ((format & RS::ARRAY_FORMAT_VERTEX) == 0 && !(format & RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY)) {
+ ERR_PRINT("Mesh created without vertex array. This mesh will not be visible with the default shader. If using an empty vertex array is intentional, create the mesh with the ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY flag to silence this error.");
+ // Set the flag here after warning to suppress errors down the pipeline.
+ format |= RS::ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY;
+ }
+
int vertex_array_size = vertex_element_size * array_len;
int attrib_array_size = attrib_element_size * array_len;
int skin_array_size = skin_element_size * array_len;
@@ -1124,7 +1119,8 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
for (int j = 0; j < p_vertex_len; j++) {
const uint32_t v = *(const uint32_t *)&r[j * vertex_elem_size + offsets[i]];
- w[j] = Vector3((v & 0x3FF) / 1023.0, ((v >> 10) & 0x3FF) / 1023.0, ((v >> 20) & 0x3FF) / 1023.0) * Vector3(2, 2, 2) - Vector3(1, 1, 1);
+
+ w[j] = Vector3::octahedron_decode(Vector2((v & 0xFFFF) / 65535.0, ((v >> 16) & 0xFFFF) / 65535.0));
}
ret[i] = arr;
@@ -1139,11 +1135,12 @@ Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector<uint8_t
for (int j = 0; j < p_vertex_len; j++) {
const uint32_t v = *(const uint32_t *)&r[j * vertex_elem_size + offsets[i]];
-
- w[j * 4 + 0] = ((v & 0x3FF) / 1023.0) * 2.0 - 1.0;
- w[j * 4 + 1] = (((v >> 10) & 0x3FF) / 1023.0) * 2.0 - 1.0;
- w[j * 4 + 2] = (((v >> 20) & 0x3FF) / 1023.0) * 2.0 - 1.0;
- w[j * 4 + 3] = ((v >> 30) / 3.0) * 2.0 - 1.0;
+ float tangent_sign;
+ Vector3 res = Vector3::octahedron_tangent_decode(Vector2((v & 0xFFFF) / 65535.0, ((v >> 16) & 0xFFFF) / 65535.0), &tangent_sign);
+ w[j * 4 + 0] = res.x;
+ w[j * 4 + 1] = res.y;
+ w[j * 4 + 2] = res.z;
+ w[j * 4 + 3] = tangent_sign;
}
ret[i] = arr;
@@ -1348,7 +1345,7 @@ Dictionary RenderingServer::mesh_surface_get_lods(RID p_mesh, int p_surface) con
return ret;
}
-Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const {
+TypedArray<Array> RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const {
SurfaceData sd = mesh_get_surface(p_mesh, p_surface);
ERR_FAIL_COND_V(sd.vertex_count == 0, Array());
@@ -1370,7 +1367,7 @@ Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_sur
ERR_FAIL_COND_V(blend_shape_count != (uint32_t)mesh_get_blend_shape_count(p_mesh), Array());
- Array blend_shape_array;
+ TypedArray<Array> blend_shape_array;
blend_shape_array.resize(mesh_get_blend_shape_count(p_mesh));
for (uint32_t i = 0; i < blend_shape_count; i++) {
Vector<uint8_t> bs_data = blend_shape_data.slice(i * divisor, (i + 1) * divisor);
@@ -1380,7 +1377,7 @@ Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_sur
return blend_shape_array;
} else {
- return Array();
+ return TypedArray<Array>();
}
}
@@ -1389,7 +1386,7 @@ Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p
Vector<uint8_t> attrib_data = p_data.attribute_data;
Vector<uint8_t> skin_data = p_data.skin_data;
- ERR_FAIL_COND_V(vertex_data.size() == 0, Array());
+ ERR_FAIL_COND_V(vertex_data.size() == 0 && (p_data.format & RS::ARRAY_FORMAT_VERTEX), Array());
int vertex_len = p_data.vertex_count;
Vector<uint8_t> index_data = p_data.index_data;
@@ -1410,7 +1407,7 @@ Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_su
}
#endif
-int RenderingServer::global_variable_type_get_shader_datatype(GlobalVariableType p_type) {
+int RenderingServer::global_shader_uniform_type_get_shader_datatype(GlobalShaderParameterType p_type) {
switch (p_type) {
case RS::GLOBAL_VAR_TYPE_BOOL:
return ShaderLanguage::TYPE_BOOL;
@@ -1511,9 +1508,9 @@ TypedArray<Image> RenderingServer::_texture_3d_get(RID p_texture) const {
return ret;
}
-TypedArray<Dictionary> RenderingServer::_shader_get_param_list(RID p_shader) const {
+TypedArray<Dictionary> RenderingServer::_shader_get_shader_parameter_list(RID p_shader) const {
List<PropertyInfo> l;
- shader_get_param_list(p_shader, &l);
+ get_shader_parameter_list(p_shader, &l);
return convert_property_list(&l);
}
@@ -1636,14 +1633,14 @@ Dictionary RenderingServer::_mesh_get_surface(RID p_mesh, int p_idx) {
return d;
}
-Array RenderingServer::_instance_geometry_get_shader_parameter_list(RID p_instance) const {
+TypedArray<Dictionary> RenderingServer::_instance_geometry_get_shader_parameter_list(RID p_instance) const {
List<PropertyInfo> params;
instance_geometry_get_shader_parameter_list(p_instance, &params);
return convert_property_list(&params);
}
TypedArray<Image> RenderingServer::_bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) {
- Vector<RID> mat_overrides;
+ TypedArray<RID> mat_overrides;
for (int i = 0; i < p_material_overrides.size(); i++) {
mat_overrides.push_back(p_material_overrides[i]);
}
@@ -1694,6 +1691,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("texture_get_path", "texture"), &RenderingServer::texture_get_path);
ClassDB::bind_method(D_METHOD("texture_set_force_redraw_if_visible", "texture", "enable"), &RenderingServer::texture_set_force_redraw_if_visible);
+ ClassDB::bind_method(D_METHOD("texture_get_rd_texture", "texture", "srgb"), &RenderingServer::texture_get_rd_texture_rid, DEFVAL(false));
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_2D_ARRAY);
BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP);
@@ -1709,12 +1707,14 @@ void RenderingServer::_bind_methods() {
/* SHADER */
ClassDB::bind_method(D_METHOD("shader_create"), &RenderingServer::shader_create);
+ ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &RenderingServer::shader_set_code);
+ ClassDB::bind_method(D_METHOD("shader_set_path_hint", "shader", "path"), &RenderingServer::shader_set_path_hint);
ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &RenderingServer::shader_get_code);
- ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list);
- ClassDB::bind_method(D_METHOD("shader_get_param_default", "shader", "param"), &RenderingServer::shader_get_param_default);
+ ClassDB::bind_method(D_METHOD("get_shader_parameter_list", "shader"), &RenderingServer::_shader_get_shader_parameter_list);
+ ClassDB::bind_method(D_METHOD("shader_get_parameter_default", "shader", "name"), &RenderingServer::shader_get_parameter_default);
- ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "param", "texture", "index"), &RenderingServer::shader_set_default_texture_param, DEFVAL(0));
- ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "param", "index"), &RenderingServer::shader_get_default_texture_param, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("shader_set_default_texture_parameter", "shader", "name", "texture", "index"), &RenderingServer::shader_set_default_texture_parameter, DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("shader_get_default_texture_parameter", "shader", "name", "index"), &RenderingServer::shader_get_default_texture_parameter, DEFVAL(0));
BIND_ENUM_CONSTANT(SHADER_SPATIAL);
BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM);
@@ -1894,9 +1894,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("light_projectors_set_filter", "filter"), &RenderingServer::light_projectors_set_filter);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST);
- BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL);
@@ -1905,6 +1906,7 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR);
BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SIZE);
@@ -1919,8 +1921,8 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_PANCAKE_SIZE);
+ BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_OPACITY);
BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BLUR);
- BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE);
BIND_ENUM_CONSTANT(LIGHT_PARAM_TRANSMITTANCE_BIAS);
BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX);
@@ -1939,8 +1941,8 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_LIGHT_ONLY);
BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SKY_MODE_SKY_ONLY);
- ClassDB::bind_method(D_METHOD("shadows_quality_set", "quality"), &RenderingServer::shadows_quality_set);
- ClassDB::bind_method(D_METHOD("directional_shadow_quality_set", "quality"), &RenderingServer::directional_shadow_quality_set);
+ ClassDB::bind_method(D_METHOD("positional_soft_shadow_filter_set_quality", "quality"), &RenderingServer::positional_soft_shadow_filter_set_quality);
+ ClassDB::bind_method(D_METHOD("directional_soft_shadow_filter_set_quality", "quality"), &RenderingServer::directional_soft_shadow_filter_set_quality);
ClassDB::bind_method(D_METHOD("directional_shadow_atlas_set_size", "size", "is_16bits"), &RenderingServer::directional_shadow_atlas_set_size);
BIND_ENUM_CONSTANT(SHADOW_QUALITY_HARD);
@@ -1998,9 +2000,10 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(DECAL_TEXTURE_MAX);
BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST);
- BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS);
+ BIND_ENUM_CONSTANT(DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC);
BIND_ENUM_CONSTANT(DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC);
/* GI API (affects VoxelGI and SDFGI) */
@@ -2021,6 +2024,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("voxel_gi_set_dynamic_range", "voxel_gi", "range"), &RenderingServer::voxel_gi_set_dynamic_range);
ClassDB::bind_method(D_METHOD("voxel_gi_set_propagation", "voxel_gi", "amount"), &RenderingServer::voxel_gi_set_propagation);
ClassDB::bind_method(D_METHOD("voxel_gi_set_energy", "voxel_gi", "energy"), &RenderingServer::voxel_gi_set_energy);
+ ClassDB::bind_method(D_METHOD("voxel_gi_set_baked_exposure_normalization", "voxel_gi", "baked_exposure"), &RenderingServer::voxel_gi_set_baked_exposure_normalization);
ClassDB::bind_method(D_METHOD("voxel_gi_set_bias", "voxel_gi", "bias"), &RenderingServer::voxel_gi_set_bias);
ClassDB::bind_method(D_METHOD("voxel_gi_set_normal_bias", "voxel_gi", "bias"), &RenderingServer::voxel_gi_set_normal_bias);
ClassDB::bind_method(D_METHOD("voxel_gi_set_interior", "voxel_gi", "enable"), &RenderingServer::voxel_gi_set_interior);
@@ -2042,6 +2046,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("lightmap_get_probe_capture_sh", "lightmap"), &RenderingServer::lightmap_get_probe_capture_sh);
ClassDB::bind_method(D_METHOD("lightmap_get_probe_capture_tetrahedra", "lightmap"), &RenderingServer::lightmap_get_probe_capture_tetrahedra);
ClassDB::bind_method(D_METHOD("lightmap_get_probe_capture_bsp_tree", "lightmap"), &RenderingServer::lightmap_get_probe_capture_bsp_tree);
+ ClassDB::bind_method(D_METHOD("lightmap_set_baked_exposure_normalization", "lightmap", "baked_exposure"), &RenderingServer::lightmap_set_baked_exposure_normalization);
ClassDB::bind_method(D_METHOD("lightmap_set_probe_capture_update_speed", "speed"), &RenderingServer::lightmap_set_probe_capture_update_speed);
@@ -2166,7 +2171,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &RenderingServer::camera_set_transform);
ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &RenderingServer::camera_set_cull_mask);
ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &RenderingServer::camera_set_environment);
- ClassDB::bind_method(D_METHOD("camera_set_camera_effects", "camera", "effects"), &RenderingServer::camera_set_camera_effects);
+ ClassDB::bind_method(D_METHOD("camera_set_camera_attributes", "camera", "effects"), &RenderingServer::camera_set_camera_attributes);
ClassDB::bind_method(D_METHOD("camera_set_use_vertical_aspect", "camera", "enable"), &RenderingServer::camera_set_use_vertical_aspect);
/* VIEWPORT */
@@ -2178,11 +2183,12 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport);
ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &RenderingServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &RenderingServer::viewport_set_render_direct_to_screen);
+ ClassDB::bind_method(D_METHOD("viewport_set_canvas_cull_mask", "viewport", "canvas_cull_mask"), &RenderingServer::viewport_set_canvas_cull_mask);
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_mode", "viewport", "scaling_3d_mode"), &RenderingServer::viewport_set_scaling_3d_mode);
ClassDB::bind_method(D_METHOD("viewport_set_scaling_3d_scale", "viewport", "scale"), &RenderingServer::viewport_set_scaling_3d_scale);
ClassDB::bind_method(D_METHOD("viewport_set_fsr_sharpness", "viewport", "sharpness"), &RenderingServer::viewport_set_fsr_sharpness);
- ClassDB::bind_method(D_METHOD("viewport_set_fsr_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_fsr_mipmap_bias);
+ ClassDB::bind_method(D_METHOD("viewport_set_texture_mipmap_bias", "viewport", "mipmap_bias"), &RenderingServer::viewport_set_texture_mipmap_bias);
ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode);
ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode);
ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture);
@@ -2207,9 +2213,10 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_set_sdf_oversize_and_scale", "viewport", "oversize", "scale"), &RenderingServer::viewport_set_sdf_oversize_and_scale);
- ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_shadow_atlas_size, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision);
- ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa);
+ ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_size", "viewport", "size", "use_16_bits"), &RenderingServer::viewport_set_positional_shadow_atlas_size, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("viewport_set_positional_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_positional_shadow_atlas_quadrant_subdivision);
+ ClassDB::bind_method(D_METHOD("viewport_set_msaa_3d", "viewport", "msaa"), &RenderingServer::viewport_set_msaa_3d);
+ ClassDB::bind_method(D_METHOD("viewport_set_msaa_2d", "viewport", "msaa"), &RenderingServer::viewport_set_msaa_2d);
ClassDB::bind_method(D_METHOD("viewport_set_screen_space_aa", "viewport", "mode"), &RenderingServer::viewport_set_screen_space_aa);
ClassDB::bind_method(D_METHOD("viewport_set_use_taa", "viewport", "enable"), &RenderingServer::viewport_set_use_taa);
ClassDB::bind_method(D_METHOD("viewport_set_use_debanding", "viewport", "enable"), &RenderingServer::viewport_set_use_debanding);
@@ -2225,6 +2232,9 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("viewport_get_measured_render_time_gpu", "viewport"), &RenderingServer::viewport_get_measured_render_time_gpu);
+ ClassDB::bind_method(D_METHOD("viewport_set_vrs_mode", "viewport", "mode"), &RenderingServer::viewport_set_vrs_mode);
+ ClassDB::bind_method(D_METHOD("viewport_set_vrs_texture", "viewport", "texture"), &RenderingServer::viewport_set_vrs_texture);
+
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_BILINEAR);
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_FSR);
BIND_ENUM_CONSTANT(VIEWPORT_SCALING_3D_MODE_MAX);
@@ -2300,6 +2310,11 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OCCLUDERS);
BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_MOTION_VECTORS);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_DISABLED);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_TEXTURE);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_XR);
+ BIND_ENUM_CONSTANT(VIEWPORT_VRS_MAX);
+
/* SKY API */
ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create);
@@ -2321,17 +2336,17 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &RenderingServer::environment_set_sky_custom_fov);
ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &RenderingServer::environment_set_sky_orientation);
ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &RenderingServer::environment_set_bg_color);
- ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &RenderingServer::environment_set_bg_energy);
+ ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "multiplier", "exposure_value"), &RenderingServer::environment_set_bg_energy);
ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &RenderingServer::environment_set_canvas_max_layer);
ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG));
ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "levels", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap", "glow_map_strength", "glow_map"), &RenderingServer::environment_set_glow);
- ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap);
+ ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white"), &RenderingServer::environment_set_tonemap);
ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "use_1d_color_correction", "color_correction"), &RenderingServer::environment_set_adjustment);
ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance"), &RenderingServer::environment_set_ssr);
ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "power", "detail", "horizon", "sharpness", "light_affect", "ao_channel_affect"), &RenderingServer::environment_set_ssao);
- ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective"), &RenderingServer::environment_set_fog);
+ ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density", "aerial_perspective", "sky_affect"), &RenderingServer::environment_set_fog);
ClassDB::bind_method(D_METHOD("environment_set_sdfgi", "env", "enable", "cascades", "min_cell_size", "y_scale", "use_occlusion", "bounce_feedback", "read_sky", "energy", "normal_bias", "probe_bias"), &RenderingServer::environment_set_sdfgi);
- ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject"), &RenderingServer::environment_set_volumetric_fog);
+ ClassDB::bind_method(D_METHOD("environment_set_volumetric_fog", "env", "enable", "density", "albedo", "emission", "emission_energy", "anisotropy", "length", "p_detail_spread", "gi_inject", "temporal_reprojection", "temporal_reprojection_amount", "ambient_inject", "sky_affect"), &RenderingServer::environment_set_volumetric_fog);
ClassDB::bind_method(D_METHOD("environment_glow_set_use_bicubic_upscale", "enable"), &RenderingServer::environment_glow_set_use_bicubic_upscale);
ClassDB::bind_method(D_METHOD("environment_glow_set_use_high_quality", "enable"), &RenderingServer::environment_glow_set_use_high_quality);
@@ -2430,13 +2445,14 @@ void RenderingServer::_bind_methods() {
/* CAMERA EFFECTS */
- ClassDB::bind_method(D_METHOD("camera_effects_create"), &RenderingServer::camera_effects_create);
+ ClassDB::bind_method(D_METHOD("camera_attributes_create"), &RenderingServer::camera_attributes_create);
- ClassDB::bind_method(D_METHOD("camera_effects_set_dof_blur_quality", "quality", "use_jitter"), &RenderingServer::camera_effects_set_dof_blur_quality);
- ClassDB::bind_method(D_METHOD("camera_effects_set_dof_blur_bokeh_shape", "shape"), &RenderingServer::camera_effects_set_dof_blur_bokeh_shape);
+ ClassDB::bind_method(D_METHOD("camera_attributes_set_dof_blur_quality", "quality", "use_jitter"), &RenderingServer::camera_attributes_set_dof_blur_quality);
+ ClassDB::bind_method(D_METHOD("camera_attributes_set_dof_blur_bokeh_shape", "shape"), &RenderingServer::camera_attributes_set_dof_blur_bokeh_shape);
- ClassDB::bind_method(D_METHOD("camera_effects_set_dof_blur", "camera_effects", "far_enable", "far_distance", "far_transition", "near_enable", "near_distance", "near_transition", "amount"), &RenderingServer::camera_effects_set_dof_blur);
- ClassDB::bind_method(D_METHOD("camera_effects_set_custom_exposure", "camera_effects", "enable", "exposure"), &RenderingServer::camera_effects_set_custom_exposure);
+ ClassDB::bind_method(D_METHOD("camera_attributes_set_dof_blur", "camera_attributes", "far_enable", "far_distance", "far_transition", "near_enable", "near_distance", "near_transition", "amount"), &RenderingServer::camera_attributes_set_dof_blur);
+ ClassDB::bind_method(D_METHOD("camera_attributes_set_exposure", "camera_attributes", "multiplier", "normalization"), &RenderingServer::camera_attributes_set_exposure);
+ ClassDB::bind_method(D_METHOD("camera_attributes_set_auto_exposure", "camera_attributes", "enable", "min_sensitivity", "max_sensitivity", "speed", "scale"), &RenderingServer::camera_attributes_set_auto_exposure);
BIND_ENUM_CONSTANT(DOF_BOKEH_BOX);
BIND_ENUM_CONSTANT(DOF_BOKEH_HEXAGON);
@@ -2452,7 +2468,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("scenario_create"), &RenderingServer::scenario_create);
ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &RenderingServer::scenario_set_environment);
ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &RenderingServer::scenario_set_fallback_environment);
- ClassDB::bind_method(D_METHOD("scenario_set_camera_effects", "scenario", "effects"), &RenderingServer::scenario_set_camera_effects);
+ ClassDB::bind_method(D_METHOD("scenario_set_camera_attributes", "scenario", "effects"), &RenderingServer::scenario_set_camera_attributes);
/* INSTANCE */
@@ -2561,6 +2577,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_set_default_texture_repeat", "item", "repeat"), &RenderingServer::canvas_item_set_default_texture_repeat);
ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &RenderingServer::canvas_item_set_visible);
ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &RenderingServer::canvas_item_set_light_mask);
+ ClassDB::bind_method(D_METHOD("canvas_item_set_visibility_layer", "item", "visibility_layer"), &RenderingServer::canvas_item_set_visibility_layer);
ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &RenderingServer::canvas_item_set_transform);
ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &RenderingServer::canvas_item_set_clip);
ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &RenderingServer::canvas_item_set_distance_field_mode);
@@ -2577,6 +2594,7 @@ void RenderingServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false));
ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region);
ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true));
ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)));
ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0));
@@ -2621,7 +2639,8 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MAX);
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_DISABLED);
- BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_OPAQUE);
+ BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_CLIP_ONLY);
+ BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_CLIP_AND_DRAW);
BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_TRANSPARENT);
/* CANVAS LIGHT */
@@ -2680,15 +2699,15 @@ void RenderingServer::_bind_methods() {
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE);
BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE);
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
- ClassDB::bind_method(D_METHOD("global_variable_add", "name", "type", "default_value"), &RenderingServer::global_variable_add);
- ClassDB::bind_method(D_METHOD("global_variable_remove", "name"), &RenderingServer::global_variable_remove);
- ClassDB::bind_method(D_METHOD("global_variable_get_list"), &RenderingServer::global_variable_get_list);
- ClassDB::bind_method(D_METHOD("global_variable_set", "name", "value"), &RenderingServer::global_variable_set);
- ClassDB::bind_method(D_METHOD("global_variable_set_override", "name", "value"), &RenderingServer::global_variable_set_override);
- ClassDB::bind_method(D_METHOD("global_variable_get", "name"), &RenderingServer::global_variable_get);
- ClassDB::bind_method(D_METHOD("global_variable_get_type", "name"), &RenderingServer::global_variable_get_type);
+ ClassDB::bind_method(D_METHOD("global_shader_parameter_add", "name", "type", "default_value"), &RenderingServer::global_shader_parameter_add);
+ ClassDB::bind_method(D_METHOD("global_shader_parameter_remove", "name"), &RenderingServer::global_shader_parameter_remove);
+ ClassDB::bind_method(D_METHOD("global_shader_parameter_get_list"), &RenderingServer::global_shader_parameter_get_list);
+ ClassDB::bind_method(D_METHOD("global_shader_parameter_set", "name", "value"), &RenderingServer::global_shader_parameter_set);
+ ClassDB::bind_method(D_METHOD("global_shader_parameter_set_override", "name", "value"), &RenderingServer::global_shader_parameter_set_override);
+ ClassDB::bind_method(D_METHOD("global_shader_parameter_get", "name"), &RenderingServer::global_shader_parameter_get);
+ ClassDB::bind_method(D_METHOD("global_shader_parameter_get_type", "name"), &RenderingServer::global_shader_parameter_get_type);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BOOL);
BIND_ENUM_CONSTANT(GLOBAL_VAR_TYPE_BVEC2);
@@ -2776,10 +2795,10 @@ void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry
Vector<Vector3> vertices;
Vector<Vector3> normals;
- for (int i = 0; i < p_mesh_data.faces.size(); i++) {
+ for (uint32_t i = 0; i < p_mesh_data.faces.size(); i++) {
const Geometry3D::MeshData::Face &f = p_mesh_data.faces[i];
- for (int j = 2; j < f.indices.size(); j++) {
+ for (uint32_t j = 2; j < f.indices.size(); j++) {
vertices.push_back(p_mesh_data.vertices[f.indices[0]]);
normals.push_back(f.plane.normal);
@@ -2821,7 +2840,6 @@ void RenderingServer::set_render_loop_enabled(bool p_enabled) {
RenderingServer::RenderingServer() {
//ERR_FAIL_COND(singleton);
- thread_pool = memnew(RendererThreadPool);
singleton = this;
}
@@ -2838,32 +2856,25 @@ void RenderingServer::init() {
GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/limits/time/time_rollover_secs", PropertyInfo(Variant::FLOAT, "rendering/limits/time/time_rollover_secs", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"));
- GLOBAL_DEF("rendering/shadows/directional_shadow/size", 4096);
- GLOBAL_DEF("rendering/shadows/directional_shadow/size.mobile", 2048);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
- GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality", 2);
- GLOBAL_DEF("rendering/shadows/directional_shadow/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/directional_shadow/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/directional_shadow/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
- GLOBAL_DEF("rendering/shadows/directional_shadow/16_bits", true);
+ GLOBAL_DEF_RST("rendering/lights_and_shadows/use_physical_light_units", false);
- GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality", 2);
- GLOBAL_DEF("rendering/shadows/shadows/soft_shadow_quality.mobile", 0);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadows/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/shadows/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ GLOBAL_DEF("rendering/lights_and_shadows/directional_shadow/size", 4096);
+ GLOBAL_DEF("rendering/lights_and_shadows/directional_shadow/size.mobile", 2048);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384"));
+ GLOBAL_DEF("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality", 2);
+ GLOBAL_DEF("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/directional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
+ GLOBAL_DEF("rendering/lights_and_shadows/directional_shadow/16_bits", true);
+
+ GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality", 2);
+ GLOBAL_DEF("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality.mobile", 0);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality", PropertyInfo(Variant::INT, "rendering/lights_and_shadows/positional_shadow/soft_shadow_filter_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Very Low (Faster),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)"));
GLOBAL_DEF("rendering/2d/shadow_atlas/size", 2048);
- GLOBAL_DEF_RST_BASIC("rendering/vulkan/rendering/back_end", 0);
- GLOBAL_DEF_RST_BASIC("rendering/vulkan/rendering/back_end.mobile", 1);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/vulkan/rendering/back_end",
- PropertyInfo(Variant::INT,
- "rendering/vulkan/rendering/back_end",
- PROPERTY_HINT_ENUM, "Forward Clustered (Supports Desktop Only),Forward Mobile (Supports Desktop and Mobile)"));
- // Already defined in RenderingDeviceVulkan::initialize which runs before this code.
- // We re-define them here just for doctool's sake. Make sure to keep default values in sync.
- GLOBAL_DEF("rendering/vulkan/staging_buffer/block_size_kb", 256);
- GLOBAL_DEF("rendering/vulkan/staging_buffer/max_size_mb", 128);
- GLOBAL_DEF("rendering/vulkan/staging_buffer/texture_upload_region_size_px", 64);
- GLOBAL_DEF("rendering/vulkan/descriptor_pools/max_descriptors_per_pool", 64);
+ // Number of commands that can be drawn per frame.
+ GLOBAL_DEF_RST("rendering/gl_compatibility/item_buffer_size", 16384);
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/gl_compatibility/item_buffer_size", PropertyInfo(Variant::INT, "rendering/gl_compatibility/item_buffer_size", PROPERTY_HINT_RANGE, "1024,1048576,1"));
GLOBAL_DEF("rendering/shader_compiler/shader_cache/enabled", true);
GLOBAL_DEF("rendering/shader_compiler/shader_cache/compress", true);
@@ -2934,10 +2945,10 @@ void RenderingServer::init() {
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/amount", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/amount", PROPERTY_HINT_RANGE, "0.01,4.0,0.01"));
ProjectSettings::get_singleton()->set_custom_property_info("rendering/anti_aliasing/screen_space_roughness_limiter/limit", PropertyInfo(Variant::FLOAT, "rendering/anti_aliasing/screen_space_roughness_limiter/limit", PROPERTY_HINT_RANGE, "0.01,1.0,0.01"));
- GLOBAL_DEF_RST("rendering/scaling_3d/mode", 0);
- GLOBAL_DEF_RST("rendering/scaling_3d/scale", 1.0);
- GLOBAL_DEF_RST("rendering/scaling_3d/fsr_sharpness", 0.2f);
- GLOBAL_DEF_RST("rendering/scaling_3d/fsr_mipmap_bias", 0.0f);
+ GLOBAL_DEF("rendering/scaling_3d/mode", 0);
+ GLOBAL_DEF("rendering/scaling_3d/scale", 1.0);
+ GLOBAL_DEF("rendering/scaling_3d/fsr_sharpness", 0.2f);
+ GLOBAL_DEF("rendering/textures/default_filters/texture_mipmap_bias", 0.0f);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/mode",
PropertyInfo(Variant::INT,
"rendering/scaling_3d/mode",
@@ -2952,18 +2963,17 @@ void RenderingServer::init() {
PropertyInfo(Variant::FLOAT,
"rendering/scaling_3d/fsr_sharpness",
PROPERTY_HINT_RANGE, "0,2,0.1"));
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/scaling_3d/fsr_mipmap_bias",
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/default_filters/texture_mipmap_bias",
PropertyInfo(Variant::FLOAT,
- "rendering/scaling_3d/fsr_mipmap_bias",
- PROPERTY_HINT_RANGE, "-2,2,0.1"));
+ "rendering/textures/default_filters/texture_mipmap_bias",
+ PROPERTY_HINT_RANGE, "-2,2,0.001"));
GLOBAL_DEF("rendering/textures/decals/filter", DECAL_FILTER_LINEAR_MIPMAPS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/decals/filter", PropertyInfo(Variant::INT, "rendering/textures/decals/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"));
GLOBAL_DEF("rendering/textures/light_projectors/filter", LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS);
- ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Nearest+Mipmaps,Linear,Linear+Mipmaps,Linear+Mipmaps Anisotropic (Slow)"));
+ ProjectSettings::get_singleton()->set_custom_property_info("rendering/textures/light_projectors/filter", PropertyInfo(Variant::INT, "rendering/textures/light_projectors/filter", PROPERTY_HINT_ENUM, "Nearest (Fast),Linear (Fast),Nearest Mipmap (Fast),Linear Mipmap (Fast),Nearest Mipmap Anisotropic (Average),Linear Mipmap Anisotropic (Average)"));
GLOBAL_DEF_RST("rendering/occlusion_culling/occlusion_rays_per_thread", 512);
- GLOBAL_DEF_RST("rendering/occlusion_culling/bvh_build_quality", 2);
ProjectSettings::get_singleton()->set_custom_property_info("rendering/occlusion_culling/bvh_build_quality", PropertyInfo(Variant::INT, "rendering/occlusion_culling/bvh_build_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"));
GLOBAL_DEF("rendering/environment/glow/upscale_mode", 1);
@@ -3022,6 +3032,5 @@ void RenderingServer::init() {
}
RenderingServer::~RenderingServer() {
- memdelete(thread_pool);
singleton = nullptr;
}
diff --git a/servers/rendering_server.h b/servers/rendering_server.h
index 39484e532a..1d364dfcff 100644
--- a/servers/rendering_server.h
+++ b/servers/rendering_server.h
@@ -35,13 +35,16 @@
#include "core/math/geometry_3d.h"
#include "core/math/transform_2d.h"
#include "core/object/class_db.h"
+#include "core/object/worker_thread_pool.h"
#include "core/templates/rid.h"
#include "core/variant/typed_array.h"
#include "core/variant/variant.h"
#include "servers/display_server.h"
-#include "servers/rendering/renderer_thread_pool.h"
#include "servers/rendering/rendering_device.h"
+template <typename T>
+class TypedArray;
+
class RenderingServer : public Object {
GDCLASS(RenderingServer, Object);
@@ -52,8 +55,6 @@ class RenderingServer : public Object {
Array _get_array_from_surface(uint32_t p_format, Vector<uint8_t> p_vertex_data, Vector<uint8_t> p_attrib_data, Vector<uint8_t> p_skin_data, int p_vertex_len, Vector<uint8_t> p_index_data, int p_index_len) const;
- RendererThreadPool *thread_pool = nullptr;
-
const Vector2 SMALL_VEC2 = Vector2(CMP_EPSILON, CMP_EPSILON);
const Vector3 SMALL_VEC3 = Vector3(CMP_EPSILON, CMP_EPSILON, CMP_EPSILON);
@@ -156,6 +157,8 @@ public:
virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0;
+ virtual RID texture_get_rd_texture_rid(RID p_texture, bool p_srgb = false) const = 0;
+
/* SHADER API */
enum ShaderMode {
@@ -170,12 +173,13 @@ public:
virtual RID shader_create() = 0;
virtual void shader_set_code(RID p_shader, const String &p_code) = 0;
+ virtual void shader_set_path_hint(RID p_shader, const String &p_path) = 0;
virtual String shader_get_code(RID p_shader) const = 0;
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
- virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0;
+ virtual void get_shader_parameter_list(RID p_shader, List<PropertyInfo> *p_param_list) const = 0;
+ virtual Variant shader_get_parameter_default(RID p_shader, const StringName &p_param) const = 0;
- virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0;
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name, int p_index = 0) const = 0;
+ virtual void shader_set_default_texture_parameter(RID p_shader, const StringName &p_name, RID p_texture, int p_index = 0) = 0;
+ virtual RID shader_get_default_texture_parameter(RID p_shader, const StringName &p_name, int p_index = 0) const = 0;
struct ShaderNativeSourceCode {
struct Version {
@@ -245,7 +249,7 @@ public:
enum ArrayFormat {
/* ARRAY FORMAT FLAGS */
- ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // Mandatory
+ ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX,
ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL,
ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT,
ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR,
@@ -263,17 +267,19 @@ public:
ARRAY_FORMAT_CUSTOM_BASE = (ARRAY_INDEX + 1),
ARRAY_FORMAT_CUSTOM_BITS = 3,
+ ARRAY_FORMAT_CUSTOM_MASK = 0x7,
ARRAY_FORMAT_CUSTOM0_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + 0),
ARRAY_FORMAT_CUSTOM1_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS),
ARRAY_FORMAT_CUSTOM2_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 2),
ARRAY_FORMAT_CUSTOM3_SHIFT = (ARRAY_FORMAT_CUSTOM_BASE + ARRAY_FORMAT_CUSTOM_BITS * 3),
- ARRAY_FORMAT_CUSTOM_MASK = 0x7,
ARRAY_COMPRESS_FLAGS_BASE = (ARRAY_INDEX + 1 + 12),
ARRAY_FLAG_USE_2D_VERTICES = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 0),
ARRAY_FLAG_USE_DYNAMIC_UPDATE = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 1),
ARRAY_FLAG_USE_8_BONE_WEIGHTS = 1 << (ARRAY_COMPRESS_FLAGS_BASE + 2),
+
+ ARRAY_FLAG_USES_EMPTY_VERTEX_ARRAY = 1 << (ARRAY_INDEX + 1 + 15),
};
enum PrimitiveType {
@@ -324,7 +330,7 @@ public:
virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0);
Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const;
Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const;
- Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
+ TypedArray<Array> mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const;
Dictionary mesh_surface_get_lods(RID p_mesh, int p_surface) const;
virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = 0);
@@ -412,6 +418,7 @@ public:
enum LightParam {
LIGHT_PARAM_ENERGY,
LIGHT_PARAM_INDIRECT_ENERGY,
+ LIGHT_PARAM_VOLUMETRIC_FOG_ENERGY,
LIGHT_PARAM_SPECULAR,
LIGHT_PARAM_RANGE,
LIGHT_PARAM_SIZE,
@@ -426,9 +433,10 @@ public:
LIGHT_PARAM_SHADOW_NORMAL_BIAS,
LIGHT_PARAM_SHADOW_BIAS,
LIGHT_PARAM_SHADOW_PANCAKE_SIZE,
+ LIGHT_PARAM_SHADOW_OPACITY,
LIGHT_PARAM_SHADOW_BLUR,
- LIGHT_PARAM_SHADOW_VOLUMETRIC_FOG_FADE,
LIGHT_PARAM_TRANSMITTANCE_BIAS,
+ LIGHT_PARAM_INTENSITY,
LIGHT_PARAM_MAX
};
@@ -479,6 +487,12 @@ public:
virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0;
virtual void light_directional_set_sky_mode(RID p_light, LightDirectionalSkyMode p_mode) = 0;
+ // Shadow atlas
+
+ virtual RID shadow_atlas_create() = 0;
+ virtual void shadow_atlas_set_size(RID p_atlas, int p_size, bool p_use_16_bits = true) = 0;
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0;
+
virtual void directional_shadow_atlas_set_size(int p_size, bool p_16_bits = true) = 0;
enum ShadowQuality {
@@ -491,14 +505,15 @@ public:
SHADOW_QUALITY_MAX
};
- virtual void shadows_quality_set(ShadowQuality p_quality) = 0;
- virtual void directional_shadow_quality_set(ShadowQuality p_quality) = 0;
+ virtual void positional_soft_shadow_filter_set_quality(ShadowQuality p_quality) = 0;
+ virtual void directional_soft_shadow_filter_set_quality(ShadowQuality p_quality) = 0;
enum LightProjectorFilter {
LIGHT_PROJECTOR_FILTER_NEAREST,
- LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
LIGHT_PROJECTOR_FILTER_LINEAR,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS,
LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS,
+ LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC,
LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
};
@@ -558,9 +573,10 @@ public:
enum DecalFilter {
DECAL_FILTER_NEAREST,
- DECAL_FILTER_NEAREST_MIPMAPS,
DECAL_FILTER_LINEAR,
+ DECAL_FILTER_NEAREST_MIPMAPS,
DECAL_FILTER_LINEAR_MIPMAPS,
+ DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC,
DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC,
};
@@ -583,6 +599,7 @@ public:
virtual void voxel_gi_set_dynamic_range(RID p_voxel_gi, float p_range) = 0;
virtual void voxel_gi_set_propagation(RID p_voxel_gi, float p_range) = 0;
virtual void voxel_gi_set_energy(RID p_voxel_gi, float p_energy) = 0;
+ virtual void voxel_gi_set_baked_exposure_normalization(RID p_voxel_gi, float p_baked_exposure) = 0;
virtual void voxel_gi_set_bias(RID p_voxel_gi, float p_bias) = 0;
virtual void voxel_gi_set_normal_bias(RID p_voxel_gi, float p_range) = 0;
virtual void voxel_gi_set_interior(RID p_voxel_gi, bool p_enable) = 0;
@@ -603,6 +620,7 @@ public:
virtual void lightmap_set_probe_bounds(RID p_lightmap, const AABB &p_bounds) = 0;
virtual void lightmap_set_probe_interior(RID p_lightmap, bool p_interior) = 0;
virtual void lightmap_set_probe_capture_data(RID p_lightmap, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree) = 0;
+ virtual void lightmap_set_baked_exposure_normalization(RID p_lightmap, float p_exposure) = 0;
virtual PackedVector3Array lightmap_get_probe_capture_points(RID p_lightmap) const = 0;
virtual PackedColorArray lightmap_get_probe_capture_sh(RID p_lightmap) const = 0;
virtual PackedInt32Array lightmap_get_probe_capture_tetrahedra(RID p_lightmap) const = 0;
@@ -755,7 +773,7 @@ public:
virtual void camera_set_transform(RID p_camera, const Transform3D &p_transform) = 0;
virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0;
virtual void camera_set_environment(RID p_camera, RID p_env) = 0;
- virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0;
+ virtual void camera_set_camera_attributes(RID p_camera, RID p_camera_attributes) = 0;
virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0;
/* VIEWPORT API */
@@ -791,6 +809,7 @@ public:
virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0;
virtual void viewport_set_active(RID p_viewport, bool p_active) = 0;
virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0;
+ virtual void viewport_set_canvas_cull_mask(RID p_viewport, uint32_t p_canvas_cull_mask) = 0;
virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0;
virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0;
@@ -798,7 +817,7 @@ public:
virtual void viewport_set_scaling_3d_mode(RID p_viewport, ViewportScaling3DMode p_scaling_3d_mode) = 0;
virtual void viewport_set_scaling_3d_scale(RID p_viewport, float p_scaling_3d_scale) = 0;
virtual void viewport_set_fsr_sharpness(RID p_viewport, float p_fsr_sharpness) = 0;
- virtual void viewport_set_fsr_mipmap_bias(RID p_viewport, float p_fsr_mipmap_bias) = 0;
+ virtual void viewport_set_texture_mipmap_bias(RID p_viewport, float p_texture_mipmap_bias) = 0;
enum ViewportUpdateMode {
VIEWPORT_UPDATE_DISABLED,
@@ -856,8 +875,8 @@ public:
virtual void viewport_set_sdf_oversize_and_scale(RID p_viewport, ViewportSDFOversize p_oversize, ViewportSDFScale p_scale) = 0;
- virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true) = 0;
- virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
+ virtual void viewport_set_positional_shadow_atlas_size(RID p_viewport, int p_size, bool p_16_bits = true) = 0;
+ virtual void viewport_set_positional_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0;
enum ViewportMSAA {
VIEWPORT_MSAA_DISABLED,
@@ -867,7 +886,8 @@ public:
VIEWPORT_MSAA_MAX,
};
- virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0;
+ virtual void viewport_set_msaa_3d(RID p_viewport, ViewportMSAA p_msaa) = 0;
+ virtual void viewport_set_msaa_2d(RID p_viewport, ViewportMSAA p_msaa) = 0;
enum ViewportScreenSpaceAA {
VIEWPORT_SCREEN_SPACE_AA_DISABLED,
@@ -944,6 +964,18 @@ public:
virtual double viewport_get_measured_render_time_cpu(RID p_viewport) const = 0;
virtual double viewport_get_measured_render_time_gpu(RID p_viewport) const = 0;
+ virtual RID viewport_find_from_screen_attachment(DisplayServer::WindowID p_id = DisplayServer::MAIN_WINDOW_ID) const = 0;
+
+ enum ViewportVRSMode {
+ VIEWPORT_VRS_DISABLED,
+ VIEWPORT_VRS_TEXTURE,
+ VIEWPORT_VRS_XR,
+ VIEWPORT_VRS_MAX,
+ };
+
+ virtual void viewport_set_vrs_mode(RID p_viewport, ViewportVRSMode p_mode) = 0;
+ virtual void viewport_set_vrs_texture(RID p_viewport, RID p_texture) = 0;
+
/* SKY API */
enum SkyMode {
@@ -991,7 +1023,7 @@ public:
virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0;
virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0;
virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0;
- virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0;
+ virtual void environment_set_bg_energy(RID p_env, float p_multiplier, float p_exposure_value) = 0;
virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0;
virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG) = 0;
@@ -1015,7 +1047,7 @@ public:
ENV_TONE_MAPPER_ACES
};
- virtual void environment_set_tonemap(RID p_env, EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_grey) = 0;
+ virtual void environment_set_tonemap(RID p_env, EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white) = 0;
virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, bool p_use_1d_color_correction, RID p_color_correction) = 0;
virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance) = 0;
@@ -1097,9 +1129,9 @@ public:
virtual void environment_set_sdfgi_frames_to_update_light(EnvironmentSDFGIFramesToUpdateLight p_update) = 0;
- virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective) = 0;
+ virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_light_color, float p_light_energy, float p_sun_scatter, float p_density, float p_height, float p_height_density, float p_aerial_perspective, float p_sky_affect) = 0;
- virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject) = 0;
+ virtual void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_albedo, const Color &p_emission, float p_emission_energy, float p_anisotropy, float p_length, float p_detail_spread, float p_gi_inject, bool p_temporal_reprojection, float p_temporal_reprojection_amount, float p_ambient_inject, float p_sky_affect) = 0;
virtual void environment_set_volumetric_fog_volume_size(int p_size, int p_depth) = 0;
virtual void environment_set_volumetric_fog_filter_active(bool p_enable) = 0;
@@ -1119,7 +1151,7 @@ public:
/* CAMERA EFFECTS */
- virtual RID camera_effects_create() = 0;
+ virtual RID camera_attributes_create() = 0;
enum DOFBlurQuality {
DOF_BLUR_QUALITY_VERY_LOW,
@@ -1128,7 +1160,7 @@ public:
DOF_BLUR_QUALITY_HIGH,
};
- virtual void camera_effects_set_dof_blur_quality(DOFBlurQuality p_quality, bool p_use_jitter) = 0;
+ virtual void camera_attributes_set_dof_blur_quality(DOFBlurQuality p_quality, bool p_use_jitter) = 0;
enum DOFBokehShape {
DOF_BOKEH_BOX,
@@ -1136,10 +1168,11 @@ public:
DOF_BOKEH_CIRCLE
};
- virtual void camera_effects_set_dof_blur_bokeh_shape(DOFBokehShape p_shape) = 0;
+ virtual void camera_attributes_set_dof_blur_bokeh_shape(DOFBokehShape p_shape) = 0;
- virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
- virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0;
+ virtual void camera_attributes_set_dof_blur(RID p_camera_attributes, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0;
+ virtual void camera_attributes_set_exposure(RID p_camera_attributes, float p_multiplier, float p_exposure_normalization) = 0;
+ virtual void camera_attributes_set_auto_exposure(RID p_camera_attributes, bool p_enable, float p_min_sensitivity, float p_max_sensitivity, float p_speed, float p_scale) = 0;
/* SCENARIO API */
@@ -1147,7 +1180,7 @@ public:
virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0;
- virtual void scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) = 0;
+ virtual void scenario_set_camera_attributes(RID p_scenario, RID p_camera_attributes) = 0;
/* INSTANCING API */
@@ -1197,9 +1230,9 @@ public:
virtual Vector<ObjectID> instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0;
virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane> &p_convex, RID p_scenario = RID()) const = 0;
- Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const;
- Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
- Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const;
+ PackedInt64Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const;
+ PackedInt64Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const;
+ PackedInt64Array _instances_cull_convex_bind(const TypedArray<Plane> &p_convex, RID p_scenario = RID()) const;
enum InstanceFlags {
INSTANCE_FLAG_USE_BAKED_LIGHT,
@@ -1245,7 +1278,7 @@ public:
BAKE_CHANNEL_EMISSION
};
- virtual TypedArray<Image> bake_render_uv2(RID p_base, const Vector<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
+ virtual TypedArray<Image> bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size) = 0;
/* CANVAS (2D) */
@@ -1290,6 +1323,7 @@ public:
virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()) = 0;
virtual void canvas_item_set_modulate(RID p_item, const Color &p_color) = 0;
virtual void canvas_item_set_self_modulate(RID p_item, const Color &p_color) = 0;
+ virtual void canvas_item_set_visibility_layer(RID p_item, uint32_t p_visibility_layer) = 0;
virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) = 0;
@@ -1307,6 +1341,7 @@ public:
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0;
virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0;
+ virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0;
@@ -1336,7 +1371,8 @@ public:
enum CanvasGroupMode {
CANVAS_GROUP_MODE_DISABLED,
- CANVAS_GROUP_MODE_OPAQUE,
+ CANVAS_GROUP_MODE_CLIP_ONLY,
+ CANVAS_GROUP_MODE_CLIP_AND_DRAW,
CANVAS_GROUP_MODE_TRANSPARENT,
};
@@ -1414,9 +1450,9 @@ public:
virtual void canvas_set_shadow_texture_size(int p_size) = 0;
- /* GLOBAL VARIABLES */
+ /* GLOBAL SHADER UNIFORMS */
- enum GlobalVariableType {
+ enum GlobalShaderParameterType {
GLOBAL_VAR_TYPE_BOOL,
GLOBAL_VAR_TYPE_BVEC2,
GLOBAL_VAR_TYPE_BVEC3,
@@ -1448,20 +1484,20 @@ public:
GLOBAL_VAR_TYPE_MAX
};
- virtual void global_variable_add(const StringName &p_name, GlobalVariableType p_type, const Variant &p_value) = 0;
- virtual void global_variable_remove(const StringName &p_name) = 0;
- virtual Vector<StringName> global_variable_get_list() const = 0;
+ virtual void global_shader_parameter_add(const StringName &p_name, GlobalShaderParameterType p_type, const Variant &p_value) = 0;
+ virtual void global_shader_parameter_remove(const StringName &p_name) = 0;
+ virtual Vector<StringName> global_shader_parameter_get_list() const = 0;
- virtual void global_variable_set(const StringName &p_name, const Variant &p_value) = 0;
- virtual void global_variable_set_override(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_parameter_set(const StringName &p_name, const Variant &p_value) = 0;
+ virtual void global_shader_parameter_set_override(const StringName &p_name, const Variant &p_value) = 0;
- virtual Variant global_variable_get(const StringName &p_name) const = 0;
- virtual GlobalVariableType global_variable_get_type(const StringName &p_name) const = 0;
+ virtual Variant global_shader_parameter_get(const StringName &p_name) const = 0;
+ virtual GlobalShaderParameterType global_shader_parameter_get_type(const StringName &p_name) const = 0;
- virtual void global_variables_load_settings(bool p_load_textures) = 0;
- virtual void global_variables_clear() = 0;
+ virtual void global_shader_parameters_load_settings(bool p_load_textures) = 0;
+ virtual void global_shader_parameters_clear() = 0;
- static int global_variable_type_get_shader_datatype(GlobalVariableType p_type);
+ static int global_shader_uniform_type_get_shader_datatype(GlobalShaderParameterType p_type);
/* FREE */
@@ -1543,6 +1579,8 @@ public:
virtual void set_print_gpu_profile(bool p_enable) = 0;
+ virtual Size2i get_maximum_viewport_size() const = 0;
+
RenderingDevice *get_rendering_device() const;
RenderingDevice *create_local_rendering_device() const;
@@ -1558,11 +1596,11 @@ private:
RID _texture_3d_create(Image::Format p_format, int p_width, int p_height, int p_depth, bool p_mipmaps, const TypedArray<Image> &p_data);
void _texture_3d_update(RID p_texture, const TypedArray<Image> &p_data);
TypedArray<Image> _texture_3d_get(RID p_texture) const;
- TypedArray<Dictionary> _shader_get_param_list(RID p_shader) const;
+ TypedArray<Dictionary> _shader_get_shader_parameter_list(RID p_shader) const;
RID _mesh_create_from_surfaces(const TypedArray<Dictionary> &p_surfaces, int p_blend_shape_count);
void _mesh_add_surface(RID p_mesh, const Dictionary &p_surface);
Dictionary _mesh_get_surface(RID p_mesh, int p_idx);
- Array _instance_geometry_get_shader_parameter_list(RID p_instance) const;
+ TypedArray<Dictionary> _instance_geometry_get_shader_parameter_list(RID p_instance) const;
TypedArray<Image> _bake_render_uv2(RID p_base, const TypedArray<RID> &p_material_overrides, const Size2i &p_image_size);
void _particles_set_trail_bind_poses(RID p_particles, const TypedArray<Transform3D> &p_bind_poses);
};
@@ -1607,6 +1645,7 @@ VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw);
VARIANT_ENUM_CAST(RenderingServer::ViewportOcclusionCullingBuildQuality);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFOversize);
VARIANT_ENUM_CAST(RenderingServer::ViewportSDFScale);
+VARIANT_ENUM_CAST(RenderingServer::ViewportVRSMode);
VARIANT_ENUM_CAST(RenderingServer::SkyMode);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG);
VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource);
@@ -1636,7 +1675,7 @@ VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightBlendMode);
VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter);
VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode);
-VARIANT_ENUM_CAST(RenderingServer::GlobalVariableType);
+VARIANT_ENUM_CAST(RenderingServer::GlobalShaderParameterType);
VARIANT_ENUM_CAST(RenderingServer::RenderingInfo);
VARIANT_ENUM_CAST(RenderingServer::Features);
VARIANT_ENUM_CAST(RenderingServer::CanvasTextureChannel);
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index 2c4aab0784..318c844a2f 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -28,6 +28,9 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
+#ifndef SERVER_WRAP_MT_COMMON_H
+#define SERVER_WRAP_MT_COMMON_H
+
#define FUNC0R(m_r, m_type) \
virtual m_r m_type() override { \
if (Thread::get_caller_id() != server_thread) { \
@@ -762,3 +765,5 @@
server_name->m_type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15); \
} \
}
+
+#endif // SERVER_WRAP_MT_COMMON_H
diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp
index 005cb68302..dd4cb5accb 100644
--- a/servers/text/text_server_extension.cpp
+++ b/servers/text/text_server_extension.cpp
@@ -31,366 +31,353 @@
#include "text_server_extension.h"
void TextServerExtension::_bind_methods() {
- GDVIRTUAL_BIND(has_feature, "feature");
- GDVIRTUAL_BIND(get_name);
- GDVIRTUAL_BIND(get_features);
+ GDVIRTUAL_BIND(_has_feature, "feature");
+ GDVIRTUAL_BIND(_get_name);
+ GDVIRTUAL_BIND(_get_features);
- GDVIRTUAL_BIND(free_rid, "rid");
- GDVIRTUAL_BIND(has, "rid");
- GDVIRTUAL_BIND(load_support_data, "filename");
+ GDVIRTUAL_BIND(_free_rid, "rid");
+ GDVIRTUAL_BIND(_has, "rid");
+ GDVIRTUAL_BIND(_load_support_data, "filename");
- GDVIRTUAL_BIND(get_support_data_filename);
- GDVIRTUAL_BIND(get_support_data_info);
- GDVIRTUAL_BIND(save_support_data, "filename");
+ GDVIRTUAL_BIND(_get_support_data_filename);
+ GDVIRTUAL_BIND(_get_support_data_info);
+ GDVIRTUAL_BIND(_save_support_data, "filename");
- GDVIRTUAL_BIND(is_locale_right_to_left, "locale");
+ GDVIRTUAL_BIND(_is_locale_right_to_left, "locale");
- GDVIRTUAL_BIND(name_to_tag, "name");
- GDVIRTUAL_BIND(tag_to_name, "tag");
+ GDVIRTUAL_BIND(_name_to_tag, "name");
+ GDVIRTUAL_BIND(_tag_to_name, "tag");
/* Font interface */
- GDVIRTUAL_BIND(create_font);
+ GDVIRTUAL_BIND(_create_font);
- GDVIRTUAL_BIND(font_set_data, "font_rid", "data");
- GDVIRTUAL_BIND(font_set_data_ptr, "font_rid", "data_ptr", "data_size");
+ GDVIRTUAL_BIND(_font_set_data, "font_rid", "data");
+ GDVIRTUAL_BIND(_font_set_data_ptr, "font_rid", "data_ptr", "data_size");
- GDVIRTUAL_BIND(font_set_style, "font_rid", "style");
- GDVIRTUAL_BIND(font_get_style, "font_rid");
+ GDVIRTUAL_BIND(_font_set_face_index, "font_rid", "face_index");
+ GDVIRTUAL_BIND(_font_get_face_index, "font_rid");
- GDVIRTUAL_BIND(font_set_name, "font_rid", "name");
- GDVIRTUAL_BIND(font_get_name, "font_rid");
+ GDVIRTUAL_BIND(_font_get_face_count, "font_rid");
- GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style");
- GDVIRTUAL_BIND(font_get_style_name, "font_rid");
+ GDVIRTUAL_BIND(_font_set_style, "font_rid", "style");
+ GDVIRTUAL_BIND(_font_get_style, "font_rid");
- GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased");
- GDVIRTUAL_BIND(font_is_antialiased, "font_rid");
+ GDVIRTUAL_BIND(_font_set_name, "font_rid", "name");
+ GDVIRTUAL_BIND(_font_get_name, "font_rid");
- GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps");
- GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid");
+ GDVIRTUAL_BIND(_font_set_style_name, "font_rid", "name_style");
+ GDVIRTUAL_BIND(_font_get_style_name, "font_rid");
- GDVIRTUAL_BIND(font_set_multichannel_signed_distance_field, "font_rid", "msdf");
- GDVIRTUAL_BIND(font_is_multichannel_signed_distance_field, "font_rid");
+ GDVIRTUAL_BIND(_font_set_antialiasing, "font_rid", "antialiasing");
+ GDVIRTUAL_BIND(_font_get_antialiasing, "font_rid");
- GDVIRTUAL_BIND(font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range");
- GDVIRTUAL_BIND(font_get_msdf_pixel_range, "font_rid");
+ GDVIRTUAL_BIND(_font_set_generate_mipmaps, "font_rid", "generate_mipmaps");
+ GDVIRTUAL_BIND(_font_get_generate_mipmaps, "font_rid");
- GDVIRTUAL_BIND(font_set_msdf_size, "font_rid", "msdf_size");
- GDVIRTUAL_BIND(font_get_msdf_size, "font_rid");
+ GDVIRTUAL_BIND(_font_set_multichannel_signed_distance_field, "font_rid", "msdf");
+ GDVIRTUAL_BIND(_font_is_multichannel_signed_distance_field, "font_rid");
- GDVIRTUAL_BIND(font_set_fixed_size, "font_rid", "fixed_size");
- GDVIRTUAL_BIND(font_get_fixed_size, "font_rid");
+ GDVIRTUAL_BIND(_font_set_msdf_pixel_range, "font_rid", "msdf_pixel_range");
+ GDVIRTUAL_BIND(_font_get_msdf_pixel_range, "font_rid");
- GDVIRTUAL_BIND(font_set_force_autohinter, "font_rid", "force_autohinter");
- GDVIRTUAL_BIND(font_is_force_autohinter, "font_rid");
+ GDVIRTUAL_BIND(_font_set_msdf_size, "font_rid", "msdf_size");
+ GDVIRTUAL_BIND(_font_get_msdf_size, "font_rid");
- GDVIRTUAL_BIND(font_set_hinting, "font_rid", "hinting");
- GDVIRTUAL_BIND(font_get_hinting, "font_rid");
+ GDVIRTUAL_BIND(_font_set_fixed_size, "font_rid", "fixed_size");
+ GDVIRTUAL_BIND(_font_get_fixed_size, "font_rid");
- GDVIRTUAL_BIND(font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
- GDVIRTUAL_BIND(font_get_subpixel_positioning, "font_rid");
+ GDVIRTUAL_BIND(_font_set_force_autohinter, "font_rid", "force_autohinter");
+ GDVIRTUAL_BIND(_font_is_force_autohinter, "font_rid");
- GDVIRTUAL_BIND(font_set_embolden, "font_rid", "strength");
- GDVIRTUAL_BIND(font_get_embolden, "font_rid");
+ GDVIRTUAL_BIND(_font_set_hinting, "font_rid", "hinting");
+ GDVIRTUAL_BIND(_font_get_hinting, "font_rid");
- GDVIRTUAL_BIND(font_set_transform, "font_rid", "transform");
- GDVIRTUAL_BIND(font_get_transform, "font_rid");
+ GDVIRTUAL_BIND(_font_set_subpixel_positioning, "font_rid", "subpixel_positioning");
+ GDVIRTUAL_BIND(_font_get_subpixel_positioning, "font_rid");
- GDVIRTUAL_BIND(font_set_variation_coordinates, "font_rid", "variation_coordinates");
- GDVIRTUAL_BIND(font_get_variation_coordinates, "font_rid");
+ GDVIRTUAL_BIND(_font_set_embolden, "font_rid", "strength");
+ GDVIRTUAL_BIND(_font_get_embolden, "font_rid");
- GDVIRTUAL_BIND(font_set_oversampling, "font_rid", "oversampling");
- GDVIRTUAL_BIND(font_get_oversampling, "font_rid");
+ GDVIRTUAL_BIND(_font_set_transform, "font_rid", "transform");
+ GDVIRTUAL_BIND(_font_get_transform, "font_rid");
- GDVIRTUAL_BIND(font_get_size_cache_list, "font_rid");
- GDVIRTUAL_BIND(font_clear_size_cache, "font_rid");
- GDVIRTUAL_BIND(font_remove_size_cache, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_set_variation_coordinates, "font_rid", "variation_coordinates");
+ GDVIRTUAL_BIND(_font_get_variation_coordinates, "font_rid");
- GDVIRTUAL_BIND(font_set_ascent, "font_rid", "size", "ascent");
- GDVIRTUAL_BIND(font_get_ascent, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_set_oversampling, "font_rid", "oversampling");
+ GDVIRTUAL_BIND(_font_get_oversampling, "font_rid");
- GDVIRTUAL_BIND(font_set_descent, "font_rid", "size", "descent");
- GDVIRTUAL_BIND(font_get_descent, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_get_size_cache_list, "font_rid");
+ GDVIRTUAL_BIND(_font_clear_size_cache, "font_rid");
+ GDVIRTUAL_BIND(_font_remove_size_cache, "font_rid", "size");
- GDVIRTUAL_BIND(font_set_underline_position, "font_rid", "size", "underline_position");
- GDVIRTUAL_BIND(font_get_underline_position, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_set_ascent, "font_rid", "size", "ascent");
+ GDVIRTUAL_BIND(_font_get_ascent, "font_rid", "size");
- GDVIRTUAL_BIND(font_set_underline_thickness, "font_rid", "size", "underline_thickness");
- GDVIRTUAL_BIND(font_get_underline_thickness, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_set_descent, "font_rid", "size", "descent");
+ GDVIRTUAL_BIND(_font_get_descent, "font_rid", "size");
- GDVIRTUAL_BIND(font_set_scale, "font_rid", "size", "scale");
- GDVIRTUAL_BIND(font_get_scale, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_set_underline_position, "font_rid", "size", "underline_position");
+ GDVIRTUAL_BIND(_font_get_underline_position, "font_rid", "size");
- GDVIRTUAL_BIND(font_set_spacing, "font_rid", "size", "spacing", "value");
- GDVIRTUAL_BIND(font_get_spacing, "font_rid", "size", "spacing");
+ GDVIRTUAL_BIND(_font_set_underline_thickness, "font_rid", "size", "underline_thickness");
+ GDVIRTUAL_BIND(_font_get_underline_thickness, "font_rid", "size");
- GDVIRTUAL_BIND(font_get_texture_count, "font_rid", "size");
- GDVIRTUAL_BIND(font_clear_textures, "font_rid", "size");
- GDVIRTUAL_BIND(font_remove_texture, "font_rid", "size", "texture_index");
+ GDVIRTUAL_BIND(_font_set_scale, "font_rid", "size", "scale");
+ GDVIRTUAL_BIND(_font_get_scale, "font_rid", "size");
- GDVIRTUAL_BIND(font_set_texture_image, "font_rid", "size", "texture_index", "image");
- GDVIRTUAL_BIND(font_get_texture_image, "font_rid", "size", "texture_index");
+ GDVIRTUAL_BIND(_font_get_texture_count, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_textures, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_texture, "font_rid", "size", "texture_index");
- GDVIRTUAL_BIND(font_set_texture_offsets, "font_rid", "size", "texture_index", "offset");
- GDVIRTUAL_BIND(font_get_texture_offsets, "font_rid", "size", "texture_index");
+ GDVIRTUAL_BIND(_font_set_texture_image, "font_rid", "size", "texture_index", "image");
+ GDVIRTUAL_BIND(_font_get_texture_image, "font_rid", "size", "texture_index");
- GDVIRTUAL_BIND(font_get_glyph_list, "font_rid", "size");
- GDVIRTUAL_BIND(font_clear_glyphs, "font_rid", "size");
- GDVIRTUAL_BIND(font_remove_glyph, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_texture_offsets, "font_rid", "size", "texture_index", "offset");
+ GDVIRTUAL_BIND(_font_get_texture_offsets, "font_rid", "size", "texture_index");
- GDVIRTUAL_BIND(font_get_glyph_advance, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_set_glyph_advance, "font_rid", "size", "glyph", "advance");
+ GDVIRTUAL_BIND(_font_get_glyph_list, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_glyphs, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_glyph, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_get_glyph_offset, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_set_glyph_offset, "font_rid", "size", "glyph", "offset");
+ GDVIRTUAL_BIND(_font_get_glyph_advance, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_advance, "font_rid", "size", "glyph", "advance");
- GDVIRTUAL_BIND(font_get_glyph_size, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_set_glyph_size, "font_rid", "size", "glyph", "gl_size");
+ GDVIRTUAL_BIND(_font_get_glyph_offset, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_offset, "font_rid", "size", "glyph", "offset");
- GDVIRTUAL_BIND(font_get_glyph_uv_rect, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect");
+ GDVIRTUAL_BIND(_font_get_glyph_size, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_size, "font_rid", "size", "glyph", "gl_size");
- GDVIRTUAL_BIND(font_get_glyph_texture_idx, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx");
+ GDVIRTUAL_BIND(_font_get_glyph_uv_rect, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_uv_rect, "font_rid", "size", "glyph", "uv_rect");
- GDVIRTUAL_BIND(font_get_glyph_texture_rid, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_get_glyph_texture_size, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_get_glyph_texture_idx, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_set_glyph_texture_idx, "font_rid", "size", "glyph", "texture_idx");
- GDVIRTUAL_BIND(font_get_glyph_contours, "font_rid", "size", "index");
+ GDVIRTUAL_BIND(_font_get_glyph_texture_rid, "font_rid", "size", "glyph");
+ GDVIRTUAL_BIND(_font_get_glyph_texture_size, "font_rid", "size", "glyph");
- GDVIRTUAL_BIND(font_get_kerning_list, "font_rid", "size");
- GDVIRTUAL_BIND(font_clear_kerning_map, "font_rid", "size");
- GDVIRTUAL_BIND(font_remove_kerning, "font_rid", "size", "glyph_pair");
+ GDVIRTUAL_BIND(_font_get_glyph_contours, "font_rid", "size", "index");
- GDVIRTUAL_BIND(font_set_kerning, "font_rid", "size", "glyph_pair", "kerning");
- GDVIRTUAL_BIND(font_get_kerning, "font_rid", "size", "glyph_pair");
+ GDVIRTUAL_BIND(_font_get_kerning_list, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_clear_kerning_map, "font_rid", "size");
+ GDVIRTUAL_BIND(_font_remove_kerning, "font_rid", "size", "glyph_pair");
- GDVIRTUAL_BIND(font_get_glyph_index, "font_rid", "size", "char", "variation_selector");
+ GDVIRTUAL_BIND(_font_set_kerning, "font_rid", "size", "glyph_pair", "kerning");
+ GDVIRTUAL_BIND(_font_get_kerning, "font_rid", "size", "glyph_pair");
- GDVIRTUAL_BIND(font_has_char, "font_rid", "char");
- GDVIRTUAL_BIND(font_get_supported_chars, "font_rid");
+ GDVIRTUAL_BIND(_font_get_glyph_index, "font_rid", "size", "char", "variation_selector");
- GDVIRTUAL_BIND(font_render_range, "font_rid", "size", "start", "end");
- GDVIRTUAL_BIND(font_render_glyph, "font_rid", "size", "index");
+ GDVIRTUAL_BIND(_font_has_char, "font_rid", "char");
+ GDVIRTUAL_BIND(_font_get_supported_chars, "font_rid");
- GDVIRTUAL_BIND(font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color");
- GDVIRTUAL_BIND(font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color");
+ GDVIRTUAL_BIND(_font_render_range, "font_rid", "size", "start", "end");
+ GDVIRTUAL_BIND(_font_render_glyph, "font_rid", "size", "index");
- GDVIRTUAL_BIND(font_is_language_supported, "font_rid", "language");
- GDVIRTUAL_BIND(font_set_language_support_override, "font_rid", "language", "supported");
- GDVIRTUAL_BIND(font_get_language_support_override, "font_rid", "language");
- GDVIRTUAL_BIND(font_remove_language_support_override, "font_rid", "language");
- GDVIRTUAL_BIND(font_get_language_support_overrides, "font_rid");
+ GDVIRTUAL_BIND(_font_draw_glyph, "font_rid", "canvas", "size", "pos", "index", "color");
+ GDVIRTUAL_BIND(_font_draw_glyph_outline, "font_rid", "canvas", "size", "outline_size", "pos", "index", "color");
- GDVIRTUAL_BIND(font_is_script_supported, "font_rid", "script");
- GDVIRTUAL_BIND(font_set_script_support_override, "font_rid", "script", "supported");
- GDVIRTUAL_BIND(font_get_script_support_override, "font_rid", "script");
- GDVIRTUAL_BIND(font_remove_script_support_override, "font_rid", "script");
- GDVIRTUAL_BIND(font_get_script_support_overrides, "font_rid");
+ GDVIRTUAL_BIND(_font_is_language_supported, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_set_language_support_override, "font_rid", "language", "supported");
+ GDVIRTUAL_BIND(_font_get_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_remove_language_support_override, "font_rid", "language");
+ GDVIRTUAL_BIND(_font_get_language_support_overrides, "font_rid");
- GDVIRTUAL_BIND(font_set_opentype_feature_overrides, "font_rid", "overrides");
- GDVIRTUAL_BIND(font_get_opentype_feature_overrides, "font_rid");
+ GDVIRTUAL_BIND(_font_is_script_supported, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_set_script_support_override, "font_rid", "script", "supported");
+ GDVIRTUAL_BIND(_font_get_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_remove_script_support_override, "font_rid", "script");
+ GDVIRTUAL_BIND(_font_get_script_support_overrides, "font_rid");
- GDVIRTUAL_BIND(font_supported_feature_list, "font_rid");
- GDVIRTUAL_BIND(font_supported_variation_list, "font_rid");
+ GDVIRTUAL_BIND(_font_set_opentype_feature_overrides, "font_rid", "overrides");
+ GDVIRTUAL_BIND(_font_get_opentype_feature_overrides, "font_rid");
- GDVIRTUAL_BIND(font_get_global_oversampling);
- GDVIRTUAL_BIND(font_set_global_oversampling, "oversampling");
+ GDVIRTUAL_BIND(_font_supported_feature_list, "font_rid");
+ GDVIRTUAL_BIND(_font_supported_variation_list, "font_rid");
- GDVIRTUAL_BIND(get_hex_code_box_size, "size", "index");
- GDVIRTUAL_BIND(draw_hex_code_box, "canvas", "size", "pos", "index", "color");
+ GDVIRTUAL_BIND(_font_get_global_oversampling);
+ GDVIRTUAL_BIND(_font_set_global_oversampling, "oversampling");
+
+ GDVIRTUAL_BIND(_get_hex_code_box_size, "size", "index");
+ GDVIRTUAL_BIND(_draw_hex_code_box, "canvas", "size", "pos", "index", "color");
/* Shaped text buffer interface */
- GDVIRTUAL_BIND(create_shaped_text, "direction", "orientation");
+ GDVIRTUAL_BIND(_create_shaped_text, "direction", "orientation");
+
+ GDVIRTUAL_BIND(_shaped_text_clear, "shaped");
+
+ GDVIRTUAL_BIND(_shaped_text_set_direction, "shaped", "direction");
+ GDVIRTUAL_BIND(_shaped_text_get_direction, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_inferred_direction, "shaped");
- GDVIRTUAL_BIND(shaped_text_clear, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_set_bidi_override, "shaped", "override");
- GDVIRTUAL_BIND(shaped_text_set_direction, "shaped", "direction");
- GDVIRTUAL_BIND(shaped_text_get_direction, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_inferred_direction, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_set_custom_punctuation, "shaped", "punct");
+ GDVIRTUAL_BIND(_shaped_text_get_custom_punctuation, "shaped");
- GDVIRTUAL_BIND(shaped_text_set_bidi_override, "shaped", "override");
+ GDVIRTUAL_BIND(_shaped_text_set_orientation, "shaped", "orientation");
+ GDVIRTUAL_BIND(_shaped_text_get_orientation, "shaped");
- GDVIRTUAL_BIND(shaped_text_set_custom_punctuation, "shaped", "punct");
- GDVIRTUAL_BIND(shaped_text_get_custom_punctuation, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_set_preserve_invalid, "shaped", "enabled");
+ GDVIRTUAL_BIND(_shaped_text_get_preserve_invalid, "shaped");
- GDVIRTUAL_BIND(shaped_text_set_orientation, "shaped", "orientation");
- GDVIRTUAL_BIND(shaped_text_get_orientation, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_set_preserve_control, "shaped", "enabled");
+ GDVIRTUAL_BIND(_shaped_text_get_preserve_control, "shaped");
- GDVIRTUAL_BIND(shaped_text_set_preserve_invalid, "shaped", "enabled");
- GDVIRTUAL_BIND(shaped_text_get_preserve_invalid, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_set_spacing, "shaped", "spacing", "value");
+ GDVIRTUAL_BIND(_shaped_text_get_spacing, "shaped", "spacing");
- GDVIRTUAL_BIND(shaped_text_set_preserve_control, "shaped", "enabled");
- GDVIRTUAL_BIND(shaped_text_get_preserve_control, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language", "meta");
+ GDVIRTUAL_BIND(_shaped_text_add_object, "shaped", "key", "size", "inline_align", "length");
+ GDVIRTUAL_BIND(_shaped_text_resize_object, "shaped", "key", "size", "inline_align");
- GDVIRTUAL_BIND(shaped_text_add_string, "shaped", "text", "fonts", "size", "opentype_features", "language", "meta");
- GDVIRTUAL_BIND(shaped_text_add_object, "shaped", "key", "size", "inline_align", "length");
- GDVIRTUAL_BIND(shaped_text_resize_object, "shaped", "key", "size", "inline_align");
+ GDVIRTUAL_BIND(_shaped_get_span_count, "shaped");
+ GDVIRTUAL_BIND(_shaped_get_span_meta, "shaped", "index");
+ GDVIRTUAL_BIND(_shaped_set_span_update_font, "shaped", "index", "fonts", "size", "opentype_features");
- GDVIRTUAL_BIND(shaped_get_span_count, "shaped");
- GDVIRTUAL_BIND(shaped_get_span_meta, "shaped", "index");
- GDVIRTUAL_BIND(shaped_set_span_update_font, "shaped", "index", "fonts", "size", "opentype_features");
+ GDVIRTUAL_BIND(_shaped_text_substr, "shaped", "start", "length");
+ GDVIRTUAL_BIND(_shaped_text_get_parent, "shaped");
- GDVIRTUAL_BIND(shaped_text_substr, "shaped", "start", "length");
- GDVIRTUAL_BIND(shaped_text_get_parent, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_fit_to_width, "shaped", "width", "jst_flags");
+ GDVIRTUAL_BIND(_shaped_text_tab_align, "shaped", "tab_stops");
- GDVIRTUAL_BIND(shaped_text_fit_to_width, "shaped", "width", "jst_flags");
- GDVIRTUAL_BIND(shaped_text_tab_align, "shaped", "tab_stops");
+ GDVIRTUAL_BIND(_shaped_text_shape, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_update_breaks, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_update_justification_ops, "shaped");
- GDVIRTUAL_BIND(shaped_text_shape, "shaped");
- GDVIRTUAL_BIND(shaped_text_update_breaks, "shaped");
- GDVIRTUAL_BIND(shaped_text_update_justification_ops, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_is_ready, "shaped");
- GDVIRTUAL_BIND(shaped_text_is_ready, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_glyphs, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_sort_logical, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_glyph_count, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_glyphs, "shaped");
- GDVIRTUAL_BIND(shaped_text_sort_logical, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_glyph_count, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_range, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_range, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_word_breaks, "shaped", "grapheme_flags");
- GDVIRTUAL_BIND(shaped_text_get_line_breaks_adv, "shaped", "width", "start", "once", "break_flags");
- GDVIRTUAL_BIND(shaped_text_get_line_breaks, "shaped", "width", "start", "break_flags");
- GDVIRTUAL_BIND(shaped_text_get_word_breaks, "shaped", "grapheme_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_trim_pos, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_pos, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyph_count, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ellipsis_glyphs, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_trim_pos, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_ellipsis_pos, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_ellipsis_glyph_count, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_ellipsis_glyphs, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags");
- GDVIRTUAL_BIND(shaped_text_overrun_trim_to_width, "shaped", "width", "trim_flags");
+ GDVIRTUAL_BIND(_shaped_text_get_objects, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_object_rect, "shaped", "key");
- GDVIRTUAL_BIND(shaped_text_get_objects, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_object_rect, "shaped", "key");
+ GDVIRTUAL_BIND(_shaped_text_get_size, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_ascent, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_descent, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_width, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_underline_position, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_underline_thickness, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_size, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_ascent, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_descent, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_width, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_underline_position, "shaped");
- GDVIRTUAL_BIND(shaped_text_get_underline_thickness, "shaped");
+ GDVIRTUAL_BIND(_shaped_text_get_dominant_direction_in_range, "shaped", "start", "end");
- GDVIRTUAL_BIND(shaped_text_get_dominant_direction_in_range, "shaped", "start", "end");
+ GDVIRTUAL_BIND(_shaped_text_get_carets, "shaped", "position", "caret");
+ GDVIRTUAL_BIND(_shaped_text_get_selection, "shaped", "start", "end");
- GDVIRTUAL_BIND(shaped_text_get_carets, "shaped", "position", "caret");
- GDVIRTUAL_BIND(shaped_text_get_selection, "shaped", "start", "end");
+ GDVIRTUAL_BIND(_shaped_text_hit_test_grapheme, "shaped", "coord");
+ GDVIRTUAL_BIND(_shaped_text_hit_test_position, "shaped", "coord");
- GDVIRTUAL_BIND(shaped_text_hit_test_grapheme, "shaped", "coord");
- GDVIRTUAL_BIND(shaped_text_hit_test_position, "shaped", "coord");
+ GDVIRTUAL_BIND(_shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color");
+ GDVIRTUAL_BIND(_shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color");
- GDVIRTUAL_BIND(shaped_text_draw, "shaped", "canvas", "pos", "clip_l", "clip_r", "color");
- GDVIRTUAL_BIND(shaped_text_draw_outline, "shaped", "canvas", "pos", "clip_l", "clip_r", "outline_size", "color");
+ GDVIRTUAL_BIND(_shaped_text_get_grapheme_bounds, "shaped", "pos");
+ GDVIRTUAL_BIND(_shaped_text_next_grapheme_pos, "shaped", "pos");
+ GDVIRTUAL_BIND(_shaped_text_prev_grapheme_pos, "shaped", "pos");
- GDVIRTUAL_BIND(shaped_text_get_grapheme_bounds, "shaped", "pos");
- GDVIRTUAL_BIND(shaped_text_next_grapheme_pos, "shaped", "pos");
- GDVIRTUAL_BIND(shaped_text_prev_grapheme_pos, "shaped", "pos");
+ GDVIRTUAL_BIND(_format_number, "string", "language");
+ GDVIRTUAL_BIND(_parse_number, "string", "language");
+ GDVIRTUAL_BIND(_percent_sign, "language");
- GDVIRTUAL_BIND(format_number, "string", "language");
- GDVIRTUAL_BIND(parse_number, "string", "language");
- GDVIRTUAL_BIND(percent_sign, "language");
+ GDVIRTUAL_BIND(_strip_diacritics, "string");
+ GDVIRTUAL_BIND(_is_valid_identifier, "string");
- GDVIRTUAL_BIND(strip_diacritics, "string");
+ GDVIRTUAL_BIND(_string_get_word_breaks, "string", "language");
- GDVIRTUAL_BIND(string_get_word_breaks, "string", "language");
+ GDVIRTUAL_BIND(_is_confusable, "string", "dict");
+ GDVIRTUAL_BIND(_spoof_check, "string");
- GDVIRTUAL_BIND(string_to_upper, "string", "language");
- GDVIRTUAL_BIND(string_to_lower, "string", "language");
+ GDVIRTUAL_BIND(_string_to_upper, "string", "language");
+ GDVIRTUAL_BIND(_string_to_lower, "string", "language");
- GDVIRTUAL_BIND(parse_structured_text, "parser_type", "args", "text");
+ GDVIRTUAL_BIND(_parse_structured_text, "parser_type", "args", "text");
}
bool TextServerExtension::has_feature(Feature p_feature) const {
- bool ret;
- if (GDVIRTUAL_CALL(has_feature, p_feature, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_has_feature, p_feature, ret);
+ return ret;
}
String TextServerExtension::get_name() const {
- String ret;
- if (GDVIRTUAL_CALL(get_name, ret)) {
- return ret;
- }
- return "Unknown";
+ String ret = "Unknown";
+ GDVIRTUAL_CALL(_get_name, ret);
+ return ret;
}
int64_t TextServerExtension::get_features() const {
- int64_t ret;
- if (GDVIRTUAL_CALL(get_features, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_get_features, ret);
+ return ret;
}
void TextServerExtension::free_rid(const RID &p_rid) {
- GDVIRTUAL_CALL(free_rid, p_rid);
+ GDVIRTUAL_CALL(_free_rid, p_rid);
}
bool TextServerExtension::has(const RID &p_rid) {
- bool ret;
- if (GDVIRTUAL_CALL(has, p_rid, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_has, p_rid, ret);
+ return ret;
}
bool TextServerExtension::load_support_data(const String &p_filename) {
- bool ret;
- if (GDVIRTUAL_CALL(load_support_data, p_filename, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_load_support_data, p_filename, ret);
+ return ret;
}
String TextServerExtension::get_support_data_filename() const {
String ret;
- if (GDVIRTUAL_CALL(get_support_data_filename, ret)) {
- return ret;
- }
- return String();
+ GDVIRTUAL_CALL(_get_support_data_filename, ret);
+ return ret;
}
String TextServerExtension::get_support_data_info() const {
String ret;
- if (GDVIRTUAL_CALL(get_support_data_info, ret)) {
- return ret;
- }
- return String();
+ GDVIRTUAL_CALL(_get_support_data_info, ret);
+ return ret;
}
bool TextServerExtension::save_support_data(const String &p_filename) const {
- bool ret;
- if (GDVIRTUAL_CALL(save_support_data, p_filename, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_save_support_data, p_filename, ret);
+ return ret;
}
bool TextServerExtension::is_locale_right_to_left(const String &p_locale) const {
- bool ret;
- if (GDVIRTUAL_CALL(is_locale_right_to_left, p_locale, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_is_locale_right_to_left, p_locale, ret);
+ return ret;
}
int64_t TextServerExtension::name_to_tag(const String &p_name) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(name_to_tag, p_name, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_name_to_tag, p_name, ret);
+ return ret;
}
String TextServerExtension::tag_to_name(int64_t p_tag) const {
String ret;
- if (GDVIRTUAL_CALL(tag_to_name, p_tag, ret)) {
- return ret;
- }
- return "";
+ GDVIRTUAL_CALL(_tag_to_name, p_tag, ret);
+ return ret;
}
/*************************************************************************/
@@ -399,622 +386,526 @@ String TextServerExtension::tag_to_name(int64_t p_tag) const {
RID TextServerExtension::create_font() {
RID ret;
- if (GDVIRTUAL_CALL(create_font, ret)) {
- return ret;
- }
- return RID();
+ GDVIRTUAL_CALL(_create_font, ret);
+ return ret;
}
void TextServerExtension::font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) {
- GDVIRTUAL_CALL(font_set_data, p_font_rid, p_data);
+ GDVIRTUAL_CALL(_font_set_data, p_font_rid, p_data);
}
void TextServerExtension::font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) {
- GDVIRTUAL_CALL(font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
+ GDVIRTUAL_CALL(_font_set_data_ptr, p_font_rid, p_data_ptr, p_data_size);
}
-void TextServerExtension::font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) {
- GDVIRTUAL_CALL(font_set_style, p_font_rid, p_style);
+void TextServerExtension::font_set_face_index(const RID &p_font_rid, int64_t p_index) {
+ GDVIRTUAL_CALL(_font_set_face_index, p_font_rid, p_index);
}
-int64_t /*FontStyle*/ TextServerExtension::font_get_style(const RID &p_font_rid) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_style, p_font_rid, ret)) {
- return ret;
- }
- return 0;
+int64_t TextServerExtension::font_get_face_index(const RID &p_font_rid) const {
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_face_index, p_font_rid, ret);
+ return ret;
+}
+
+int64_t TextServerExtension::font_get_face_count(const RID &p_font_rid) const {
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_face_count, p_font_rid, ret);
+ return ret;
+}
+
+void TextServerExtension::font_set_style(const RID &p_font_rid, BitField<TextServer::FontStyle> p_style) {
+ GDVIRTUAL_CALL(_font_set_style, p_font_rid, p_style);
+}
+
+BitField<TextServer::FontStyle> TextServerExtension::font_get_style(const RID &p_font_rid) const {
+ BitField<TextServer::FontStyle> ret = 0;
+ GDVIRTUAL_CALL(_font_get_style, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_style_name(const RID &p_font_rid, const String &p_name) {
- GDVIRTUAL_CALL(font_set_style_name, p_font_rid, p_name);
+ GDVIRTUAL_CALL(_font_set_style_name, p_font_rid, p_name);
}
String TextServerExtension::font_get_style_name(const RID &p_font_rid) const {
String ret;
- if (GDVIRTUAL_CALL(font_get_style_name, p_font_rid, ret)) {
- return ret;
- }
- return String();
+ GDVIRTUAL_CALL(_font_get_style_name, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_name(const RID &p_font_rid, const String &p_name) {
- GDVIRTUAL_CALL(font_set_name, p_font_rid, p_name);
+ GDVIRTUAL_CALL(_font_set_name, p_font_rid, p_name);
}
String TextServerExtension::font_get_name(const RID &p_font_rid) const {
String ret;
- if (GDVIRTUAL_CALL(font_get_name, p_font_rid, ret)) {
- return ret;
- }
- return String();
+ GDVIRTUAL_CALL(_font_get_name, p_font_rid, ret);
+ return ret;
}
-void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) {
- GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased);
+void TextServerExtension::font_set_antialiasing(const RID &p_font_rid, TextServer::FontAntialiasing p_antialiasing) {
+ GDVIRTUAL_CALL(_font_set_antialiasing, p_font_rid, p_antialiasing);
}
-bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) {
- return ret;
- }
- return false;
+TextServer::FontAntialiasing TextServerExtension::font_get_antialiasing(const RID &p_font_rid) const {
+ TextServer::FontAntialiasing ret = TextServer::FONT_ANTIALIASING_NONE;
+ GDVIRTUAL_CALL(_font_get_antialiasing, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) {
- GDVIRTUAL_CALL(font_set_generate_mipmaps, p_font_rid, p_generate_mipmaps);
+ GDVIRTUAL_CALL(_font_set_generate_mipmaps, p_font_rid, p_generate_mipmaps);
}
bool TextServerExtension::font_get_generate_mipmaps(const RID &p_font_rid) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_get_generate_mipmaps, p_font_rid, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_get_generate_mipmaps, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) {
- GDVIRTUAL_CALL(font_set_multichannel_signed_distance_field, p_font_rid, p_msdf);
+ GDVIRTUAL_CALL(_font_set_multichannel_signed_distance_field, p_font_rid, p_msdf);
}
bool TextServerExtension::font_is_multichannel_signed_distance_field(const RID &p_font_rid) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_is_multichannel_signed_distance_field, p_font_rid, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_is_multichannel_signed_distance_field, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) {
- GDVIRTUAL_CALL(font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range);
+ GDVIRTUAL_CALL(_font_set_msdf_pixel_range, p_font_rid, p_msdf_pixel_range);
}
int64_t TextServerExtension::font_get_msdf_pixel_range(const RID &p_font_rid) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_msdf_pixel_range, p_font_rid, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_msdf_pixel_range, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) {
- GDVIRTUAL_CALL(font_set_msdf_size, p_font_rid, p_msdf_size);
+ GDVIRTUAL_CALL(_font_set_msdf_size, p_font_rid, p_msdf_size);
}
int64_t TextServerExtension::font_get_msdf_size(const RID &p_font_rid) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_msdf_size, p_font_rid, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_msdf_size, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) {
- GDVIRTUAL_CALL(font_set_fixed_size, p_font_rid, p_fixed_size);
+ GDVIRTUAL_CALL(_font_set_fixed_size, p_font_rid, p_fixed_size);
}
int64_t TextServerExtension::font_get_fixed_size(const RID &p_font_rid) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_fixed_size, p_font_rid, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_fixed_size, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) {
- GDVIRTUAL_CALL(font_set_force_autohinter, p_font_rid, p_force_autohinter);
+ GDVIRTUAL_CALL(_font_set_force_autohinter, p_font_rid, p_force_autohinter);
}
bool TextServerExtension::font_is_force_autohinter(const RID &p_font_rid) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_is_force_autohinter, p_font_rid, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_is_force_autohinter, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_hinting(const RID &p_font_rid, TextServer::Hinting p_hinting) {
- GDVIRTUAL_CALL(font_set_hinting, p_font_rid, p_hinting);
+ GDVIRTUAL_CALL(_font_set_hinting, p_font_rid, p_hinting);
}
TextServer::Hinting TextServerExtension::font_get_hinting(const RID &p_font_rid) const {
- TextServer::Hinting ret;
- if (GDVIRTUAL_CALL(font_get_hinting, p_font_rid, ret)) {
- return (TextServer::Hinting)ret;
- }
- return TextServer::Hinting::HINTING_NONE;
+ TextServer::Hinting ret = TextServer::HINTING_NONE;
+ GDVIRTUAL_CALL(_font_get_hinting, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_subpixel_positioning(const RID &p_font_rid, TextServer::SubpixelPositioning p_subpixel) {
- GDVIRTUAL_CALL(font_set_subpixel_positioning, p_font_rid, p_subpixel);
+ GDVIRTUAL_CALL(_font_set_subpixel_positioning, p_font_rid, p_subpixel);
}
TextServer::SubpixelPositioning TextServerExtension::font_get_subpixel_positioning(const RID &p_font_rid) const {
- TextServer::SubpixelPositioning ret;
- if (GDVIRTUAL_CALL(font_get_subpixel_positioning, p_font_rid, ret)) {
- return (TextServer::SubpixelPositioning)ret;
- }
- return TextServer::SubpixelPositioning::SUBPIXEL_POSITIONING_DISABLED;
+ TextServer::SubpixelPositioning ret = TextServer::SUBPIXEL_POSITIONING_DISABLED;
+ GDVIRTUAL_CALL(_font_get_subpixel_positioning, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_embolden(const RID &p_font_rid, double p_strength) {
- GDVIRTUAL_CALL(font_set_embolden, p_font_rid, p_strength);
+ GDVIRTUAL_CALL(_font_set_embolden, p_font_rid, p_strength);
}
double TextServerExtension::font_get_embolden(const RID &p_font_rid) const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_embolden, p_font_rid, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_embolden, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) {
- GDVIRTUAL_CALL(font_set_transform, p_font_rid, p_transform);
+ GDVIRTUAL_CALL(_font_set_transform, p_font_rid, p_transform);
}
Transform2D TextServerExtension::font_get_transform(const RID &p_font_rid) const {
Transform2D ret;
- if (GDVIRTUAL_CALL(font_get_transform, p_font_rid, ret)) {
- return ret;
- }
- return Transform2D();
+ GDVIRTUAL_CALL(_font_get_transform, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) {
- GDVIRTUAL_CALL(font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
+ GDVIRTUAL_CALL(_font_set_variation_coordinates, p_font_rid, p_variation_coordinates);
}
Dictionary TextServerExtension::font_get_variation_coordinates(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(font_get_variation_coordinates, p_font_rid, ret)) {
- return ret;
- }
- return Dictionary();
+ GDVIRTUAL_CALL(_font_get_variation_coordinates, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_oversampling(const RID &p_font_rid, double p_oversampling) {
- GDVIRTUAL_CALL(font_set_oversampling, p_font_rid, p_oversampling);
+ GDVIRTUAL_CALL(_font_set_oversampling, p_font_rid, p_oversampling);
}
double TextServerExtension::font_get_oversampling(const RID &p_font_rid) const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_oversampling, p_font_rid, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_oversampling, p_font_rid, ret);
+ return ret;
}
-Array TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const {
- Array ret;
- if (GDVIRTUAL_CALL(font_get_size_cache_list, p_font_rid, ret)) {
- return ret;
- }
- return Array();
+TypedArray<Vector2i> TextServerExtension::font_get_size_cache_list(const RID &p_font_rid) const {
+ TypedArray<Vector2i> ret;
+ GDVIRTUAL_CALL(_font_get_size_cache_list, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_clear_size_cache(const RID &p_font_rid) {
- GDVIRTUAL_CALL(font_clear_size_cache, p_font_rid);
+ GDVIRTUAL_CALL(_font_clear_size_cache, p_font_rid);
}
void TextServerExtension::font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(font_remove_size_cache, p_font_rid, p_size);
+ GDVIRTUAL_CALL(_font_remove_size_cache, p_font_rid, p_size);
}
void TextServerExtension::font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) {
- GDVIRTUAL_CALL(font_set_ascent, p_font_rid, p_size, p_ascent);
+ GDVIRTUAL_CALL(_font_set_ascent, p_font_rid, p_size, p_ascent);
}
double TextServerExtension::font_get_ascent(const RID &p_font_rid, int64_t p_size) const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_ascent, p_font_rid, p_size, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_ascent, p_font_rid, p_size, ret);
+ return ret;
}
void TextServerExtension::font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) {
- GDVIRTUAL_CALL(font_set_descent, p_font_rid, p_size, p_descent);
+ GDVIRTUAL_CALL(_font_set_descent, p_font_rid, p_size, p_descent);
}
double TextServerExtension::font_get_descent(const RID &p_font_rid, int64_t p_size) const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_descent, p_font_rid, p_size, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_descent, p_font_rid, p_size, ret);
+ return ret;
}
void TextServerExtension::font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) {
- GDVIRTUAL_CALL(font_set_underline_position, p_font_rid, p_size, p_underline_position);
+ GDVIRTUAL_CALL(_font_set_underline_position, p_font_rid, p_size, p_underline_position);
}
double TextServerExtension::font_get_underline_position(const RID &p_font_rid, int64_t p_size) const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_underline_position, p_font_rid, p_size, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_underline_position, p_font_rid, p_size, ret);
+ return ret;
}
void TextServerExtension::font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) {
- GDVIRTUAL_CALL(font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
+ GDVIRTUAL_CALL(_font_set_underline_thickness, p_font_rid, p_size, p_underline_thickness);
}
double TextServerExtension::font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_underline_thickness, p_font_rid, p_size, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_underline_thickness, p_font_rid, p_size, ret);
+ return ret;
}
void TextServerExtension::font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) {
- GDVIRTUAL_CALL(font_set_scale, p_font_rid, p_size, p_scale);
+ GDVIRTUAL_CALL(_font_set_scale, p_font_rid, p_size, p_scale);
}
double TextServerExtension::font_get_scale(const RID &p_font_rid, int64_t p_size) const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_scale, p_font_rid, p_size, ret)) {
- return ret;
- }
- return 0.0;
-}
-
-void TextServerExtension::font_set_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing, int64_t p_value) {
- GDVIRTUAL_CALL(font_set_spacing, p_font_rid, p_size, p_spacing, p_value);
-}
-
-int64_t TextServerExtension::font_get_spacing(const RID &p_font_rid, int64_t p_size, TextServer::SpacingType p_spacing) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_spacing, p_font_rid, p_size, p_spacing, ret)) {
- return ret;
- }
- return 0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_scale, p_font_rid, p_size, ret);
+ return ret;
}
int64_t TextServerExtension::font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_texture_count, p_font_rid, p_size, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_texture_count, p_font_rid, p_size, ret);
+ return ret;
}
void TextServerExtension::font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(font_clear_textures, p_font_rid, p_size);
+ GDVIRTUAL_CALL(_font_clear_textures, p_font_rid, p_size);
}
void TextServerExtension::font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) {
- GDVIRTUAL_CALL(font_remove_texture, p_font_rid, p_size, p_texture_index);
+ GDVIRTUAL_CALL(_font_remove_texture, p_font_rid, p_size, p_texture_index);
}
void TextServerExtension::font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) {
- GDVIRTUAL_CALL(font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
+ GDVIRTUAL_CALL(_font_set_texture_image, p_font_rid, p_size, p_texture_index, p_image);
}
Ref<Image> TextServerExtension::font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
Ref<Image> ret;
- if (GDVIRTUAL_CALL(font_get_texture_image, p_font_rid, p_size, p_texture_index, ret)) {
- return ret;
- }
- return Ref<Image>();
+ GDVIRTUAL_CALL(_font_get_texture_image, p_font_rid, p_size, p_texture_index, ret);
+ return ret;
}
void TextServerExtension::font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) {
- GDVIRTUAL_CALL(font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset);
+ GDVIRTUAL_CALL(_font_set_texture_offsets, p_font_rid, p_size, p_texture_index, p_offset);
}
PackedInt32Array TextServerExtension::font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret)) {
- return ret;
- }
- return PackedInt32Array();
+ GDVIRTUAL_CALL(_font_get_texture_offsets, p_font_rid, p_size, p_texture_index, ret);
+ return ret;
}
-Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
- Array ret;
- if (GDVIRTUAL_CALL(font_get_glyph_list, p_font_rid, p_size, ret)) {
- return ret;
- }
- return Array();
+PackedInt32Array TextServerExtension::font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const {
+ PackedInt32Array ret;
+ GDVIRTUAL_CALL(_font_get_glyph_list, p_font_rid, p_size, ret);
+ return ret;
}
void TextServerExtension::font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) {
- GDVIRTUAL_CALL(font_clear_glyphs, p_font_rid, p_size);
+ GDVIRTUAL_CALL(_font_clear_glyphs, p_font_rid, p_size);
}
void TextServerExtension::font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) {
- GDVIRTUAL_CALL(font_remove_glyph, p_font_rid, p_size, p_glyph);
+ GDVIRTUAL_CALL(_font_remove_glyph, p_font_rid, p_size, p_glyph);
}
Vector2 TextServerExtension::font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret)) {
- return ret;
- }
- return Vector2();
+ GDVIRTUAL_CALL(_font_get_glyph_advance, p_font_rid, p_size, p_glyph, ret);
+ return ret;
}
void TextServerExtension::font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) {
- GDVIRTUAL_CALL(font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
+ GDVIRTUAL_CALL(_font_set_glyph_advance, p_font_rid, p_size, p_glyph, p_advance);
}
Vector2 TextServerExtension::font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret)) {
- return ret;
- }
- return Vector2();
+ GDVIRTUAL_CALL(_font_get_glyph_offset, p_font_rid, p_size, p_glyph, ret);
+ return ret;
}
void TextServerExtension::font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) {
- GDVIRTUAL_CALL(font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
+ GDVIRTUAL_CALL(_font_set_glyph_offset, p_font_rid, p_size, p_glyph, p_offset);
}
Vector2 TextServerExtension::font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(font_get_glyph_size, p_font_rid, p_size, p_glyph, ret)) {
- return ret;
- }
- return Vector2();
+ GDVIRTUAL_CALL(_font_get_glyph_size, p_font_rid, p_size, p_glyph, ret);
+ return ret;
}
void TextServerExtension::font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) {
- GDVIRTUAL_CALL(font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
+ GDVIRTUAL_CALL(_font_set_glyph_size, p_font_rid, p_size, p_glyph, p_gl_size);
}
Rect2 TextServerExtension::font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Rect2 ret;
- if (GDVIRTUAL_CALL(font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret)) {
- return ret;
- }
- return Rect2();
+ GDVIRTUAL_CALL(_font_get_glyph_uv_rect, p_font_rid, p_size, p_glyph, ret);
+ return ret;
}
void TextServerExtension::font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) {
- GDVIRTUAL_CALL(font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect);
+ GDVIRTUAL_CALL(_font_set_glyph_uv_rect, p_font_rid, p_size, p_glyph, p_uv_rect);
}
int64_t TextServerExtension::font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_glyph_texture_idx, p_font_rid, p_size, p_glyph, ret);
+ return ret;
}
void TextServerExtension::font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) {
- GDVIRTUAL_CALL(font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
+ GDVIRTUAL_CALL(_font_set_glyph_texture_idx, p_font_rid, p_size, p_glyph, p_texture_idx);
}
RID TextServerExtension::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
RID ret;
- if (GDVIRTUAL_CALL(font_get_glyph_texture_rid, p_font_rid, p_size, p_glyph, ret)) {
- return ret;
- }
- return RID();
+ GDVIRTUAL_CALL(_font_get_glyph_texture_rid, p_font_rid, p_size, p_glyph, ret);
+ return ret;
}
Size2 TextServerExtension::font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const {
Size2 ret;
- if (GDVIRTUAL_CALL(font_get_glyph_texture_size, p_font_rid, p_size, p_glyph, ret)) {
- return ret;
- }
- return Size2();
+ GDVIRTUAL_CALL(_font_get_glyph_texture_size, p_font_rid, p_size, p_glyph, ret);
+ return ret;
}
Dictionary TextServerExtension::font_get_glyph_contours(const RID &p_font_rid, int64_t p_size, int64_t p_index) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(font_get_glyph_contours, p_font_rid, p_size, p_index, ret)) {
- return ret;
- }
- return Dictionary();
+ GDVIRTUAL_CALL(_font_get_glyph_contours, p_font_rid, p_size, p_index, ret);
+ return ret;
}
-Array TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const {
- Array ret;
- if (GDVIRTUAL_CALL(font_get_kerning_list, p_font_rid, p_size, ret)) {
- return ret;
- }
- return Array();
+TypedArray<Vector2i> TextServerExtension::font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const {
+ TypedArray<Vector2i> ret;
+ GDVIRTUAL_CALL(_font_get_kerning_list, p_font_rid, p_size, ret);
+ return ret;
}
void TextServerExtension::font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) {
- GDVIRTUAL_CALL(font_clear_kerning_map, p_font_rid, p_size);
+ GDVIRTUAL_CALL(_font_clear_kerning_map, p_font_rid, p_size);
}
void TextServerExtension::font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) {
- GDVIRTUAL_CALL(font_remove_kerning, p_font_rid, p_size, p_glyph_pair);
+ GDVIRTUAL_CALL(_font_remove_kerning, p_font_rid, p_size, p_glyph_pair);
}
void TextServerExtension::font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) {
- GDVIRTUAL_CALL(font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning);
+ GDVIRTUAL_CALL(_font_set_kerning, p_font_rid, p_size, p_glyph_pair, p_kerning);
}
Vector2 TextServerExtension::font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret)) {
- return ret;
- }
- return Vector2();
+ GDVIRTUAL_CALL(_font_get_kerning, p_font_rid, p_size, p_glyph_pair, ret);
+ return ret;
}
int64_t TextServerExtension::font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_font_get_glyph_index, p_font_rid, p_size, p_char, p_variation_selector, ret);
+ return ret;
}
bool TextServerExtension::font_has_char(const RID &p_font_rid, int64_t p_char) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_has_char, p_font_rid, p_char, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_has_char, p_font_rid, p_char, ret);
+ return ret;
}
String TextServerExtension::font_get_supported_chars(const RID &p_font_rid) const {
String ret;
- if (GDVIRTUAL_CALL(font_get_supported_chars, p_font_rid, ret)) {
- return ret;
- }
- return String();
+ GDVIRTUAL_CALL(_font_get_supported_chars, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_render_range(const RID &p_font_rid, const Vector2i &p_size, int64_t p_start, int64_t p_end) {
- GDVIRTUAL_CALL(font_render_range, p_font_rid, p_size, p_start, p_end);
+ GDVIRTUAL_CALL(_font_render_range, p_font_rid, p_size, p_start, p_end);
}
void TextServerExtension::font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) {
- GDVIRTUAL_CALL(font_render_glyph, p_font_rid, p_size, p_index);
+ GDVIRTUAL_CALL(_font_render_glyph, p_font_rid, p_size, p_index);
}
void TextServerExtension::font_draw_glyph(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
- GDVIRTUAL_CALL(font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color);
+ GDVIRTUAL_CALL(_font_draw_glyph, p_font_rid, p_canvas, p_size, p_pos, p_index, p_color);
}
void TextServerExtension::font_draw_glyph_outline(const RID &p_font_rid, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
- GDVIRTUAL_CALL(font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
+ GDVIRTUAL_CALL(_font_draw_glyph_outline, p_font_rid, p_canvas, p_size, p_outline_size, p_pos, p_index, p_color);
}
bool TextServerExtension::font_is_language_supported(const RID &p_font_rid, const String &p_language) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_is_language_supported, p_font_rid, p_language, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_is_language_supported, p_font_rid, p_language, ret);
+ return ret;
}
void TextServerExtension::font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) {
- GDVIRTUAL_CALL(font_set_language_support_override, p_font_rid, p_language, p_supported);
+ GDVIRTUAL_CALL(_font_set_language_support_override, p_font_rid, p_language, p_supported);
}
bool TextServerExtension::font_get_language_support_override(const RID &p_font_rid, const String &p_language) {
- bool ret;
- if (GDVIRTUAL_CALL(font_get_language_support_override, p_font_rid, p_language, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_get_language_support_override, p_font_rid, p_language, ret);
+ return ret;
}
void TextServerExtension::font_remove_language_support_override(const RID &p_font_rid, const String &p_language) {
- GDVIRTUAL_CALL(font_remove_language_support_override, p_font_rid, p_language);
+ GDVIRTUAL_CALL(_font_remove_language_support_override, p_font_rid, p_language);
}
PackedStringArray TextServerExtension::font_get_language_support_overrides(const RID &p_font_rid) {
PackedStringArray ret;
- if (GDVIRTUAL_CALL(font_get_language_support_overrides, p_font_rid, ret)) {
- return ret;
- }
- return PackedStringArray();
+ GDVIRTUAL_CALL(_font_get_language_support_overrides, p_font_rid, ret);
+ return ret;
}
bool TextServerExtension::font_is_script_supported(const RID &p_font_rid, const String &p_script) const {
- bool ret;
- if (GDVIRTUAL_CALL(font_is_script_supported, p_font_rid, p_script, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_is_script_supported, p_font_rid, p_script, ret);
+ return ret;
}
void TextServerExtension::font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) {
- GDVIRTUAL_CALL(font_set_script_support_override, p_font_rid, p_script, p_supported);
+ GDVIRTUAL_CALL(_font_set_script_support_override, p_font_rid, p_script, p_supported);
}
bool TextServerExtension::font_get_script_support_override(const RID &p_font_rid, const String &p_script) {
- bool ret;
- if (GDVIRTUAL_CALL(font_get_script_support_override, p_font_rid, p_script, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_font_get_script_support_override, p_font_rid, p_script, ret);
+ return ret;
}
void TextServerExtension::font_remove_script_support_override(const RID &p_font_rid, const String &p_script) {
- GDVIRTUAL_CALL(font_remove_script_support_override, p_font_rid, p_script);
+ GDVIRTUAL_CALL(_font_remove_script_support_override, p_font_rid, p_script);
}
PackedStringArray TextServerExtension::font_get_script_support_overrides(const RID &p_font_rid) {
PackedStringArray ret;
- if (GDVIRTUAL_CALL(font_get_script_support_overrides, p_font_rid, ret)) {
- return ret;
- }
- return PackedStringArray();
+ GDVIRTUAL_CALL(_font_get_script_support_overrides, p_font_rid, ret);
+ return ret;
}
void TextServerExtension::font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) {
- GDVIRTUAL_CALL(font_set_opentype_feature_overrides, p_font_rid, p_overrides);
+ GDVIRTUAL_CALL(_font_set_opentype_feature_overrides, p_font_rid, p_overrides);
}
Dictionary TextServerExtension::font_get_opentype_feature_overrides(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(font_get_opentype_feature_overrides, p_font_rid, ret)) {
- return ret;
- }
- return Dictionary();
+ GDVIRTUAL_CALL(_font_get_opentype_feature_overrides, p_font_rid, ret);
+ return ret;
}
Dictionary TextServerExtension::font_supported_feature_list(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(font_supported_feature_list, p_font_rid, ret)) {
- return ret;
- }
- return Dictionary();
+ GDVIRTUAL_CALL(_font_supported_feature_list, p_font_rid, ret);
+ return ret;
}
Dictionary TextServerExtension::font_supported_variation_list(const RID &p_font_rid) const {
Dictionary ret;
- if (GDVIRTUAL_CALL(font_supported_variation_list, p_font_rid, ret)) {
- return ret;
- }
- return Dictionary();
+ GDVIRTUAL_CALL(_font_supported_variation_list, p_font_rid, ret);
+ return ret;
}
double TextServerExtension::font_get_global_oversampling() const {
- double ret;
- if (GDVIRTUAL_CALL(font_get_global_oversampling, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_font_get_global_oversampling, ret);
+ return ret;
}
void TextServerExtension::font_set_global_oversampling(double p_oversampling) {
- GDVIRTUAL_CALL(font_set_global_oversampling, p_oversampling);
+ GDVIRTUAL_CALL(_font_set_global_oversampling, p_oversampling);
}
Vector2 TextServerExtension::get_hex_code_box_size(int64_t p_size, int64_t p_index) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(get_hex_code_box_size, p_size, p_index, ret)) {
+ if (GDVIRTUAL_CALL(_get_hex_code_box_size, p_size, p_index, ret)) {
return ret;
}
return TextServer::get_hex_code_box_size(p_size, p_index);
}
void TextServerExtension::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const {
- if (!GDVIRTUAL_CALL(draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) {
+ if (!GDVIRTUAL_CALL(_draw_hex_code_box, p_canvas, p_size, p_pos, p_index, p_color)) {
TextServer::draw_hex_code_box(p_canvas, p_size, p_pos, p_index, p_color);
}
}
@@ -1025,355 +916,293 @@ void TextServerExtension::draw_hex_code_box(const RID &p_canvas, int64_t p_size,
RID TextServerExtension::create_shaped_text(TextServer::Direction p_direction, TextServer::Orientation p_orientation) {
RID ret;
- if (GDVIRTUAL_CALL(create_shaped_text, p_direction, p_orientation, ret)) {
- return ret;
- }
- return RID();
+ GDVIRTUAL_CALL(_create_shaped_text, p_direction, p_orientation, ret);
+ return ret;
}
void TextServerExtension::shaped_text_clear(const RID &p_shaped) {
- GDVIRTUAL_CALL(shaped_text_clear, p_shaped);
+ GDVIRTUAL_CALL(_shaped_text_clear, p_shaped);
}
void TextServerExtension::shaped_text_set_direction(const RID &p_shaped, TextServer::Direction p_direction) {
- GDVIRTUAL_CALL(shaped_text_set_direction, p_shaped, p_direction);
+ GDVIRTUAL_CALL(_shaped_text_set_direction, p_shaped, p_direction);
}
TextServer::Direction TextServerExtension::shaped_text_get_direction(const RID &p_shaped) const {
- TextServer::Direction ret;
- if (GDVIRTUAL_CALL(shaped_text_get_direction, p_shaped, ret)) {
- return (TextServer::Direction)ret;
- }
- return TextServer::Direction::DIRECTION_AUTO;
+ TextServer::Direction ret = TextServer::DIRECTION_AUTO;
+ GDVIRTUAL_CALL(_shaped_text_get_direction, p_shaped, ret);
+ return ret;
}
TextServer::Direction TextServerExtension::shaped_text_get_inferred_direction(const RID &p_shaped) const {
- TextServer::Direction ret;
- if (GDVIRTUAL_CALL(shaped_text_get_inferred_direction, p_shaped, ret)) {
- return (TextServer::Direction)ret;
- }
- return TextServer::Direction::DIRECTION_LTR;
+ TextServer::Direction ret = TextServer::DIRECTION_LTR;
+ GDVIRTUAL_CALL(_shaped_text_get_inferred_direction, p_shaped, ret);
+ return ret;
}
void TextServerExtension::shaped_text_set_orientation(const RID &p_shaped, TextServer::Orientation p_orientation) {
- GDVIRTUAL_CALL(shaped_text_set_orientation, p_shaped, p_orientation);
+ GDVIRTUAL_CALL(_shaped_text_set_orientation, p_shaped, p_orientation);
}
TextServer::Orientation TextServerExtension::shaped_text_get_orientation(const RID &p_shaped) const {
- TextServer::Orientation ret;
- if (GDVIRTUAL_CALL(shaped_text_get_orientation, p_shaped, ret)) {
- return (TextServer::Orientation)ret;
- }
- return TextServer::Orientation::ORIENTATION_HORIZONTAL;
+ TextServer::Orientation ret = TextServer::ORIENTATION_HORIZONTAL;
+ GDVIRTUAL_CALL(_shaped_text_get_orientation, p_shaped, ret);
+ return ret;
}
void TextServerExtension::shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) {
- GDVIRTUAL_CALL(shaped_text_set_bidi_override, p_shaped, p_override);
+ GDVIRTUAL_CALL(_shaped_text_set_bidi_override, p_shaped, p_override);
}
void TextServerExtension::shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) {
- GDVIRTUAL_CALL(shaped_text_set_custom_punctuation, p_shaped, p_punct);
+ GDVIRTUAL_CALL(_shaped_text_set_custom_punctuation, p_shaped, p_punct);
}
String TextServerExtension::shaped_text_get_custom_punctuation(const RID &p_shaped) const {
String ret;
- if (GDVIRTUAL_CALL(shaped_text_get_custom_punctuation, p_shaped, ret)) {
- return ret;
- }
- return String();
+ GDVIRTUAL_CALL(_shaped_text_get_custom_punctuation, p_shaped, ret);
+ return ret;
}
void TextServerExtension::shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) {
- GDVIRTUAL_CALL(shaped_text_set_preserve_invalid, p_shaped, p_enabled);
+ GDVIRTUAL_CALL(_shaped_text_set_preserve_invalid, p_shaped, p_enabled);
}
bool TextServerExtension::shaped_text_get_preserve_invalid(const RID &p_shaped) const {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_get_preserve_invalid, p_shaped, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_get_preserve_invalid, p_shaped, ret);
+ return ret;
}
void TextServerExtension::shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) {
- GDVIRTUAL_CALL(shaped_text_set_preserve_control, p_shaped, p_enabled);
+ GDVIRTUAL_CALL(_shaped_text_set_preserve_control, p_shaped, p_enabled);
}
bool TextServerExtension::shaped_text_get_preserve_control(const RID &p_shaped) const {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_get_preserve_control, p_shaped, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_get_preserve_control, p_shaped, ret);
+ return ret;
}
-bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret)) {
- return ret;
- }
- return false;
+void TextServerExtension::shaped_text_set_spacing(const RID &p_shaped, TextServer::SpacingType p_spacing, int64_t p_value) {
+ GDVIRTUAL_CALL(_shaped_text_set_spacing, p_shaped, p_spacing, p_value);
+}
+
+int64_t TextServerExtension::shaped_text_get_spacing(const RID &p_shaped, TextServer::SpacingType p_spacing) const {
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_get_spacing, p_shaped, p_spacing, ret);
+ return ret;
+}
+
+bool TextServerExtension::shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features, const String &p_language, const Variant &p_meta) {
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_add_string, p_shaped, p_text, p_fonts, p_size, p_opentype_features, p_language, p_meta, ret);
+ return ret;
}
bool TextServerExtension::shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align, int64_t p_length) {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_add_object, p_shaped, p_key, p_size, p_inline_align, p_length, ret);
+ return ret;
}
bool TextServerExtension::shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align) {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_resize_object, p_shaped, p_key, p_size, p_inline_align, ret);
+ return ret;
}
int64_t TextServerExtension::shaped_get_span_count(const RID &p_shaped) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(shaped_get_span_count, p_shaped, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_shaped_get_span_count, p_shaped, ret);
+ return ret;
}
Variant TextServerExtension::shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const {
- Variant ret;
- if (GDVIRTUAL_CALL(shaped_get_span_meta, p_shaped, p_index, ret)) {
- return ret;
- }
- return false;
+ Variant ret = false;
+ GDVIRTUAL_CALL(_shaped_get_span_meta, p_shaped, p_index, ret);
+ return ret;
}
-void TextServerExtension::shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) {
- GDVIRTUAL_CALL(shaped_set_span_update_font, p_shaped, p_index, p_fonts, p_size, p_opentype_features);
+void TextServerExtension::shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features) {
+ GDVIRTUAL_CALL(_shaped_set_span_update_font, p_shaped, p_index, p_fonts, p_size, p_opentype_features);
}
RID TextServerExtension::shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const {
RID ret;
- if (GDVIRTUAL_CALL(shaped_text_substr, p_shaped, p_start, p_length, ret)) {
- return ret;
- }
- return RID();
+ GDVIRTUAL_CALL(_shaped_text_substr, p_shaped, p_start, p_length, ret);
+ return ret;
}
RID TextServerExtension::shaped_text_get_parent(const RID &p_shaped) const {
RID ret;
- if (GDVIRTUAL_CALL(shaped_text_get_parent, p_shaped, ret)) {
- return ret;
- }
- return RID();
+ GDVIRTUAL_CALL(_shaped_text_get_parent, p_shaped, ret);
+ return ret;
}
-double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t p_jst_flags) {
- double ret;
- if (GDVIRTUAL_CALL(shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret)) {
- return ret;
- }
- return 0.0;
+double TextServerExtension::shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags) {
+ double ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_fit_to_width, p_shaped, p_width, p_jst_flags, ret);
+ return ret;
}
double TextServerExtension::shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) {
- double ret;
- if (GDVIRTUAL_CALL(shaped_text_tab_align, p_shaped, p_tab_stops, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_tab_align, p_shaped, p_tab_stops, ret);
+ return ret;
}
bool TextServerExtension::shaped_text_shape(const RID &p_shaped) {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_shape, p_shaped, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_shape, p_shaped, ret);
+ return ret;
}
bool TextServerExtension::shaped_text_update_breaks(const RID &p_shaped) {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_update_breaks, p_shaped, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_update_breaks, p_shaped, ret);
+ return ret;
}
bool TextServerExtension::shaped_text_update_justification_ops(const RID &p_shaped) {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_update_justification_ops, p_shaped, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_update_justification_ops, p_shaped, ret);
+ return ret;
}
bool TextServerExtension::shaped_text_is_ready(const RID &p_shaped) const {
- bool ret;
- if (GDVIRTUAL_CALL(shaped_text_is_ready, p_shaped, ret)) {
- return ret;
- }
- return false;
+ bool ret = false;
+ GDVIRTUAL_CALL(_shaped_text_is_ready, p_shaped, ret);
+ return ret;
}
const Glyph *TextServerExtension::shaped_text_get_glyphs(const RID &p_shaped) const {
GDNativeConstPtr<const Glyph> ret;
- if (GDVIRTUAL_CALL(shaped_text_get_glyphs, p_shaped, ret)) {
- return ret;
- }
- return nullptr;
+ GDVIRTUAL_CALL(_shaped_text_get_glyphs, p_shaped, ret);
+ return ret;
}
const Glyph *TextServerExtension::shaped_text_sort_logical(const RID &p_shaped) {
GDNativeConstPtr<const Glyph> ret;
- if (GDVIRTUAL_CALL(shaped_text_sort_logical, p_shaped, ret)) {
- return ret;
- }
- return nullptr;
+ GDVIRTUAL_CALL(_shaped_text_sort_logical, p_shaped, ret);
+ return ret;
}
int64_t TextServerExtension::shaped_text_get_glyph_count(const RID &p_shaped) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_get_glyph_count, p_shaped, ret)) {
- return ret;
- }
- return 0;
+ int64_t ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_get_glyph_count, p_shaped, ret);
+ return ret;
}
Vector2i TextServerExtension::shaped_text_get_range(const RID &p_shaped) const {
Vector2i ret;
- if (GDVIRTUAL_CALL(shaped_text_get_range, p_shaped, ret)) {
- return ret;
- }
- return Vector2i();
+ GDVIRTUAL_CALL(_shaped_text_get_range, p_shaped, ret);
+ return ret;
}
-PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t p_break_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks_adv, p_shaped, p_width, p_start, p_once, p_break_flags, ret)) {
return ret;
}
return TextServer::shaped_text_get_line_breaks_adv(p_shaped, p_width, p_start, p_once, p_break_flags);
}
-PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t p_break_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_get_line_breaks, p_shaped, p_width, p_start, p_break_flags, ret)) {
return ret;
}
return TextServer::shaped_text_get_line_breaks(p_shaped, p_width, p_start, p_break_flags);
}
-PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const {
+PackedInt32Array TextServerExtension::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_get_word_breaks, p_shaped, p_grapheme_flags, ret)) {
return ret;
}
return TextServer::shaped_text_get_word_breaks(p_shaped, p_grapheme_flags);
}
int64_t TextServerExtension::shaped_text_get_trim_pos(const RID &p_shaped) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_get_trim_pos, p_shaped, ret)) {
- return ret;
- }
- return -1;
+ int64_t ret = -1;
+ GDVIRTUAL_CALL(_shaped_text_get_trim_pos, p_shaped, ret);
+ return ret;
}
int64_t TextServerExtension::shaped_text_get_ellipsis_pos(const RID &p_shaped) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_pos, p_shaped, ret)) {
- return ret;
- }
- return -1;
+ int64_t ret = -1;
+ GDVIRTUAL_CALL(_shaped_text_get_ellipsis_pos, p_shaped, ret);
+ return ret;
}
const Glyph *TextServerExtension::shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const {
GDNativeConstPtr<const Glyph> ret;
- if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_glyphs, p_shaped, ret)) {
- return ret;
- }
- return nullptr;
+ GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyphs, p_shaped, ret);
+ return ret;
}
int64_t TextServerExtension::shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const {
- int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_get_ellipsis_glyph_count, p_shaped, ret)) {
- return ret;
- }
- return -1;
+ int64_t ret = -1;
+ GDVIRTUAL_CALL(_shaped_text_get_ellipsis_glyph_count, p_shaped, ret);
+ return ret;
}
-void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, int64_t p_trim_flags) {
- GDVIRTUAL_CALL(shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags);
+void TextServerExtension::shaped_text_overrun_trim_to_width(const RID &p_shaped_line, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) {
+ GDVIRTUAL_CALL(_shaped_text_overrun_trim_to_width, p_shaped_line, p_width, p_trim_flags);
}
Array TextServerExtension::shaped_text_get_objects(const RID &p_shaped) const {
Array ret;
- if (GDVIRTUAL_CALL(shaped_text_get_objects, p_shaped, ret)) {
- return ret;
- }
- return Array();
+ GDVIRTUAL_CALL(_shaped_text_get_objects, p_shaped, ret);
+ return ret;
}
Rect2 TextServerExtension::shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const {
Rect2 ret;
- if (GDVIRTUAL_CALL(shaped_text_get_object_rect, p_shaped, p_key, ret)) {
- return ret;
- }
- return Rect2();
+ GDVIRTUAL_CALL(_shaped_text_get_object_rect, p_shaped, p_key, ret);
+ return ret;
}
Size2 TextServerExtension::shaped_text_get_size(const RID &p_shaped) const {
Size2 ret;
- if (GDVIRTUAL_CALL(shaped_text_get_size, p_shaped, ret)) {
- return ret;
- }
- return Size2();
+ GDVIRTUAL_CALL(_shaped_text_get_size, p_shaped, ret);
+ return ret;
}
double TextServerExtension::shaped_text_get_ascent(const RID &p_shaped) const {
- double ret;
- if (GDVIRTUAL_CALL(shaped_text_get_ascent, p_shaped, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_get_ascent, p_shaped, ret);
+ return ret;
}
double TextServerExtension::shaped_text_get_descent(const RID &p_shaped) const {
- double ret;
- if (GDVIRTUAL_CALL(shaped_text_get_descent, p_shaped, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_get_descent, p_shaped, ret);
+ return ret;
}
double TextServerExtension::shaped_text_get_width(const RID &p_shaped) const {
- double ret;
- if (GDVIRTUAL_CALL(shaped_text_get_width, p_shaped, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_get_width, p_shaped, ret);
+ return ret;
}
double TextServerExtension::shaped_text_get_underline_position(const RID &p_shaped) const {
- double ret;
- if (GDVIRTUAL_CALL(shaped_text_get_underline_position, p_shaped, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_get_underline_position, p_shaped, ret);
+ return ret;
}
double TextServerExtension::shaped_text_get_underline_thickness(const RID &p_shaped) const {
- double ret;
- if (GDVIRTUAL_CALL(shaped_text_get_underline_thickness, p_shaped, ret)) {
- return ret;
- }
- return 0.0;
+ double ret = 0;
+ GDVIRTUAL_CALL(_shaped_text_get_underline_thickness, p_shaped, ret);
+ return ret;
}
TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_get_dominant_direction_in_range, p_shaped, p_start, p_end, ret)) {
return (TextServer::Direction)ret;
}
return TextServer::shaped_text_get_dominant_direction_in_range(p_shaped, p_start, p_end);
@@ -1381,7 +1210,7 @@ TextServer::Direction TextServerExtension::shaped_text_get_dominant_direction_in
CaretInfo TextServerExtension::shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const {
CaretInfo ret;
- if (GDVIRTUAL_CALL(shaped_text_get_carets, p_shaped, p_position, &ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_get_carets, p_shaped, p_position, &ret)) {
return ret;
}
return TextServer::shaped_text_get_carets(p_shaped, p_position);
@@ -1389,7 +1218,7 @@ CaretInfo TextServerExtension::shaped_text_get_carets(const RID &p_shaped, int64
Vector<Vector2> TextServerExtension::shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const {
Vector<Vector2> ret;
- if (GDVIRTUAL_CALL(shaped_text_get_selection, p_shaped, p_start, p_end, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_get_selection, p_shaped, p_start, p_end, ret)) {
return ret;
}
return TextServer::shaped_text_get_selection(p_shaped, p_start, p_end);
@@ -1397,7 +1226,7 @@ Vector<Vector2> TextServerExtension::shaped_text_get_selection(const RID &p_shap
int64_t TextServerExtension::shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const {
int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_hit_test_grapheme, p_shaped, p_coords, ret)) {
return ret;
}
return TextServer::shaped_text_hit_test_grapheme(p_shaped, p_coords);
@@ -1405,21 +1234,21 @@ int64_t TextServerExtension::shaped_text_hit_test_grapheme(const RID &p_shaped,
int64_t TextServerExtension::shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const {
int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_hit_test_position, p_shaped, p_coords, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_hit_test_position, p_shaped, p_coords, ret)) {
return ret;
}
return TextServer::shaped_text_hit_test_position(p_shaped, p_coords);
}
void TextServerExtension::shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, const Color &p_color) const {
- if (GDVIRTUAL_CALL(shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) {
+ if (GDVIRTUAL_CALL(_shaped_text_draw, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color)) {
return;
}
TextServer::shaped_text_draw(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_color);
}
void TextServerExtension::shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l, double p_clip_r, int64_t p_outline_size, const Color &p_color) const {
- if (GDVIRTUAL_CALL(shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) {
+ if (GDVIRTUAL_CALL(_shaped_text_draw_outline, p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color)) {
return;
}
TextServer::shaped_text_draw_outline(p_shaped, p_canvas, p_pos, p_clip_l, p_clip_r, p_outline_size, p_color);
@@ -1427,7 +1256,7 @@ void TextServerExtension::shaped_text_draw_outline(const RID &p_shaped, const RI
Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const {
Vector2 ret;
- if (GDVIRTUAL_CALL(shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_get_grapheme_bounds, p_shaped, p_pos, ret)) {
return ret;
}
return TextServer::shaped_text_get_grapheme_bounds(p_shaped, p_pos);
@@ -1435,7 +1264,7 @@ Vector2 TextServerExtension::shaped_text_get_grapheme_bounds(const RID &p_shaped
int64_t TextServerExtension::shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const {
int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_next_grapheme_pos, p_shaped, p_pos, ret)) {
return ret;
}
return TextServer::shaped_text_next_grapheme_pos(p_shaped, p_pos);
@@ -1443,7 +1272,7 @@ int64_t TextServerExtension::shaped_text_next_grapheme_pos(const RID &p_shaped,
int64_t TextServerExtension::shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const {
int64_t ret;
- if (GDVIRTUAL_CALL(shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) {
+ if (GDVIRTUAL_CALL(_shaped_text_prev_grapheme_pos, p_shaped, p_pos, ret)) {
return ret;
}
return TextServer::shaped_text_prev_grapheme_pos(p_shaped, p_pos);
@@ -1451,7 +1280,7 @@ int64_t TextServerExtension::shaped_text_prev_grapheme_pos(const RID &p_shaped,
String TextServerExtension::format_number(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(format_number, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(_format_number, p_string, p_language, ret)) {
return ret;
}
return p_string;
@@ -1459,23 +1288,29 @@ String TextServerExtension::format_number(const String &p_string, const String &
String TextServerExtension::parse_number(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(parse_number, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(_parse_number, p_string, p_language, ret)) {
return ret;
}
return p_string;
}
String TextServerExtension::percent_sign(const String &p_language) const {
- String ret;
- if (GDVIRTUAL_CALL(percent_sign, p_language, ret)) {
+ String ret = "%";
+ GDVIRTUAL_CALL(_percent_sign, p_language, ret);
+ return ret;
+}
+
+bool TextServerExtension::is_valid_identifier(const String &p_string) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_is_valid_identifier, p_string, ret)) {
return ret;
}
- return "%";
+ return TextServer::is_valid_identifier(p_string);
}
String TextServerExtension::strip_diacritics(const String &p_string) const {
String ret;
- if (GDVIRTUAL_CALL(strip_diacritics, p_string, ret)) {
+ if (GDVIRTUAL_CALL(_strip_diacritics, p_string, ret)) {
return ret;
}
return TextServer::strip_diacritics(p_string);
@@ -1483,7 +1318,7 @@ String TextServerExtension::strip_diacritics(const String &p_string) const {
String TextServerExtension::string_to_upper(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(string_to_upper, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(_string_to_upper, p_string, p_language, ret)) {
return ret;
}
return p_string;
@@ -1491,26 +1326,38 @@ String TextServerExtension::string_to_upper(const String &p_string, const String
String TextServerExtension::string_to_lower(const String &p_string, const String &p_language) const {
String ret;
- if (GDVIRTUAL_CALL(string_to_lower, p_string, p_language, ret)) {
+ if (GDVIRTUAL_CALL(_string_to_lower, p_string, p_language, ret)) {
return ret;
}
return p_string;
}
-Array TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- Array ret;
- if (GDVIRTUAL_CALL(parse_structured_text, p_parser_type, p_args, p_text, ret)) {
- return ret;
- }
- return Array();
+TypedArray<Vector2i> TextServerExtension::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector2i> ret;
+ GDVIRTUAL_CALL(_parse_structured_text, p_parser_type, p_args, p_text, ret);
+ return ret;
}
PackedInt32Array TextServerExtension::string_get_word_breaks(const String &p_string, const String &p_language) const {
PackedInt32Array ret;
- if (GDVIRTUAL_CALL(string_get_word_breaks, p_string, p_language, ret)) {
+ GDVIRTUAL_CALL(_string_get_word_breaks, p_string, p_language, ret);
+ return ret;
+}
+
+int64_t TextServerExtension::is_confusable(const String &p_string, const PackedStringArray &p_dict) const {
+ int64_t ret;
+ if (GDVIRTUAL_CALL(_is_confusable, p_string, p_dict, ret)) {
+ return ret;
+ }
+ return TextServer::is_confusable(p_string, p_dict);
+}
+
+bool TextServerExtension::spoof_check(const String &p_string) const {
+ bool ret;
+ if (GDVIRTUAL_CALL(_spoof_check, p_string, ret)) {
return ret;
}
- return PackedInt32Array();
+ return TextServer::spoof_check(p_string);
}
TextServerExtension::TextServerExtension() {
diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h
index 7b7fc61ed7..992b708045 100644
--- a/servers/text/text_server_extension.h
+++ b/servers/text/text_server_extension.h
@@ -35,6 +35,7 @@
#include "core/object/script_language.h"
#include "core/os/thread_safe.h"
#include "core/variant/native_ptr.h"
+#include "core/variant/typed_array.h"
#include "servers/text_server.h"
class TextServerExtension : public TextServer {
@@ -49,393 +50,402 @@ public:
virtual bool has_feature(Feature p_feature) const override;
virtual String get_name() const override;
virtual int64_t get_features() const override;
- GDVIRTUAL1RC(bool, has_feature, Feature);
- GDVIRTUAL0RC(String, get_name);
- GDVIRTUAL0RC(int64_t, get_features);
+ GDVIRTUAL1RC(bool, _has_feature, Feature);
+ GDVIRTUAL0RC(String, _get_name);
+ GDVIRTUAL0RC(int64_t, _get_features);
virtual void free_rid(const RID &p_rid) override;
virtual bool has(const RID &p_rid) override;
virtual bool load_support_data(const String &p_filename) override;
- GDVIRTUAL1(free_rid, RID);
- GDVIRTUAL1R(bool, has, RID);
- GDVIRTUAL1R(bool, load_support_data, const String &);
+ GDVIRTUAL1(_free_rid, RID);
+ GDVIRTUAL1R(bool, _has, RID);
+ GDVIRTUAL1R(bool, _load_support_data, const String &);
virtual String get_support_data_filename() const override;
virtual String get_support_data_info() const override;
virtual bool save_support_data(const String &p_filename) const override;
- GDVIRTUAL0RC(String, get_support_data_filename);
- GDVIRTUAL0RC(String, get_support_data_info);
- GDVIRTUAL1RC(bool, save_support_data, const String &);
+ GDVIRTUAL0RC(String, _get_support_data_filename);
+ GDVIRTUAL0RC(String, _get_support_data_info);
+ GDVIRTUAL1RC(bool, _save_support_data, const String &);
virtual bool is_locale_right_to_left(const String &p_locale) const override;
- GDVIRTUAL1RC(bool, is_locale_right_to_left, const String &);
+ GDVIRTUAL1RC(bool, _is_locale_right_to_left, const String &);
virtual int64_t name_to_tag(const String &p_name) const override;
virtual String tag_to_name(int64_t p_tag) const override;
- GDVIRTUAL1RC(int64_t, name_to_tag, const String &);
- GDVIRTUAL1RC(String, tag_to_name, int64_t);
+ GDVIRTUAL1RC(int64_t, _name_to_tag, const String &);
+ GDVIRTUAL1RC(String, _tag_to_name, int64_t);
/* Font interface */
+
virtual RID create_font() override;
- GDVIRTUAL0R(RID, create_font);
+ GDVIRTUAL0R(RID, _create_font);
virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) override;
virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) override;
- GDVIRTUAL2(font_set_data, RID, const PackedByteArray &);
- GDVIRTUAL3(font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, int64_t);
+ GDVIRTUAL2(_font_set_data, RID, const PackedByteArray &);
+ GDVIRTUAL3(_font_set_data_ptr, RID, GDNativeConstPtr<const uint8_t>, int64_t);
+
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) override;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_face_index, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, _font_get_face_index, RID);
- virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) override;
- virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_style, RID, int64_t);
- GDVIRTUAL1RC(int64_t, font_get_style, RID);
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const override;
+ GDVIRTUAL1RC(int64_t, _font_get_face_count, RID);
+
+ virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) override;
+ virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_style, RID, BitField<FontStyle>);
+ GDVIRTUAL1RC(BitField<FontStyle>, _font_get_style, RID);
virtual void font_set_name(const RID &p_font_rid, const String &p_name) override;
virtual String font_get_name(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_name, RID, const String &);
- GDVIRTUAL1RC(String, font_get_name, RID);
+ GDVIRTUAL2(_font_set_name, RID, const String &);
+ GDVIRTUAL1RC(String, _font_get_name, RID);
virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) override;
virtual String font_get_style_name(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_style_name, RID, const String &);
- GDVIRTUAL1RC(String, font_get_style_name, RID);
+ GDVIRTUAL2(_font_set_style_name, RID, const String &);
+ GDVIRTUAL1RC(String, _font_get_style_name, RID);
- virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override;
- virtual bool font_is_antialiased(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_antialiased, RID, bool);
- GDVIRTUAL1RC(bool, font_is_antialiased, RID);
+ virtual void font_set_antialiasing(const RID &p_font_rid, TextServer::FontAntialiasing p_antialiasing) override;
+ virtual TextServer::FontAntialiasing font_get_antialiasing(const RID &p_font_rid) const override;
+ GDVIRTUAL2(_font_set_antialiasing, RID, TextServer::FontAntialiasing);
+ GDVIRTUAL1RC(TextServer::FontAntialiasing, _font_get_antialiasing, RID);
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_generate_mipmaps, RID, bool);
- GDVIRTUAL1RC(bool, font_get_generate_mipmaps, RID);
+ GDVIRTUAL2(_font_set_generate_mipmaps, RID, bool);
+ GDVIRTUAL1RC(bool, _font_get_generate_mipmaps, RID);
virtual void font_set_multichannel_signed_distance_field(const RID &p_font_rid, bool p_msdf) override;
virtual bool font_is_multichannel_signed_distance_field(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_multichannel_signed_distance_field, RID, bool);
- GDVIRTUAL1RC(bool, font_is_multichannel_signed_distance_field, RID);
+ GDVIRTUAL2(_font_set_multichannel_signed_distance_field, RID, bool);
+ GDVIRTUAL1RC(bool, _font_is_multichannel_signed_distance_field, RID);
virtual void font_set_msdf_pixel_range(const RID &p_font_rid, int64_t p_msdf_pixel_range) override;
virtual int64_t font_get_msdf_pixel_range(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_msdf_pixel_range, RID, int64_t);
- GDVIRTUAL1RC(int64_t, font_get_msdf_pixel_range, RID);
+ GDVIRTUAL2(_font_set_msdf_pixel_range, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, _font_get_msdf_pixel_range, RID);
virtual void font_set_msdf_size(const RID &p_font_rid, int64_t p_msdf_size) override;
virtual int64_t font_get_msdf_size(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_msdf_size, RID, int64_t);
- GDVIRTUAL1RC(int64_t, font_get_msdf_size, RID);
+ GDVIRTUAL2(_font_set_msdf_size, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, _font_get_msdf_size, RID);
virtual void font_set_fixed_size(const RID &p_font_rid, int64_t p_fixed_size) override;
virtual int64_t font_get_fixed_size(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_fixed_size, RID, int64_t);
- GDVIRTUAL1RC(int64_t, font_get_fixed_size, RID);
+ GDVIRTUAL2(_font_set_fixed_size, RID, int64_t);
+ GDVIRTUAL1RC(int64_t, _font_get_fixed_size, RID);
virtual void font_set_subpixel_positioning(const RID &p_font_rid, SubpixelPositioning p_subpixel) override;
virtual SubpixelPositioning font_get_subpixel_positioning(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_subpixel_positioning, RID, SubpixelPositioning);
- GDVIRTUAL1RC(SubpixelPositioning, font_get_subpixel_positioning, RID);
+ GDVIRTUAL2(_font_set_subpixel_positioning, RID, SubpixelPositioning);
+ GDVIRTUAL1RC(SubpixelPositioning, _font_get_subpixel_positioning, RID);
virtual void font_set_embolden(const RID &p_font_rid, double p_strength) override;
virtual double font_get_embolden(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_embolden, RID, double);
- GDVIRTUAL1RC(double, font_get_embolden, RID);
+ GDVIRTUAL2(_font_set_embolden, RID, double);
+ GDVIRTUAL1RC(double, _font_get_embolden, RID);
virtual void font_set_transform(const RID &p_font_rid, const Transform2D &p_transform) override;
virtual Transform2D font_get_transform(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_transform, RID, Transform2D);
- GDVIRTUAL1RC(Transform2D, font_get_transform, RID);
+ GDVIRTUAL2(_font_set_transform, RID, Transform2D);
+ GDVIRTUAL1RC(Transform2D, _font_get_transform, RID);
virtual void font_set_force_autohinter(const RID &p_font_rid, bool p_force_autohinter) override;
virtual bool font_is_force_autohinter(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_force_autohinter, RID, bool);
- GDVIRTUAL1RC(bool, font_is_force_autohinter, RID);
+ GDVIRTUAL2(_font_set_force_autohinter, RID, bool);
+ GDVIRTUAL1RC(bool, _font_is_force_autohinter, RID);
virtual void font_set_hinting(const RID &p_font_rid, Hinting p_hinting) override;
virtual Hinting font_get_hinting(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_hinting, RID, Hinting);
- GDVIRTUAL1RC(Hinting, font_get_hinting, RID);
+ GDVIRTUAL2(_font_set_hinting, RID, Hinting);
+ GDVIRTUAL1RC(Hinting, _font_get_hinting, RID);
virtual void font_set_variation_coordinates(const RID &p_font_rid, const Dictionary &p_variation_coordinates) override;
virtual Dictionary font_get_variation_coordinates(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_variation_coordinates, RID, Dictionary);
- GDVIRTUAL1RC(Dictionary, font_get_variation_coordinates, RID);
+ GDVIRTUAL2(_font_set_variation_coordinates, RID, Dictionary);
+ GDVIRTUAL1RC(Dictionary, _font_get_variation_coordinates, RID);
virtual void font_set_oversampling(const RID &p_font_rid, double p_oversampling) override;
virtual double font_get_oversampling(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_oversampling, RID, double);
- GDVIRTUAL1RC(double, font_get_oversampling, RID);
+ GDVIRTUAL2(_font_set_oversampling, RID, double);
+ GDVIRTUAL1RC(double, _font_get_oversampling, RID);
- virtual Array font_get_size_cache_list(const RID &p_font_rid) const override;
+ virtual TypedArray<Vector2i> font_get_size_cache_list(const RID &p_font_rid) const override;
virtual void font_clear_size_cache(const RID &p_font_rid) override;
virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) override;
- GDVIRTUAL1RC(Array, font_get_size_cache_list, RID);
- GDVIRTUAL1(font_clear_size_cache, RID);
- GDVIRTUAL2(font_remove_size_cache, RID, const Vector2i &);
+ GDVIRTUAL1RC(TypedArray<Vector2i>, _font_get_size_cache_list, RID);
+ GDVIRTUAL1(_font_clear_size_cache, RID);
+ GDVIRTUAL2(_font_remove_size_cache, RID, const Vector2i &);
virtual void font_set_ascent(const RID &p_font_rid, int64_t p_size, double p_ascent) override;
virtual double font_get_ascent(const RID &p_font_rid, int64_t p_size) const override;
- GDVIRTUAL3(font_set_ascent, RID, int64_t, double);
- GDVIRTUAL2RC(double, font_get_ascent, RID, int64_t);
+ GDVIRTUAL3(_font_set_ascent, RID, int64_t, double);
+ GDVIRTUAL2RC(double, _font_get_ascent, RID, int64_t);
virtual void font_set_descent(const RID &p_font_rid, int64_t p_size, double p_descent) override;
virtual double font_get_descent(const RID &p_font_rid, int64_t p_size) const override;
- GDVIRTUAL3(font_set_descent, RID, int64_t, double);
- GDVIRTUAL2RC(double, font_get_descent, RID, int64_t);
+ GDVIRTUAL3(_font_set_descent, RID, int64_t, double);
+ GDVIRTUAL2RC(double, _font_get_descent, RID, int64_t);
virtual void font_set_underline_position(const RID &p_font_rid, int64_t p_size, double p_underline_position) override;
virtual double font_get_underline_position(const RID &p_font_rid, int64_t p_size) const override;
- GDVIRTUAL3(font_set_underline_position, RID, int64_t, double);
- GDVIRTUAL2RC(double, font_get_underline_position, RID, int64_t);
+ GDVIRTUAL3(_font_set_underline_position, RID, int64_t, double);
+ GDVIRTUAL2RC(double, _font_get_underline_position, RID, int64_t);
virtual void font_set_underline_thickness(const RID &p_font_rid, int64_t p_size, double p_underline_thickness) override;
virtual double font_get_underline_thickness(const RID &p_font_rid, int64_t p_size) const override;
- GDVIRTUAL3(font_set_underline_thickness, RID, int64_t, double);
- GDVIRTUAL2RC(double, font_get_underline_thickness, RID, int64_t);
+ GDVIRTUAL3(_font_set_underline_thickness, RID, int64_t, double);
+ GDVIRTUAL2RC(double, _font_get_underline_thickness, RID, int64_t);
virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) override;
virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const override;
- GDVIRTUAL3(font_set_scale, RID, int64_t, double);
- GDVIRTUAL2RC(double, font_get_scale, RID, int64_t);
-
- virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) override;
- virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const override;
- GDVIRTUAL4(font_set_spacing, RID, int64_t, SpacingType, int64_t);
- GDVIRTUAL3RC(int64_t, font_get_spacing, RID, int64_t, SpacingType);
+ GDVIRTUAL3(_font_set_scale, RID, int64_t, double);
+ GDVIRTUAL2RC(double, _font_get_scale, RID, int64_t);
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) override;
- GDVIRTUAL2RC(int64_t, font_get_texture_count, RID, const Vector2i &);
- GDVIRTUAL2(font_clear_textures, RID, const Vector2i &);
- GDVIRTUAL3(font_remove_texture, RID, const Vector2i &, int64_t);
+ GDVIRTUAL2RC(int64_t, _font_get_texture_count, RID, const Vector2i &);
+ GDVIRTUAL2(_font_clear_textures, RID, const Vector2i &);
+ GDVIRTUAL3(_font_remove_texture, RID, const Vector2i &, int64_t);
virtual void font_set_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const Ref<Image> &p_image) override;
virtual Ref<Image> font_get_texture_image(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const override;
- GDVIRTUAL4(font_set_texture_image, RID, const Vector2i &, int64_t, const Ref<Image> &);
- GDVIRTUAL3RC(Ref<Image>, font_get_texture_image, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(_font_set_texture_image, RID, const Vector2i &, int64_t, const Ref<Image> &);
+ GDVIRTUAL3RC(Ref<Image>, _font_get_texture_image, RID, const Vector2i &, int64_t);
virtual void font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) override;
virtual PackedInt32Array font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const override;
- GDVIRTUAL4(font_set_texture_offsets, RID, const Vector2i &, int64_t, const PackedInt32Array &);
- GDVIRTUAL3RC(PackedInt32Array, font_get_texture_offsets, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(_font_set_texture_offsets, RID, const Vector2i &, int64_t, const PackedInt32Array &);
+ GDVIRTUAL3RC(PackedInt32Array, _font_get_texture_offsets, RID, const Vector2i &, int64_t);
- virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const override;
+ virtual PackedInt32Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const override;
virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) override;
virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) override;
- GDVIRTUAL2RC(Array, font_get_glyph_list, RID, const Vector2i &);
- GDVIRTUAL2(font_clear_glyphs, RID, const Vector2i &);
- GDVIRTUAL3(font_remove_glyph, RID, const Vector2i &, int64_t);
+ GDVIRTUAL2RC(PackedInt32Array, _font_get_glyph_list, RID, const Vector2i &);
+ GDVIRTUAL2(_font_clear_glyphs, RID, const Vector2i &);
+ GDVIRTUAL3(_font_remove_glyph, RID, const Vector2i &, int64_t);
virtual Vector2 font_get_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph) const override;
virtual void font_set_glyph_advance(const RID &p_font_rid, int64_t p_size, int64_t p_glyph, const Vector2 &p_advance) override;
- GDVIRTUAL3RC(Vector2, font_get_glyph_advance, RID, int64_t, int64_t);
- GDVIRTUAL4(font_set_glyph_advance, RID, int64_t, int64_t, const Vector2 &);
+ GDVIRTUAL3RC(Vector2, _font_get_glyph_advance, RID, int64_t, int64_t);
+ GDVIRTUAL4(_font_set_glyph_advance, RID, int64_t, int64_t, const Vector2 &);
virtual Vector2 font_get_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
virtual void font_set_glyph_offset(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_offset) override;
- GDVIRTUAL3RC(Vector2, font_get_glyph_offset, RID, const Vector2i &, int64_t);
- GDVIRTUAL4(font_set_glyph_offset, RID, const Vector2i &, int64_t, const Vector2 &);
+ GDVIRTUAL3RC(Vector2, _font_get_glyph_offset, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(_font_set_glyph_offset, RID, const Vector2i &, int64_t, const Vector2 &);
virtual Vector2 font_get_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
virtual void font_set_glyph_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Vector2 &p_gl_size) override;
- GDVIRTUAL3RC(Vector2, font_get_glyph_size, RID, const Vector2i &, int64_t);
- GDVIRTUAL4(font_set_glyph_size, RID, const Vector2i &, int64_t, const Vector2 &);
+ GDVIRTUAL3RC(Vector2, _font_get_glyph_size, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(_font_set_glyph_size, RID, const Vector2i &, int64_t, const Vector2 &);
virtual Rect2 font_get_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
virtual void font_set_glyph_uv_rect(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, const Rect2 &p_uv_rect) override;
- GDVIRTUAL3RC(Rect2, font_get_glyph_uv_rect, RID, const Vector2i &, int64_t);
- GDVIRTUAL4(font_set_glyph_uv_rect, RID, const Vector2i &, int64_t, const Rect2 &);
+ GDVIRTUAL3RC(Rect2, _font_get_glyph_uv_rect, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(_font_set_glyph_uv_rect, RID, const Vector2i &, int64_t, const Rect2 &);
virtual int64_t font_get_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
virtual void font_set_glyph_texture_idx(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph, int64_t p_texture_idx) override;
- GDVIRTUAL3RC(int64_t, font_get_glyph_texture_idx, RID, const Vector2i &, int64_t);
- GDVIRTUAL4(font_set_glyph_texture_idx, RID, const Vector2i &, int64_t, int64_t);
+ GDVIRTUAL3RC(int64_t, _font_get_glyph_texture_idx, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(_font_set_glyph_texture_idx, RID, const Vector2i &, int64_t, int64_t);
virtual RID font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
- GDVIRTUAL3RC(RID, font_get_glyph_texture_rid, RID, const Vector2i &, int64_t);
+ GDVIRTUAL3RC(RID, _font_get_glyph_texture_rid, RID, const Vector2i &, int64_t);
virtual Size2 font_get_glyph_texture_size(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) const override;
- GDVIRTUAL3RC(Size2, font_get_glyph_texture_size, RID, const Vector2i &, int64_t);
+ GDVIRTUAL3RC(Size2, _font_get_glyph_texture_size, RID, const Vector2i &, int64_t);
virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const override;
- GDVIRTUAL3RC(Dictionary, font_get_glyph_contours, RID, int64_t, int64_t);
+ GDVIRTUAL3RC(Dictionary, _font_get_glyph_contours, RID, int64_t, int64_t);
- virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override;
+ virtual TypedArray<Vector2i> font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const override;
virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) override;
virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) override;
- GDVIRTUAL2RC(Array, font_get_kerning_list, RID, int64_t);
- GDVIRTUAL2(font_clear_kerning_map, RID, int64_t);
- GDVIRTUAL3(font_remove_kerning, RID, int64_t, const Vector2i &);
+ GDVIRTUAL2RC(TypedArray<Vector2i>, _font_get_kerning_list, RID, int64_t);
+ GDVIRTUAL2(_font_clear_kerning_map, RID, int64_t);
+ GDVIRTUAL3(_font_remove_kerning, RID, int64_t, const Vector2i &);
virtual void font_set_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair, const Vector2 &p_kerning) override;
virtual Vector2 font_get_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) const override;
- GDVIRTUAL4(font_set_kerning, RID, int64_t, const Vector2i &, const Vector2 &);
- GDVIRTUAL3RC(Vector2, font_get_kerning, RID, int64_t, const Vector2i &);
+ GDVIRTUAL4(_font_set_kerning, RID, int64_t, const Vector2i &, const Vector2 &);
+ GDVIRTUAL3RC(Vector2, _font_get_kerning, RID, int64_t, const Vector2i &);
virtual int64_t font_get_glyph_index(const RID &p_font_rid, int64_t p_size, int64_t p_char, int64_t p_variation_selector = 0) const override;
- GDVIRTUAL4RC(int64_t, font_get_glyph_index, RID, int64_t, int64_t, int64_t);
+ GDVIRTUAL4RC(int64_t, _font_get_glyph_index, RID, int64_t, int64_t, int64_t);
virtual bool font_has_char(const RID &p_font_rid, int64_t p_char) const override;
virtual String font_get_supported_chars(const RID &p_font_rid) const override;
- GDVIRTUAL2RC(bool, font_has_char, RID, int64_t);
- GDVIRTUAL1RC(String, font_get_supported_chars, RID);
+ GDVIRTUAL2RC(bool, _font_has_char, RID, int64_t);
+ GDVIRTUAL1RC(String, _font_get_supported_chars, RID);
virtual void font_render_range(const RID &p_font, const Vector2i &p_size, int64_t p_start, int64_t p_end) override;
virtual void font_render_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_index) override;
- GDVIRTUAL4(font_render_range, RID, const Vector2i &, int64_t, int64_t);
- GDVIRTUAL3(font_render_glyph, RID, const Vector2i &, int64_t);
+ GDVIRTUAL4(_font_render_range, RID, const Vector2i &, int64_t, int64_t);
+ GDVIRTUAL3(_font_render_glyph, RID, const Vector2i &, int64_t);
virtual void font_draw_glyph(const RID &p_font, const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
virtual void font_draw_glyph_outline(const RID &p_font, const RID &p_canvas, int64_t p_size, int64_t p_outline_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color = Color(1, 1, 1)) const override;
- GDVIRTUAL6C(font_draw_glyph, RID, RID, int64_t, const Vector2 &, int64_t, const Color &);
- GDVIRTUAL7C(font_draw_glyph_outline, RID, RID, int64_t, int64_t, const Vector2 &, int64_t, const Color &);
+ GDVIRTUAL6C(_font_draw_glyph, RID, RID, int64_t, const Vector2 &, int64_t, const Color &);
+ GDVIRTUAL7C(_font_draw_glyph_outline, RID, RID, int64_t, int64_t, const Vector2 &, int64_t, const Color &);
virtual bool font_is_language_supported(const RID &p_font_rid, const String &p_language) const override;
virtual void font_set_language_support_override(const RID &p_font_rid, const String &p_language, bool p_supported) override;
virtual bool font_get_language_support_override(const RID &p_font_rid, const String &p_language) override;
virtual void font_remove_language_support_override(const RID &p_font_rid, const String &p_language) override;
virtual PackedStringArray font_get_language_support_overrides(const RID &p_font_rid) override;
- GDVIRTUAL2RC(bool, font_is_language_supported, RID, const String &);
- GDVIRTUAL3(font_set_language_support_override, RID, const String &, bool);
- GDVIRTUAL2R(bool, font_get_language_support_override, RID, const String &);
- GDVIRTUAL2(font_remove_language_support_override, RID, const String &);
- GDVIRTUAL1R(PackedStringArray, font_get_language_support_overrides, RID);
+ GDVIRTUAL2RC(bool, _font_is_language_supported, RID, const String &);
+ GDVIRTUAL3(_font_set_language_support_override, RID, const String &, bool);
+ GDVIRTUAL2R(bool, _font_get_language_support_override, RID, const String &);
+ GDVIRTUAL2(_font_remove_language_support_override, RID, const String &);
+ GDVIRTUAL1R(PackedStringArray, _font_get_language_support_overrides, RID);
virtual bool font_is_script_supported(const RID &p_font_rid, const String &p_script) const override;
virtual void font_set_script_support_override(const RID &p_font_rid, const String &p_script, bool p_supported) override;
virtual bool font_get_script_support_override(const RID &p_font_rid, const String &p_script) override;
virtual void font_remove_script_support_override(const RID &p_font_rid, const String &p_script) override;
virtual PackedStringArray font_get_script_support_overrides(const RID &p_font_rid) override;
- GDVIRTUAL2RC(bool, font_is_script_supported, RID, const String &);
- GDVIRTUAL3(font_set_script_support_override, RID, const String &, bool);
- GDVIRTUAL2R(bool, font_get_script_support_override, RID, const String &);
- GDVIRTUAL2(font_remove_script_support_override, RID, const String &);
- GDVIRTUAL1R(PackedStringArray, font_get_script_support_overrides, RID);
+ GDVIRTUAL2RC(bool, _font_is_script_supported, RID, const String &);
+ GDVIRTUAL3(_font_set_script_support_override, RID, const String &, bool);
+ GDVIRTUAL2R(bool, _font_get_script_support_override, RID, const String &);
+ GDVIRTUAL2(_font_remove_script_support_override, RID, const String &);
+ GDVIRTUAL1R(PackedStringArray, _font_get_script_support_overrides, RID);
virtual void font_set_opentype_feature_overrides(const RID &p_font_rid, const Dictionary &p_overrides) override;
virtual Dictionary font_get_opentype_feature_overrides(const RID &p_font_rid) const override;
- GDVIRTUAL2(font_set_opentype_feature_overrides, RID, const Dictionary &);
- GDVIRTUAL1RC(Dictionary, font_get_opentype_feature_overrides, RID);
+ GDVIRTUAL2(_font_set_opentype_feature_overrides, RID, const Dictionary &);
+ GDVIRTUAL1RC(Dictionary, _font_get_opentype_feature_overrides, RID);
virtual Dictionary font_supported_feature_list(const RID &p_font_rid) const override;
virtual Dictionary font_supported_variation_list(const RID &p_font_rid) const override;
- GDVIRTUAL1RC(Dictionary, font_supported_feature_list, RID);
- GDVIRTUAL1RC(Dictionary, font_supported_variation_list, RID);
+ GDVIRTUAL1RC(Dictionary, _font_supported_feature_list, RID);
+ GDVIRTUAL1RC(Dictionary, _font_supported_variation_list, RID);
virtual double font_get_global_oversampling() const override;
virtual void font_set_global_oversampling(double p_oversampling) override;
- GDVIRTUAL0RC(double, font_get_global_oversampling);
- GDVIRTUAL1(font_set_global_oversampling, double);
+ GDVIRTUAL0RC(double, _font_get_global_oversampling);
+ GDVIRTUAL1(_font_set_global_oversampling, double);
virtual Vector2 get_hex_code_box_size(int64_t p_size, int64_t p_index) const override;
virtual void draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Vector2 &p_pos, int64_t p_index, const Color &p_color) const override;
- GDVIRTUAL2RC(Vector2, get_hex_code_box_size, int64_t, int64_t);
- GDVIRTUAL5C(draw_hex_code_box, RID, int64_t, const Vector2 &, int64_t, const Color &);
+ GDVIRTUAL2RC(Vector2, _get_hex_code_box_size, int64_t, int64_t);
+ GDVIRTUAL5C(_draw_hex_code_box, RID, int64_t, const Vector2 &, int64_t, const Color &);
/* Shaped text buffer interface */
virtual RID create_shaped_text(Direction p_direction = DIRECTION_AUTO, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
- GDVIRTUAL2R(RID, create_shaped_text, Direction, Orientation);
+ GDVIRTUAL2R(RID, _create_shaped_text, Direction, Orientation);
virtual void shaped_text_clear(const RID &p_shaped) override;
- GDVIRTUAL1(shaped_text_clear, RID);
+ GDVIRTUAL1(_shaped_text_clear, RID);
virtual void shaped_text_set_direction(const RID &p_shaped, Direction p_direction = DIRECTION_AUTO) override;
virtual Direction shaped_text_get_direction(const RID &p_shaped) const override;
virtual Direction shaped_text_get_inferred_direction(const RID &p_shaped) const override;
- GDVIRTUAL2(shaped_text_set_direction, RID, Direction);
- GDVIRTUAL1RC(Direction, shaped_text_get_direction, RID);
- GDVIRTUAL1RC(Direction, shaped_text_get_inferred_direction, RID);
+ GDVIRTUAL2(_shaped_text_set_direction, RID, Direction);
+ GDVIRTUAL1RC(Direction, _shaped_text_get_direction, RID);
+ GDVIRTUAL1RC(Direction, _shaped_text_get_inferred_direction, RID);
virtual void shaped_text_set_bidi_override(const RID &p_shaped, const Array &p_override) override;
- GDVIRTUAL2(shaped_text_set_bidi_override, RID, const Array &);
+ GDVIRTUAL2(_shaped_text_set_bidi_override, RID, const Array &);
virtual void shaped_text_set_custom_punctuation(const RID &p_shaped, const String &p_punct) override;
virtual String shaped_text_get_custom_punctuation(const RID &p_shaped) const override;
- GDVIRTUAL2(shaped_text_set_custom_punctuation, RID, String);
- GDVIRTUAL1RC(String, shaped_text_get_custom_punctuation, RID);
+ GDVIRTUAL2(_shaped_text_set_custom_punctuation, RID, String);
+ GDVIRTUAL1RC(String, _shaped_text_get_custom_punctuation, RID);
virtual void shaped_text_set_orientation(const RID &p_shaped, Orientation p_orientation = ORIENTATION_HORIZONTAL) override;
virtual Orientation shaped_text_get_orientation(const RID &p_shaped) const override;
- GDVIRTUAL2(shaped_text_set_orientation, RID, Orientation);
- GDVIRTUAL1RC(Orientation, shaped_text_get_orientation, RID);
+ GDVIRTUAL2(_shaped_text_set_orientation, RID, Orientation);
+ GDVIRTUAL1RC(Orientation, _shaped_text_get_orientation, RID);
virtual void shaped_text_set_preserve_invalid(const RID &p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_invalid(const RID &p_shaped) const override;
- GDVIRTUAL2(shaped_text_set_preserve_invalid, RID, bool);
- GDVIRTUAL1RC(bool, shaped_text_get_preserve_invalid, RID);
+ GDVIRTUAL2(_shaped_text_set_preserve_invalid, RID, bool);
+ GDVIRTUAL1RC(bool, _shaped_text_get_preserve_invalid, RID);
virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) override;
virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const override;
- GDVIRTUAL2(shaped_text_set_preserve_control, RID, bool);
- GDVIRTUAL1RC(bool, shaped_text_get_preserve_control, RID);
+ GDVIRTUAL2(_shaped_text_set_preserve_control, RID, bool);
+ GDVIRTUAL1RC(bool, _shaped_text_get_preserve_control, RID);
- virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
+ virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) override;
+ virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const override;
+ GDVIRTUAL3(_shaped_text_set_spacing, RID, SpacingType, int64_t);
+ GDVIRTUAL2RC(int64_t, _shaped_text_get_spacing, RID, SpacingType);
+
+ virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) override;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) override;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) override;
- GDVIRTUAL7R(bool, shaped_text_add_string, RID, const String &, const Array &, int64_t, const Dictionary &, const String &, const Variant &);
- GDVIRTUAL5R(bool, shaped_text_add_object, RID, const Variant &, const Size2 &, InlineAlignment, int64_t);
- GDVIRTUAL4R(bool, shaped_text_resize_object, RID, const Variant &, const Size2 &, InlineAlignment);
+ GDVIRTUAL7R(bool, _shaped_text_add_string, RID, const String &, const TypedArray<RID> &, int64_t, const Dictionary &, const String &, const Variant &);
+ GDVIRTUAL5R(bool, _shaped_text_add_object, RID, const Variant &, const Size2 &, InlineAlignment, int64_t);
+ GDVIRTUAL4R(bool, _shaped_text_resize_object, RID, const Variant &, const Size2 &, InlineAlignment);
virtual int64_t shaped_get_span_count(const RID &p_shaped) const override;
virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const override;
- virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) override;
- GDVIRTUAL1RC(int64_t, shaped_get_span_count, RID);
- GDVIRTUAL2RC(Variant, shaped_get_span_meta, RID, int64_t);
- GDVIRTUAL5(shaped_set_span_update_font, RID, int64_t, const Array &, int64_t, const Dictionary &);
+ virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) override;
+ GDVIRTUAL1RC(int64_t, _shaped_get_span_count, RID);
+ GDVIRTUAL2RC(Variant, _shaped_get_span_meta, RID, int64_t);
+ GDVIRTUAL5(_shaped_set_span_update_font, RID, int64_t, const TypedArray<RID> &, int64_t, const Dictionary &);
virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const override;
virtual RID shaped_text_get_parent(const RID &p_shaped) const override;
- GDVIRTUAL3RC(RID, shaped_text_substr, RID, int64_t, int64_t);
- GDVIRTUAL1RC(RID, shaped_text_get_parent, RID);
+ GDVIRTUAL3RC(RID, _shaped_text_substr, RID, int64_t, int64_t);
+ GDVIRTUAL1RC(RID, _shaped_text_get_parent, RID);
- virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) override;
virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) override;
- GDVIRTUAL3R(double, shaped_text_fit_to_width, RID, double, int64_t);
- GDVIRTUAL2R(double, shaped_text_tab_align, RID, const PackedFloat32Array &);
+ GDVIRTUAL3R(double, _shaped_text_fit_to_width, RID, double, BitField<TextServer::JustificationFlag>);
+ GDVIRTUAL2R(double, _shaped_text_tab_align, RID, const PackedFloat32Array &);
virtual bool shaped_text_shape(const RID &p_shaped) override;
virtual bool shaped_text_update_breaks(const RID &p_shaped) override;
virtual bool shaped_text_update_justification_ops(const RID &p_shaped) override;
- GDVIRTUAL1R(bool, shaped_text_shape, RID);
- GDVIRTUAL1R(bool, shaped_text_update_breaks, RID);
- GDVIRTUAL1R(bool, shaped_text_update_justification_ops, RID);
+ GDVIRTUAL1R(bool, _shaped_text_shape, RID);
+ GDVIRTUAL1R(bool, _shaped_text_update_breaks, RID);
+ GDVIRTUAL1R(bool, _shaped_text_update_justification_ops, RID);
virtual bool shaped_text_is_ready(const RID &p_shaped) const override;
- GDVIRTUAL1RC(bool, shaped_text_is_ready, RID);
+ GDVIRTUAL1RC(bool, _shaped_text_is_ready, RID);
virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const override;
virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) override;
virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const override;
- GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_glyphs, RID);
- GDVIRTUAL1R(GDNativeConstPtr<const Glyph>, shaped_text_sort_logical, RID);
- GDVIRTUAL1RC(int64_t, shaped_text_get_glyph_count, RID);
+ GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, _shaped_text_get_glyphs, RID);
+ GDVIRTUAL1R(GDNativeConstPtr<const Glyph>, _shaped_text_sort_logical, RID);
+ GDVIRTUAL1RC(int64_t, _shaped_text_get_glyph_count, RID);
virtual Vector2i shaped_text_get_range(const RID &p_shaped) const override;
- GDVIRTUAL1RC(Vector2i, shaped_text_get_range, RID);
+ GDVIRTUAL1RC(Vector2i, _shaped_text_get_range, RID);
- virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
- virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
- virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
- GDVIRTUAL5RC(PackedInt32Array, shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, int64_t);
- GDVIRTUAL4RC(PackedInt32Array, shaped_text_get_line_breaks, RID, double, int64_t, int64_t);
- GDVIRTUAL2RC(PackedInt32Array, shaped_text_get_word_breaks, RID, int64_t);
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const override;
+ virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const override;
+ GDVIRTUAL5RC(PackedInt32Array, _shaped_text_get_line_breaks_adv, RID, const PackedFloat32Array &, int64_t, bool, BitField<TextServer::LineBreakFlag>);
+ GDVIRTUAL4RC(PackedInt32Array, _shaped_text_get_line_breaks, RID, double, int64_t, BitField<TextServer::LineBreakFlag>);
+ GDVIRTUAL2RC(PackedInt32Array, _shaped_text_get_word_breaks, RID, BitField<TextServer::GraphemeFlag>);
virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const override;
virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const override;
virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const override;
virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const override;
- GDVIRTUAL1RC(int64_t, shaped_text_get_trim_pos, RID);
- GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_pos, RID);
- GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, shaped_text_get_ellipsis_glyphs, RID);
- GDVIRTUAL1RC(int64_t, shaped_text_get_ellipsis_glyph_count, RID);
+ GDVIRTUAL1RC(int64_t, _shaped_text_get_trim_pos, RID);
+ GDVIRTUAL1RC(int64_t, _shaped_text_get_ellipsis_pos, RID);
+ GDVIRTUAL1RC(GDNativeConstPtr<const Glyph>, _shaped_text_get_ellipsis_glyphs, RID);
+ GDVIRTUAL1RC(int64_t, _shaped_text_get_ellipsis_glyph_count, RID);
- virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) override;
- GDVIRTUAL3(shaped_text_overrun_trim_to_width, RID, double, int64_t);
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) override;
+ GDVIRTUAL3(_shaped_text_overrun_trim_to_width, RID, double, BitField<TextServer::TextOverrunFlag>);
virtual Array shaped_text_get_objects(const RID &p_shaped) const override;
virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const override;
- GDVIRTUAL1RC(Array, shaped_text_get_objects, RID);
- GDVIRTUAL2RC(Rect2, shaped_text_get_object_rect, RID, const Variant &);
+ GDVIRTUAL1RC(Array, _shaped_text_get_objects, RID);
+ GDVIRTUAL2RC(Rect2, _shaped_text_get_object_rect, RID, const Variant &);
virtual Size2 shaped_text_get_size(const RID &p_shaped) const override;
virtual double shaped_text_get_ascent(const RID &p_shaped) const override;
@@ -443,58 +453,66 @@ public:
virtual double shaped_text_get_width(const RID &p_shaped) const override;
virtual double shaped_text_get_underline_position(const RID &p_shaped) const override;
virtual double shaped_text_get_underline_thickness(const RID &p_shaped) const override;
- GDVIRTUAL1RC(Size2, shaped_text_get_size, RID);
- GDVIRTUAL1RC(double, shaped_text_get_ascent, RID);
- GDVIRTUAL1RC(double, shaped_text_get_descent, RID);
- GDVIRTUAL1RC(double, shaped_text_get_width, RID);
- GDVIRTUAL1RC(double, shaped_text_get_underline_position, RID);
- GDVIRTUAL1RC(double, shaped_text_get_underline_thickness, RID);
+ GDVIRTUAL1RC(Size2, _shaped_text_get_size, RID);
+ GDVIRTUAL1RC(double, _shaped_text_get_ascent, RID);
+ GDVIRTUAL1RC(double, _shaped_text_get_descent, RID);
+ GDVIRTUAL1RC(double, _shaped_text_get_width, RID);
+ GDVIRTUAL1RC(double, _shaped_text_get_underline_position, RID);
+ GDVIRTUAL1RC(double, _shaped_text_get_underline_thickness, RID);
virtual Direction shaped_text_get_dominant_direction_in_range(const RID &p_shaped, int64_t p_start, int64_t p_end) const override;
- GDVIRTUAL3RC(int64_t, shaped_text_get_dominant_direction_in_range, RID, int64_t, int64_t);
+ GDVIRTUAL3RC(int64_t, _shaped_text_get_dominant_direction_in_range, RID, int64_t, int64_t);
virtual CaretInfo shaped_text_get_carets(const RID &p_shaped, int64_t p_position) const override;
virtual Vector<Vector2> shaped_text_get_selection(const RID &p_shaped, int64_t p_start, int64_t p_end) const override;
- GDVIRTUAL3C(shaped_text_get_carets, RID, int64_t, GDNativePtr<CaretInfo>);
- GDVIRTUAL3RC(Vector<Vector2>, shaped_text_get_selection, RID, int64_t, int64_t);
+ GDVIRTUAL3C(_shaped_text_get_carets, RID, int64_t, GDNativePtr<CaretInfo>);
+ GDVIRTUAL3RC(Vector<Vector2>, _shaped_text_get_selection, RID, int64_t, int64_t);
virtual int64_t shaped_text_hit_test_grapheme(const RID &p_shaped, double p_coords) const override;
virtual int64_t shaped_text_hit_test_position(const RID &p_shaped, double p_coords) const override;
- GDVIRTUAL2RC(int64_t, shaped_text_hit_test_grapheme, RID, double);
- GDVIRTUAL2RC(int64_t, shaped_text_hit_test_position, RID, double);
+ GDVIRTUAL2RC(int64_t, _shaped_text_hit_test_grapheme, RID, double);
+ GDVIRTUAL2RC(int64_t, _shaped_text_hit_test_position, RID, double);
virtual void shaped_text_draw(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, const Color &p_color = Color(1, 1, 1)) const override;
virtual void shaped_text_draw_outline(const RID &p_shaped, const RID &p_canvas, const Vector2 &p_pos, double p_clip_l = -1.0, double p_clip_r = -1.0, int64_t p_outline_size = 1, const Color &p_color = Color(1, 1, 1)) const override;
- GDVIRTUAL6C(shaped_text_draw, RID, RID, const Vector2 &, double, double, const Color &);
- GDVIRTUAL7C(shaped_text_draw_outline, RID, RID, const Vector2 &, double, double, int64_t, const Color &);
+ GDVIRTUAL6C(_shaped_text_draw, RID, RID, const Vector2 &, double, double, const Color &);
+ GDVIRTUAL7C(_shaped_text_draw_outline, RID, RID, const Vector2 &, double, double, int64_t, const Color &);
virtual Vector2 shaped_text_get_grapheme_bounds(const RID &p_shaped, int64_t p_pos) const override;
virtual int64_t shaped_text_next_grapheme_pos(const RID &p_shaped, int64_t p_pos) const override;
virtual int64_t shaped_text_prev_grapheme_pos(const RID &p_shaped, int64_t p_pos) const override;
- GDVIRTUAL2RC(Vector2, shaped_text_get_grapheme_bounds, RID, int64_t);
- GDVIRTUAL2RC(int64_t, shaped_text_next_grapheme_pos, RID, int64_t);
- GDVIRTUAL2RC(int64_t, shaped_text_prev_grapheme_pos, RID, int64_t);
+ GDVIRTUAL2RC(Vector2, _shaped_text_get_grapheme_bounds, RID, int64_t);
+ GDVIRTUAL2RC(int64_t, _shaped_text_next_grapheme_pos, RID, int64_t);
+ GDVIRTUAL2RC(int64_t, _shaped_text_prev_grapheme_pos, RID, int64_t);
virtual String format_number(const String &p_string, const String &p_language = "") const override;
virtual String parse_number(const String &p_string, const String &p_language = "") const override;
virtual String percent_sign(const String &p_language = "") const override;
- GDVIRTUAL2RC(String, format_number, const String &, const String &);
- GDVIRTUAL2RC(String, parse_number, const String &, const String &);
- GDVIRTUAL1RC(String, percent_sign, const String &);
+ GDVIRTUAL2RC(String, _format_number, const String &, const String &);
+ GDVIRTUAL2RC(String, _parse_number, const String &, const String &);
+ GDVIRTUAL1RC(String, _percent_sign, const String &);
virtual String strip_diacritics(const String &p_string) const override;
- GDVIRTUAL1RC(String, strip_diacritics, const String &);
+ GDVIRTUAL1RC(String, _strip_diacritics, const String &);
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const override;
- GDVIRTUAL2RC(PackedInt32Array, string_get_word_breaks, const String &, const String &);
+ GDVIRTUAL2RC(PackedInt32Array, _string_get_word_breaks, const String &, const String &);
+
+ virtual bool is_valid_identifier(const String &p_string) const override;
+ GDVIRTUAL1RC(bool, _is_valid_identifier, const String &);
virtual String string_to_upper(const String &p_string, const String &p_language = "") const override;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const override;
- GDVIRTUAL2RC(String, string_to_upper, const String &, const String &);
- GDVIRTUAL2RC(String, string_to_lower, const String &, const String &);
+ GDVIRTUAL2RC(String, _string_to_upper, const String &, const String &);
+ GDVIRTUAL2RC(String, _string_to_lower, const String &, const String &);
+
+ TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ GDVIRTUAL3RC(TypedArray<Vector2i>, _parse_structured_text, StructuredTextParser, const Array &, const String &);
- Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
- GDVIRTUAL3RC(Array, parse_structured_text, StructuredTextParser, const Array &, const String &);
+ virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const override;
+ virtual bool spoof_check(const String &p_string) const override;
+ GDVIRTUAL2RC(int64_t, _is_confusable, const String &, const PackedStringArray &);
+ GDVIRTUAL1RC(bool, _spoof_check, const String &);
TextServerExtension();
~TextServerExtension();
diff --git a/servers/text_server.cpp b/servers/text_server.cpp
index 20e62037e6..dfeb5cb70c 100644
--- a/servers/text_server.cpp
+++ b/servers/text_server.cpp
@@ -29,6 +29,7 @@
/*************************************************************************/
#include "servers/text_server.h"
+#include "core/variant/typed_array.h"
#include "servers/rendering_server.h"
TextServerManager *TextServerManager::singleton = nullptr;
@@ -103,8 +104,8 @@ Ref<TextServer> TextServerManager::find_interface(const String &p_name) const {
return interfaces[idx];
}
-Array TextServerManager::get_interfaces() const {
- Array ret;
+TypedArray<Dictionary> TextServerManager::get_interfaces() const {
+ TypedArray<Dictionary> ret;
for (int i = 0; i < interfaces.size(); i++) {
Dictionary iface_info;
@@ -208,6 +209,11 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_data", "font_rid", "data"), &TextServer::font_set_data);
+ ClassDB::bind_method(D_METHOD("font_set_face_index", "font_rid", "face_index"), &TextServer::font_set_face_index);
+ ClassDB::bind_method(D_METHOD("font_get_face_index", "font_rid"), &TextServer::font_get_face_index);
+
+ ClassDB::bind_method(D_METHOD("font_get_face_count", "font_rid"), &TextServer::font_get_face_count);
+
ClassDB::bind_method(D_METHOD("font_set_style", "font_rid", "style"), &TextServer::font_set_style);
ClassDB::bind_method(D_METHOD("font_get_style", "font_rid"), &TextServer::font_get_style);
@@ -217,8 +223,8 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name);
ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name);
- ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased);
- ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased);
+ ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing);
+ ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing);
ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps);
ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps);
@@ -275,9 +281,6 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("font_set_scale", "font_rid", "size", "scale"), &TextServer::font_set_scale);
ClassDB::bind_method(D_METHOD("font_get_scale", "font_rid", "size"), &TextServer::font_get_scale);
- ClassDB::bind_method(D_METHOD("font_set_spacing", "font_rid", "size", "spacing", "value"), &TextServer::font_set_spacing);
- ClassDB::bind_method(D_METHOD("font_get_spacing", "font_rid", "size", "spacing"), &TextServer::font_get_spacing);
-
ClassDB::bind_method(D_METHOD("font_get_texture_count", "font_rid", "size"), &TextServer::font_get_texture_count);
ClassDB::bind_method(D_METHOD("font_clear_textures", "font_rid", "size"), &TextServer::font_clear_textures);
ClassDB::bind_method(D_METHOD("font_remove_texture", "font_rid", "size", "texture_index"), &TextServer::font_remove_texture);
@@ -378,6 +381,9 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_set_preserve_control", "shaped", "enabled"), &TextServer::shaped_text_set_preserve_control);
ClassDB::bind_method(D_METHOD("shaped_text_get_preserve_control", "shaped"), &TextServer::shaped_text_get_preserve_control);
+ ClassDB::bind_method(D_METHOD("shaped_text_set_spacing", "shaped", "spacing", "value"), &TextServer::shaped_text_set_spacing);
+ ClassDB::bind_method(D_METHOD("shaped_text_get_spacing", "shaped", "spacing"), &TextServer::shaped_text_get_spacing);
+
ClassDB::bind_method(D_METHOD("shaped_text_add_string", "shaped", "text", "fonts", "size", "opentype_features", "language", "meta"), &TextServer::shaped_text_add_string, DEFVAL(Dictionary()), DEFVAL(""), DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("shaped_text_add_object", "shaped", "key", "size", "inline_align", "length"), &TextServer::shaped_text_add_object, DEFVAL(INLINE_ALIGNMENT_CENTER), DEFVAL(1));
ClassDB::bind_method(D_METHOD("shaped_text_resize_object", "shaped", "key", "size", "inline_align"), &TextServer::shaped_text_resize_object, DEFVAL(INLINE_ALIGNMENT_CENTER));
@@ -408,7 +414,7 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_glyphs", "shaped"), &TextServer::_shaped_text_get_ellipsis_glyphs_wrapper);
ClassDB::bind_method(D_METHOD("shaped_text_get_ellipsis_glyph_count", "shaped"), &TextServer::shaped_text_get_ellipsis_glyph_count);
- ClassDB::bind_method(D_METHOD("shaped_text_overrun_trim_to_width", "shaped", "width", "overrun_trim_flags"), &TextServer::shaped_text_overrun_trim_to_width, DEFVAL(0), DEFVAL(OVERRUN_NO_TRIMMING));
+ ClassDB::bind_method(D_METHOD("shaped_text_overrun_trim_to_width", "shaped", "width", "overrun_trim_flags"), &TextServer::shaped_text_overrun_trim_to_width, DEFVAL(0), DEFVAL(OVERRUN_NO_TRIM));
ClassDB::bind_method(D_METHOD("shaped_text_get_objects", "shaped"), &TextServer::shaped_text_get_objects);
ClassDB::bind_method(D_METHOD("shaped_text_get_object_rect", "shaped", "key"), &TextServer::shaped_text_get_object_rect);
@@ -441,13 +447,29 @@ void TextServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("string_get_word_breaks", "string", "language"), &TextServer::string_get_word_breaks, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("is_confusable", "string", "dict"), &TextServer::is_confusable);
+ ClassDB::bind_method(D_METHOD("spoof_check", "string"), &TextServer::spoof_check);
+
ClassDB::bind_method(D_METHOD("strip_diacritics", "string"), &TextServer::strip_diacritics);
+ ClassDB::bind_method(D_METHOD("is_valid_identifier", "string"), &TextServer::is_valid_identifier);
ClassDB::bind_method(D_METHOD("string_to_upper", "string", "language"), &TextServer::string_to_upper, DEFVAL(""));
ClassDB::bind_method(D_METHOD("string_to_lower", "string", "language"), &TextServer::string_to_lower, DEFVAL(""));
ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text);
+ /* Font AA */
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_NONE);
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_GRAY);
+ BIND_ENUM_CONSTANT(FONT_ANTIALIASING_LCD);
+
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_NONE);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HRGB);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HBGR);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VRGB);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VBGR);
+ BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_MAX);
+
/* Direction */
BIND_ENUM_CONSTANT(DIRECTION_AUTO);
BIND_ENUM_CONSTANT(DIRECTION_LTR);
@@ -458,40 +480,62 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(ORIENTATION_VERTICAL);
/* JustificationFlag */
- BIND_ENUM_CONSTANT(JUSTIFICATION_NONE);
- BIND_ENUM_CONSTANT(JUSTIFICATION_KASHIDA);
- BIND_ENUM_CONSTANT(JUSTIFICATION_WORD_BOUND);
- BIND_ENUM_CONSTANT(JUSTIFICATION_TRIM_EDGE_SPACES);
- BIND_ENUM_CONSTANT(JUSTIFICATION_AFTER_LAST_TAB);
- BIND_ENUM_CONSTANT(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_NONE);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_KASHIDA);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_WORD_BOUND);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_TRIM_EDGE_SPACES);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_AFTER_LAST_TAB);
+ BIND_BITFIELD_FLAG(JUSTIFICATION_CONSTRAIN_ELLIPSIS);
+
+ /* AutowrapMode */
+ BIND_ENUM_CONSTANT(AUTOWRAP_OFF);
+ BIND_ENUM_CONSTANT(AUTOWRAP_ARBITRARY);
+ BIND_ENUM_CONSTANT(AUTOWRAP_WORD);
+ BIND_ENUM_CONSTANT(AUTOWRAP_WORD_SMART);
/* LineBreakFlag */
- BIND_ENUM_CONSTANT(BREAK_NONE);
- BIND_ENUM_CONSTANT(BREAK_MANDATORY);
- BIND_ENUM_CONSTANT(BREAK_WORD_BOUND);
- BIND_ENUM_CONSTANT(BREAK_GRAPHEME_BOUND);
- BIND_ENUM_CONSTANT(BREAK_WORD_BOUND_ADAPTIVE);
+ BIND_BITFIELD_FLAG(BREAK_NONE);
+ BIND_BITFIELD_FLAG(BREAK_MANDATORY);
+ BIND_BITFIELD_FLAG(BREAK_WORD_BOUND);
+ BIND_BITFIELD_FLAG(BREAK_GRAPHEME_BOUND);
+ BIND_BITFIELD_FLAG(BREAK_ADAPTIVE);
+ BIND_BITFIELD_FLAG(BREAK_TRIM_EDGE_SPACES);
+
+ /* VisibleCharactersBehavior */
+ BIND_ENUM_CONSTANT(VC_CHARS_BEFORE_SHAPING);
+ BIND_ENUM_CONSTANT(VC_CHARS_AFTER_SHAPING);
+ BIND_ENUM_CONSTANT(VC_GLYPHS_AUTO);
+ BIND_ENUM_CONSTANT(VC_GLYPHS_LTR);
+ BIND_ENUM_CONSTANT(VC_GLYPHS_RTL);
+
+ /* OverrunBehavior */
+ BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_CHAR);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_ELLIPSIS);
+ BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ELLIPSIS);
/* TextOverrunFlag */
- BIND_ENUM_CONSTANT(OVERRUN_NO_TRIMMING);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM);
- BIND_ENUM_CONSTANT(OVERRUN_TRIM_WORD_ONLY);
- BIND_ENUM_CONSTANT(OVERRUN_ADD_ELLIPSIS);
- BIND_ENUM_CONSTANT(OVERRUN_ENFORCE_ELLIPSIS);
- BIND_ENUM_CONSTANT(OVERRUN_JUSTIFICATION_AWARE);
+ BIND_BITFIELD_FLAG(OVERRUN_NO_TRIM);
+ BIND_BITFIELD_FLAG(OVERRUN_TRIM);
+ BIND_BITFIELD_FLAG(OVERRUN_TRIM_WORD_ONLY);
+ BIND_BITFIELD_FLAG(OVERRUN_ADD_ELLIPSIS);
+ BIND_BITFIELD_FLAG(OVERRUN_ENFORCE_ELLIPSIS);
+ BIND_BITFIELD_FLAG(OVERRUN_JUSTIFICATION_AWARE);
/* GraphemeFlag */
- BIND_ENUM_CONSTANT(GRAPHEME_IS_VALID);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_RTL);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_VIRTUAL);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_SPACE);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_HARD);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_BREAK_SOFT);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_TAB);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_ELONGATION);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_PUNCTUATION);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_UNDERSCORE);
- BIND_ENUM_CONSTANT(GRAPHEME_IS_CONNECTED);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_VALID);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_RTL);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_VIRTUAL);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_SPACE);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_HARD);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_BREAK_SOFT);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_TAB);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_ELONGATION);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_PUNCTUATION);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_UNDERSCORE);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_CONNECTED);
+ BIND_BITFIELD_FLAG(GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL);
/* Hinting */
BIND_ENUM_CONSTANT(HINTING_NONE);
@@ -520,6 +564,8 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(FEATURE_FONT_VARIABLE);
BIND_ENUM_CONSTANT(FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION);
BIND_ENUM_CONSTANT(FEATURE_USE_SUPPORT_DATA);
+ BIND_ENUM_CONSTANT(FEATURE_UNICODE_IDENTIFIERS);
+ BIND_ENUM_CONSTANT(FEATURE_UNICODE_SECURITY);
/* FT Contour Point Types */
BIND_ENUM_CONSTANT(CONTOUR_CURVE_TAG_ON);
@@ -531,11 +577,12 @@ void TextServer::_bind_methods() {
BIND_ENUM_CONSTANT(SPACING_SPACE);
BIND_ENUM_CONSTANT(SPACING_TOP);
BIND_ENUM_CONSTANT(SPACING_BOTTOM);
+ BIND_ENUM_CONSTANT(SPACING_MAX);
/* Font Style */
- BIND_ENUM_CONSTANT(FONT_BOLD);
- BIND_ENUM_CONSTANT(FONT_ITALIC);
- BIND_ENUM_CONSTANT(FONT_FIXED_WIDTH);
+ BIND_BITFIELD_FLAG(FONT_BOLD);
+ BIND_BITFIELD_FLAG(FONT_ITALIC);
+ BIND_BITFIELD_FLAG(FONT_FIXED_WIDTH);
/* Structured text parser */
BIND_ENUM_CONSTANT(STRUCTURED_TEXT_DEFAULT);
@@ -625,7 +672,7 @@ void TextServer::draw_hex_code_box(const RID &p_canvas, int64_t p_size, const Ve
}
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, int64_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start, bool p_once, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array lines;
ERR_FAIL_COND_V(p_width.is_empty(), lines);
@@ -635,24 +682,44 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
real_t width = 0.f;
int line_start = MAX(p_start, range.x);
+ int prev_safe_break = 0;
int last_safe_break = -1;
+ int word_count = 0;
int chunk = 0;
+ bool trim_next = false;
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
+ prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
if ((p_width[chunk] > 0) && (width + l_gl[i].advance > p_width[chunk]) && (last_safe_break >= 0)) {
- lines.push_back(line_start);
- lines.push_back(l_gl[last_safe_break].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = last_safe_break;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ trim_next = true;
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
+ }
line_start = l_gl[last_safe_break].end;
+ prev_safe_break = last_safe_break + 1;
i = last_safe_break;
last_safe_break = -1;
width = 0;
+ word_count = 0;
chunk++;
if (chunk >= p_width.size()) {
chunk = 0;
@@ -662,11 +729,26 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
}
continue;
}
- if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
+ if (p_break_flags.has_flag(BREAK_MANDATORY)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(line_start);
- lines.push_back(l_gl[i].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = i;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ trim_next = false;
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
+ }
line_start = l_gl[i].end;
+ prev_safe_break = i + 1;
last_safe_break = -1;
width = 0;
chunk = 0;
@@ -676,12 +758,13 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
continue;
}
}
- if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) {
+ if (p_break_flags.has_flag(BREAK_WORD_BOUND)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_safe_break = i;
+ word_count++;
}
}
- if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) {
+ if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND) && word_count == 0) {
last_safe_break = i;
}
}
@@ -689,8 +772,17 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
}
if (l_size > 0) {
- if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
- lines.push_back(line_start);
+ if (lines.size() == 0 || (lines[lines.size() - 1] < range.y && prev_safe_break < l_size)) {
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1;
+ int end_pos = l_size - 1;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ } else {
+ lines.push_back(line_start);
+ }
lines.push_back(range.y);
}
} else {
@@ -701,7 +793,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks_adv(const RID &p_shaped
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, int64_t /*TextBreakFlag*/ p_break_flags) const {
+PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start, BitField<TextServer::LineBreakFlag> p_break_flags) const {
PackedInt32Array lines;
const_cast<TextServer *>(this)->shaped_text_update_breaks(p_shaped);
@@ -709,47 +801,80 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
double width = 0.f;
int line_start = MAX(p_start, range.x);
+ int prev_safe_break = 0;
int last_safe_break = -1;
int word_count = 0;
+ bool trim_next = false;
int l_size = shaped_text_get_glyph_count(p_shaped);
const Glyph *l_gl = const_cast<TextServer *>(this)->shaped_text_sort_logical(p_shaped);
for (int i = 0; i < l_size; i++) {
if (l_gl[i].start < p_start) {
+ prev_safe_break = i + 1;
continue;
}
if (l_gl[i].count > 0) {
if ((p_width > 0) && (width + l_gl[i].advance * l_gl[i].repeat > p_width) && (last_safe_break >= 0)) {
- lines.push_back(line_start);
- lines.push_back(l_gl[last_safe_break].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = last_safe_break;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ trim_next = true;
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[last_safe_break].end);
+ }
line_start = l_gl[last_safe_break].end;
+ prev_safe_break = last_safe_break + 1;
i = last_safe_break;
last_safe_break = -1;
width = 0;
word_count = 0;
continue;
}
- if ((p_break_flags & BREAK_MANDATORY) == BREAK_MANDATORY) {
+ if (p_break_flags.has_flag(BREAK_MANDATORY)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD) {
- lines.push_back(line_start);
- lines.push_back(l_gl[i].end);
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = prev_safe_break;
+ int end_pos = i;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ while ((start_pos < end_pos) && ((l_gl[end_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[end_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ end_pos -= l_gl[end_pos].count;
+ }
+ trim_next = false;
+ lines.push_back(l_gl[start_pos].start);
+ lines.push_back(l_gl[end_pos].end);
+ } else {
+ lines.push_back(line_start);
+ lines.push_back(l_gl[i].end);
+ }
line_start = l_gl[i].end;
+ prev_safe_break = i + 1;
last_safe_break = -1;
width = 0;
continue;
}
}
- if ((p_break_flags & BREAK_WORD_BOUND) == BREAK_WORD_BOUND) {
+ if (p_break_flags.has_flag(BREAK_WORD_BOUND)) {
if ((l_gl[i].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT) {
last_safe_break = i;
word_count++;
}
+ if (p_break_flags.has_flag(BREAK_ADAPTIVE) && word_count == 0) {
+ last_safe_break = i;
+ }
}
- if (((p_break_flags & BREAK_WORD_BOUND_ADAPTIVE) == BREAK_WORD_BOUND_ADAPTIVE) && word_count == 0) {
- last_safe_break = i;
- }
- if ((p_break_flags & BREAK_GRAPHEME_BOUND) == BREAK_GRAPHEME_BOUND) {
+ if (p_break_flags.has_flag(BREAK_GRAPHEME_BOUND)) {
last_safe_break = i;
}
}
@@ -757,8 +882,17 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
}
if (l_size > 0) {
- if (lines.size() == 0 || lines[lines.size() - 1] < range.y) {
- lines.push_back(line_start);
+ if (lines.size() == 0 || (lines[lines.size() - 1] < range.y && prev_safe_break < l_size)) {
+ if (p_break_flags.has_flag(BREAK_TRIM_EDGE_SPACES)) {
+ int start_pos = (prev_safe_break < l_size) ? prev_safe_break : l_size - 1;
+ int end_pos = l_size - 1;
+ while (trim_next && (start_pos < end_pos) && ((l_gl[start_pos].flags & GRAPHEME_IS_SPACE) == GRAPHEME_IS_SPACE || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_HARD) == GRAPHEME_IS_BREAK_HARD || (l_gl[start_pos].flags & GRAPHEME_IS_BREAK_SOFT) == GRAPHEME_IS_BREAK_SOFT)) {
+ start_pos += l_gl[start_pos].count;
+ }
+ lines.push_back(l_gl[start_pos].start);
+ } else {
+ lines.push_back(line_start);
+ }
lines.push_back(range.y);
}
} else {
@@ -769,7 +903,7 @@ PackedInt32Array TextServer::shaped_text_get_line_breaks(const RID &p_shaped, do
return lines;
}
-PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags) const {
+PackedInt32Array TextServer::shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags) const {
PackedInt32Array words;
const_cast<TextServer *>(this)->shaped_text_update_justification_ops(p_shaped);
@@ -822,6 +956,11 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
if (glyphs[i].count > 0) {
// Caret before grapheme (top / left).
if (p_position == glyphs[i].start && ((glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL)) {
+ real_t advance = 0.f;
+ for (int j = 0; j < glyphs[i].count; j++) {
+ advance += glyphs[i + j].advance * glyphs[i + j].repeat;
+ }
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
Rect2 cr;
if (orientation == ORIENTATION_HORIZONTAL) {
if (glyphs[i].start == range.x) {
@@ -833,15 +972,11 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
caret.t_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.x += advance;
+ cr.size.x = -char_adv;
} else {
caret.t_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.size.x = char_adv;
}
} else {
if (glyphs[i].start == range.x) {
@@ -853,21 +988,22 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
caret.t_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.y += advance;
+ cr.size.y = -char_adv;
} else {
caret.t_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.size.y = char_adv;
}
}
caret.t_caret = cr;
}
// Caret after grapheme (bottom / right).
if (p_position == glyphs[i].end && ((glyphs[i].flags & GRAPHEME_IS_VIRTUAL) != GRAPHEME_IS_VIRTUAL)) {
+ real_t advance = 0.f;
+ for (int j = 0; j < glyphs[i].count; j++) {
+ advance += glyphs[i + j].advance * glyphs[i + j].repeat;
+ }
+ real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
Rect2 cr;
if (orientation == ORIENTATION_HORIZONTAL) {
if (glyphs[i].end == range.y) {
@@ -880,15 +1016,11 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.x = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
caret.l_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.x -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.x += advance;
+ cr.size.x = -char_adv;
} else {
caret.l_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.x += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.size.x = char_adv;
}
} else {
cr.size.y = 1.0f;
@@ -902,15 +1034,12 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
cr.position.y = off;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) != GRAPHEME_IS_RTL) {
caret.l_dir = DIRECTION_LTR;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.position.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- cr.size.y -= glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.y += advance;
+ cr.size.y = -char_adv;
} else {
caret.l_dir = DIRECTION_RTL;
- for (int j = 0; j < glyphs[i].count; j++) {
- cr.size.y += glyphs[i + j].advance * glyphs[i + j].repeat;
- }
+ cr.position.x += advance;
+ cr.size.y = char_adv;
}
}
caret.l_caret = cr;
@@ -924,22 +1053,24 @@ CaretInfo TextServer::shaped_text_get_carets(const RID &p_shaped, int64_t p_posi
real_t char_adv = advance / (real_t)(glyphs[i].end - glyphs[i].start);
Rect2 cr;
if (orientation == ORIENTATION_HORIZONTAL) {
- cr.size.x = 1.0f;
cr.size.y = height * 2;
cr.position.y = -ascent;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
cr.position.x = off + char_adv * (glyphs[i].end - p_position);
+ cr.size.x = -char_adv;
} else {
cr.position.x = off + char_adv * (p_position - glyphs[i].start);
+ cr.size.x = char_adv;
}
} else {
- cr.size.y = 1.0f;
cr.size.x = height * 2;
cr.position.x = -ascent;
if ((glyphs[i].flags & GRAPHEME_IS_RTL) == GRAPHEME_IS_RTL) {
cr.position.y = off + char_adv * (glyphs[i].end - p_position);
+ cr.size.y = -char_adv;
} else {
cr.position.y = off + char_adv * (p_position - glyphs[i].start);
+ cr.size.y = char_adv;
}
}
caret.t_caret = cr;
@@ -1552,8 +1683,8 @@ String TextServer::strip_diacritics(const String &p_string) const {
return result;
}
-Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
- Array ret;
+TypedArray<Vector2i> TextServer::parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const {
+ TypedArray<Vector2i> ret;
switch (p_parser_type) {
case STRUCTURED_TEXT_URI: {
int prev = 0;
@@ -1594,7 +1725,7 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
ret.push_back(Vector2i(prev, i));
ret.push_back(Vector2i(i, i + 1));
prev = i + 1;
- } else if (!local & (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
+ } else if (!local && (p_text[i] == '.')) { // Add each dot separated "domain" part as context.
if (prev != i) {
ret.push_back(Vector2i(prev, i));
}
@@ -1629,8 +1760,8 @@ Array TextServer::parse_structured_text(StructuredTextParser p_parser_type, cons
return ret;
}
-Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
- Array ret;
+TypedArray<Dictionary> TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
+ TypedArray<Dictionary> ret;
const Glyph *glyphs = shaped_text_get_glyphs(p_shaped);
int gl_size = shaped_text_get_glyph_count(p_shaped);
@@ -1654,7 +1785,7 @@ Array TextServer::_shaped_text_get_glyphs_wrapper(const RID &p_shaped) const {
return ret;
}
-Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
+TypedArray<Dictionary> TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
Array ret;
const Glyph *glyphs = shaped_text_sort_logical(p_shaped);
@@ -1679,8 +1810,8 @@ Array TextServer::_shaped_text_sort_logical_wrapper(const RID &p_shaped) {
return ret;
}
-Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const {
- Array ret;
+TypedArray<Dictionary> TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const {
+ TypedArray<Dictionary> ret;
const Glyph *glyphs = shaped_text_get_ellipsis_glyphs(p_shaped);
int gl_size = shaped_text_get_ellipsis_glyph_count(p_shaped);
@@ -1704,6 +1835,26 @@ Array TextServer::_shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped)
return ret;
}
+bool TextServer::is_valid_identifier(const String &p_string) const {
+ const char32_t *str = p_string.ptr();
+ int len = p_string.length();
+
+ if (len == 0) {
+ return false; // Empty string.
+ }
+
+ if (!is_unicode_identifier_start(str[0])) {
+ return false;
+ }
+
+ for (int i = 1; i < len; i++) {
+ if (!is_unicode_identifier_continue(str[i])) {
+ return false;
+ }
+ }
+ return true;
+}
+
TextServer::TextServer() {
_init_diacritics_map();
}
diff --git a/servers/text_server.h b/servers/text_server.h
index f96146a549..a4e6080fd0 100644
--- a/servers/text_server.h
+++ b/servers/text_server.h
@@ -37,6 +37,9 @@
#include "core/variant/native_ptr.h"
#include "core/variant/variant.h"
+template <typename T>
+class TypedArray;
+
struct Glyph;
struct CaretInfo;
@@ -44,6 +47,21 @@ class TextServer : public RefCounted {
GDCLASS(TextServer, RefCounted);
public:
+ enum FontAntialiasing {
+ FONT_ANTIALIASING_NONE,
+ FONT_ANTIALIASING_GRAY,
+ FONT_ANTIALIASING_LCD,
+ };
+
+ enum FontLCDSubpixelLayout {
+ FONT_LCD_SUBPIXEL_LAYOUT_NONE,
+ FONT_LCD_SUBPIXEL_LAYOUT_HRGB,
+ FONT_LCD_SUBPIXEL_LAYOUT_HBGR,
+ FONT_LCD_SUBPIXEL_LAYOUT_VRGB,
+ FONT_LCD_SUBPIXEL_LAYOUT_VBGR,
+ FONT_LCD_SUBPIXEL_LAYOUT_MAX,
+ };
+
enum Direction {
DIRECTION_AUTO,
DIRECTION_LTR,
@@ -64,16 +82,40 @@ public:
JUSTIFICATION_CONSTRAIN_ELLIPSIS = 1 << 4,
};
- enum LineBreakFlag { // LineBreakFlag can be passed in the same value as the JustificationFlag, do not use the same values.
+ enum VisibleCharactersBehavior {
+ VC_CHARS_BEFORE_SHAPING,
+ VC_CHARS_AFTER_SHAPING,
+ VC_GLYPHS_AUTO,
+ VC_GLYPHS_LTR,
+ VC_GLYPHS_RTL,
+ };
+
+ enum AutowrapMode {
+ AUTOWRAP_OFF,
+ AUTOWRAP_ARBITRARY,
+ AUTOWRAP_WORD,
+ AUTOWRAP_WORD_SMART
+ };
+
+ enum LineBreakFlag {
BREAK_NONE = 0,
- BREAK_MANDATORY = 1 << 5,
- BREAK_WORD_BOUND = 1 << 6,
- BREAK_GRAPHEME_BOUND = 1 << 7,
- BREAK_WORD_BOUND_ADAPTIVE = 1 << 6 | 1 << 8,
+ BREAK_MANDATORY = 1 << 0,
+ BREAK_WORD_BOUND = 1 << 1,
+ BREAK_GRAPHEME_BOUND = 1 << 2,
+ BREAK_ADAPTIVE = 1 << 3,
+ BREAK_TRIM_EDGE_SPACES = 1 << 4,
+ };
+
+ enum OverrunBehavior {
+ OVERRUN_NO_TRIMMING,
+ OVERRUN_TRIM_CHAR,
+ OVERRUN_TRIM_WORD,
+ OVERRUN_TRIM_ELLIPSIS,
+ OVERRUN_TRIM_WORD_ELLIPSIS,
};
enum TextOverrunFlag {
- OVERRUN_NO_TRIMMING = 0,
+ OVERRUN_NO_TRIM = 0,
OVERRUN_TRIM = 1 << 0,
OVERRUN_TRIM_WORD_ONLY = 1 << 1,
OVERRUN_ADD_ELLIPSIS = 1 << 2,
@@ -93,6 +135,7 @@ public:
GRAPHEME_IS_PUNCTUATION = 1 << 8, // Punctuation, except underscore (can be used as word break, but not line break or justifiction).
GRAPHEME_IS_UNDERSCORE = 1 << 9, // Underscore (can be used as word break).
GRAPHEME_IS_CONNECTED = 1 << 10, // Connected to previous grapheme.
+ GRAPHEME_IS_SAFE_TO_INSERT_TATWEEL = 1 << 11, // It is safe to insert a U+0640 before this grapheme for elongation.
};
enum Hinting {
@@ -125,6 +168,8 @@ public:
FEATURE_FONT_VARIABLE = 1 << 10,
FEATURE_CONTEXT_SENSITIVE_CASE_CONVERSION = 1 << 11,
FEATURE_USE_SUPPORT_DATA = 1 << 12,
+ FEATURE_UNICODE_IDENTIFIERS = 1 << 13,
+ FEATURE_UNICODE_SECURITY = 1 << 14,
};
enum ContourPointTag {
@@ -138,6 +183,7 @@ public:
SPACING_SPACE,
SPACING_TOP,
SPACING_BOTTOM,
+ SPACING_MAX,
};
enum FontStyle {
@@ -184,13 +230,19 @@ public:
virtual String tag_to_name(int64_t p_tag) const { return ""; };
/* Font interface */
+
virtual RID create_font() = 0;
virtual void font_set_data(const RID &p_font_rid, const PackedByteArray &p_data) = 0;
virtual void font_set_data_ptr(const RID &p_font_rid, const uint8_t *p_data_ptr, int64_t p_data_size) = 0;
- virtual void font_set_style(const RID &p_font_rid, int64_t /*FontStyle*/ p_style) = 0;
- virtual int64_t /*FontStyle*/ font_get_style(const RID &p_font_rid) const = 0;
+ virtual void font_set_face_index(const RID &p_font_rid, int64_t p_index) = 0;
+ virtual int64_t font_get_face_index(const RID &p_font_rid) const = 0;
+
+ virtual int64_t font_get_face_count(const RID &p_font_rid) const = 0;
+
+ virtual void font_set_style(const RID &p_font_rid, BitField<FontStyle> p_style) = 0;
+ virtual BitField<FontStyle> font_get_style(const RID &p_font_rid) const = 0;
virtual void font_set_name(const RID &p_font_rid, const String &p_name) = 0;
virtual String font_get_name(const RID &p_font_rid) const = 0;
@@ -198,8 +250,8 @@ public:
virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0;
virtual String font_get_style_name(const RID &p_font_rid) const = 0;
- virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0;
- virtual bool font_is_antialiased(const RID &p_font_rid) const = 0;
+ virtual void font_set_antialiasing(const RID &p_font_rid, FontAntialiasing p_antialiasing) = 0;
+ virtual FontAntialiasing font_get_antialiasing(const RID &p_font_rid) const = 0;
virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0;
virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0;
@@ -237,7 +289,7 @@ public:
virtual void font_set_oversampling(const RID &p_font_rid, double p_oversampling) = 0;
virtual double font_get_oversampling(const RID &p_font_rid) const = 0;
- virtual Array font_get_size_cache_list(const RID &p_font_rid) const = 0;
+ virtual TypedArray<Vector2i> font_get_size_cache_list(const RID &p_font_rid) const = 0;
virtual void font_clear_size_cache(const RID &p_font_rid) = 0;
virtual void font_remove_size_cache(const RID &p_font_rid, const Vector2i &p_size) = 0;
@@ -256,9 +308,6 @@ public:
virtual void font_set_scale(const RID &p_font_rid, int64_t p_size, double p_scale) = 0;
virtual double font_get_scale(const RID &p_font_rid, int64_t p_size) const = 0;
- virtual void font_set_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing, int64_t p_value) = 0;
- virtual int64_t font_get_spacing(const RID &p_font_rid, int64_t p_size, SpacingType p_spacing) const = 0;
-
virtual int64_t font_get_texture_count(const RID &p_font_rid, const Vector2i &p_size) const = 0;
virtual void font_clear_textures(const RID &p_font_rid, const Vector2i &p_size) = 0;
virtual void font_remove_texture(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) = 0;
@@ -269,7 +318,7 @@ public:
virtual void font_set_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index, const PackedInt32Array &p_offset) = 0;
virtual PackedInt32Array font_get_texture_offsets(const RID &p_font_rid, const Vector2i &p_size, int64_t p_texture_index) const = 0;
- virtual Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const = 0;
+ virtual PackedInt32Array font_get_glyph_list(const RID &p_font_rid, const Vector2i &p_size) const = 0;
virtual void font_clear_glyphs(const RID &p_font_rid, const Vector2i &p_size) = 0;
virtual void font_remove_glyph(const RID &p_font_rid, const Vector2i &p_size, int64_t p_glyph) = 0;
@@ -292,7 +341,7 @@ public:
virtual Dictionary font_get_glyph_contours(const RID &p_font, int64_t p_size, int64_t p_index) const = 0;
- virtual Array font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const = 0;
+ virtual TypedArray<Vector2i> font_get_kerning_list(const RID &p_font_rid, int64_t p_size) const = 0;
virtual void font_clear_kerning_map(const RID &p_font_rid, int64_t p_size) = 0;
virtual void font_remove_kerning(const RID &p_font_rid, int64_t p_size, const Vector2i &p_glyph_pair) = 0;
@@ -358,18 +407,21 @@ public:
virtual void shaped_text_set_preserve_control(const RID &p_shaped, bool p_enabled) = 0;
virtual bool shaped_text_get_preserve_control(const RID &p_shaped) const = 0;
- virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0;
+ virtual void shaped_text_set_spacing(const RID &p_shaped, SpacingType p_spacing, int64_t p_value) = 0;
+ virtual int64_t shaped_text_get_spacing(const RID &p_shaped, SpacingType p_spacing) const = 0;
+
+ virtual bool shaped_text_add_string(const RID &p_shaped, const String &p_text, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary(), const String &p_language = "", const Variant &p_meta = Variant()) = 0;
virtual bool shaped_text_add_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER, int64_t p_length = 1) = 0;
virtual bool shaped_text_resize_object(const RID &p_shaped, const Variant &p_key, const Size2 &p_size, InlineAlignment p_inline_align = INLINE_ALIGNMENT_CENTER) = 0;
virtual int64_t shaped_get_span_count(const RID &p_shaped) const = 0;
virtual Variant shaped_get_span_meta(const RID &p_shaped, int64_t p_index) const = 0;
- virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const Array &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) = 0;
+ virtual void shaped_set_span_update_font(const RID &p_shaped, int64_t p_index, const TypedArray<RID> &p_fonts, int64_t p_size, const Dictionary &p_opentype_features = Dictionary()) = 0;
virtual RID shaped_text_substr(const RID &p_shaped, int64_t p_start, int64_t p_length) const = 0; // Copy shaped substring (e.g. line break) without reshaping, but correctly reordered, preservers range.
virtual RID shaped_text_get_parent(const RID &p_shaped) const = 0;
- virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, int64_t /*JustificationFlag*/ p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
+ virtual double shaped_text_fit_to_width(const RID &p_shaped, double p_width, BitField<TextServer::JustificationFlag> p_jst_flags = JUSTIFICATION_WORD_BOUND | JUSTIFICATION_KASHIDA) = 0;
virtual double shaped_text_tab_align(const RID &p_shaped, const PackedFloat32Array &p_tab_stops) = 0;
virtual bool shaped_text_shape(const RID &p_shaped) = 0;
@@ -379,24 +431,24 @@ public:
virtual bool shaped_text_is_ready(const RID &p_shaped) const = 0;
virtual const Glyph *shaped_text_get_glyphs(const RID &p_shaped) const = 0;
- Array _shaped_text_get_glyphs_wrapper(const RID &p_shaped) const;
+ TypedArray<Dictionary> _shaped_text_get_glyphs_wrapper(const RID &p_shaped) const;
virtual const Glyph *shaped_text_sort_logical(const RID &p_shaped) = 0;
- Array _shaped_text_sort_logical_wrapper(const RID &p_shaped);
+ TypedArray<Dictionary> _shaped_text_sort_logical_wrapper(const RID &p_shaped);
virtual int64_t shaped_text_get_glyph_count(const RID &p_shaped) const = 0;
virtual Vector2i shaped_text_get_range(const RID &p_shaped) const = 0;
- virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, int64_t /*TextBreakFlag*/ p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
- virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, int64_t p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
+ virtual PackedInt32Array shaped_text_get_line_breaks_adv(const RID &p_shaped, const PackedFloat32Array &p_width, int64_t p_start = 0, bool p_once = true, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_line_breaks(const RID &p_shaped, double p_width, int64_t p_start = 0, BitField<TextServer::LineBreakFlag> p_break_flags = BREAK_MANDATORY | BREAK_WORD_BOUND) const;
+ virtual PackedInt32Array shaped_text_get_word_breaks(const RID &p_shaped, BitField<TextServer::GraphemeFlag> p_grapheme_flags = GRAPHEME_IS_SPACE | GRAPHEME_IS_PUNCTUATION) const;
virtual int64_t shaped_text_get_trim_pos(const RID &p_shaped) const = 0;
virtual int64_t shaped_text_get_ellipsis_pos(const RID &p_shaped) const = 0;
virtual const Glyph *shaped_text_get_ellipsis_glyphs(const RID &p_shaped) const = 0;
- Array _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const;
+ TypedArray<Dictionary> _shaped_text_get_ellipsis_glyphs_wrapper(const RID &p_shaped) const;
virtual int64_t shaped_text_get_ellipsis_glyph_count(const RID &p_shaped) const = 0;
- virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, int64_t p_trim_flags) = 0;
+ virtual void shaped_text_overrun_trim_to_width(const RID &p_shaped, double p_width, BitField<TextServer::TextOverrunFlag> p_trim_flags) = 0;
virtual Array shaped_text_get_objects(const RID &p_shaped) const = 0;
virtual Rect2 shaped_text_get_object_rect(const RID &p_shaped, const Variant &p_key) const = 0;
@@ -434,13 +486,17 @@ public:
// String functions.
virtual PackedInt32Array string_get_word_breaks(const String &p_string, const String &p_language = "") const = 0;
+ virtual int64_t is_confusable(const String &p_string, const PackedStringArray &p_dict) const { return -1; };
+ virtual bool spoof_check(const String &p_string) const { return false; };
+
virtual String strip_diacritics(const String &p_string) const;
+ virtual bool is_valid_identifier(const String &p_string) const;
// Other string operations.
virtual String string_to_upper(const String &p_string, const String &p_language = "") const = 0;
virtual String string_to_lower(const String &p_string, const String &p_language = "") const = 0;
- Array parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
+ TypedArray<Vector2i> parse_structured_text(StructuredTextParser p_parser_type, const Array &p_args, const String &p_text) const;
TextServer();
~TextServer();
@@ -502,7 +558,7 @@ public:
int get_interface_count() const;
Ref<TextServer> get_interface(int p_index) const;
Ref<TextServer> find_interface(const String &p_name) const;
- Array get_interfaces() const;
+ TypedArray<Dictionary> get_interfaces() const;
_FORCE_INLINE_ Ref<TextServer> get_primary_interface() const {
return primary_interface;
@@ -517,19 +573,24 @@ public:
#define TS TextServerManager::get_singleton()->get_primary_interface()
+VARIANT_ENUM_CAST(TextServer::VisibleCharactersBehavior);
+VARIANT_ENUM_CAST(TextServer::AutowrapMode);
+VARIANT_ENUM_CAST(TextServer::OverrunBehavior);
VARIANT_ENUM_CAST(TextServer::Direction);
VARIANT_ENUM_CAST(TextServer::Orientation);
-VARIANT_ENUM_CAST(TextServer::JustificationFlag);
-VARIANT_ENUM_CAST(TextServer::LineBreakFlag);
-VARIANT_ENUM_CAST(TextServer::TextOverrunFlag);
-VARIANT_ENUM_CAST(TextServer::GraphemeFlag);
+VARIANT_BITFIELD_CAST(TextServer::JustificationFlag);
+VARIANT_BITFIELD_CAST(TextServer::LineBreakFlag);
+VARIANT_BITFIELD_CAST(TextServer::TextOverrunFlag);
+VARIANT_BITFIELD_CAST(TextServer::GraphemeFlag);
VARIANT_ENUM_CAST(TextServer::Hinting);
VARIANT_ENUM_CAST(TextServer::SubpixelPositioning);
VARIANT_ENUM_CAST(TextServer::Feature);
VARIANT_ENUM_CAST(TextServer::ContourPointTag);
VARIANT_ENUM_CAST(TextServer::SpacingType);
-VARIANT_ENUM_CAST(TextServer::FontStyle);
+VARIANT_BITFIELD_CAST(TextServer::FontStyle);
VARIANT_ENUM_CAST(TextServer::StructuredTextParser);
+VARIANT_ENUM_CAST(TextServer::FontAntialiasing);
+VARIANT_ENUM_CAST(TextServer::FontLCDSubpixelLayout);
GDVIRTUAL_NATIVE_PTR(Glyph);
GDVIRTUAL_NATIVE_PTR(CaretInfo);
diff --git a/servers/xr/xr_interface.cpp b/servers/xr/xr_interface.cpp
index 7ae111b5e7..4d58d24405 100644
--- a/servers/xr/xr_interface.cpp
+++ b/servers/xr/xr_interface.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "xr_interface.h"
-// #include "servers/rendering/renderer_compositor.h"
+#include "servers/rendering/renderer_compositor.h"
void XRInterface::_bind_methods() {
ADD_SIGNAL(MethodInfo("play_area_changed", PropertyInfo(Variant::INT, "mode")));
@@ -68,6 +68,13 @@ void XRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_anchor_detection_is_enabled", "enable"), &XRInterface::set_anchor_detection_is_enabled);
ClassDB::bind_method(D_METHOD("get_camera_feed_id"), &XRInterface::get_camera_feed_id);
+ ClassDB::bind_method(D_METHOD("is_passthrough_supported"), &XRInterface::is_passthrough_supported);
+ ClassDB::bind_method(D_METHOD("is_passthrough_enabled"), &XRInterface::is_passthrough_enabled);
+ ClassDB::bind_method(D_METHOD("start_passthrough"), &XRInterface::start_passthrough);
+ ClassDB::bind_method(D_METHOD("stop_passthrough"), &XRInterface::stop_passthrough);
+ ClassDB::bind_method(D_METHOD("get_transform_for_view", "view", "cam_transform"), &XRInterface::get_transform_for_view);
+ ClassDB::bind_method(D_METHOD("get_projection_for_view", "view", "aspect", "near", "far"), &XRInterface::get_projection_for_view);
+
ADD_GROUP("AR", "ar_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ar_is_anchor_detection_enabled"), "set_anchor_detection_is_enabled", "get_anchor_detection_is_enabled");
@@ -114,7 +121,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,7 +163,94 @@ 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...
+ Projection 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;
+ }
+ }
+ images.push_back(Image::create_from_data(vrs_sizei.x, vrs_sizei.y, false, Image::FORMAT_R8, data));
+ }
+
+ 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 **/
+
+RID XRInterface::get_color_texture() {
+ return RID();
+}
+
+RID XRInterface::get_depth_texture() {
+ return RID();
+}
+
+RID XRInterface::get_velocity_texture() {
+ return RID();
+}
+
PackedStringArray XRInterface::get_suggested_tracker_names() const {
PackedStringArray arr;
diff --git a/servers/xr/xr_interface.h b/servers/xr/xr_interface.h
index 62eba2f00b..86d328d41c 100644
--- a/servers/xr/xr_interface.h
+++ b/servers/xr/xr_interface.h
@@ -31,7 +31,7 @@
#ifndef XR_INTERFACE_H
#define XR_INTERFACE_H
-#include "core/math/camera_matrix.h"
+#include "core/math/projection.h"
#include "core/os/thread_safe.h"
#include "servers/xr_server.h"
@@ -119,9 +119,11 @@ public:
virtual uint32_t get_view_count() = 0; /* returns the view count we need (1 is monoscopic, 2 is stereoscopic but can be more) */
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 */
-
- // note, external color/depth/vrs texture support will be added here soon.
+ virtual Projection 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 */
+ virtual RID get_color_texture(); /* obtain color output texture (if applicable) */
+ virtual RID get_depth_texture(); /* obtain depth output texture (if applicable, used for reprojection) */
+ virtual RID get_velocity_texture(); /* obtain velocity output texture (if applicable, used for spacewarp) */
virtual void process() = 0;
virtual void pre_render(){};
@@ -129,10 +131,23 @@ public:
virtual Vector<BlitToScreen> post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) = 0; /* inform XR interface we finished our viewport draw process */
virtual void end_frame(){};
+ /** passthrough **/
+
+ virtual bool is_passthrough_supported() { return false; }
+ virtual bool is_passthrough_enabled() { return false; }
+ virtual bool start_passthrough() { return false; }
+ virtual void stop_passthrough() {}
+
virtual void notification(int p_what){};
XRInterface();
~XRInterface();
+
+private:
+ struct VRSData {
+ RID vrs_texture;
+ Size2i size;
+ } vrs;
};
VARIANT_ENUM_CAST(XRInterface::Capabilities);
diff --git a/servers/xr/xr_interface_extension.cpp b/servers/xr/xr_interface_extension.cpp
index a0bec0f95b..89752b3017 100644
--- a/servers/xr/xr_interface_extension.cpp
+++ b/servers/xr/xr_interface_extension.cpp
@@ -29,9 +29,7 @@
/*************************************************************************/
#include "xr_interface_extension.h"
-#include "servers/rendering/renderer_rd/renderer_storage_rd.h"
#include "servers/rendering/renderer_rd/storage_rd/texture_storage.h"
-#include "servers/rendering/renderer_storage.h"
#include "servers/rendering/rendering_server_globals.h"
void XRInterfaceExtension::_bind_methods() {
@@ -52,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);
@@ -75,6 +74,15 @@ void XRInterfaceExtension::_bind_methods() {
GDVIRTUAL_BIND(_set_anchor_detection_is_enabled, "enabled");
GDVIRTUAL_BIND(_get_camera_feed_id);
+ // override output methods
+ GDVIRTUAL_BIND(_get_color_texture);
+ GDVIRTUAL_BIND(_get_depth_texture);
+ GDVIRTUAL_BIND(_get_velocity_texture);
+
+ ClassDB::bind_method(D_METHOD("get_color_texture"), &XRInterfaceExtension::get_color_texture);
+ ClassDB::bind_method(D_METHOD("get_depth_texture"), &XRInterfaceExtension::get_depth_texture);
+ ClassDB::bind_method(D_METHOD("get_velocity_texture"), &XRInterfaceExtension::get_velocity_texture);
+
// helper methods
ClassDB::bind_method(D_METHOD("add_blit", "render_target", "src_rect", "dst_rect", "use_layer", "layer", "apply_lens_distortion", "eye_center", "k1", "k2", "upscale", "aspect_ratio"), &XRInterfaceExtension::add_blit);
ClassDB::bind_method(D_METHOD("get_render_target_texture", "render_target"), &XRInterfaceExtension::get_render_target_texture);
@@ -92,33 +100,21 @@ StringName XRInterfaceExtension::get_name() const {
}
uint32_t XRInterfaceExtension::get_capabilities() const {
- uint32_t capabilities;
-
- if (GDVIRTUAL_CALL(_get_capabilities, capabilities)) {
- return capabilities;
- }
-
- return 0;
+ uint32_t capabilities = 0;
+ GDVIRTUAL_CALL(_get_capabilities, capabilities);
+ return capabilities;
}
bool XRInterfaceExtension::is_initialized() const {
- bool initialised = false;
-
- if (GDVIRTUAL_CALL(_is_initialized, initialised)) {
- return initialised;
- }
-
- return false;
+ bool initialized = false;
+ GDVIRTUAL_CALL(_is_initialized, initialized);
+ return initialized;
}
bool XRInterfaceExtension::initialize() {
- bool initialised = false;
-
- if (GDVIRTUAL_CALL(_initialize, initialised)) {
- return initialised;
- }
-
- return false;
+ bool initialized = false;
+ GDVIRTUAL_CALL(_initialize, initialized);
+ return initialized;
}
void XRInterfaceExtension::uninitialize() {
@@ -142,13 +138,9 @@ PackedStringArray XRInterfaceExtension::get_suggested_pose_names(const StringNam
}
XRInterface::TrackingStatus XRInterfaceExtension::get_tracking_status() const {
- uint32_t status;
-
- if (GDVIRTUAL_CALL(_get_tracking_status, status)) {
- return TrackingStatus(status);
- }
-
- return XR_UNKNOWN_TRACKING;
+ uint32_t status = XR_UNKNOWN_TRACKING;
+ GDVIRTUAL_CALL(_get_tracking_status, status);
+ return TrackingStatus(status);
}
void XRInterfaceExtension::trigger_haptic_pulse(const String &p_action_name, const StringName &p_tracker_name, double p_frequency, double p_amplitude, double p_duration_sec, double p_delay_sec) {
@@ -156,52 +148,34 @@ void XRInterfaceExtension::trigger_haptic_pulse(const String &p_action_name, con
}
bool XRInterfaceExtension::supports_play_area_mode(XRInterface::PlayAreaMode p_mode) {
- bool is_supported;
-
- if (GDVIRTUAL_CALL(_supports_play_area_mode, p_mode, is_supported)) {
- return is_supported;
- }
-
- return false;
+ bool is_supported = false;
+ GDVIRTUAL_CALL(_supports_play_area_mode, p_mode, is_supported);
+ return is_supported;
}
XRInterface::PlayAreaMode XRInterfaceExtension::get_play_area_mode() const {
- uint32_t mode;
-
- if (GDVIRTUAL_CALL(_get_play_area_mode, mode)) {
- return XRInterface::PlayAreaMode(mode);
- }
-
- return XRInterface::XR_PLAY_AREA_UNKNOWN;
+ uint32_t mode = XR_PLAY_AREA_UNKNOWN;
+ GDVIRTUAL_CALL(_get_play_area_mode, mode);
+ return XRInterface::PlayAreaMode(mode);
}
bool XRInterfaceExtension::set_play_area_mode(XRInterface::PlayAreaMode p_mode) {
- bool success;
-
- if (GDVIRTUAL_CALL(_set_play_area_mode, p_mode, success)) {
- return success;
- }
-
- return false;
+ bool success = false;
+ GDVIRTUAL_CALL(_set_play_area_mode, p_mode, success);
+ return success;
}
PackedVector3Array XRInterfaceExtension::get_play_area() const {
PackedVector3Array arr;
-
GDVIRTUAL_CALL(_get_play_area, arr);
-
return arr;
}
/** these will only be implemented on AR interfaces, so we want dummies for VR **/
bool XRInterfaceExtension::get_anchor_detection_is_enabled() const {
- bool enabled;
-
- if (GDVIRTUAL_CALL(_get_anchor_detection_is_enabled, enabled)) {
- return enabled;
- }
-
- return false;
+ bool enabled = false;
+ GDVIRTUAL_CALL(_get_anchor_detection_is_enabled, enabled);
+ return enabled;
}
void XRInterfaceExtension::set_anchor_detection_is_enabled(bool p_enable) {
@@ -210,69 +184,76 @@ void XRInterfaceExtension::set_anchor_detection_is_enabled(bool p_enable) {
}
int XRInterfaceExtension::get_camera_feed_id() {
- int feed_id;
-
- if (GDVIRTUAL_CALL(_get_camera_feed_id, feed_id)) {
- return feed_id;
- }
-
- return 0;
+ int feed_id = 0;
+ GDVIRTUAL_CALL(_get_camera_feed_id, feed_id);
+ return feed_id;
}
Size2 XRInterfaceExtension::get_render_target_size() {
Size2 size;
-
- if (GDVIRTUAL_CALL(_get_render_target_size, size)) {
- return size;
- }
-
- return Size2(0, 0);
+ GDVIRTUAL_CALL(_get_render_target_size, size);
+ return size;
}
uint32_t XRInterfaceExtension::get_view_count() {
- uint32_t view_count;
-
- if (GDVIRTUAL_CALL(_get_view_count, view_count)) {
- return view_count;
- }
-
- return 1;
+ uint32_t view_count = 1;
+ GDVIRTUAL_CALL(_get_view_count, view_count);
+ return view_count;
}
Transform3D XRInterfaceExtension::get_camera_transform() {
Transform3D transform;
-
- if (GDVIRTUAL_CALL(_get_camera_transform, transform)) {
- return transform;
- }
-
- return Transform3D();
+ GDVIRTUAL_CALL(_get_camera_transform, transform);
+ return transform;
}
Transform3D XRInterfaceExtension::get_transform_for_view(uint32_t p_view, const Transform3D &p_cam_transform) {
Transform3D transform;
-
- if (GDVIRTUAL_CALL(_get_transform_for_view, p_view, p_cam_transform, transform)) {
- return transform;
- }
-
- return Transform3D();
+ GDVIRTUAL_CALL(_get_transform_for_view, p_view, p_cam_transform, transform);
+ return transform;
}
-CameraMatrix XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
- CameraMatrix cm;
+Projection XRInterfaceExtension::get_projection_for_view(uint32_t p_view, double p_aspect, double p_z_near, double p_z_far) {
+ Projection cm;
PackedFloat64Array arr;
if (GDVIRTUAL_CALL(_get_projection_for_view, p_view, p_aspect, p_z_near, p_z_far, arr)) {
- ERR_FAIL_COND_V_MSG(arr.size() != 16, CameraMatrix(), "Projection matrix must contain 16 floats");
- real_t *m = (real_t *)cm.matrix;
+ ERR_FAIL_COND_V_MSG(arr.size() != 16, Projection(), "Projection matrix must contain 16 floats");
+ real_t *m = (real_t *)cm.columns;
for (int i = 0; i < 16; i++) {
m[i] = arr[i];
}
return cm;
}
- return CameraMatrix();
+ return Projection();
+}
+
+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();
+ }
+}
+
+RID XRInterfaceExtension::get_color_texture() {
+ RID texture;
+ GDVIRTUAL_CALL(_get_color_texture, texture);
+ return texture;
+}
+
+RID XRInterfaceExtension::get_depth_texture() {
+ RID texture;
+ GDVIRTUAL_CALL(_get_depth_texture, texture);
+ return texture;
+}
+
+RID XRInterfaceExtension::get_velocity_texture() {
+ RID texture;
+ GDVIRTUAL_CALL(_get_velocity_texture, texture);
+ return 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) {
@@ -307,13 +288,8 @@ void XRInterfaceExtension::pre_render() {
bool XRInterfaceExtension::pre_draw_viewport(RID p_render_target) {
bool do_render = true;
-
- if (GDVIRTUAL_CALL(_pre_draw_viewport, p_render_target, do_render)) {
- return do_render;
- } else {
- // if not implemented we're returning true
- return true;
- }
+ GDVIRTUAL_CALL(_pre_draw_viewport, p_render_target, do_render);
+ return do_render; // If not implemented we're returning true.
}
Vector<BlitToScreen> XRInterfaceExtension::post_draw_viewport(RID p_render_target, const Rect2 &p_screen_rect) {
@@ -350,9 +326,5 @@ RID XRInterfaceExtension::get_render_target_texture(RID p_render_target) {
RID XRInterfaceExtension::get_render_target_depth(RID p_render_target) {
// TODO implement this, the problem is that our depth texture isn't part of our render target as it is used for 3D rendering only
// but we don't have access to our render buffers from here....
- RendererSceneRenderRD * rd_scene = ?????;
- ERR_FAIL_NULL_V_MSG(rd_scene, RID(), "Renderer scene render not setup");
-
- return rd_scene->render_buffers_get_depth_texture(????????????);
}
*/
diff --git a/servers/xr/xr_interface_extension.h b/servers/xr/xr_interface_extension.h
index 5a436b9fd0..2235b57cb3 100644
--- a/servers/xr/xr_interface_extension.h
+++ b/servers/xr/xr_interface_extension.h
@@ -100,13 +100,21 @@ public:
virtual uint32_t get_view_count() override;
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 Projection 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;
+ virtual RID get_color_texture() override;
+ virtual RID get_depth_texture() override;
+ virtual RID get_velocity_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);
+ GDVIRTUAL0R(RID, _get_color_texture);
+ GDVIRTUAL0R(RID, _get_depth_texture);
+ GDVIRTUAL0R(RID, _get_velocity_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);
@@ -130,4 +138,4 @@ public:
// RID get_render_target_depth(RID p_render_target);
};
-#endif // !XR_INTERFACE_EXTENSION_H
+#endif // XR_INTERFACE_EXTENSION_H
diff --git a/servers/xr/xr_pose.h b/servers/xr/xr_pose.h
index f306c22390..e7d363764b 100644
--- a/servers/xr/xr_pose.h
+++ b/servers/xr/xr_pose.h
@@ -78,4 +78,4 @@ public:
VARIANT_ENUM_CAST(XRPose::TrackingConfidence);
-#endif
+#endif // XR_POSE_H
diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp
index ad61aa94bc..e26212ada1 100644
--- a/servers/xr_server.cpp
+++ b/servers/xr_server.cpp
@@ -33,6 +33,16 @@
#include "xr/xr_interface.h"
#include "xr/xr_positional_tracker.h"
+XRServer::XRMode XRServer::xr_mode = XRMODE_DEFAULT;
+
+XRServer::XRMode XRServer::get_xr_mode() {
+ return xr_mode;
+}
+
+void XRServer::set_xr_mode(XRServer::XRMode p_mode) {
+ xr_mode = p_mode;
+}
+
XRServer *XRServer::singleton = nullptr;
XRServer *XRServer::get_singleton() {
@@ -216,7 +226,7 @@ Ref<XRInterface> XRServer::find_interface(const String &p_name) const {
return interfaces[idx];
};
-Array XRServer::get_interfaces() const {
+TypedArray<Dictionary> XRServer::get_interfaces() const {
Array ret;
for (int i = 0; i < interfaces.size(); i++) {
diff --git a/servers/xr_server.h b/servers/xr_server.h
index d9188d2de1..4da5619fd3 100644
--- a/servers/xr_server.h
+++ b/servers/xr_server.h
@@ -57,6 +57,12 @@ class XRServer : public Object {
_THREAD_SAFE_CLASS_
public:
+ enum XRMode {
+ XRMODE_DEFAULT, /* Default behavior, means we check project settings */
+ XRMODE_OFF, /* Ignore project settings, disable OpenXR, disable shaders */
+ XRMODE_ON, /* Ignore project settings, enable OpenXR, enable shaders, run editor in VR (if applicable) */
+ };
+
enum TrackerType {
TRACKER_HEAD = 0x01, /* tracks the position of the players head (or in case of handheld AR, location of the phone) */
TRACKER_CONTROLLER = 0x02, /* tracks a controller */
@@ -75,6 +81,8 @@ public:
};
private:
+ static XRMode xr_mode;
+
Vector<Ref<XRInterface>> interfaces;
Dictionary trackers;
@@ -90,6 +98,9 @@ protected:
static void _bind_methods();
public:
+ static XRMode get_xr_mode();
+ static void set_xr_mode(XRMode p_mode);
+
static XRServer *get_singleton();
/*
@@ -146,7 +157,7 @@ public:
int get_interface_count() const;
Ref<XRInterface> get_interface(int p_index) const;
Ref<XRInterface> find_interface(const String &p_name) const;
- Array get_interfaces() const;
+ TypedArray<Dictionary> get_interfaces() const;
/*
note, more then one interface can technically be active, especially on mobile, but only one interface is used for