diff options
Diffstat (limited to 'servers')
88 files changed, 2569 insertions, 1498 deletions
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp index ff0d2cad65..a2abbeb686 100644 --- a/servers/audio/audio_driver_dummy.cpp +++ b/servers/audio/audio_driver_dummy.cpp @@ -30,8 +30,8 @@ #include "audio_driver_dummy.h" +#include "core/config/project_settings.h" #include "core/os/os.h" -#include "core/project_settings.h" Error AudioDriverDummy::init() { active = false; diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h index 76cb8a209c..b1be5dfea1 100644 --- a/servers/audio/audio_effect.h +++ b/servers/audio/audio_effect.h @@ -31,8 +31,8 @@ #ifndef AUDIOEFFECT_H #define AUDIOEFFECT_H +#include "core/io/resource.h" #include "core/math/audio_frame.h" -#include "core/resource.h" class AudioEffectInstance : public Reference { GDCLASS(AudioEffectInstance, Reference); diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 2cc2f5c291..a7c9443dcf 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -30,8 +30,8 @@ #include "audio_stream.h" +#include "core/config/project_settings.h" #include "core/os/os.h" -#include "core/project_settings.h" ////////////////////////////// diff --git a/servers/audio/audio_stream.h b/servers/audio/audio_stream.h index 9720196cc2..0bbb29b15c 100644 --- a/servers/audio/audio_stream.h +++ b/servers/audio/audio_stream.h @@ -31,8 +31,8 @@ #ifndef AUDIO_STREAM_H #define AUDIO_STREAM_H -#include "core/image.h" -#include "core/resource.h" +#include "core/io/image.h" +#include "core/io/resource.h" #include "servers/audio/audio_filter_sw.h" #include "servers/audio_server.h" diff --git a/servers/audio/effects/audio_stream_generator.h b/servers/audio/effects/audio_stream_generator.h index c90983a66f..49bda0fcf9 100644 --- a/servers/audio/effects/audio_stream_generator.h +++ b/servers/audio/effects/audio_stream_generator.h @@ -31,7 +31,7 @@ #ifndef AUDIO_STREAM_GENERATOR_H #define AUDIO_STREAM_GENERATOR_H -#include "core/ring_buffer.h" +#include "core/templates/ring_buffer.h" #include "servers/audio/audio_stream.h" class AudioStreamGenerator : public AudioStream { diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp index 08a6cf55fa..15abeea5f3 100644 --- a/servers/audio/effects/eq.cpp +++ b/servers/audio/effects/eq.cpp @@ -31,7 +31,7 @@ // Author: reduzio@gmail.com (C) 2006 #include "eq.h" -#include "core/error_macros.h" +#include "core/error/error_macros.h" #include "core/math/math_funcs.h" #include <math.h> diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h index 391a7aa24b..720c4dfcaf 100644 --- a/servers/audio/effects/eq.h +++ b/servers/audio/effects/eq.h @@ -33,8 +33,8 @@ #ifndef EQ_FILTER_H #define EQ_FILTER_H +#include "core/templates/vector.h" #include "core/typedefs.h" -#include "core/vector.h" /** @author Juan Linietsky diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 6b70f41e57..fdce55320c 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -30,11 +30,11 @@ #include "audio_server.h" +#include "core/config/project_settings.h" #include "core/debugger/engine_debugger.h" #include "core/io/resource_loader.h" #include "core/os/file_access.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "scene/resources/audio_stream_sample.h" #include "servers/audio/audio_driver_dummy.h" #include "servers/audio/effects/audio_effect_compressor.h" diff --git a/servers/audio_server.h b/servers/audio_server.h index 80e244aacd..507aea7b89 100644 --- a/servers/audio_server.h +++ b/servers/audio_server.h @@ -32,9 +32,9 @@ #define AUDIO_SERVER_H #include "core/math/audio_frame.h" -#include "core/object.h" +#include "core/object/class_db.h" #include "core/os/os.h" -#include "core/variant.h" +#include "core/variant/variant.h" #include "servers/audio/audio_effect.h" class AudioDriverDummy; diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h index 52a737cd8d..dca583c9de 100644 --- a/servers/camera/camera_feed.h +++ b/servers/camera/camera_feed.h @@ -31,7 +31,7 @@ #ifndef CAMERA_FEED_H #define CAMERA_FEED_H -#include "core/image.h" +#include "core/io/image.h" #include "core/math/transform_2d.h" #include "servers/camera_server.h" #include "servers/rendering_server.h" diff --git a/servers/camera_server.h b/servers/camera_server.h index b268553fe5..54acce006a 100644 --- a/servers/camera_server.h +++ b/servers/camera_server.h @@ -31,11 +31,11 @@ #ifndef CAMERA_SERVER_H #define CAMERA_SERVER_H -#include "core/object.h" +#include "core/object/class_db.h" +#include "core/object/reference.h" #include "core/os/thread_safe.h" -#include "core/reference.h" -#include "core/rid.h" -#include "core/variant.h" +#include "core/templates/rid.h" +#include "core/variant/variant.h" /** @author Bastiaan Olij <mux213@gmail.com> diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 356f4b884a..e678c6919b 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -31,7 +31,6 @@ #include "display_server.h" #include "core/input/input.h" -#include "core/method_bind_ext.gen.inc" #include "scene/resources/texture.h" DisplayServer *DisplayServer::singleton = nullptr; diff --git a/servers/display_server.h b/servers/display_server.h index 3ee0da709b..c2ffb23531 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -31,10 +31,10 @@ #ifndef DISPLAY_SERVER_H #define DISPLAY_SERVER_H -#include "core/callable.h" #include "core/input/input.h" +#include "core/io/resource.h" #include "core/os/os.h" -#include "core/resource.h" +#include "core/variant/callable.h" class Texture2D; diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h index d7384bae74..895e41558a 100644 --- a/servers/navigation_server_2d.h +++ b/servers/navigation_server_2d.h @@ -35,8 +35,8 @@ #ifndef NAVIGATION_2D_SERVER_H #define NAVIGATION_2D_SERVER_H -#include "core/object.h" -#include "core/rid.h" +#include "core/object/class_db.h" +#include "core/templates/rid.h" #include "scene/2d/navigation_region_2d.h" // This server exposes the `NavigationServer3D` features in the 2D world. diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h index c34bd2391b..e6421462b0 100644 --- a/servers/navigation_server_3d.h +++ b/servers/navigation_server_3d.h @@ -35,8 +35,8 @@ #ifndef NAVIGATION_SERVER_H #define NAVIGATION_SERVER_H -#include "core/object.h" -#include "core/rid.h" +#include "core/object/class_db.h" +#include "core/templates/rid.h" #include "scene/3d/navigation_region_3d.h" /// This server uses the concept of internal mutability. diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index f14466f582..d6b358a657 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -32,7 +32,7 @@ #define AREA_2D_SW_H #include "collision_object_2d_sw.h" -#include "core/self_list.h" +#include "core/templates/self_list.h" #include "servers/physics_server_2d.h" //#include "servers/physics_3d/query_sw.h" diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index 4a3ef718ec..bbc22a67df 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -33,7 +33,7 @@ #include "area_2d_sw.h" #include "collision_object_2d_sw.h" -#include "core/vset.h" +#include "core/templates/vset.h" class Constraint2DSW; diff --git a/servers/physics_2d/broad_phase_2d_basic.h b/servers/physics_2d/broad_phase_2d_basic.h index ec5cfdbf1d..97e1c900b9 100644 --- a/servers/physics_2d/broad_phase_2d_basic.h +++ b/servers/physics_2d/broad_phase_2d_basic.h @@ -31,7 +31,7 @@ #ifndef BROAD_PHASE_2D_BASIC_H #define BROAD_PHASE_2D_BASIC_H -#include "core/map.h" +#include "core/templates/map.h" #include "space_2d_sw.h" class BroadPhase2DBasic : public BroadPhase2DSW { struct Element { diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp index ec74507e03..c8b3d193c9 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp +++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp @@ -30,7 +30,7 @@ #include "broad_phase_2d_hash_grid.h" #include "collision_object_2d_sw.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" #define LARGE_ELEMENT_FI 1.01239812 diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.h b/servers/physics_2d/broad_phase_2d_hash_grid.h index de1ada0932..54994992c9 100644 --- a/servers/physics_2d/broad_phase_2d_hash_grid.h +++ b/servers/physics_2d/broad_phase_2d_hash_grid.h @@ -32,7 +32,7 @@ #define BROAD_PHASE_2D_HASH_GRID_H #include "broad_phase_2d_sw.h" -#include "core/map.h" +#include "core/templates/map.h" class BroadPhase2DHashGrid : public BroadPhase2DSW { struct PairData { diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 8caa53680d..36b7073a5c 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -32,7 +32,7 @@ #define COLLISION_OBJECT_2D_SW_H #include "broad_phase_2d_sw.h" -#include "core/self_list.h" +#include "core/templates/self_list.h" #include "servers/physics_server_2d.h" #include "shape_2d_sw.h" diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp index 1b396190e9..9d00d01759 100644 --- a/servers/physics_2d/physics_server_2d_sw.cpp +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -33,9 +33,9 @@ #include "broad_phase_2d_basic.h" #include "broad_phase_2d_hash_grid.h" #include "collision_solver_2d_sw.h" +#include "core/config/project_settings.h" #include "core/debugger/engine_debugger.h" #include "core/os/os.h" -#include "core/project_settings.h" #define FLUSH_QUERY_CHECK(m_object) \ ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h index e88db28056..9bd9655e2c 100644 --- a/servers/physics_2d/physics_server_2d_sw.h +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -31,7 +31,7 @@ #ifndef PHYSICS_2D_SERVER_SW #define PHYSICS_2D_SERVER_SW -#include "core/rid_owner.h" +#include "core/templates/rid_owner.h" #include "joints_2d_sw.h" #include "servers/physics_server_2d.h" #include "shape_2d_sw.h" diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h index 586dbe9e12..1269cadd33 100644 --- a/servers/physics_2d/physics_server_2d_wrap_mt.h +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -31,9 +31,9 @@ #ifndef PHYSICS2DSERVERWRAPMT_H #define PHYSICS2DSERVERWRAPMT_H -#include "core/command_queue_mt.h" +#include "core/config/project_settings.h" #include "core/os/thread.h" -#include "core/project_settings.h" +#include "core/templates/command_queue_mt.h" #include "servers/physics_server_2d.h" #ifdef DEBUG_SYNC diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 87e22ef1c9..afb1112fc0 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -31,7 +31,7 @@ #include "shape_2d_sw.h" #include "core/math/geometry_2d.h" -#include "core/sort_array.h" +#include "core/templates/sort_array.h" void Shape2DSW::configure(const Rect2 &p_aabb) { aabb = p_aabb; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 966dcbd651..a8ab731ead 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -32,7 +32,7 @@ #include "collision_solver_2d_sw.h" #include "core/os/os.h" -#include "core/pair.h" +#include "core/templates/pair.h" #include "physics_server_2d_sw.h" _FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (!(p_object->get_collision_layer() & p_collision_mask)) { diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 1eee83dfe9..5c5144ae22 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -37,8 +37,8 @@ #include "body_pair_2d_sw.h" #include "broad_phase_2d_sw.h" #include "collision_object_2d_sw.h" -#include "core/hash_map.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" +#include "core/templates/hash_map.h" #include "core/typedefs.h" class PhysicsDirectSpaceState2DSW : public PhysicsDirectSpaceState2D { diff --git a/servers/physics_3d/area_3d_sw.h b/servers/physics_3d/area_3d_sw.h index 6af3976167..a2efe6af51 100644 --- a/servers/physics_3d/area_3d_sw.h +++ b/servers/physics_3d/area_3d_sw.h @@ -32,7 +32,7 @@ #define AREA_SW_H #include "collision_object_3d_sw.h" -#include "core/self_list.h" +#include "core/templates/self_list.h" #include "servers/physics_server_3d.h" //#include "servers/physics_3d/query_sw.h" diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h index b642729404..6dbda8670a 100644 --- a/servers/physics_3d/body_3d_sw.h +++ b/servers/physics_3d/body_3d_sw.h @@ -33,7 +33,7 @@ #include "area_3d_sw.h" #include "collision_object_3d_sw.h" -#include "core/vset.h" +#include "core/templates/vset.h" class Constraint3DSW; diff --git a/servers/physics_3d/broad_phase_3d_basic.cpp b/servers/physics_3d/broad_phase_3d_basic.cpp index f5ea1897a9..15a5968087 100644 --- a/servers/physics_3d/broad_phase_3d_basic.cpp +++ b/servers/physics_3d/broad_phase_3d_basic.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "broad_phase_3d_basic.h" -#include "core/list.h" -#include "core/print_string.h" +#include "core/string/print_string.h" +#include "core/templates/list.h" BroadPhase3DSW::ID BroadPhase3DBasic::create(CollisionObject3DSW *p_object, int p_subindex) { ERR_FAIL_COND_V(p_object == nullptr, 0); diff --git a/servers/physics_3d/broad_phase_3d_basic.h b/servers/physics_3d/broad_phase_3d_basic.h index 4b644bf818..361d322e14 100644 --- a/servers/physics_3d/broad_phase_3d_basic.h +++ b/servers/physics_3d/broad_phase_3d_basic.h @@ -32,7 +32,7 @@ #define BROAD_PHASE_BASIC_H #include "broad_phase_3d_sw.h" -#include "core/map.h" +#include "core/templates/map.h" class BroadPhase3DBasic : public BroadPhase3DSW { struct Element { diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h index a3a5787ced..e1220f8855 100644 --- a/servers/physics_3d/collision_object_3d_sw.h +++ b/servers/physics_3d/collision_object_3d_sw.h @@ -32,7 +32,7 @@ #define COLLISION_OBJECT_SW_H #include "broad_phase_3d_sw.h" -#include "core/self_list.h" +#include "core/templates/self_list.h" #include "servers/physics_server_3d.h" #include "shape_3d_sw.h" diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h index d9c86312cc..a45ee7c2c8 100644 --- a/servers/physics_3d/physics_server_3d_sw.h +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -31,7 +31,7 @@ #ifndef PHYSICS_SERVER_SW #define PHYSICS_SERVER_SW -#include "core/rid_owner.h" +#include "core/templates/rid_owner.h" #include "joints_3d_sw.h" #include "servers/physics_server_3d.h" #include "shape_3d_sw.h" diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp index ca33241d29..b8b01de3c3 100644 --- a/servers/physics_3d/shape_3d_sw.cpp +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -32,7 +32,7 @@ #include "core/math/geometry_3d.h" #include "core/math/quick_hull.h" -#include "core/sort_array.h" +#include "core/templates/sort_array.h" #define _POINT_SNAP 0.001953125 #define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002 diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp index 48f250ba35..d9170cd986 100644 --- a/servers/physics_3d/space_3d_sw.cpp +++ b/servers/physics_3d/space_3d_sw.cpp @@ -31,7 +31,7 @@ #include "space_3d_sw.h" #include "collision_solver_3d_sw.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" #include "physics_server_3d_sw.h" _FORCE_INLINE_ static bool _can_collide_with(CollisionObject3DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h index 4aba80c8f3..6380bcc6dc 100644 --- a/servers/physics_3d/space_3d_sw.h +++ b/servers/physics_3d/space_3d_sw.h @@ -37,8 +37,8 @@ #include "body_pair_3d_sw.h" #include "broad_phase_3d_sw.h" #include "collision_object_3d_sw.h" -#include "core/hash_map.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" +#include "core/templates/hash_map.h" #include "core/typedefs.h" class PhysicsDirectSpaceState3DSW : public PhysicsDirectSpaceState3D { diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index 0dac08015f..88cdd9f991 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -30,9 +30,8 @@ #include "physics_server_2d.h" -#include "core/method_bind_ext.gen.inc" -#include "core/print_string.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" +#include "core/string/print_string.h" PhysicsServer2D *PhysicsServer2D::singleton = nullptr; diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index f609adccf9..283a2ab58c 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -31,9 +31,9 @@ #ifndef PHYSICS_2D_SERVER_H #define PHYSICS_2D_SERVER_H -#include "core/object.h" -#include "core/reference.h" -#include "core/resource.h" +#include "core/io/resource.h" +#include "core/object/class_db.h" +#include "core/object/reference.h" class PhysicsDirectSpaceState2D; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 33a2b91902..5796bccbac 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -30,9 +30,8 @@ #include "physics_server_3d.h" -#include "core/method_bind_ext.gen.inc" -#include "core/print_string.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" +#include "core/string/print_string.h" PhysicsServer3D *PhysicsServer3D::singleton = nullptr; diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index b779942460..90ef2bb8dd 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -31,8 +31,8 @@ #ifndef PHYSICS_SERVER_H #define PHYSICS_SERVER_H -#include "core/object.h" -#include "core/resource.h" +#include "core/io/resource.h" +#include "core/object/class_db.h" class PhysicsDirectSpaceState3D; diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index adca7b8055..34980aaf66 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -30,8 +30,8 @@ #include "register_server_types.h" -#include "core/engine.h" -#include "core/project_settings.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" #include "audio/audio_effect.h" #include "audio/audio_stream.h" diff --git a/servers/rendering/rasterizer.cpp b/servers/rendering/rasterizer.cpp index 566a14b655..32084c8a3e 100644 --- a/servers/rendering/rasterizer.cpp +++ b/servers/rendering/rasterizer.cpp @@ -31,7 +31,7 @@ #include "rasterizer.h" #include "core/os/os.h" -#include "core/print_string.h" +#include "core/string/print_string.h" Rasterizer *(*Rasterizer::_create_func)() = nullptr; diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h index 84c04f34b6..efaa8f138a 100644 --- a/servers/rendering/rasterizer.h +++ b/servers/rendering/rasterizer.h @@ -32,8 +32,8 @@ #define RASTERIZER_H #include "core/math/camera_matrix.h" -#include "core/pair.h" -#include "core/self_list.h" +#include "core/templates/pair.h" +#include "core/templates/self_list.h" #include "servers/rendering_server.h" class RasterizerScene { @@ -84,7 +84,7 @@ public: virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; #endif - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, 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) = 0; + 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) = 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; @@ -111,7 +111,7 @@ public: virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 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) = 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 Ref<Image> environment_bake_panorama(RID p_env, bool p_bake_irradiance, const Size2i &p_size) = 0; @@ -306,7 +306,7 @@ public: 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_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa) = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) = 0; virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_amount, float p_limit) = 0; virtual bool screen_space_roughness_limiter_is_active() const = 0; @@ -351,10 +351,6 @@ public: virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0; -#endif virtual void texture_set_path(RID p_texture, const String &p_path) = 0; virtual String texture_get_path(RID p_texture) const = 0; @@ -372,6 +368,15 @@ 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; + /* CANVAS TEXTURE API */ + + virtual RID canvas_texture_create() = 0; + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) = 0; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; + + virtual void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) = 0; + /* SHADER API */ virtual RID shader_create() = 0; @@ -810,7 +815,8 @@ public: CANVAS_RECT_FLIP_H = 4, CANVAS_RECT_FLIP_V = 8, CANVAS_RECT_TRANSPOSE = 16, - CANVAS_RECT_CLIP_UV = 32 + CANVAS_RECT_CLIP_UV = 32, + CANVAS_RECT_IS_GROUP = 64, }; struct Light { @@ -826,7 +832,9 @@ public: int layer_max; int item_mask; int item_shadow_mask; + float directional_distance; RS::CanvasLightMode mode; + RS::CanvasLightBlendMode blend_mode; RID texture; Vector2 texture_offset; RID canvas; @@ -848,7 +856,7 @@ public: Light *shadows_next_ptr; Light *filter_next_ptr; Light *next_ptr; - Light *mask_next_ptr; + Light *directional_next_ptr; RID light_internal; uint64_t version; @@ -869,52 +877,25 @@ public: scale = 1.0; energy = 1.0; item_shadow_mask = 1; - mode = RS::CANVAS_LIGHT_MODE_ADD; + mode = RS::CANVAS_LIGHT_MODE_POINT; + blend_mode = RS::CANVAS_LIGHT_BLEND_MODE_ADD; // texture_cache = nullptr; next_ptr = nullptr; - mask_next_ptr = nullptr; + directional_next_ptr = nullptr; filter_next_ptr = nullptr; use_shadow = false; shadow_buffer_size = 2048; shadow_filter = RS::CANVAS_LIGHT_FILTER_NONE; shadow_smooth = 0.0; render_index_cache = -1; + directional_distance = 10000.0; } }; - typedef uint64_t TextureBindingID; - - virtual TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) = 0; - virtual void free_texture_binding(TextureBindingID p_binding) = 0; - //easier wrap to avoid mistakes struct Item; - struct TextureBinding { - TextureBindingID binding_id; - - _FORCE_INLINE_ void create(RS::CanvasItemTextureFilter p_item_filter, RS::CanvasItemTextureRepeat p_item_repeat, RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { - if (p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { - p_filter = p_item_filter; - } - if (p_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { - p_repeat = p_item_repeat; - } - if (p_texture != RID() || p_normalmap != RID() || p_specular != RID() || p_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT || p_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT || p_multimesh.is_valid()) { - ERR_FAIL_COND(binding_id != 0); - binding_id = singleton->request_texture_binding(p_texture, p_normalmap, p_specular, p_filter, p_repeat, p_multimesh); - } - } - - _FORCE_INLINE_ TextureBinding() { binding_id = 0; } - _FORCE_INLINE_ ~TextureBinding() { - if (binding_id) { - singleton->free_texture_binding(binding_id); - } - } - }; - typedef uint64_t PolygonID; virtual PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()) = 0; virtual void free_polygon(PolygonID p_polygon) = 0; @@ -984,9 +965,8 @@ public: Color modulate; Rect2 source; uint8_t flags; - Color specular_shininess; - TextureBinding texture_binding; + RID texture; CommandRect() { flags = 0; @@ -1002,8 +982,9 @@ public: Color color; RS::NinePatchAxisMode axis_x; RS::NinePatchAxisMode axis_y; - Color specular_shininess; - TextureBinding texture_binding; + + RID texture; + CommandNinePatch() { draw_center = true; type = TYPE_NINEPATCH; @@ -1013,8 +994,9 @@ public: struct CommandPolygon : public Command { RS::PrimitiveType primitive; Polygon polygon; - Color specular_shininess; - TextureBinding texture_binding; + + RID texture; + CommandPolygon() { type = TYPE_POLYGON; } @@ -1025,8 +1007,9 @@ public: Vector2 points[4]; Vector2 uvs[4]; Color colors[4]; - Color specular_shininess; - TextureBinding texture_binding; + + RID texture; + CommandPrimitive() { type = TYPE_PRIMITIVE; } @@ -1036,22 +1019,25 @@ public: RID mesh; Transform2D transform; Color modulate; - Color specular_shininess; - TextureBinding texture_binding; + + RID texture; + CommandMesh() { type = TYPE_MESH; } }; struct CommandMultiMesh : public Command { RID multimesh; - Color specular_shininess; - TextureBinding texture_binding; + + RID texture; + CommandMultiMesh() { type = TYPE_MULTIMESH; } }; struct CommandParticles : public Command { RID particles; - Color specular_shininess; - TextureBinding texture_binding; + + RID texture; + CommandParticles() { type = TYPE_PARTICLES; } }; @@ -1079,7 +1065,16 @@ public: bool visible; bool behind; bool update_when_visible; - //RS::MaterialBlendMode blend_mode; + + struct CanvasGroup { + RS::CanvasGroupMode mode; + bool fit_empty; + float fit_margin; + bool blur_mipmaps; + float clear_margin; + }; + + CanvasGroup *canvas_group = nullptr; int light_mask; int z_final; @@ -1103,6 +1098,7 @@ public: Rect2 final_clip_rect; Item *final_clip_owner; Item *material_owner; + Item *canvas_group_owner; ViewportRender *vp_render; bool distance_field; bool light_masked; @@ -1260,13 +1256,9 @@ public: return command; } - struct CustomData { - virtual ~CustomData() {} - }; - - mutable CustomData *custom_data; //implementation dependent - void clear() { + // The first one is always allocated on heap + // the rest go in the blocks Command *c = commands; while (c) { Command *n = c->next; @@ -1295,6 +1287,10 @@ public: material_owner = nullptr; light_masked = false; } + + RS::CanvasItemTextureFilter texture_filter; + RS::CanvasItemTextureRepeat texture_repeat; + Item() { commands = nullptr; last_command = nullptr; @@ -1303,6 +1299,7 @@ public: vp_render = nullptr; next = nullptr; final_clip_owner = nullptr; + canvas_group_owner = nullptr; clip = false; final_modulate = Color(1, 1, 1, 1); visible = true; @@ -1315,7 +1312,8 @@ public: light_masked = false; update_when_visible = false; z_final = 0; - custom_data = nullptr; + texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; } virtual ~Item() { clear(); @@ -1325,13 +1323,10 @@ public: if (copy_back_buffer) { memdelete(copy_back_buffer); } - if (custom_data) { - memdelete(custom_data); - } } }; - virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) = 0; + 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) = 0; virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; struct LightOccluderInstance { @@ -1357,12 +1352,14 @@ public: virtual RID light_create() = 0; virtual void light_set_texture(RID p_rid, RID p_texture) = 0; - virtual void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) = 0; - virtual void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; + virtual void light_set_use_shadow(RID p_rid, bool p_enable) = 0; + virtual void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; + virtual void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) = 0; virtual RID occluder_polygon_create() = 0; virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines) = 0; virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0; + virtual void set_shadow_texture_size(int p_size) = 0; virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0; diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp index aad2be45c6..01ed7b8d6a 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "rasterizer_canvas_rd.h" +#include "core/config/project_settings.h" #include "core/math/math_funcs.h" -#include "core/project_settings.h" #include "rasterizer_rd.h" void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) { @@ -92,152 +92,6 @@ void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform, p_mat4[15] = 1; } -void RasterizerCanvasRD::_update_specular_shininess(const Color &p_transform, uint32_t *r_ss) { - *r_ss = uint32_t(CLAMP(p_transform.a * 255.0, 0, 255)) << 24; - *r_ss |= uint32_t(CLAMP(p_transform.b * 255.0, 0, 255)) << 16; - *r_ss |= uint32_t(CLAMP(p_transform.g * 255.0, 0, 255)) << 8; - *r_ss |= uint32_t(CLAMP(p_transform.r * 255.0, 0, 255)); -} - -RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { - Vector<RD::Uniform> uniform_set; - - { // COLOR TEXTURE - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - RID texture = storage->texture_get_rd_texture(p_texture); - if (!texture.is_valid()) { - //use default white texture - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - } - u.ids.push_back(texture); - uniform_set.push_back(u); - } - - { // NORMAL TEXTURE - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - RID texture = storage->texture_get_rd_texture(p_normalmap); - if (!texture.is_valid()) { - //use default normal texture - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); - } - u.ids.push_back(texture); - uniform_set.push_back(u); - } - - { // SPECULAR TEXTURE - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 3; - RID texture = storage->texture_get_rd_texture(p_specular); - if (!texture.is_valid()) { - //use default white texture - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - } - u.ids.push_back(texture); - uniform_set.push_back(u); - } - - { // SAMPLER - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 4; - RID sampler = storage->sampler_rd_get_default(p_filter, p_repeat); - ERR_FAIL_COND_V(sampler.is_null(), RID()); - u.ids.push_back(sampler); - uniform_set.push_back(u); - } - - { // MULTIMESH TEXTURE BUFFER - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; - u.binding = 5; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER)); - uniform_set.push_back(u); - } - - return RD::get_singleton()->uniform_set_create(uniform_set, shader.default_version_rd_shader, 0); -} - -RasterizerCanvas::TextureBindingID RasterizerCanvasRD::request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { - if (p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { - p_filter = default_samplers.default_filter; - } - - if (p_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { - p_repeat = default_samplers.default_repeat; - } - - TextureBindingKey key; - key.texture = p_texture; - key.normalmap = p_normalmap; - key.specular = p_specular; - key.multimesh = p_multimesh; - key.texture_filter = p_filter; - key.texture_repeat = p_repeat; - - TextureBinding *binding; - TextureBindingID id; - { - TextureBindingID *idptr = bindings.texture_key_bindings.getptr(key); - - if (!idptr) { - id = bindings.id_generator++; - bindings.texture_key_bindings[key] = id; - binding = memnew(TextureBinding); - binding->key = key; - binding->id = id; - - bindings.texture_bindings[id] = binding; - - } else { - id = *idptr; - binding = bindings.texture_bindings[id]; - } - } - - binding->reference_count++; - - if (binding->to_dispose.in_list()) { - //was queued for disposal previously, but ended up reused. - bindings.to_dispose_list.remove(&binding->to_dispose); - } - - if (binding->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(binding->uniform_set)) { - binding->uniform_set = _create_texture_binding(p_texture, p_normalmap, p_specular, p_filter, p_repeat, p_multimesh); - } - - return id; -} - -void RasterizerCanvasRD::free_texture_binding(TextureBindingID p_binding) { - TextureBinding **binding_ptr = bindings.texture_bindings.getptr(p_binding); - ERR_FAIL_COND(!binding_ptr); - TextureBinding *binding = *binding_ptr; - ERR_FAIL_COND(binding->reference_count == 0); - binding->reference_count--; - if (binding->reference_count == 0) { - bindings.to_dispose_list.add(&binding->to_dispose); - } -} - -void RasterizerCanvasRD::_dispose_bindings() { - while (bindings.to_dispose_list.first()) { - TextureBinding *binding = bindings.to_dispose_list.first()->self(); - if (binding->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(binding->uniform_set)) { - RD::get_singleton()->free(binding->uniform_set); - } - - bindings.texture_key_bindings.erase(binding->key); - bindings.texture_bindings.erase(binding->id); - bindings.to_dispose_list.remove(&binding->to_dispose); - memdelete(binding); - } -} - RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights) { // Care must be taken to generate array formats // in ways where they could be reused, so we will @@ -457,36 +311,72 @@ void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) { polygon_buffers.polygons.erase(p_polygon); } -Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD::DrawListID p_draw_list, uint32_t &flags) { - TextureBinding **texture_binding_ptr = bindings.texture_bindings.getptr(p_binding); - ERR_FAIL_COND_V(!texture_binding_ptr, Size2i()); - TextureBinding *texture_binding = *texture_binding_ptr; +//////////////////// - if (texture_binding->key.normalmap.is_valid()) { - flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; +void RasterizerCanvasRD::_bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size) { + if (p_texture == RID()) { + p_texture = default_canvas_texture; } - if (texture_binding->key.specular.is_valid()) { - flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + + if (r_last_texture == p_texture) { + return; //nothing to do, its the same } - if (!RD::get_singleton()->uniform_set_is_valid(texture_binding->uniform_set)) { - //texture may have changed (erased or replaced, see if we can fix) - texture_binding->uniform_set = _create_texture_binding(texture_binding->key.texture, texture_binding->key.normalmap, texture_binding->key.specular, texture_binding->key.texture_filter, texture_binding->key.texture_repeat, texture_binding->key.multimesh); - ERR_FAIL_COND_V(!texture_binding->uniform_set.is_valid(), Size2i(1, 1)); + RID uniform_set; + Color specular_shininess; + Size2i size; + bool use_normal; + bool use_specular; + + bool success = storage->canvas_texture_get_uniform_set(p_texture, p_base_filter, p_base_repeat, shader.default_version_rd_shader, CANVAS_TEXTURE_UNIFORM_SET, uniform_set, size, specular_shininess, use_normal, use_specular); + //something odd happened + if (!success) { + _bind_canvas_texture(p_draw_list, default_canvas_texture, p_base_filter, p_base_repeat, r_last_texture, push_constant, r_texpixel_size); + return; } - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, texture_binding->uniform_set, 0); - if (texture_binding->key.texture.is_valid()) { - return storage->texture_2d_get_size(texture_binding->key.texture); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, uniform_set, CANVAS_TEXTURE_UNIFORM_SET); + + if (specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } else { + push_constant.flags &= ~FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + if (use_normal) { + push_constant.flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; } else { - return Size2i(1, 1); + push_constant.flags &= ~FLAGS_DEFAULT_NORMAL_MAP_USED; } + + push_constant.specular_shininess = uint32_t(CLAMP(specular_shininess.a * 255.0, 0, 255)) << 24; + push_constant.specular_shininess |= uint32_t(CLAMP(specular_shininess.b * 255.0, 0, 255)) << 16; + push_constant.specular_shininess |= uint32_t(CLAMP(specular_shininess.g * 255.0, 0, 255)) << 8; + push_constant.specular_shininess |= uint32_t(CLAMP(specular_shininess.r * 255.0, 0, 255)); + + r_texpixel_size.x = 1.0 / float(size.x); + r_texpixel_size.y = 1.0 / float(size.y); + + push_constant.color_texture_pixel_size[0] = r_texpixel_size.x; + push_constant.color_texture_pixel_size[1] = r_texpixel_size.y; + + r_last_texture = p_texture; } -//////////////////// void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { //create an empty push constant + RS::CanvasItemTextureFilter current_filter = default_filter; + RS::CanvasItemTextureRepeat current_repeat = default_repeat; + + if (p_item->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { + current_filter = p_item->texture_filter; + } + + if (p_item->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { + current_repeat = p_item->texture_repeat; + } + PushConstant push_constant; Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; _update_transform_2d_to_mat2x3(base_transform, push_constant.world); @@ -513,16 +403,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ uint32_t base_flags = 0; - bool light_uniform_set_dirty = false; - - if (!p_item->custom_data) { - p_item->custom_data = memnew(ItemStateData); - light_uniform_set_dirty = true; - } - - ItemStateData *state_data = (ItemStateData *)p_item->custom_data; - - Light *light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; uint16_t light_count = 0; PipelineLightMode light_mode; @@ -534,160 +414,30 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ uint32_t light_index = light->render_index_cache; push_constant.lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); - if (!light_uniform_set_dirty && (state_data->light_cache[light_count].light != light || state_data->light_cache[light_count].light_version != light->version)) { - light_uniform_set_dirty = true; - } - - light_cache[light_count] = light; - light_count++; - if (light->mode == RS::CANVAS_LIGHT_MODE_MASK) { - base_flags |= FLAGS_USING_LIGHT_MASK; - } - if (light_count == state.max_lights_per_item) { + + if (light_count == MAX_LIGHTS_PER_ITEM) { break; } } light = light->next_ptr; } - if (light_count != state_data->light_cache_count) { - light_uniform_set_dirty = true; - } base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; } - { - RID &canvas_item_state = light_count ? state_data->state_uniform_set_with_light : state_data->state_uniform_set; - - bool invalid_uniform = canvas_item_state.is_valid() && !RD::get_singleton()->uniform_set_is_valid(canvas_item_state); - - if (canvas_item_state.is_null() || invalid_uniform || (light_count > 0 && light_uniform_set_dirty)) { - //re create canvas state - Vector<RD::Uniform> uniforms; - - if (state_data->state_uniform_set_with_light.is_valid() && !invalid_uniform) { - RD::get_singleton()->free(canvas_item_state); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(state.canvas_state_buffer); - uniforms.push_back(u); - } - - if (false && p_item->skeleton.is_valid()) { - //bind skeleton stuff - } else { - //bind default - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; - u.binding = 1; - u.ids.push_back(shader.default_skeleton_texture_buffer); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.ids.push_back(shader.default_skeleton_uniform_buffer); - uniforms.push_back(u); - } - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 7; - u.ids.push_back(storage->global_variables_get_storage_buffer()); - uniforms.push_back(u); - } - - //validate and update lighs if they are being used - - if (light_count > 0) { - //recreate uniform set - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 3; - u.ids.push_back(state.lights_uniform_buffer); - uniforms.push_back(u); - } - - { - RD::Uniform u_lights; - u_lights.type = RD::UNIFORM_TYPE_TEXTURE; - u_lights.binding = 4; - - RD::Uniform u_shadows; - u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; - u_shadows.binding = 5; - - //lights - for (uint32_t i = 0; i < state.max_lights_per_item; i++) { - if (i < light_count) { - CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal); - ERR_CONTINUE(!cl); - - RID rd_texture; - - if (cl->texture.is_valid()) { - rd_texture = storage->texture_get_rd_texture(cl->texture); - } - if (rd_texture.is_valid()) { - u_lights.ids.push_back(rd_texture); - } else { - u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - } - if (cl->shadow.texture.is_valid()) { - u_shadows.ids.push_back(cl->shadow.texture); - } else { - u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); - } - } else { - u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); - } - } - - uniforms.push_back(u_lights); - uniforms.push_back(u_shadows); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 6; - u.ids.push_back(state.shadow_sampler); - uniforms.push_back(u); - } - - canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader_light, 2); - } else { - canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 2); - } - } - - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, canvas_item_state, 2); - } - - light_mode = light_count > 0 ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED; + light_mode = (light_count > 0 || using_directional_lights) ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED; PipelineVariants *pipeline_variants = p_pipeline_variants; bool reclip = false; + RID last_texture; + Size2 texpixel_size; + const Item::Command *c = p_item->commands; while (c) { - push_constant.flags = base_flags; //reset on each command for sanity - push_constant.specular_shininess = 0xFFFFFFFF; + push_constant.flags = base_flags | (push_constant.flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config switch (c->type) { case Item::Command::TYPE_RECT: { @@ -701,26 +451,12 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind textures - Size2 texpixel_size; - { - texpixel_size = _bind_texture_binding(rect->texture_binding.binding_id, p_draw_list, push_constant.flags); - texpixel_size.x = 1.0 / texpixel_size.x; - texpixel_size.y = 1.0 / texpixel_size.y; - } - - if (rect->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(rect->specular_shininess, &push_constant.specular_shininess); + _bind_canvas_texture(p_draw_list, rect->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); Rect2 src_rect; Rect2 dst_rect; - if (texpixel_size != Vector2()) { - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - + if (rect->texture != RID()) { src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1); dst_rect = Rect2(rect->rect.position, rect->rect.size); @@ -762,7 +498,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } src_rect = Rect2(0, 0, 1, 1); - texpixel_size = Vector2(1, 1); } push_constant.modulation[0] = rect->modulate.r * base_color.r; @@ -780,9 +515,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.dst_rect[2] = dst_rect.size.width; push_constant.dst_rect[3] = dst_rect.size.height; - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); RD::get_singleton()->draw_list_draw(p_draw_list, true); @@ -800,30 +532,21 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind textures - Size2 texpixel_size; - { - texpixel_size = _bind_texture_binding(np->texture_binding.binding_id, p_draw_list, push_constant.flags); - texpixel_size.x = 1.0 / texpixel_size.x; - texpixel_size.y = 1.0 / texpixel_size.y; - } - - if (np->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(np->specular_shininess, &push_constant.specular_shininess); + _bind_canvas_texture(p_draw_list, np->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); Rect2 src_rect; Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); - if (texpixel_size == Size2()) { + if (np->texture == RID()) { texpixel_size = Size2(1, 1); src_rect = Rect2(0, 0, 1, 1); } else { if (np->source != Rect2()) { src_rect = Rect2(np->source.position.x * texpixel_size.width, np->source.position.y * texpixel_size.height, np->source.size.x * texpixel_size.width, np->source.size.y * texpixel_size.height); - texpixel_size = Size2(1.0 / np->source.size.width, 1.0 / np->source.size.height); + push_constant.color_texture_pixel_size[0] = 1.0 / np->source.size.width; + push_constant.color_texture_pixel_size[1] = 1.0 / np->source.size.height; + } else { src_rect = Rect2(0, 0, 1, 1); } @@ -844,9 +567,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.dst_rect[2] = dst_rect.size.width; push_constant.dst_rect[3] = dst_rect.size.height; - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - push_constant.flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT; push_constant.flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT; @@ -863,6 +583,10 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); RD::get_singleton()->draw_list_draw(p_draw_list, true); + //restore if overrided + push_constant.color_texture_pixel_size[0] = texpixel_size.x; + push_constant.color_texture_pixel_size[1] = texpixel_size.y; + } break; case Item::Command::TYPE_POLYGON: { const Item::CommandPolygon *polygon = static_cast<const Item::CommandPolygon *>(c); @@ -884,18 +608,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind textures - Size2 texpixel_size; - { - texpixel_size = _bind_texture_binding(polygon->texture_binding.binding_id, p_draw_list, push_constant.flags); - texpixel_size.x = 1.0 / texpixel_size.x; - texpixel_size.y = 1.0 / texpixel_size.y; - } - - if (polygon->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(polygon->specular_shininess, &push_constant.specular_shininess); + _bind_canvas_texture(p_draw_list, polygon->texture, current_filter, current_repeat, last_texture, push_constant, texpixel_size); push_constant.modulation[0] = base_color.r; push_constant.modulation[1] = base_color.g; @@ -908,9 +621,6 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ push_constant.ninepatch_margins[j] = 0; } - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array); if (pb->indices.is_valid()) { @@ -932,15 +642,7 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ //bind textures - { - _bind_texture_binding(primitive->texture_binding.binding_id, p_draw_list, push_constant.flags); - } - - if (primitive->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(primitive->specular_shininess, &push_constant.specular_shininess); + _bind_canvas_texture(p_draw_list, RID(), 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(3, primitive->point_count) - 1]); @@ -1295,31 +997,146 @@ void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_ } } -void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set) { +RID RasterizerCanvasRD::_create_base_uniform_set(RID p_to_render_target, bool p_backbuffer) { + //re create canvas state + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 1; + u.ids.push_back(state.canvas_state_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.ids.push_back(state.lights_uniform_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + u.ids.push_back(storage->decal_atlas_get_texture()); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 4; + u.ids.push_back(state.shadow_texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 5; + u.ids.push_back(state.shadow_sampler); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 6; + RID screen; + if (p_backbuffer) { + screen = storage->render_target_get_rd_texture(p_to_render_target); + } else { + screen = storage->render_target_get_rd_backbuffer(p_to_render_target); + if (screen.is_null()) { //unallocated backbuffer + screen = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + } + } + u.ids.push_back(screen); + uniforms.push_back(u); + } + + { + //needs samplers for the material (uses custom textures) create them + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 7; + u.ids.resize(12); + RID *ids_ptr = u.ids.ptrw(); + ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 8; + u.ids.push_back(storage->global_variables_get_storage_buffer()); + uniforms.push_back(u); + } + + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, BASE_UNIFORM_SET); + if (p_backbuffer) { + storage->render_target_set_backbuffer_uniform_set(p_to_render_target, uniform_set); + } else { + storage->render_target_set_framebuffer_uniform_set(p_to_render_target, uniform_set); + } + + return uniform_set; +} + +void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer) { Item *current_clip = nullptr; Transform2D canvas_transform_inverse = p_canvas_transform_inverse; - RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target); - - Vector<Color> clear_colors; + RID framebuffer; + RID fb_uniform_set; bool clear = false; - if (storage->render_target_is_clear_requested(p_to_render_target)) { - clear = true; - clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target)); - storage->render_target_disable_clear_request(p_to_render_target); - } + Vector<Color> clear_colors; + + if (p_to_backbuffer) { + framebuffer = storage->render_target_get_rd_backbuffer_framebuffer(p_to_render_target); + fb_uniform_set = storage->render_target_get_backbuffer_uniform_set(p_to_render_target); + } else { + framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target); + + if (storage->render_target_is_clear_requested(p_to_render_target)) { + clear = true; + clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target)); + 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 + fb_uniform_set = storage->render_target_get_framebuffer_uniform_set(p_to_render_target); + } + + if (fb_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(fb_uniform_set)) { + fb_uniform_set = _create_base_uniform_set(p_to_render_target, p_to_backbuffer); + } + RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); - if (p_screen_uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_screen_uniform_set, 3); - } + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, fb_uniform_set, BASE_UNIFORM_SET); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, state.default_transforms_uniform_set, TRANSFORMS_UNIFORM_SET); + RID prev_material; PipelineVariants *pipeline_variants = &shader.pipeline_variants; @@ -1339,17 +1156,23 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, } } - if (ci->material != prev_material) { + RID material = ci->material; + + if (material.is_null() && ci->canvas_group != nullptr) { + material = default_canvas_group_material; + } + + if (material != prev_material) { MaterialData *material_data = nullptr; - if (ci->material.is_valid()) { - material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); + if (material.is_valid()) { + material_data = (MaterialData *)storage->material_get_data(material, RasterizerStorageRD::SHADER_TYPE_2D); } if (material_data) { if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) { pipeline_variants = &material_data->shader_data->pipeline_variants; if (material_data->uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, MATERIAL_UNIFORM_SET); } } else { pipeline_variants = &shader.pipeline_variants; @@ -1361,55 +1184,89 @@ void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, _render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants); - prev_material = ci->material; + prev_material = material; } RD::get_singleton()->draw_list_end(); } -void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) { +void RasterizerCanvasRD::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, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) { int item_count = 0; //setup canvas state uniforms if needed Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse(); + //setup directional lights if exist + + uint32_t light_count = 0; + uint32_t directional_light_count = 0; { - //update canvas state uniform buffer - State::Buffer state_buffer; + Light *l = p_directional_light_list; + uint32_t index = 0; - Size2i ssize = storage->render_target_get_size(p_to_render_target); + while (l) { + if (index == state.max_lights_per_render) { + l->render_index_cache = -1; + l = l->next_ptr; + continue; + } - Transform screen_transform; - screen_transform.translate(-(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); + CanvasLight *clight = canvas_light_owner.getornull(l->light_internal); + if (!clight) { //unused or invalid texture + l->render_index_cache = -1; + l = l->next_ptr; + ERR_CONTINUE(!clight); + } - Transform2D normal_transform = p_canvas_transform; - normal_transform.elements[0].normalize(); - normal_transform.elements[1].normalize(); - normal_transform.elements[2] = Vector2(); - _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform); + Vector2 canvas_light_dir = l->xform_cache.elements[1].normalized(); - state_buffer.canvas_modulate[0] = p_modulate.r; - state_buffer.canvas_modulate[1] = p_modulate.g; - state_buffer.canvas_modulate[2] = p_modulate.b; - state_buffer.canvas_modulate[3] = p_modulate.a; + state.light_uniforms[index].position[0] = -canvas_light_dir.x; + state.light_uniforms[index].position[1] = -canvas_light_dir.y; - Size2 render_target_size = storage->render_target_get_size(p_to_render_target); - state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x; - state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y; + _update_transform_2d_to_mat2x4(clight->shadow.directional_xform, state.light_uniforms[index].shadow_matrix); - state_buffer.time = state.time; - RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true); + state.light_uniforms[index].height = l->height; //0..1 here + + for (int i = 0; i < 4; i++) { + state.light_uniforms[index].shadow_color[i] = uint8_t(CLAMP(int32_t(l->shadow_color[i] * 255.0), 0, 255)); + state.light_uniforms[index].color[i] = l->color[i]; + } + + state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate + + if (state.shadow_fb.is_valid()) { + state.light_uniforms[index].shadow_pixel_size = (1.0 / state.shadow_texture_size) * (1.0 + l->shadow_smooth); + state.light_uniforms[index].shadow_z_far_inv = 1.0 / clight->shadow.z_far; + state.light_uniforms[index].shadow_y_ofs = clight->shadow.y_offset; + } else { + state.light_uniforms[index].shadow_pixel_size = 1.0; + state.light_uniforms[index].shadow_z_far_inv = 1.0; + state.light_uniforms[index].shadow_y_ofs = 0; + } + + state.light_uniforms[index].flags = l->blend_mode << LIGHT_FLAGS_BLEND_SHIFT; + state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT; + if (clight->shadow.enabled) { + state.light_uniforms[index].flags |= LIGHT_FLAGS_HAS_SHADOW; + } + + l->render_index_cache = index; + + index++; + l = l->next_ptr; + } + + light_count = index; + directional_light_count = light_count; + using_directional_lights = directional_light_count > 0; } //setup lights if exist { Light *l = p_light_list; - uint32_t index = 0; + uint32_t index = light_count; while (l) { if (index == state.max_lights_per_render) { @@ -1435,33 +1292,93 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss for (int i = 0; i < 4; i++) { - state.light_uniforms[index].shadow_color[i] = l->shadow_color[i]; + state.light_uniforms[index].shadow_color[i] = uint8_t(CLAMP(int32_t(l->shadow_color[i] * 255.0), 0, 255)); state.light_uniforms[index].color[i] = l->color[i]; } state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate - if (clight->shadow.texture.is_valid()) { - state.light_uniforms[index].shadow_pixel_size = (1.0 / clight->shadow.size) * (1.0 + l->shadow_smooth); + if (state.shadow_fb.is_valid()) { + state.light_uniforms[index].shadow_pixel_size = (1.0 / state.shadow_texture_size) * (1.0 + l->shadow_smooth); + state.light_uniforms[index].shadow_z_far_inv = 1.0 / clight->shadow.z_far; + state.light_uniforms[index].shadow_y_ofs = clight->shadow.y_offset; } else { state.light_uniforms[index].shadow_pixel_size = 1.0; + state.light_uniforms[index].shadow_z_far_inv = 1.0; + state.light_uniforms[index].shadow_y_ofs = 0; } - state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT; + state.light_uniforms[index].flags = l->blend_mode << LIGHT_FLAGS_BLEND_SHIFT; state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT; - if (clight->shadow.texture.is_valid()) { + if (clight->shadow.enabled) { state.light_uniforms[index].flags |= LIGHT_FLAGS_HAS_SHADOW; } + if (clight->texture.is_valid()) { + Rect2 atlas_rect = storage->decal_atlas_get_texture_rect(clight->texture); + state.light_uniforms[index].atlas_rect[0] = atlas_rect.position.x; + state.light_uniforms[index].atlas_rect[1] = atlas_rect.position.y; + state.light_uniforms[index].atlas_rect[2] = atlas_rect.size.width; + state.light_uniforms[index].atlas_rect[3] = atlas_rect.size.height; + + } else { + state.light_uniforms[index].atlas_rect[0] = 0; + state.light_uniforms[index].atlas_rect[1] = 0; + state.light_uniforms[index].atlas_rect[2] = 0; + state.light_uniforms[index].atlas_rect[3] = 0; + } + l->render_index_cache = index; index++; l = l->next_ptr; } - if (index > 0) { - RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * index, &state.light_uniforms[0], true); - } + light_count = index; + } + + if (light_count > 0) { + RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * light_count, &state.light_uniforms[0], true); + } + + { + //update canvas state uniform buffer + State::Buffer state_buffer; + + Size2i ssize = storage->render_target_get_size(p_to_render_target); + + Transform screen_transform; + screen_transform.translate(-(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); + + Transform2D normal_transform = p_canvas_transform; + normal_transform.elements[0].normalize(); + normal_transform.elements[1].normalize(); + normal_transform.elements[2] = Vector2(); + _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform); + + state_buffer.canvas_modulate[0] = p_modulate.r; + state_buffer.canvas_modulate[1] = p_modulate.g; + state_buffer.canvas_modulate[2] = p_modulate.b; + state_buffer.canvas_modulate[3] = p_modulate.a; + + Size2 render_target_size = storage->render_target_get_size(p_to_render_target); + state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x; + state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y; + + state_buffer.time = state.time; + state_buffer.use_pixel_snap = p_snap_2d_vertices_to_pixel; + + state_buffer.directional_light_count = directional_light_count; + + RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true); + } + + { //default filter/repeat + default_filter = p_default_filter; + default_repeat = p_default_repeat; } //fill the list until rendering is possible. @@ -1469,10 +1386,11 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite Item *ci = p_item_list; Rect2 back_buffer_rect; bool backbuffer_copy = false; - RID screen_uniform_set; + + Item *canvas_group_owner = nullptr; while (ci) { - if (ci->copy_back_buffer) { + if (ci->copy_back_buffer && canvas_group_owner == nullptr) { backbuffer_copy = true; if (ci->copy_back_buffer->full) { @@ -1485,15 +1403,11 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite if (ci->material.is_valid()) { MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); if (md && md->shader_data->valid) { - if (md->shader_data->uses_screen_texture) { + if (md->shader_data->uses_screen_texture && canvas_group_owner == nullptr) { if (!material_screen_texture_found) { backbuffer_copy = true; back_buffer_rect = Rect2(); } - if (screen_uniform_set.is_null()) { - RID backbuffer_shader = shader.canvas_shader.version_get_shader(md->shader_data->version, 0); //any version is fine - screen_uniform_set = storage->render_target_get_back_buffer_uniform_set(p_to_render_target, backbuffer_shader); - } } if (md->last_frame != RasterizerRD::singleton->get_frame_number()) { @@ -1507,12 +1421,44 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite } } + if (ci->canvas_group_owner != nullptr) { + if (canvas_group_owner == nullptr) { + //Canvas group begins here, render until before this item + _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) { + storage->render_target_copy_to_back_buffer(p_to_render_target, group_rect, false); + } else { + storage->render_target_clear_back_buffer(p_to_render_target, group_rect, Color(0, 0, 0, 0)); + } + + backbuffer_copy = false; + canvas_group_owner = ci->canvas_group_owner; //continue until owner found + } + + ci->canvas_group_owner = nullptr; //must be cleared + } + + if (ci == canvas_group_owner) { + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, true); + item_count = 0; + + if (ci->canvas_group->blur_mipmaps) { + storage->render_target_gen_back_buffer_mipmaps(p_to_render_target, ci->global_rect_cache); + } + + canvas_group_owner = nullptr; + } + if (backbuffer_copy) { //render anything pending, including clearing if no items - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); item_count = 0; - storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect); + storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect, true); backbuffer_copy = false; material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies @@ -1521,7 +1467,7 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite items[item_count++] = ci; if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set); + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list); //then reset item_count = 0; } @@ -1532,7 +1478,6 @@ void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_ite RID RasterizerCanvasRD::light_create() { CanvasLight canvas_light; - canvas_light.shadow.size = 0; return canvas_light_owner.make_rid(canvas_light); } @@ -1542,71 +1487,74 @@ void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { if (cl->texture == p_texture) { return; } - + if (cl->texture.is_valid()) { + storage->texture_remove_from_decal_atlas(cl->texture); + } cl->texture = p_texture; + + if (cl->texture.is_valid()) { + storage->texture_add_to_decal_atlas(cl->texture); + } } -void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) { +void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND(!cl); - ERR_FAIL_COND(p_resolution < 64); - if (cl->shadow.texture.is_valid() == p_enable && p_resolution == cl->shadow.size) { - return; - } - if (cl->shadow.texture.is_valid()) { - RD::get_singleton()->free(cl->shadow.fb); - RD::get_singleton()->free(cl->shadow.depth); - RD::get_singleton()->free(cl->shadow.texture); - cl->shadow.fb = RID(); - cl->shadow.texture = RID(); - cl->shadow.depth = RID(); - } + cl->shadow.enabled = p_enable; +} + +void RasterizerCanvasRD::_update_shadow_atlas() { + if (state.shadow_fb == RID()) { + //ah, we lack the shadow texture.. + RD::get_singleton()->free(state.shadow_texture); //erase placeholder - if (p_enable) { Vector<RID> fb_textures; { //texture RD::TextureFormat tf; tf.type = RD::TEXTURE_TYPE_2D; - tf.width = p_resolution; - tf.height = 1; + tf.width = state.shadow_texture_size; + tf.height = state.max_lights_per_render * 2; tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; tf.format = RD::DATA_FORMAT_R32_SFLOAT; - cl->shadow.texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - fb_textures.push_back(cl->shadow.texture); + state.shadow_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + fb_textures.push_back(state.shadow_texture); } { RD::TextureFormat tf; tf.type = RD::TEXTURE_TYPE_2D; - tf.width = p_resolution; - tf.height = 1; + tf.width = state.shadow_texture_size; + tf.height = state.max_lights_per_render * 2; tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT; + tf.format = RD::DATA_FORMAT_D32_SFLOAT; //chunks to write - cl->shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - fb_textures.push_back(cl->shadow.depth); + state.shadow_depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + fb_textures.push_back(state.shadow_depth_texture); } - cl->shadow.fb = RD::get_singleton()->framebuffer_create(fb_textures); + state.shadow_fb = RD::get_singleton()->framebuffer_create(fb_textures); } - - cl->shadow.size = p_resolution; } - -void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { +void RasterizerCanvasRD::light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); - ERR_FAIL_COND(cl->shadow.texture.is_null()); + ERR_FAIL_COND(!cl->shadow.enabled); + + _update_shadow_atlas(); + + cl->shadow.z_far = p_far; + cl->shadow.y_offset = float(p_shadow_index * 2 + 1) / float(state.max_lights_per_render * 2); + Vector<Color> cc; + cc.push_back(Color(p_far, p_far, p_far, 1.0)); for (int i = 0; i < 4; i++) { //make sure it remains orthogonal, makes easy to read angle later //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); - Vector<Color> cc; - cc.push_back(Color(p_far, p_far, p_far, 1.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, Rect2i((cl->shadow.size / 4) * i, 0, (cl->shadow.size / 4), 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); CameraMatrix projection; { @@ -1635,8 +1583,8 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; push_constant.direction[0] = directions[i].x; push_constant.direction[1] = directions[i].y; - push_constant.pad[0] = 0; - push_constant.pad[1] = 0; + push_constant.z_far = p_far; + push_constant.pad = 0; /*if (i == 0) *p_xform_cache = projection;*/ @@ -1667,6 +1615,86 @@ void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_lig } } +void RasterizerCanvasRD::light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders) { + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND(!cl->shadow.enabled); + + _update_shadow_atlas(); + + Vector2 light_dir = p_light_xform.elements[1].normalized(); + + Vector2 center = p_clip_rect.position + p_clip_rect.size * 0.5; + + float to_edge_distance = ABS(light_dir.dot(p_clip_rect.get_support(light_dir)) - light_dir.dot(center)); + + Vector2 from_pos = center - light_dir * (to_edge_distance + p_cull_distance); + float distance = to_edge_distance * 2.0 + p_cull_distance; + float half_size = p_clip_rect.size.length() * 0.5; //shadow length, must keep this no matter the angle + + cl->shadow.z_far = distance; + cl->shadow.y_offset = float(p_shadow_index * 2 + 1) / float(state.max_lights_per_render * 2); + + Transform2D to_light_xform; + + to_light_xform[2] = from_pos; + to_light_xform[1] = light_dir; + to_light_xform[0] = -light_dir.tangent(); + + to_light_xform.invert(); + + Vector<Color> cc; + 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); + + CameraMatrix projection; + projection.set_orthogonal(-half_size, half_size, -0.5, 0.5, 0.0, distance); + projection = projection * CameraMatrix(Transform().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.direction[0] = 0.0; + push_constant.direction[1] = 1.0; + push_constant.z_far = distance; + push_constant.pad = 0; + + LightOccluderInstance *instance = p_occluders; + + while (instance) { + OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder); + + if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) { + instance = instance->next; + continue; + } + + _update_transform_2d_to_mat2x4(to_light_xform * instance->xform_cache, push_constant.modelview); + + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[co->cull_mode]); + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, co->index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ShadowRenderPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + + instance = instance->next; + } + + RD::get_singleton()->draw_list_end(); + + Transform2D to_shadow; + to_shadow.elements[0].x = 1.0 / -(half_size * 2.0); + to_shadow.elements[2].x = 0.5; + + cl->shadow.directional_xform = to_shadow * to_light_xform; +} + RID RasterizerCanvasRD::occluder_polygon_create() { OccluderPolygon occluder; occluder.point_count = 0; @@ -1774,7 +1802,6 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { ubo_size = 0; uniforms.clear(); uses_screen_texture = false; - uses_material_samplers = false; if (code == String()) { return; //just invalid, but no error @@ -1812,10 +1839,6 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { version = canvas_singleton->shader.canvas_shader.version_create(); } - if (gen_code.texture_uniforms.size() || uses_screen_texture) { //requires the samplers - gen_code.defines.push_back("\n#define USE_MATERIAL_SAMPLERS\n"); - uses_material_samplers = true; - } #if 0 print_line("**compiling shader:"); print_line("**defines:\n"); @@ -1847,10 +1870,11 @@ void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { } break; case BLEND_MODE_MIX: { attachment.enable_blend = true; - attachment.alpha_blend_op = RD::BLEND_OP_ADD; attachment.color_blend_op = RD::BLEND_OP_ADD; attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + attachment.alpha_blend_op = RD::BLEND_OP_ADD; attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; @@ -2022,7 +2046,6 @@ Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName & RasterizerCanvasRD::ShaderData::ShaderData() { valid = false; uses_screen_texture = false; - uses_material_samplers = false; } RasterizerCanvasRD::ShaderData::~ShaderData() { @@ -2085,7 +2108,7 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false); } - if (shader_data->ubo_size == 0 && !shader_data->uses_material_samplers) { + if (shader_data->ubo_size == 0) { // This material does not require an uniform set, so don't create it. return; } @@ -2098,32 +2121,10 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V Vector<RD::Uniform> uniforms; { - if (shader_data->uses_material_samplers) { - //needs samplers for the material (uses custom textures) create them - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 0; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); - ids_ptr[0] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - uniforms.push_back(u); - } - if (shader_data->ubo_size) { RD::Uniform u; u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 1; + u.binding = 0; u.ids.push_back(uniform_buffer); uniforms.push_back(u); } @@ -2132,13 +2133,13 @@ void RasterizerCanvasRD::MaterialData::update_parameters(const Map<StringName, V for (uint32_t i = 0; i < tex_uniform_count; i++) { RD::Uniform u; u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2 + i; + u.binding = 1 + i; u.ids.push_back(textures[i]); uniforms.push_back(u); } } - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), 1); + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); } RasterizerCanvasRD::MaterialData::~MaterialData() { @@ -2164,7 +2165,6 @@ void RasterizerCanvasRD::set_time(double p_time) { } void RasterizerCanvasRD::update() { - _dispose_bindings(); } RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { @@ -2178,22 +2178,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { { //shader variants - uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); - String global_defines; - if (textures_per_stage <= 16) { - //ARM pretty much, and very old Intel GPUs under Linux - state.max_lights_per_item = 4; //sad - global_defines += "#define MAX_LIGHT_TEXTURES 4\n"; - } else if (textures_per_stage <= 32) { - //Apple (Metal) - state.max_lights_per_item = 8; //sad - global_defines += "#define MAX_LIGHT_TEXTURES 8\n"; - } else { - //Anything else (16 lights per item) - state.max_lights_per_item = DEFAULT_MAX_LIGHTS_PER_ITEM; - global_defines += "#define MAX_LIGHT_TEXTURES " + itos(DEFAULT_MAX_LIGHTS_PER_ITEM) + "\n"; - } uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); if (uniform_max_size < 65536) { @@ -2226,7 +2211,20 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { shader.default_version = shader.canvas_shader.version_create(); shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD); - shader.default_version_rd_shader_light = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD_LIGHT); + + RD::PipelineColorBlendState blend_state; + RD::PipelineColorBlendState::Attachment blend_attachment; + + blend_attachment.enable_blend = true; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + blend_state.attachments.push_back(blend_attachment); for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { @@ -2269,7 +2267,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { }; 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(), RD::PipelineColorBlendState::create_blend(), 0); + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); } } } @@ -2327,8 +2325,8 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { actions.custom_samplers["SPECULAR_SHININESS_TEXTURE"] = "texture_sampler"; actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; //mipmap and filter for screen texture actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 2; - actions.texture_layout_set = 1; + actions.base_texture_binding_index = 1; + actions.texture_layout_set = MATERIAL_UNIFORM_SET; actions.base_uniform_string = "material."; actions.default_filter = ShaderLanguage::FILTER_LINEAR; actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; @@ -2354,7 +2352,7 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { attachments.push_back(af_color); RD::AttachmentFormat af_depth; - af_depth.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; + af_depth.format = RD::DATA_FORMAT_D32_SFLOAT; af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; attachments.push_back(af_depth); @@ -2386,21 +2384,17 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { } { //bindings - bindings.id_generator = 0; - //generate for 0 - bindings.default_empty = request_texture_binding(RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, RID()); - - { //state allocate - state.canvas_state_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(State::Buffer)); - state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render); - - RD::SamplerState shadow_sampler_state; - shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - shadow_sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; //shadow wrap around - shadow_sampler_state.compare_op = RD::COMPARE_OP_GREATER; - state.shadow_sampler = RD::get_singleton()->sampler_create(shadow_sampler_state); - } + + state.canvas_state_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(State::Buffer)); + state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render); + + RD::SamplerState shadow_sampler_state; + shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + shadow_sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; //shadow wrap around + shadow_sampler_state.compare_op = RD::COMPARE_OP_GREATER; + shadow_sampler_state.enable_compare = true; + state.shadow_sampler = RD::get_singleton()->sampler_create(shadow_sampler_state); } { @@ -2443,6 +2437,35 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT); } + { + //default shadow texture to keep uniform set happy + RD::TextureFormat tf; + tf.type = RD::TEXTURE_TYPE_2D; + tf.width = 4; + tf.height = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + + state.shadow_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + { + Vector<RD::Uniform> uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(storage->get_default_rd_storage_buffer()); + uniforms.push_back(u); + } + + state.default_transforms_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, TRANSFORMS_UNIFORM_SET); + } + + default_canvas_texture = storage->canvas_texture_create(); + + state.shadow_texture_size = GLOBAL_GET("rendering/quality/2d_shadow_atlas/size"); //create functions for shader and material storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_shader_funcs); @@ -2450,6 +2473,13 @@ RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { state.time = 0; + { + default_canvas_group_shader = storage->shader_create(); + storage->shader_set_code(default_canvas_group_shader, "shader_type canvas_item; \nvoid fragment() {\n\tvec4 c = textureLod(SCREEN_TEXTURE,SCREEN_UV,0.0); if (c.a > 0.0001) c.rgb/=c.a; COLOR *= c; \n}\n"); + default_canvas_group_material = storage->material_create(); + storage->material_set_shader(default_canvas_group_material, default_canvas_group_shader); + } + static_assert(sizeof(PushConstant) == 128); } @@ -2457,7 +2487,7 @@ bool RasterizerCanvasRD::free(RID p_rid) { if (canvas_light_owner.owns(p_rid)) { CanvasLight *cl = canvas_light_owner.getornull(p_rid); ERR_FAIL_COND_V(!cl, false); - light_set_use_shadow(p_rid, false, 64); + light_set_use_shadow(p_rid, false); canvas_light_owner.free(p_rid); } else if (occluder_polygon_owner.owns(p_rid)) { occluder_polygon_set_shape_as_lines(p_rid, Vector<Vector2>()); @@ -2469,9 +2499,37 @@ bool RasterizerCanvasRD::free(RID p_rid) { return true; } +void RasterizerCanvasRD::set_shadow_texture_size(int p_size) { + p_size = nearest_power_of_2_templated(p_size); + if (p_size == state.shadow_texture_size) { + return; + } + state.shadow_texture_size = p_size; + if (state.shadow_fb.is_valid()) { + RD::get_singleton()->free(state.shadow_texture); + RD::get_singleton()->free(state.shadow_depth_texture); + state.shadow_fb = RID(); + + { + //create a default shadow texture to keep uniform set happy (and that it gets erased when a new one is created) + RD::TextureFormat tf; + tf.type = RD::TEXTURE_TYPE_2D; + tf.width = 4; + tf.height = 4; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + + state.shadow_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + } +} + RasterizerCanvasRD::~RasterizerCanvasRD() { //canvas state + storage->free(default_canvas_group_material); + storage->free(default_canvas_group_shader); + { if (state.canvas_state_buffer.is_valid()) { RD::get_singleton()->free(state.canvas_state_buffer); @@ -2490,24 +2548,6 @@ RasterizerCanvasRD::~RasterizerCanvasRD() { RD::get_singleton()->free(state.shadow_sampler); } //bindings - { - free_texture_binding(bindings.default_empty); - - //dispose pending - _dispose_bindings(); - //anything remains? - if (bindings.texture_bindings.size()) { - ERR_PRINT("Some texture bindings were not properly freed (leaked CanvasItems?)"); - const TextureBindingID *key = nullptr; - while ((key = bindings.texture_bindings.next(key))) { - TextureBinding *tb = bindings.texture_bindings[*key]; - tb->reference_count = 1; - free_texture_binding(*key); - } - //dispose pending - _dispose_bindings(); - } - } //shaders @@ -2520,5 +2560,13 @@ RasterizerCanvasRD::~RasterizerCanvasRD() { //primitives are erase by dependency } + if (state.shadow_fb.is_valid()) { + RD::get_singleton()->free(state.shadow_depth_texture); + } + RD::get_singleton()->free(state.shadow_texture); + + storage->free(default_canvas_texture); //pipelines don't need freeing, they are all gone after shaders are gone + + RD::get_singleton()->free(state.default_transforms_uniform_set); } diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h index bfe4e61f47..b516f63cbf 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h @@ -42,6 +42,13 @@ class RasterizerCanvasRD : public RasterizerCanvas { RasterizerStorageRD *storage; + enum { + BASE_UNIFORM_SET = 0, + MATERIAL_UNIFORM_SET = 1, + TRANSFORMS_UNIFORM_SET = 2, + CANVAS_TEXTURE_UNIFORM_SET = 3, + }; + enum ShaderVariant { SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, @@ -68,11 +75,9 @@ class RasterizerCanvasRD : public RasterizerCanvas { FLAGS_CLIP_RECT_UV = (1 << 9), FLAGS_TRANSPOSE_RECT = (1 << 10), - FLAGS_USING_LIGHT_MASK = (1 << 11), FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), FLAGS_USING_PARTICLES = (1 << 13), - FLAGS_USE_PIXEL_SNAP = (1 << 14), FLAGS_USE_SKELETON = (1 << 15), FLAGS_NINEPATCH_H_MODE_SHIFT = 16, @@ -100,7 +105,7 @@ class RasterizerCanvasRD : public RasterizerCanvas { enum { MAX_RENDER_ITEMS = 256 * 1024, MAX_LIGHT_TEXTURES = 1024, - DEFAULT_MAX_LIGHTS_PER_ITEM = 16, + MAX_LIGHTS_PER_ITEM = 16, DEFAULT_MAX_LIGHTS_PER_RENDER = 256 }; @@ -135,7 +140,6 @@ class RasterizerCanvasRD : public RasterizerCanvas { CanvasShaderRD canvas_shader; RID default_version; RID default_version_rd_shader; - RID default_version_rd_shader_light; RID quad_index_buffer; RID quad_index_array; PipelineVariants pipeline_variants; @@ -178,7 +182,6 @@ class RasterizerCanvasRD : public RasterizerCanvas { Map<StringName, RID> default_texture_params; bool uses_screen_texture; - bool uses_material_samplers; virtual void set_code(const String &p_Code); virtual void set_default_texture_param(const StringName &p_name, RID p_texture); @@ -218,60 +221,9 @@ class RasterizerCanvasRD : public RasterizerCanvas { } /**************************/ - /**** TEXTURE BINDINGS ****/ + /**** CANVAS TEXTURES *****/ /**************************/ - // bindings used to render commands, - // cached for performance. - - struct TextureBindingKey { - RID texture; - RID normalmap; - RID specular; - RID multimesh; - RS::CanvasItemTextureFilter texture_filter; - RS::CanvasItemTextureRepeat texture_repeat; - bool operator==(const TextureBindingKey &p_key) const { - return texture == p_key.texture && normalmap == p_key.normalmap && specular == p_key.specular && multimesh == p_key.specular && texture_filter == p_key.texture_filter && texture_repeat == p_key.texture_repeat; - } - }; - - struct TextureBindingKeyHasher { - static _FORCE_INLINE_ uint32_t hash(const TextureBindingKey &p_key) { - uint32_t hash = hash_djb2_one_64(p_key.texture.get_id()); - hash = hash_djb2_one_64(p_key.normalmap.get_id(), hash); - hash = hash_djb2_one_64(p_key.specular.get_id(), hash); - hash = hash_djb2_one_64(p_key.multimesh.get_id(), hash); - hash = hash_djb2_one_32(uint32_t(p_key.texture_filter) << 16 | uint32_t(p_key.texture_repeat), hash); - return hash; - } - }; - - struct TextureBinding { - TextureBindingID id; - TextureBindingKey key; - SelfList<TextureBinding> to_dispose; - uint32_t reference_count; - RID uniform_set; - TextureBinding() : - to_dispose(this) { - reference_count = 0; - } - }; - - struct { - SelfList<TextureBinding>::List to_dispose_list; - - TextureBindingID id_generator; - HashMap<TextureBindingKey, TextureBindingID, TextureBindingKeyHasher> texture_key_bindings; - HashMap<TextureBindingID, TextureBinding *> texture_bindings; - - TextureBindingID default_empty; - } bindings; - - RID _create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh); - void _dispose_bindings(); - struct { RS::CanvasItemTextureFilter default_filter; RS::CanvasItemTextureRepeat default_repeat; @@ -313,10 +265,10 @@ class RasterizerCanvasRD : public RasterizerCanvas { struct CanvasLight { RID texture; struct { - int size; - RID texture; - RID depth; - RID fb; + bool enabled = false; + float z_far; + float y_offset; + Transform2D directional_xform; } shadow; }; @@ -326,7 +278,8 @@ class RasterizerCanvasRD : public RasterizerCanvas { float projection[16]; float modelview[8]; float direction[2]; - float pad[2]; + float z_far; + float pad; }; struct OccluderPolygon { @@ -342,12 +295,17 @@ class RasterizerCanvasRD : public RasterizerCanvas { float matrix[8]; //light to texture coordinate matrix float shadow_matrix[8]; //light to shadow coordinate matrix float color[4]; - float shadow_color[4]; - float position[2]; + + uint8_t shadow_color[4]; uint32_t flags; //index to light texture - float height; float shadow_pixel_size; - float pad[3]; + float height; + + float position[2]; + float shadow_z_far_inv; + float shadow_y_ofs; + + float atlas_rect[4]; }; RID_Owner<OccluderPolygon> occluder_polygon_owner; @@ -366,34 +324,6 @@ class RasterizerCanvasRD : public RasterizerCanvas { //state that does not vary across rendering all items - struct ItemStateData : public Item::CustomData { - struct LightCache { - uint64_t light_version; - Light *light; - }; - - LightCache light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; - uint32_t light_cache_count; - RID state_uniform_set_with_light; - RID state_uniform_set; - ItemStateData() { - for (int i = 0; i < DEFAULT_MAX_LIGHTS_PER_ITEM; i++) { - light_cache[i].light_version = 0; - light_cache[i].light = nullptr; - } - light_cache_count = 0xFFFFFFFF; - } - - ~ItemStateData() { - if (state_uniform_set_with_light.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set_with_light)) { - RD::get_singleton()->free(state_uniform_set_with_light); - } - if (state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set)) { - RD::get_singleton()->free(state_uniform_set); - } - } - }; - struct State { //state buffer struct Buffer { @@ -401,12 +331,13 @@ class RasterizerCanvasRD : public RasterizerCanvas { float screen_transform[16]; float canvas_normal_transform[16]; float canvas_modulate[4]; + float screen_pixel_size[2]; float time; - float pad; + uint32_t use_pixel_snap; - //uint32_t light_count; - //uint32_t pad[3]; + uint32_t directional_light_count; + uint32_t pad[3]; }; LightUniform *light_uniforms; @@ -414,11 +345,18 @@ class RasterizerCanvasRD : public RasterizerCanvas { RID lights_uniform_buffer; RID canvas_state_buffer; RID shadow_sampler; + RID shadow_texture; + RID shadow_depth_texture; + RID shadow_fb; + int shadow_texture_size = 2048; + + RID default_transforms_uniform_set; uint32_t max_lights_per_render; uint32_t max_lights_per_item; double time; + } state; struct PushConstant { @@ -452,9 +390,20 @@ class RasterizerCanvasRD : public RasterizerCanvas { Item *items[MAX_RENDER_ITEMS]; - Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags); + bool using_directional_lights = false; + RID default_canvas_texture; + + RID default_canvas_group_shader; + RID default_canvas_group_material; + + RS::CanvasItemTextureFilter default_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; + RS::CanvasItemTextureRepeat default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; + + RID _create_base_uniform_set(RID p_to_render_target, bool p_backbuffer); + + inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead. void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants); - void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set); + void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false); _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); _FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3); @@ -462,30 +411,30 @@ class RasterizerCanvasRD : public RasterizerCanvas { _FORCE_INLINE_ void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4); _FORCE_INLINE_ void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4); - _FORCE_INLINE_ void _update_specular_shininess(const Color &p_transform, uint32_t *r_ss); + void _update_shadow_atlas(); public: - TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh); - void free_texture_binding(TextureBindingID p_binding); - PolygonID request_polygon(const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>()); void free_polygon(PolygonID p_polygon); RID light_create(); void light_set_texture(RID p_rid, RID p_texture); - void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution); - void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders); + void light_set_use_shadow(RID p_rid, bool p_enable); + void light_update_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders); + void light_update_directional_shadow(RID p_rid, int p_shadow_index, const Transform2D &p_light_xform, int p_light_mask, float p_cull_distance, const Rect2 &p_clip_rect, LightOccluderInstance *p_occluders); RID occluder_polygon_create(); void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector<Vector2> &p_lines); void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode); - void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform); + 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); void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) {} void draw_window_margins(int *p_margins, RID *p_margin_textures) {} + virtual void set_shadow_texture_size(int p_size); + void set_time(double p_time); void update(); bool free(RID p_rid); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp index 71acd4ceb6..97c1e7ba70 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp @@ -30,8 +30,8 @@ #include "rasterizer_effects_rd.h" +#include "core/config/project_settings.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "thirdparty/misc/cubemap_coeffs.h" @@ -246,7 +246,7 @@ void RasterizerEffectsRD::copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_fr RD::get_singleton()->draw_list_end(); } -void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst) { +void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, bool p_force_luminance, bool p_all_source, bool p_8_bit_dst, bool p_alpha_to_one) { zeromem(©.push_constant, sizeof(CopyPushConstant)); if (p_flip_y) { copy.push_constant.flags |= COPY_FLAG_FLIP_Y; @@ -260,6 +260,10 @@ void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_textu copy.push_constant.flags |= COPY_FLAG_ALL_SOURCE; } + if (p_alpha_to_one) { + 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[2] = p_rect.size.width; @@ -354,6 +358,31 @@ void RasterizerEffectsRD::copy_depth_to_rect(RID p_source_rd_texture, RID p_dest RD::get_singleton()->compute_list_end(); } +void RasterizerEffectsRD::set_color(RID p_dest_texture, const Color &p_color, const Rect2i &p_region, bool p_8bit_dst) { + zeromem(©.push_constant, sizeof(CopyPushConstant)); + + copy.push_constant.section[0] = 0; + copy.push_constant.section[1] = 0; + copy.push_constant.section[2] = p_region.size.width; + copy.push_constant.section[3] = p_region.size.height; + copy.push_constant.target[0] = p_region.position.x; + copy.push_constant.target[1] = p_region.position.y; + copy.push_constant.set_color[0] = p_color.r; + copy.push_constant.set_color[1] = p_color.g; + copy.push_constant.set_color[2] = p_color.b; + copy.push_constant.set_color[3] = p_color.a; + + int32_t x_groups = (p_region.size.width - 1) / 8 + 1; + int32_t y_groups = (p_region.size.height - 1) / 8 + 1; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_SET_COLOR_8BIT : COPY_MODE_SET_COLOR]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_texture), 3); + RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_end(); +} + void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst) { zeromem(©.push_constant, sizeof(CopyPushConstant)); @@ -369,7 +398,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RD::DrawListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[p_8bit_dst ? COPY_MODE_GAUSSIAN_COPY_8BIT : COPY_MODE_GAUSSIAN_COPY]); 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_back_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3); copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL; RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); @@ -380,7 +409,7 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, //VERTICAL RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_back_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_texture), 3); copy.push_constant.flags = base_flags; RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); @@ -389,14 +418,14 @@ void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_texture, RD::get_singleton()->compute_list_end(); } -void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_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_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { +void RasterizerEffectsRD::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_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { zeromem(©.push_constant, sizeof(CopyPushConstant)); CopyMode copy_mode = p_first_pass && p_auto_exposure.is_valid() ? COPY_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : COPY_MODE_GAUSSIAN_GLOW; uint32_t base_flags = 0; - int32_t x_groups = (p_size.width - 1) / 8 + 1; - int32_t y_groups = (p_size.height - 1) / 8 + 1; + int32_t x_groups = (p_size.width + 7) / 8; + int32_t y_groups = (p_size.height + 7) / 8; copy.push_constant.section[2] = p_size.x; copy.push_constant.section[3] = p_size.y; @@ -411,29 +440,15 @@ void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_texture, copy.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also - //HORIZONTAL RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]); 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_texture), 3); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3); if (p_auto_exposure.is_valid() && p_first_pass) { RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_auto_exposure), 1); } - copy.push_constant.flags = base_flags | COPY_FLAG_HORIZONTAL | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - copy_mode = COPY_MODE_GAUSSIAN_GLOW; - - //VERTICAL - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, copy.pipelines[copy_mode]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_back_texture), 3); - - copy.push_constant.flags = base_flags; + copy.push_constant.flags = base_flags | (p_first_pass ? COPY_FLAG_GLOW_FIRST_PASS : 0) | (p_high_quality ? COPY_FLAG_HIGH_QUALITY_GLOW : 0); RD::get_singleton()->compute_list_set_push_constant(compute_list, ©.push_constant, sizeof(CopyPushConstant)); RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); @@ -692,7 +707,13 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, tonemap.push_constant.use_glow = p_settings.use_glow; tonemap.push_constant.glow_intensity = p_settings.glow_intensity; - tonemap.push_constant.glow_level_flags = p_settings.glow_level_flags; + tonemap.push_constant.glow_levels[0] = p_settings.glow_levels[0]; // clean this up to just pass by pointer or something + tonemap.push_constant.glow_levels[1] = p_settings.glow_levels[1]; + tonemap.push_constant.glow_levels[2] = p_settings.glow_levels[2]; + tonemap.push_constant.glow_levels[3] = p_settings.glow_levels[3]; + tonemap.push_constant.glow_levels[4] = p_settings.glow_levels[4]; + tonemap.push_constant.glow_levels[5] = p_settings.glow_levels[5]; + tonemap.push_constant.glow_levels[6] = p_settings.glow_levels[6]; tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x; tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y; tonemap.push_constant.glow_mode = p_settings.glow_mode; @@ -708,6 +729,7 @@ void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, tonemap.push_constant.use_color_correction = p_settings.use_color_correction; tonemap.push_constant.use_fxaa = p_settings.use_fxaa; + tonemap.push_constant.use_debanding = p_settings.use_debanding; tonemap.push_constant.pixel_size[0] = 1.0 / p_settings.texture_size.x; tonemap.push_constant.pixel_size[1] = 1.0 / p_settings.texture_size.y; @@ -1353,6 +1375,8 @@ RasterizerEffectsRD::RasterizerEffectsRD() { copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); copy_modes.push_back("\n#define MODE_SIMPLE_COPY\n#define DST_IMAGE_8BIT\n"); copy_modes.push_back("\n#define MODE_SIMPLE_COPY_DEPTH\n"); + copy_modes.push_back("\n#define MODE_SET_COLOR\n"); + copy_modes.push_back("\n#define MODE_SET_COLOR\n#define DST_IMAGE_8BIT\n"); copy_modes.push_back("\n#define MODE_MIPMAP\n"); copy_modes.push_back("\n#define MODE_LINEARIZE_DEPTH_COPY\n"); copy_modes.push_back("\n#define MODE_CUBEMAP_TO_PANORAMA\n"); diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h index e434bbc372..a0bdd59fd2 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h @@ -66,6 +66,8 @@ class RasterizerEffectsRD { COPY_MODE_SIMPLY_COPY, COPY_MODE_SIMPLY_COPY_8BIT, COPY_MODE_SIMPLY_COPY_DEPTH, + COPY_MODE_SET_COLOR, + COPY_MODE_SET_COLOR_8BIT, COPY_MODE_MIPMAP, COPY_MODE_LINEARIZE_DEPTH, COPY_MODE_CUBE_TO_PANORAMA, @@ -83,7 +85,8 @@ class RasterizerEffectsRD { COPY_FLAG_FLIP_Y = (1 << 5), COPY_FLAG_FORCE_LUMINANCE = (1 << 6), COPY_FLAG_ALL_SOURCE = (1 << 7), - COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8) + COPY_FLAG_HIGH_QUALITY_GLOW = (1 << 8), + COPY_FLAG_ALPHA_TO_ONE = (1 << 9), }; struct CopyPushConstant { @@ -105,6 +108,8 @@ class RasterizerEffectsRD { float camera_z_far; float camera_z_near; uint32_t pad2[2]; + //SET color + float set_color[4]; }; struct Copy { @@ -175,18 +180,20 @@ class RasterizerEffectsRD { uint32_t tonemapper; uint32_t glow_texture_size[2]; - float glow_intensity; - uint32_t glow_level_flags; + uint32_t pad3; + uint32_t glow_mode; + float glow_levels[7]; float exposure; float white; float auto_exposure_grey; + uint32_t pad2; float pixel_size[2]; uint32_t use_fxaa; - uint32_t pad; + uint32_t use_debanding; }; /* tonemap actually writes to a framebuffer, which is @@ -601,13 +608,14 @@ class RasterizerEffectsRD { public: void copy_to_fb_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2i &p_rect, bool p_flip_y = false, bool p_force_luminance = false, bool p_alpha_to_zero = false, bool p_srgb = false, RID p_secondary = RID()); - 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); + 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); void copy_depth_to_rect_and_linearize(RID p_source_rd_texture, RID p_dest_texture, const Rect2i &p_rect, bool p_flip_y, float p_z_near, float p_z_far); void copy_to_atlas_fb(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_uv_rect, RD::DrawListID p_draw_list, bool p_flip_y = false, bool p_panorama = false); void gaussian_blur(RID p_source_rd_texture, RID p_texture, RID p_back_texture, const Rect2i &p_region, bool p_8bit_dst = false); - void gaussian_glow(RID p_source_rd_texture, RID p_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_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); + void set_color(RID p_dest_texture, const Color &p_color, 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_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); void cubemap_roughness(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 make_mipmap(RID p_source_rd_texture, RID p_dest_texture, const Size2i &p_size); @@ -627,7 +635,7 @@ public: GlowMode glow_mode = GLOW_MODE_ADD; float glow_intensity = 1.0; - uint32_t glow_level_flags = 0; + float glow_levels[7] = { 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0 }; Vector2i glow_texture_size; bool glow_use_bicubic_upscale = false; RID glow_texture; @@ -649,6 +657,7 @@ public: RID color_correction_texture; bool use_fxaa = false; + bool use_debanding = false; Vector2i texture_size; }; diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp index 509bd3ee73..5f8cf0ee8c 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp @@ -30,7 +30,7 @@ #include "rasterizer_rd.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" void RasterizerRD::prepare_for_blitting_render_targets() { RD::get_singleton()->prepare_screen_for_drawing(); diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.h b/servers/rendering/rasterizer_rd/rasterizer_rd.h index cdcc6bfd73..59fb8d2049 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_rd.h @@ -32,7 +32,7 @@ #define RASTERIZER_RD_H #include "core/os/os.h" -#include "core/thread_work_pool.h" +#include "core/templates/thread_work_pool.h" #include "servers/rendering/rasterizer.h" #include "servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h" #include "servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h" diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index ac028e93f1..a275e46473 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "rasterizer_scene_high_end_rd.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server_raster.h" @@ -51,6 +51,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { int blend_mode = BLEND_MODE_MIX; int depth_testi = DEPTH_TEST_ENABLED; + int alpha_antialiasing_mode = ALPHA_ANTIALIASING_OFF; int cull = CULL_BACK; uses_point_size = false; @@ -82,6 +83,9 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { actions.render_mode_values["blend_sub"] = Pair<int *, int>(&blend_mode, BLEND_MODE_SUB); actions.render_mode_values["blend_mul"] = Pair<int *, int>(&blend_mode, BLEND_MODE_MUL); + actions.render_mode_values["alpha_to_coverage"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE); + actions.render_mode_values["alpha_to_coverage_and_one"] = Pair<int *, int>(&alpha_antialiasing_mode, ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE); + actions.render_mode_values["depth_draw_never"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_DISABLED); actions.render_mode_values["depth_draw_opaque"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_OPAQUE); actions.render_mode_values["depth_draw_always"] = Pair<int *, int>(&depth_drawi, DEPTH_DRAW_ALWAYS); @@ -154,6 +158,11 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { //blend modes + // if any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage + if (alpha_antialiasing_mode != ALPHA_ANTIALIASING_OFF) { + blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE; + } + RD::PipelineColorBlendState::Attachment blend_attachment; switch (blend_mode) { @@ -199,6 +208,15 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; uses_blend_alpha = true; //force alpha used because of blend } break; + case BLEND_MODE_ALPHA_TO_COVERAGE: { + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + } } RD::PipelineColorBlendState blend_state_blend; @@ -245,8 +263,17 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { RD::PipelineColorBlendState blend_state; RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; + RD::PipelineMultisampleState multisample_state; if (uses_alpha || uses_blend_alpha) { + // only allow these flags to go through if we have some form of msaa + if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE) { + multisample_state.enable_alpha_to_coverage = true; + } else if (alpha_antialiasing_mode == ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE) { + multisample_state.enable_alpha_to_coverage = true; + multisample_state.enable_alpha_to_one = true; + } + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_COLOR_PASS_WITH_FORWARD_GI || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { blend_state = blend_state_blend; if (depth_draw == DEPTH_DRAW_OPAQUE) { @@ -286,7 +313,7 @@ void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { } RID shader_variant = scene_singleton->shader.scene_shader.version_get_shader(version, k); - pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, RD::PipelineMultisampleState(), depth_stencil, blend_state, 0); + pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, multisample_state, depth_stencil, blend_state, 0); } } } @@ -1335,6 +1362,7 @@ void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, RID p_rende if (scene_state.ubo.fog_height_density >= 0.0001) { scene_state.ubo.fog_height_density = 1.0 / scene_state.ubo.fog_height_density; } + scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_environment); Color fog_color = environment_get_fog_light_color(p_environment).to_linear(); float fog_energy = environment_get_fog_light_energy(p_environment); @@ -2724,6 +2752,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.renames["POINT_SIZE"] = "gl_PointSize"; actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; + actions.renames["ALPHA_SCISSOR_THRESHOLD"] = "alpha_scissor_threshold"; + actions.renames["ALPHA_HASH_SCALE"] = "alpha_hash_scale"; + actions.renames["ALPHA_ANTIALIASING_EDGE"] = "alpha_antialiasing_edge"; + actions.renames["ALPHA_TEXTURE_COORDINATE"] = "alpha_texture_coordinate"; + //builtins actions.renames["TIME"] = "scene_data.time"; @@ -2761,6 +2794,9 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag 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["RADIANCE"] = "custom_radiance"; + actions.renames["IRRADIANCE"] = "custom_irradiance"; //for light actions.renames["VIEW"] = "view"; @@ -2789,6 +2825,11 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; + actions.usage_defines["ALPHA_SCISSOR_THRESHOLD"] = "#define ALPHA_SCISSOR_USED\n"; + actions.usage_defines["ALPHA_HASH_SCALE"] = "#define ALPHA_HASH_USED\n"; + actions.usage_defines["ALPHA_ANTIALIASING_EDGE"] = "#define ALPHA_ANTIALIASING_EDGE_USED\n"; + actions.usage_defines["ALPHA_TEXTURE_COORDINATE"] = "@ALPHA_ANTIALIASING_EDGE"; + actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; actions.usage_defines["SSS_TRANSMITTANCE_DEPTH"] = "#define ENABLE_TRANSMITTANCE\n"; actions.usage_defines["BACKLIGHT"] = "#define LIGHT_BACKLIGHT_USED\n"; @@ -2798,6 +2839,10 @@ RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storag actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; actions.usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions.usage_defines["FOG"] = "#define CUSTOM_FOG_USED\n"; + actions.usage_defines["RADIANCE"] = "#define CUSTOM_RADIANCE_USED\n"; + actions.usage_defines["IRRADIANCE"] = "#define CUSTOM_IRRADIANCE_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"; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h index 4c89928c95..db083a75cc 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -83,6 +83,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { BLEND_MODE_ADD, BLEND_MODE_SUB, BLEND_MODE_MUL, + BLEND_MODE_ALPHA_TO_COVERAGE }; enum DepthDraw { @@ -110,6 +111,12 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { }; + enum AlphaAntiAliasing { + ALPHA_ANTIALIASING_OFF, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE, + ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE + }; + bool valid; RID version; uint32_t vertex_input_mask; @@ -132,6 +139,7 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { bool uses_point_size; bool uses_alpha; bool uses_blend_alpha; + bool uses_alpha_clip; bool uses_depth_pre_pass; bool uses_discard; bool uses_roughness; @@ -308,12 +316,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float viewport_size[2]; float screen_pixel_size[2]; - float time; - float reflection_multiplier; - - uint32_t pancake_shadows; - uint32_t pad; - float directional_penumbra_shadow_kernel[128]; //32 vec4s float directional_soft_shadow_kernel[128]; float penumbra_shadow_kernel[128]; @@ -366,7 +368,6 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { uint32_t volumetric_fog_pad; // Fog - uint32_t fog_enabled; float fog_density; float fog_height; @@ -374,6 +375,13 @@ class RasterizerSceneHighEndRD : public RasterizerSceneRD { float fog_light_color[3]; float fog_sun_scatter; + + float fog_aerial_perspective; + + float time; + float reflection_multiplier; + + uint32_t pancake_shadows; }; UBO ubo; diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp index 934330cc9b..e1be9b0ef4 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -30,8 +30,8 @@ #include "rasterizer_scene_rd.h" +#include "core/config/project_settings.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "rasterizer_rd.h" #include "servers/rendering/rendering_server_raster.h" @@ -1173,6 +1173,94 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm /* Update dynamic lights */ { + int32_t cascade_light_count[SDFGI::MAX_CASCADES]; + + for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { + SDFGI::Cascade &cascade = rb->sdfgi->cascades[i]; + + SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS]; + uint32_t idx = 0; + for (uint32_t j = 0; j < p_directional_light_count; j++) { + if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { + break; + } + + LightInstance *li = light_instance_owner.getornull(p_directional_light_instances[j]); + ERR_CONTINUE(!li); + Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); + dir.y *= rb->sdfgi->y_mult; + dir.normalize(); + lights[idx].direction[0] = dir.x; + lights[idx].direction[1] = dir.y; + lights[idx].direction[2] = dir.z; + Color color = storage->light_get_color(li->light); + color = color.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 = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].has_shadow = storage->light_has_shadow(li->light); + + idx++; + } + + AABB cascade_aabb; + cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + cascade.position)) * cascade.cell_size; + cascade_aabb.size = Vector3(1, 1, 1) * rb->sdfgi->cascade_size * cascade.cell_size; + + for (uint32_t j = 0; j < p_positional_light_count; j++) { + if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { + break; + } + + LightInstance *li = light_instance_owner.getornull(p_positional_light_instances[j]); + ERR_CONTINUE(!li); + + uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light); + if (i > max_sdfgi_cascade) { + continue; + } + + if (!cascade_aabb.intersects(li->aabb)) { + continue; + } + + Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); + //faster to not do this here + //dir.y *= rb->sdfgi->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; + pos.y *= rb->sdfgi->y_mult; + lights[idx].position[0] = pos.x; + lights[idx].position[1] = pos.y; + lights[idx].position[2] = pos.z; + Color color = storage->light_get_color(li->light); + color = color.to_linear(); + lights[idx].color[0] = color.r; + lights[idx].color[1] = color.g; + lights[idx].color[2] = color.b; + lights[idx].type = storage->light_get_type(li->light); + lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); + lights[idx].has_shadow = storage->light_has_shadow(li->light); + lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); + lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); + lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)); + lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + idx++; + } + + if (idx > 0) { + RD::get_singleton()->buffer_update(cascade.lights_buffer, 0, idx * sizeof(SDGIShader::Light), lights, true); + } + + cascade_light_count[i] = idx; + } + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.direct_light_pipeline[SDGIShader::DIRECT_LIGHT_MODE_DYNAMIC]); @@ -1191,91 +1279,7 @@ void RasterizerSceneRD::sdfgi_update_probes(RID p_render_buffers, RID p_environm for (uint32_t i = 0; i < rb->sdfgi->cascades.size(); i++) { SDFGI::Cascade &cascade = rb->sdfgi->cascades[i]; - - { //fill light buffer - - SDGIShader::Light lights[SDFGI::MAX_DYNAMIC_LIGHTS]; - uint32_t idx = 0; - for (uint32_t j = 0; j < p_directional_light_count; j++) { - if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { - break; - } - - LightInstance *li = light_instance_owner.getornull(p_directional_light_instances[j]); - ERR_CONTINUE(!li); - Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); - dir.y *= rb->sdfgi->y_mult; - dir.normalize(); - lights[idx].direction[0] = dir.x; - lights[idx].direction[1] = dir.y; - lights[idx].direction[2] = dir.z; - Color color = storage->light_get_color(li->light); - color = color.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 = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); - lights[idx].has_shadow = storage->light_has_shadow(li->light); - - idx++; - } - - AABB cascade_aabb; - cascade_aabb.position = Vector3((Vector3i(1, 1, 1) * -int32_t(rb->sdfgi->cascade_size >> 1) + cascade.position)) * cascade.cell_size; - cascade_aabb.size = Vector3(1, 1, 1) * rb->sdfgi->cascade_size * cascade.cell_size; - - for (uint32_t j = 0; j < p_positional_light_count; j++) { - if (idx == SDFGI::MAX_DYNAMIC_LIGHTS) { - break; - } - - LightInstance *li = light_instance_owner.getornull(p_positional_light_instances[j]); - ERR_CONTINUE(!li); - - uint32_t max_sdfgi_cascade = storage->light_get_max_sdfgi_cascade(li->light); - if (i > max_sdfgi_cascade) { - continue; - } - - if (!cascade_aabb.intersects(li->aabb)) { - continue; - } - - Vector3 dir = -li->transform.basis.get_axis(Vector3::AXIS_Z); - //faster to not do this here - //dir.y *= rb->sdfgi->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; - pos.y *= rb->sdfgi->y_mult; - lights[idx].position[0] = pos.x; - lights[idx].position[1] = pos.y; - lights[idx].position[2] = pos.z; - Color color = storage->light_get_color(li->light); - color = color.to_linear(); - lights[idx].color[0] = color.r; - lights[idx].color[1] = color.g; - lights[idx].color[2] = color.b; - lights[idx].type = storage->light_get_type(li->light); - lights[idx].energy = storage->light_get_param(li->light, RS::LIGHT_PARAM_ENERGY); - lights[idx].has_shadow = storage->light_has_shadow(li->light); - lights[idx].attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); - lights[idx].radius = storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].spot_angle = Math::deg2rad(storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE)); - lights[idx].spot_attenuation = storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); - - idx++; - } - - if (idx > 0) { - RD::get_singleton()->buffer_update(cascade.lights_buffer, 0, idx * sizeof(SDGIShader::Light), lights, true); - } - push_constant.light_count = idx; - } - + push_constant.light_count = cascade_light_count[i]; push_constant.cascade = i; RD::get_singleton()->compute_list_bind_uniform_set(compute_list, cascade.sdf_direct_light_uniform_set, 0); @@ -2322,6 +2326,7 @@ void RasterizerSceneRD::_setup_sky(RID p_environment, RID p_render_buffers, cons sky_scene_state.ubo.z_far = p_projection.get_z_far(); sky_scene_state.ubo.fog_enabled = environment_is_fog_enabled(p_environment); sky_scene_state.ubo.fog_density = environment_get_fog_density(p_environment); + sky_scene_state.ubo.fog_aerial_perspective = environment_get_fog_aerial_perspective(p_environment); Color fog_color = environment_get_fog_light_color(p_environment).to_linear(); float fog_energy = environment_get_fog_light_energy(p_environment); sky_scene_state.ubo.fog_light_color[0] = fog_color.r * fog_energy; @@ -2932,11 +2937,12 @@ void RasterizerSceneRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMa env->auto_exp_scale = p_auto_exp_scale; } -void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, 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) { +void RasterizerSceneRD::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) { Environment *env = environment_owner.getornull(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_level_flags; + env->glow_levels = p_levels; env->glow_intensity = p_intensity; env->glow_strength = p_strength; env->glow_mix = p_mix; @@ -2971,7 +2977,7 @@ void RasterizerSceneRD::environment_set_sdfgi(RID p_env, bool p_enable, RS::Envi env->sdfgi_y_scale = p_y_scale; } -void RasterizerSceneRD::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) { +void RasterizerSceneRD::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) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -2982,6 +2988,7 @@ void RasterizerSceneRD::environment_set_fog(RID p_env, bool p_enable, const Colo 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; } bool RasterizerSceneRD::environment_is_fog_enabled(RID p_env) const { @@ -3022,6 +3029,12 @@ float RasterizerSceneRD::environment_get_fog_height_density(RID p_env) const { return env->fog_height_density; } +float RasterizerSceneRD::environment_get_fog_aerial_perspective(RID p_env) const { + const Environment *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->fog_aerial_perspective; +} + void RasterizerSceneRD::environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RenderingServer::EnvVolumetricFogShadowFilter p_shadow_filter) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -5237,25 +5250,21 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu } int max_glow_level = -1; - int glow_mask = 0; if (can_use_effects && env && env->glow_enabled) { /* see that blur textures are allocated */ - if (rb->blur[0].texture.is_null()) { + if (rb->blur[1].texture.is_null()) { _allocate_blur_textures(rb); _render_buffers_uniform_set_changed(p_render_buffers); } for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { - if (env->glow_levels & (1 << i)) { + if (env->glow_levels[i] > 0.0) { if (i >= rb->blur[1].mipmaps.size()) { max_glow_level = rb->blur[1].mipmaps.size() - 1; - glow_mask |= 1 << max_glow_level; - } else { max_glow_level = i; - glow_mask |= (1 << i); } } } @@ -5269,9 +5278,9 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu if (env->auto_exposure && rb->luminance.current.is_valid()) { luminance_texture = rb->luminance.current; } - storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].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); + storage->get_effects()->gaussian_glow(rb->texture, rb->blur[1].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); } else { - storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); + storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[1].mipmaps[i].texture, Size2i(vp_w, vp_h), env->glow_strength, glow_high_quality); } } } @@ -5294,7 +5303,9 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu tonemap.use_glow = true; tonemap.glow_mode = RasterizerEffectsRD::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_level_flags = glow_mask; + for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { + tonemap.glow_levels[i] = env->glow_levels[i]; + } tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width; tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height; tonemap.glow_use_bicubic_upscale = glow_bicubic_upscale; @@ -5307,6 +5318,7 @@ void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_bu tonemap.use_fxaa = true; } + tonemap.use_debanding = rb->use_debanding; tonemap.texture_size = Vector2i(rb->width, rb->height); if (env) { @@ -5686,13 +5698,14 @@ float RasterizerSceneRD::render_buffers_get_volumetric_fog_detail_spread(RID p_r return rb->volumetric_fog->spread; } -void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa) { +void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RenderingServer::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding) { RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); rb->width = p_width; rb->height = p_height; rb->render_target = p_render_target; rb->msaa = p_msaa; rb->screen_space_aa = p_screen_space_aa; + rb->use_debanding = p_use_debanding; _free_render_buffer_data(rb); { @@ -7227,8 +7240,9 @@ void RasterizerSceneRD::render_sdfgi(RID p_render_buffers, int p_region, Instanc push_constant.grid_size = rb->sdfgi->cascade_size; push_constant.cascade = cascade; - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); if (rb->sdfgi->cascades[cascade].dirty_regions != SDFGI::Cascade::DIRTY_ALL) { + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + //must pre scroll existing data because not all is dirty RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, sdfgi_shader.preprocess_pipeline[SDGIShader::PRE_PROCESS_SCROLL]); RD::get_singleton()->compute_list_bind_uniform_set(compute_list, rb->sdfgi->cascades[cascade].scroll_uniform_set, 0); @@ -7302,13 +7316,15 @@ void RasterizerSceneRD::render_sdfgi(RID p_render_buffers, int p_region, Instanc } //ok finally barrier - RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->compute_list_end(); } //clear dispatch indirect data uint32_t dispatch_indirct_data[4] = { 0, 0, 0, 0 }; RD::get_singleton()->buffer_update(rb->sdfgi->cascades[cascade].solid_cell_dispatch_buffer, 0, sizeof(uint32_t) * 4, dispatch_indirct_data, true); + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + bool half_size = true; //much faster, very little difference static const int optimized_jf_group_size = 8; @@ -7992,6 +8008,7 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { actions.renames["HALF_RES_COLOR"] = "half_res_color"; actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color"; actions.renames["RADIANCE"] = "radiance"; + actions.renames["FOG"] = "custom_fog"; actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled"; actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction_energy.xyz"; actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].direction_energy.w"; @@ -8317,8 +8334,8 @@ RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { { RD::SamplerState sampler; - sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; + 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); diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h index 0e7e56716b..3d5310bb7e 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -31,8 +31,8 @@ #ifndef RASTERIZER_SCENE_RD_H #define RASTERIZER_SCENE_RD_H -#include "core/local_vector.h" -#include "core/rid_owner.h" +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" #include "servers/rendering/rasterizer.h" #include "servers/rendering/rasterizer_rd/light_cluster_builder.h" #include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" @@ -67,7 +67,8 @@ protected: uint32_t volumetric_fog_enabled; float volumetric_fog_inv_length; float volumetric_fog_detail_spread; - uint32_t volumetric_fog_pad; + + float fog_aerial_perspective; float fog_light_color[3]; float fog_sun_scatter; @@ -706,6 +707,7 @@ private: 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 /// @@ -721,7 +723,7 @@ private: /// Glow bool glow_enabled = false; - int glow_levels = (1 << 2) | (1 << 4); + Vector<float> glow_levels; float glow_intensity = 0.8; float glow_strength = 1.0; float glow_bloom = 0.0; @@ -813,6 +815,7 @@ private: int width = 0, height = 0; RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; RS::ViewportScreenSpaceAA screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + bool use_debanding = false; RID render_target; @@ -1530,11 +1533,11 @@ public: bool is_environment(RID p_env) const; - void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, 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); + 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); void environment_glow_set_use_bicubic_upscale(bool p_enable); void environment_glow_set_use_high_quality(bool p_enable); - 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); + 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); 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; @@ -1542,6 +1545,7 @@ public: 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; void environment_set_volumetric_fog(RID p_env, bool p_enable, float p_density, const Color &p_light, float p_light_energy, float p_length, float p_detail_spread, float p_gi_inject, RS::EnvVolumetricFogShadowFilter p_shadow_filter); @@ -1842,7 +1846,7 @@ public: } */ RID render_buffers_create(); - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa); + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa, RS::ViewportScreenSpaceAA p_screen_space_aa, bool p_use_debanding); RID render_buffers_get_ao_texture(RID p_render_buffers); RID render_buffers_get_back_buffer_texture(RID p_render_buffers); diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index 90dd6af319..8bd4362637 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -30,9 +30,9 @@ #include "rasterizer_storage_rd.h" -#include "core/engine.h" +#include "core/config/engine.h" +#include "core/config/project_settings.h" #include "core/io/resource_loader.h" -#include "core/project_settings.h" #include "rasterizer_rd.h" #include "servers/rendering/shader_language.h" @@ -1118,6 +1118,11 @@ void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) { } RD::get_singleton()->free(tex->rd_texture); + if (tex->canvas_texture) { + memdelete(tex->canvas_texture); + tex->canvas_texture = nullptr; + } + Vector<RID> proxies_to_update = tex->proxies; Vector<RID> proxies_to_redirect = by_tex->proxies; @@ -1125,6 +1130,10 @@ void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) { tex->proxies = proxies_to_update; //restore proxies, so they can be updated + if (tex->canvas_texture) { + tex->canvas_texture->diffuse = p_texture; //update + } + for (int i = 0; i < proxies_to_update.size(); i++) { texture_proxy_update(proxies_to_update[i], p_texture); } @@ -1193,6 +1202,167 @@ Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) { return texture_2d_get_size(p_proxy); } +/* CANVAS TEXTURE */ + +void RasterizerStorageRD::CanvasTexture::clear_sets() { + if (cleared_cache) { + return; + } + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + if (RD::get_singleton()->uniform_set_is_valid(uniform_sets[i][j])) { + RD::get_singleton()->free(uniform_sets[i][j]); + uniform_sets[i][j] = RID(); + } + } + } + cleared_cache = true; +} + +RasterizerStorageRD::CanvasTexture::~CanvasTexture() { + clear_sets(); +} + +RID RasterizerStorageRD::canvas_texture_create() { + return canvas_texture_owner.make_rid(memnew(CanvasTexture)); +} + +void RasterizerStorageRD::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { + CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); + switch (p_channel) { + case RS::CANVAS_TEXTURE_CHANNEL_DIFFUSE: { + ct->diffuse = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_NORMAL: { + ct->normalmap = p_texture; + } break; + case RS::CANVAS_TEXTURE_CHANNEL_SPECULAR: { + ct->specular = p_texture; + } break; + } + + ct->clear_sets(); +} + +void RasterizerStorageRD::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess) { + CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); + ct->specular_color.r = p_specular_color.r; + ct->specular_color.g = p_specular_color.g; + ct->specular_color.b = p_specular_color.b; + ct->specular_color.a = p_shininess; + ct->clear_sets(); +} + +void RasterizerStorageRD::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { + CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); + ct->texture_filter = p_filter; + ct->clear_sets(); +} + +void RasterizerStorageRD::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { + CanvasTexture *ct = canvas_texture_owner.getornull(p_canvas_texture); + ct->texture_repeat = p_repeat; + ct->clear_sets(); +} + +bool RasterizerStorageRD::canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular) { + CanvasTexture *ct = nullptr; + + Texture *t = texture_owner.getornull(p_texture); + + if (t) { + //regular texture + if (!t->canvas_texture) { + t->canvas_texture = memnew(CanvasTexture); + t->canvas_texture->diffuse = p_texture; + } + + ct = t->canvas_texture; + } else { + ct = canvas_texture_owner.getornull(p_texture); + } + + if (!ct) { + return false; //invalid texture RID + } + + RS::CanvasItemTextureFilter filter = ct->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT ? ct->texture_filter : p_base_filter; + ERR_FAIL_COND_V(filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, false); + + RS::CanvasItemTextureRepeat repeat = ct->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT ? ct->texture_repeat : p_base_repeat; + ERR_FAIL_COND_V(repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, false); + + RID uniform_set = ct->uniform_sets[filter][repeat]; + if (!RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //create and update + Vector<RD::Uniform> uniforms; + { //diffuse + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + + t = texture_owner.getornull(ct->diffuse); + if (!t) { + u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->size_cache = Size2i(1, 1); + } else { + u.ids.push_back(t->rd_texture); + ct->size_cache = Size2i(t->width_2d, t->height_2d); + } + uniforms.push_back(u); + } + { //normal + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + + t = texture_owner.getornull(ct->normalmap); + if (!t) { + u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL)); + ct->use_normal_cache = false; + } else { + u.ids.push_back(t->rd_texture); + ct->use_normal_cache = true; + } + uniforms.push_back(u); + } + { //specular + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + + t = texture_owner.getornull(ct->specular); + if (!t) { + u.ids.push_back(texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE)); + ct->use_specular_cache = false; + } else { + u.ids.push_back(t->rd_texture); + ct->use_specular_cache = true; + } + uniforms.push_back(u); + } + { //sampler + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 3; + u.ids.push_back(sampler_rd_get_default(filter, repeat)); + uniforms.push_back(u); + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, p_base_set); + ct->uniform_sets[filter][repeat] = uniform_set; + ct->cleared_cache = false; + } + + r_uniform_set = uniform_set; + r_size = ct->size_cache; + r_specular_shininess = ct->specular_color; + r_use_normal = ct->use_normal_cache; + r_use_specular = ct->use_specular_cache; + + return true; +} + /* SHADER API */ RID RasterizerStorageRD::shader_create() { @@ -1256,6 +1426,10 @@ void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) { } material->shader_type = new_type; } + + for (Map<StringName, RID>::Element *E = shader->default_texture_parameter.front(); E; E = E->next()) { + shader->data->set_default_texture_param(E->key(), E->get()); + } } if (shader->data) { @@ -1292,7 +1466,9 @@ void RasterizerStorageRD::shader_set_default_texture_param(RID p_shader, const S } else { shader->default_texture_parameter.erase(p_name); } - + if (shader->data) { + shader->data->set_default_texture_param(p_name, p_texture); + } for (Set<Material *>::Element *E = shader->owners.front(); E; E = E->next()) { Material *material = E->get(); _material_queue_update(material, false, true); @@ -5836,6 +6012,7 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) { //free in reverse dependency order if (rt->framebuffer.is_valid()) { RD::get_singleton()->free(rt->framebuffer); + rt->framebuffer_uniform_set = RID(); //chain deleted } if (rt->color.is_valid()) { @@ -5850,10 +6027,7 @@ void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) { RD::get_singleton()->free(rt->backbuffer_mipmaps[i].mipmap_copy); } rt->backbuffer_mipmaps.clear(); - if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) { - RD::get_singleton()->free(rt->backbuffer_uniform_set); - } - rt->backbuffer_uniform_set = RID(); + rt->backbuffer_uniform_set = RID(); //chain deleted } rt->framebuffer = RID(); @@ -5957,12 +6131,23 @@ void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) { tf.width = rt->size.width; tf.height = rt->size.height; tf.type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; tf.mipmaps = mipmaps_required; rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); rt->backbuffer_mipmap0 = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0); + { + Vector<RID> fb_tex; + fb_tex.push_back(rt->backbuffer_mipmap0); + rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(fb_tex); + } + + if (rt->framebuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->framebuffer_uniform_set)) { + //the new one will require the backbuffer. + RD::get_singleton()->free(rt->framebuffer_uniform_set); + rt->framebuffer_uniform_set = RID(); + } //create mipmaps for (uint32_t i = 1; i < mipmaps_required; i++) { RenderTarget::BackbufferMipmap mm; @@ -6060,6 +6245,23 @@ RID RasterizerStorageRD::render_target_get_rd_texture(RID p_render_target) { return rt->color; } +RID RasterizerStorageRD::render_target_get_rd_backbuffer(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + return rt->backbuffer; +} + +RID RasterizerStorageRD::render_target_get_rd_backbuffer_framebuffer(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + if (!rt->backbuffer.is_valid()) { + _create_render_target_backbuffer(rt); + } + + return rt->backbuffer_fb; +} + void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); @@ -6098,21 +6300,30 @@ void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) { rt->clear_requested = false; } -void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region) { +void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region, bool p_gen_mipmaps) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); } - Rect2i region = p_region; - if (region == Rect2i()) { + Rect2i region; + if (p_region == Rect2i()) { region.size = rt->size; + } else { + region = Rect2i(Size2i(), rt->size).clip(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } } //single texture copy for backbuffer - RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); - //effects.copy(rt->color, rt->backbuffer_fb, blur_region); + //RD::get_singleton()->texture_copy(rt->color, rt->backbuffer_mipmap0, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); + effects.copy_to_rect(rt->color, rt->backbuffer_mipmap0, region, false, false, false, true, true); + + if (!p_gen_mipmaps) { + return; + } //then mipmap blur RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps. @@ -6129,32 +6340,81 @@ void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, } } -RID RasterizerStorageRD::render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader) { +void RasterizerStorageRD::render_target_clear_back_buffer(RID p_render_target, const Rect2i &p_region, const Color &p_color) { RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); + ERR_FAIL_COND(!rt); + if (!rt->backbuffer.is_valid()) { + _create_render_target_backbuffer(rt); + } + Rect2i region; + if (p_region == Rect2i()) { + region.size = rt->size; + } else { + region = Rect2i(Size2i(), rt->size).clip(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } + } + + //single texture copy for backbuffer + effects.set_color(rt->backbuffer_mipmap0, p_color, region, true); +} + +void RasterizerStorageRD::render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); if (!rt->backbuffer.is_valid()) { _create_render_target_backbuffer(rt); } - if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) { - return rt->backbuffer_uniform_set; //if still valid, return/reuse it. + Rect2i region; + if (p_region == Rect2i()) { + region.size = rt->size; + } else { + region = Rect2i(Size2i(), rt->size).clip(p_region); + if (region.size == Size2i()) { + return; //nothing to do + } } - //create otherwise - Vector<RD::Uniform> uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - u.ids.push_back(rt->backbuffer); - uniforms.push_back(u); + //then mipmap blur + RID prev_texture = rt->backbuffer_mipmap0; + + for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { + region.position.x >>= 1; + region.position.y >>= 1; + region.size.x = MAX(1, region.size.x >> 1); + region.size.y = MAX(1, region.size.y >> 1); - rt->backbuffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, 3); - ERR_FAIL_COND_V(!rt->backbuffer_uniform_set.is_valid(), RID()); + const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i]; + effects.gaussian_blur(prev_texture, mm.mipmap, mm.mipmap_copy, region, true); + prev_texture = mm.mipmap; + } +} +RID RasterizerStorageRD::render_target_get_framebuffer_uniform_set(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + return rt->framebuffer_uniform_set; +} +RID RasterizerStorageRD::render_target_get_backbuffer_uniform_set(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); return rt->backbuffer_uniform_set; } +void RasterizerStorageRD::render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + rt->framebuffer_uniform_set = p_uniform_set; +} +void RasterizerStorageRD::render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + rt->backbuffer_uniform_set = p_uniform_set; +} + void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { if (mesh_owner.owns(p_base)) { Mesh *mesh = mesh_owner.getornull(p_base); @@ -7186,8 +7446,16 @@ bool RasterizerStorageRD::free(RID p_rid) { p->rd_texture = RID(); p->rd_texture_srgb = RID(); } + + if (t->canvas_texture) { + memdelete(t->canvas_texture); + } texture_owner.free(p_rid); + } else if (canvas_texture_owner.owns(p_rid)) { + CanvasTexture *ct = canvas_texture_owner.getornull(p_rid); + memdelete(ct); + canvas_texture_owner.free(p_rid); } else if (shader_owner.owns(p_rid)) { Shader *shader = shader_owner.getornull(p_rid); //make material unreference this diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h index b03a26e200..05cb1b4a73 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h @@ -31,7 +31,7 @@ #ifndef RASTERIZER_STORAGE_RD_H #define RASTERIZER_STORAGE_RD_H -#include "core/rid_owner.h" +#include "core/templates/rid_owner.h" #include "servers/rendering/rasterizer.h" #include "servers/rendering/rasterizer_rd/rasterizer_effects_rd.h" #include "servers/rendering/rasterizer_rd/shader_compiler_rd.h" @@ -174,6 +174,29 @@ public: }; private: + /* CANVAS TEXTURE API (2D) */ + + struct CanvasTexture { + RID diffuse; + RID normalmap; + 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(); + }; + + RID_PtrOwner<CanvasTexture> canvas_texture_owner; + /* TEXTURE API */ struct Texture { enum Type { @@ -231,6 +254,8 @@ private: RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; void *detect_roughness_callback_ud = nullptr; + + CanvasTexture *canvas_texture = nullptr; }; struct TextureToRDFormat { @@ -964,6 +989,7 @@ private: bool flags[RENDER_TARGET_FLAG_MAX]; RID backbuffer; //used for effects + RID backbuffer_fb; RID backbuffer_mipmap0; struct BackbufferMipmap { @@ -972,6 +998,8 @@ private: }; Vector<BackbufferMipmap> backbuffer_mipmaps; + + RID framebuffer_uniform_set; RID backbuffer_uniform_set; //texture generated for this owner (nor RD). @@ -1147,6 +1175,18 @@ public: return default_rd_samplers[p_filter][p_repeat]; } + /* CANVAS TEXTURE API */ + + virtual RID canvas_texture_create(); + + virtual void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture); + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_specular_color, float p_shininess); + + virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter); + virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat); + + bool canvas_texture_get_uniform_set(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID p_base_shader, int p_base_set, RID &r_uniform_set, Size2i &r_size, Color &r_specular_shininess, bool &r_use_normal, bool &r_use_specular); + /* SHADER API */ RID shader_create(); @@ -1877,7 +1917,10 @@ public: void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value); bool render_target_was_used(RID p_render_target); void render_target_set_as_unused(RID p_render_target); - void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region); + 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); + void render_target_gen_back_buffer_mipmaps(RID p_render_target, const Rect2i &p_region); + RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader); virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color); @@ -1889,6 +1932,14 @@ public: Size2 render_target_get_size(RID p_render_target); 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_backbuffer(RID p_render_target); + RID render_target_get_rd_backbuffer_framebuffer(RID p_render_target); + + RID render_target_get_framebuffer_uniform_set(RID p_render_target); + RID render_target_get_backbuffer_uniform_set(RID p_render_target); + + void render_target_set_framebuffer_uniform_set(RID p_render_target, RID p_uniform_set); + void render_target_set_backbuffer_uniform_set(RID p_render_target, RID p_uniform_set); RS::InstanceType get_base_type(RID p_rid) const; @@ -1916,6 +1967,8 @@ public: virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const; virtual String get_captured_timestamp_name(uint32_t p_index) const; + RID get_default_rd_storage_buffer() { return default_rd_storage_buffer; } + static RasterizerStorageRD *base_singleton; RasterizerEffectsRD *get_effects(); diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h index cf15e79586..6a72dbc77c 100644 --- a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h +++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h @@ -31,7 +31,7 @@ #ifndef RENDER_PIPELINE_CACHE_RD_H #define RENDER_PIPELINE_CACHE_RD_H -#include "core/spin_lock.h" +#include "core/os/spin_lock.h" #include "servers/rendering/rendering_device.h" class RenderPipelineVertexFormatCacheRD { diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp index f70ddbb75a..1a33e9a567 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp @@ -30,8 +30,8 @@ #include "shader_compiler_rd.h" +#include "core/config/project_settings.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "rasterizer_storage_rd.h" #include "servers/rendering_server.h" @@ -423,13 +423,13 @@ static String _get_global_variable_from_type_and_index(const String &p_buffer, c return "(" + p_buffer + "[" + p_index + "].x != 0.0)"; } case ShaderLanguage::TYPE_BVEC2: { - return "(" + p_buffer + "[" + p_index + "].xy != vec2(0.0))"; + return "(notEqual(" + p_buffer + "[" + p_index + "].xy, vec2(0.0)))"; } case ShaderLanguage::TYPE_BVEC3: { - return "(" + p_buffer + "[" + p_index + "].xyz != vec3(0.0))"; + return "(notEqual(" + p_buffer + "[" + p_index + "].xyz, vec3(0.0)))"; } case ShaderLanguage::TYPE_BVEC4: { - return "(" + p_buffer + "[" + p_index + "].xyzw != vec4(0.0))"; + return "(notEqual(" + p_buffer + "[" + p_index + "].xyzw, vec4(0.0)))"; } case ShaderLanguage::TYPE_INT: { return "floatBitsToInt(" + p_buffer + "[" + p_index + "].x)"; @@ -444,16 +444,16 @@ static String _get_global_variable_from_type_and_index(const String &p_buffer, c return "floatBitsToInt(" + p_buffer + "[" + p_index + "].xyzw)"; } case ShaderLanguage::TYPE_UINT: { - return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].x)"; + return "floatBitsToUint(" + p_buffer + "[" + p_index + "].x)"; } case ShaderLanguage::TYPE_UVEC2: { - return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xy)"; + return "floatBitsToUint(" + p_buffer + "[" + p_index + "].xy)"; } case ShaderLanguage::TYPE_UVEC3: { - return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xyz)"; + return "floatBitsToUint(" + p_buffer + "[" + p_index + "].xyz)"; } case ShaderLanguage::TYPE_UVEC4: { - return "floatBitsToUInt(" + p_buffer + "[" + p_index + "].xyzw)"; + return "floatBitsToUint(" + p_buffer + "[" + p_index + "].xyzw)"; } case ShaderLanguage::TYPE_FLOAT: { return "(" + p_buffer + "[" + p_index + "].x)"; @@ -1295,6 +1295,8 @@ void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) { texture_functions.insert("textureLod"); texture_functions.insert("textureProjLod"); texture_functions.insert("textureGrad"); + texture_functions.insert("textureSize"); + texture_functions.insert("texelFetch"); } ShaderCompilerRD::ShaderCompilerRD() { diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.h b/servers/rendering/rasterizer_rd/shader_compiler_rd.h index 565520ec65..694f8fff91 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.h +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.h @@ -31,7 +31,7 @@ #ifndef SHADER_COMPILER_RD_H #define SHADER_COMPILER_RD_H -#include "core/pair.h" +#include "core/templates/pair.h" #include "servers/rendering/shader_language.h" #include "servers/rendering/shader_types.h" #include "servers/rendering_server.h" diff --git a/servers/rendering/rasterizer_rd/shader_rd.cpp b/servers/rendering/rasterizer_rd/shader_rd.cpp index 8c57651263..865a1e1bbe 100644 --- a/servers/rendering/rasterizer_rd/shader_rd.cpp +++ b/servers/rendering/rasterizer_rd/shader_rd.cpp @@ -30,7 +30,7 @@ #include "shader_rd.h" -#include "core/string_builder.h" +#include "core/string/string_builder.h" #include "rasterizer_rd.h" #include "servers/rendering/rendering_device.h" diff --git a/servers/rendering/rasterizer_rd/shader_rd.h b/servers/rendering/rasterizer_rd/shader_rd.h index d9bb068ba6..0c379db6f2 100644 --- a/servers/rendering/rasterizer_rd/shader_rd.h +++ b/servers/rendering/rasterizer_rd/shader_rd.h @@ -31,11 +31,11 @@ #ifndef SHADER_RD_H #define SHADER_RD_H -#include "core/hash_map.h" -#include "core/map.h" #include "core/os/mutex.h" -#include "core/rid_owner.h" -#include "core/variant.h" +#include "core/templates/hash_map.h" +#include "core/templates/map.h" +#include "core/templates/rid_owner.h" +#include "core/variant/variant.h" #include <stdio.h> /** diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl index 4a40584e16..2a0f94e733 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas.glsl +++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl @@ -26,7 +26,7 @@ layout(location = 3) out vec2 pixel_size_interp; #endif #ifdef USE_MATERIAL_UNIFORMS -layout(set = 1, binding = 1, std140) uniform MaterialUniforms{ +layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ /* clang-format off */ MATERIAL_UNIFORMS /* clang-format on */ @@ -144,7 +144,7 @@ VERTEX_SHADER_CODE color_interp = color; - if (bool(draw_data.flags & FLAGS_USE_PIXEL_SNAP)) { + if (canvas_data.use_pixel_snap) { vertex = floor(vertex + 0.5); // precision issue on some hardware creates artifacts within texture // offset uv by a small amount to avoid @@ -226,7 +226,7 @@ layout(location = 3) in vec2 pixel_size_interp; layout(location = 0) out vec4 frag_color; #ifdef USE_MATERIAL_UNIFORMS -layout(set = 1, binding = 1, std140) uniform MaterialUniforms{ +layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ /* clang-format off */ MATERIAL_UNIFORMS /* clang-format on */ @@ -249,7 +249,7 @@ vec4 light_compute( inout vec4 shadow_modulate, vec2 screen_uv, vec2 uv, - vec4 color) { + vec4 color, bool is_directional) { vec4 light = vec4(0.0); /* clang-format off */ LIGHT_SHADER_CODE @@ -302,6 +302,99 @@ float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, flo #endif +#ifdef USE_LIGHTING + +vec3 light_normal_compute(vec3 light_vec, vec3 normal, vec3 base_color, vec3 light_color, vec4 specular_shininess, bool specular_shininess_used) { + float cNdotL = max(0.0, dot(normal, light_vec)); + + if (specular_shininess_used) { + //blinn + vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough + vec3 half_vec = normalize(view + light_vec); + + float cNdotV = max(dot(normal, view), 0.0); + float cNdotH = max(dot(normal, half_vec), 0.0); + float cVdotH = max(dot(view, half_vec), 0.0); + float cLdotH = max(dot(light_vec, half_vec), 0.0); + float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + + return specular_shininess.rgb * light_color * s + light_color * base_color * cNdotL; + } else { + return light_color * base_color * cNdotL; + } +} + +//float distance = length(shadow_pos); +vec4 light_shadow_compute(uint light_base, vec4 light_color, vec4 shadow_uv +#ifdef LIGHT_SHADER_CODE_USED + , + vec3 shadow_modulate +#endif +) { + float shadow; + uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK; + + if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) { + shadow = textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x; + } else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) { + vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); + shadow = 0.0; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x; + shadow /= 5.0; + } else { //PCF13 + vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); + shadow = 0.0; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 6.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 5.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 4.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 3.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size * 2.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv - shadow_pixel_size, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 2.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 3.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 4.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 5.0, 0.0).x; + shadow += textureProjLod(sampler2DShadow(shadow_atlas_texture, shadow_sampler), shadow_uv + shadow_pixel_size * 6.0, 0.0).x; + shadow /= 13.0; + } + + vec4 shadow_color = unpackUnorm4x8(light_array.data[light_base].shadow_color); +#ifdef LIGHT_SHADER_CODE_USED + shadow_color *= shadow_modulate; +#endif + + shadow_color.a *= light_color.a; //respect light alpha + + return mix(light_color, shadow_color, shadow); +} + +void light_blend_compute(uint light_base, vec4 light_color, inout vec3 color) { + uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK; + + switch (blend_mode) { + case LIGHT_FLAGS_BLEND_MODE_ADD: { + color.rgb += light_color.rgb * light_color.a; + } break; + case LIGHT_FLAGS_BLEND_MODE_SUB: { + color.rgb -= light_color.rgb * light_color.a; + } break; + case LIGHT_FLAGS_BLEND_MODE_MIX: { + color.rgb = mix(color.rgb, light_color.rgb, light_color.a); + } break; + } +} + +#endif + void main() { vec4 color = color_interp; vec2 uv = uv_interp; @@ -332,6 +425,7 @@ void main() { color *= texture(sampler2D(color_texture, texture_sampler), uv); uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights + bool using_light = light_count > 0 || canvas_data.directional_light_count > 0; vec3 normal; @@ -341,7 +435,7 @@ void main() { bool normal_used = false; #endif - if (normal_used || (light_count > 0 && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { + if (normal_used || (using_light && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); normal_used = true; @@ -358,7 +452,7 @@ void main() { bool specular_shininess_used = false; #endif - if (specular_shininess_used || (light_count > 0 && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { + if (specular_shininess_used || (using_light && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv); specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess); specular_shininess_used = true; @@ -401,14 +495,53 @@ FRAGMENT_SHADER_CODE normal = normalize((canvas_data.canvas_normal_transform * vec4(normal, 0.0)).xyz); } - vec4 base_color = color; + vec3 base_color = color.rgb; if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) { color = vec4(0.0); //invisible by default due to using light mask } color *= canvas_data.canvas_modulation; #ifdef USE_LIGHTING - for (uint i = 0; i < MAX_LIGHT_TEXTURES; i++) { + + // Directional Lights + + for (uint i = 0; i < canvas_data.directional_light_count; i++) { + uint light_base = i; + + vec2 direction = light_array.data[light_base].position; + vec4 light_color = light_array.data[light_base].color; + +#ifdef LIGHT_SHADER_CODE_USED + + vec4 shadow_modulate = vec4(1.0); + light_color = light_compute(light_vertex, direction, normal, light_color, light_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, 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); + } +#endif + + if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. + + vec4 shadow_uv = vec4(shadow_pos.x, light_array.data[light_base].shadow_y_ofs, shadow_pos.y * light_array.data[light_base].shadow_zfar_inv, 1.0); + + light_color = light_shadow_compute(light_base, light_color, shadow_uv +#ifdef LIGHT_SHADER_CODE_USED + , + shadow_modulate +#endif + ); + } + + light_blend_compute(light_base, light_color, color.rgb); + } + + // Positional Lights + + for (uint i = 0; i < MAX_LIGHTS_PER_ITEM; i++) { if (i >= light_count) { break; } @@ -430,7 +563,8 @@ FRAGMENT_SHADER_CODE light_base &= 0xFF; vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array.data[light_base].texture_matrix[0], light_array.data[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. - vec4 light_color = texture(sampler2D(light_textures[i], texture_sampler), tex_uv); + vec2 tex_uv_atlas = tex_uv * light_array.data[light_base].atlas_rect.zw + light_array.data[light_base].atlas_rect.xy; + vec4 light_color = textureLod(sampler2D(atlas_texture, texture_sampler), tex_uv_atlas, 0.0); vec4 light_base_color = light_array.data[light_base].color; #ifdef LIGHT_SHADER_CODE_USED @@ -439,7 +573,7 @@ FRAGMENT_SHADER_CODE 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, color, uv); + light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv, false); #else light_color.rgb *= light_base_color.rgb * light_base_color.a; @@ -450,24 +584,7 @@ FRAGMENT_SHADER_CODE vec3 light_vec = normalize(light_pos - pos); float cNdotL = max(0.0, dot(normal, light_vec)); - if (specular_shininess_used) { - //blinn - vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough - vec3 half_vec = normalize(view + light_vec); - - float cNdotV = max(dot(normal, view), 0.0); - float cNdotH = max(dot(normal, half_vec), 0.0); - float cVdotH = max(dot(view, half_vec), 0.0); - float cLdotH = max(dot(light_vec, half_vec), 0.0); - float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess); - blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); - - light_color.rgb = specular_shininess.rgb * light_base_color.rgb * s + light_color.rgb * cNdotL; - } else { - light_color.rgb *= cNdotL; - } + light_color.rgb = light_normal_compute(light_vec, normal, base_color, light_color.rgb, specular_shininess, specular_shininess_used); } #endif if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) { @@ -502,66 +619,20 @@ FRAGMENT_SHADER_CODE } } + distance *= light_array.data[light_base].shadow_zfar_inv; + //float distance = length(shadow_pos); - float shadow; - uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK; - - vec4 shadow_uv = vec4(tex_ofs, 0.0, distance, 1.0); - - if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) { - shadow = textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; - } else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) { - vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); - shadow = 0.0; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x; - shadow /= 5.0; - } else { //PCF13 - vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); - shadow = 0.0; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 6.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 5.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 4.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 3.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 3.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 4.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 5.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 6.0).x; - shadow /= 13.0; - } + vec4 shadow_uv = vec4(tex_ofs, light_array.data[light_base].shadow_y_ofs, distance, 1.0); - vec4 shadow_color = light_array.data[light_base].shadow_color; + light_color = light_shadow_compute(light_base, light_color, shadow_uv #ifdef LIGHT_SHADER_CODE_USED - shadow_color *= shadow_modulate; + , + shadow_modulate #endif - light_color = mix(light_color, shadow_color, shadow); + ); } - uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK; - - switch (blend_mode) { - case LIGHT_FLAGS_BLEND_MODE_ADD: { - color.rgb += light_color.rgb * light_color.a; - } break; - case LIGHT_FLAGS_BLEND_MODE_SUB: { - color.rgb -= light_color.rgb * light_color.a; - } break; - case LIGHT_FLAGS_BLEND_MODE_MIX: { - color.rgb = mix(color.rgb, light_color.rgb, light_color.a); - } break; - case LIGHT_FLAGS_BLEND_MODE_MASK: { - light_color.a *= base_color.a; - color.rgb = mix(color.rgb, light_color.rgb, light_color.a); - } break; - } + light_blend_compute(light_base, light_color, color.rgb); } #endif diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl index 99e70a1976..421282cd4d 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl +++ b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl @@ -8,7 +8,8 @@ layout(push_constant, binding = 0, std430) uniform Constants { mat4 projection; mat2x4 modelview; vec2 direction; - vec2 pad; + float z_far; + float pad; } constants; @@ -25,9 +26,18 @@ void main() { #version 450 +layout(push_constant, binding = 0, std430) uniform Constants { + mat4 projection; + mat2x4 modelview; + vec2 direction; + float z_far; + float pad; +} +constants; + layout(location = 0) in highp float depth; layout(location = 0) out highp float distance_buf; void main() { - distance_buf = depth; + distance_buf = depth / constants.z_far; } diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl index a39866004b..bb39584cbb 100644 --- a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl @@ -1,3 +1,6 @@ + +#define MAX_LIGHTS_PER_ITEM 16 + #define M_PI 3.14159265359 #define FLAGS_INSTANCING_STRIDE_MASK 0xF @@ -12,7 +15,6 @@ #define FLAGS_USING_LIGHT_MASK (1 << 11) #define FLAGS_NINEPACH_DRAW_CENTER (1 << 12) #define FLAGS_USING_PARTICLES (1 << 13) -#define FLAGS_USE_PIXEL_SNAP (1 << 14) #define FLAGS_NINEPATCH_H_MODE_SHIFT 16 #define FLAGS_NINEPATCH_V_MODE_SHIFT 18 @@ -22,13 +24,7 @@ #define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26) #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) -// In vulkan, sets should always be ordered using the following logic: -// Lower Sets: Sets that change format and layout less often -// Higher sets: Sets that change format and layout very often -// This is because changing a set for another with a different layout or format, -// invalidates all the upper ones. - -/* SET0: Draw Primitive */ +// Push Constant layout(push_constant, binding = 0, std430) uniform DrawData { vec2 world_x; @@ -53,46 +49,31 @@ layout(push_constant, binding = 0, std430) uniform DrawData { } draw_data; -// The values passed per draw primitives are cached within it - -layout(set = 0, binding = 1) uniform texture2D color_texture; -layout(set = 0, binding = 2) uniform texture2D normal_texture; -layout(set = 0, binding = 3) uniform texture2D specular_texture; -layout(set = 0, binding = 4) uniform sampler texture_sampler; - -layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer; - -/* SET1: Is reserved for the material */ - -#ifdef USE_MATERIAL_SAMPLERS - -layout(set = 1, binding = 0) uniform sampler material_samplers[12]; +// In vulkan, sets should always be ordered using the following logic: +// Lower Sets: Sets that change format and layout less often +// Higher sets: Sets that change format and layout very often +// This is because changing a set for another with a different layout or format, +// invalidates all the upper ones (as likely internal base offset changes) -#endif +/* SET0: Globals */ -/* SET2: Canvas Item State (including lighting) */ +// The values passed per draw primitives are cached within it -layout(set = 2, binding = 0, std140) uniform CanvasData { +layout(set = 0, binding = 1, std140) uniform CanvasData { mat4 canvas_transform; mat4 screen_transform; mat4 canvas_normal_transform; vec4 canvas_modulation; vec2 screen_pixel_size; float time; - float time_pad; - //uint light_count; -} -canvas_data; - -layout(set = 2, binding = 1) uniform textureBuffer skeleton_buffer; + bool use_pixel_snap; -layout(set = 2, binding = 2, std140) uniform SkeletonData { - mat4 skeleton_transform; //in world coordinates - mat4 skeleton_transform_inverse; + uint directional_light_count; + uint pad0; + uint pad1; + uint pad2; } -skeleton_data; - -#ifdef USE_LIGHTING +canvas_data; #define LIGHT_FLAGS_BLEND_MASK (3 << 16) #define LIGHT_FLAGS_BLEND_MODE_ADD (0 << 16) @@ -110,37 +91,52 @@ struct Light { mat2x4 texture_matrix; //light to texture coordinate matrix (transposed) mat2x4 shadow_matrix; //light to shadow coordinate matrix (transposed) vec4 color; - vec4 shadow_color; - vec2 position; + + uint shadow_color; // packed uint flags; //index to light texture - float height; float shadow_pixel_size; - float pad0; - float pad1; - float pad2; + float height; + + vec2 position; + float shadow_zfar_inv; + float shadow_y_ofs; + + vec4 atlas_rect; }; -layout(set = 2, binding = 3, std140) uniform LightData { +layout(set = 0, binding = 2, std140) uniform LightData { Light data[MAX_LIGHTS]; } light_array; -layout(set = 2, binding = 4) uniform texture2D light_textures[MAX_LIGHT_TEXTURES]; -layout(set = 2, binding = 5) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES]; +layout(set = 0, binding = 3) uniform texture2D atlas_texture; +layout(set = 0, binding = 4) uniform texture2D shadow_atlas_texture; -layout(set = 2, binding = 6) uniform sampler shadow_sampler; +layout(set = 0, binding = 5) uniform sampler shadow_sampler; -#endif +layout(set = 0, binding = 6) uniform texture2D screen_texture; -layout(set = 2, binding = 7, std430) restrict readonly buffer GlobalVariableData { +layout(set = 0, binding = 7) uniform sampler material_samplers[12]; + +layout(set = 0, binding = 8, std430) restrict readonly buffer GlobalVariableData { vec4 data[]; } global_variables; -/* SET3: Render Target Data */ +/* SET1: Is reserved for the material */ + +// -#ifdef SCREEN_TEXTURE_USED +/* SET2: Instancing and Skeleton */ -layout(set = 3, binding = 0) uniform texture2D screen_texture; +layout(set = 2, binding = 0, std430) restrict readonly buffer Transforms { + vec4 data[]; +} +transforms; -#endif +/* SET3: Texture */ + +layout(set = 3, binding = 0) uniform texture2D color_texture; +layout(set = 3, binding = 1) uniform texture2D normal_texture; +layout(set = 3, binding = 2) uniform texture2D specular_texture; +layout(set = 3, binding = 3) uniform sampler texture_sampler; diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl index e565bd8e3d..cdd35dfb3f 100644 --- a/servers/rendering/rasterizer_rd/shaders/copy.glsl +++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl @@ -15,6 +15,7 @@ layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; #define FLAG_FORCE_LUMINANCE (1 << 6) #define FLAG_COPY_ALL_SOURCE (1 << 7) #define FLAG_HIGH_QUALITY_GLOW (1 << 8) +#define FLAG_ALPHA_TO_ONE (1 << 9) layout(push_constant, binding = 1, std430) uniform Params { ivec4 section; @@ -35,6 +36,8 @@ layout(push_constant, binding = 1, std430) uniform Params { float camera_z_far; float camera_z_near; uint pad2[2]; + + vec4 set_color; } params; @@ -42,7 +45,7 @@ params; layout(set = 0, binding = 0) uniform samplerCubeArray source_color; #elif defined(MODE_CUBEMAP_TO_PANORAMA) layout(set = 0, binding = 0) uniform samplerCube source_color; -#else +#elif !defined(MODE_SET_COLOR) layout(set = 0, binding = 0) uniform sampler2D source_color; #endif @@ -58,12 +61,20 @@ layout(rgba8, set = 3, binding = 0) uniform restrict writeonly image2D dest_buff layout(rgba32f, set = 3, binding = 0) uniform restrict writeonly image2D dest_buffer; #endif +#ifdef MODE_GAUSSIAN_GLOW +shared vec4 local_cache[256]; +shared vec4 temp_cache[128]; +#endif + void main() { // Pixel being shaded ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + +#ifndef MODE_GAUSSIAN_GLOW // Glow needs the extra threads if (any(greaterThanEqual(pos, params.section.zw))) { //too large, do nothing return; } +#endif #ifdef MODE_MIPMAP @@ -104,70 +115,69 @@ void main() { #ifdef MODE_GAUSSIAN_GLOW - //Glow uses larger sigma 1 for a more rounded blur effect + // First pass copy texture into 16x16 local memory for every 8x8 thread block + vec2 quad_center_uv = clamp(vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.5) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw)); + uint dest_index = gl_LocalInvocationID.x * 2 + gl_LocalInvocationID.y * 2 * 16; -#define GLOW_ADD(m_ofs, m_mult) \ - { \ - ivec2 ofs = base_pos + m_ofs; \ - if (all(greaterThanEqual(ofs, section_begin)) && all(lessThan(ofs, section_end))) { \ - color += texelFetch(source_color, ofs, 0) * m_mult; \ - } \ + if (bool(params.flags & FLAG_HIGH_QUALITY_GLOW)) { + vec2 quad_offset_uv = clamp((vec2(gl_GlobalInvocationID.xy + gl_LocalInvocationID.xy - 3.0)) / params.section.zw, vec2(0.5 / params.section.zw), vec2(1.0 - 1.5 / params.section.zw)); + + local_cache[dest_index] = (textureLod(source_color, quad_center_uv, 0) + textureLod(source_color, quad_offset_uv, 0)) * 0.5; + local_cache[dest_index + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.z, 0.0), 0)) * 0.5; + local_cache[dest_index + 16] = (textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0) + textureLod(source_color, quad_offset_uv + vec2(0.0, 1.0 / params.section.w), 0)) * 0.5; + local_cache[dest_index + 16 + 1] = (textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0) + textureLod(source_color, quad_offset_uv + vec2(1.0 / params.section.zw), 0)) * 0.5; + } else { + local_cache[dest_index] = textureLod(source_color, quad_center_uv, 0); + local_cache[dest_index + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.z, 0.0), 0); + local_cache[dest_index + 16] = textureLod(source_color, quad_center_uv + vec2(0.0, 1.0 / params.section.w), 0); + local_cache[dest_index + 16 + 1] = textureLod(source_color, quad_center_uv + vec2(1.0 / params.section.zw), 0); } + memoryBarrierShared(); + barrier(); + + // Horizontal pass. Needs to copy into 8x16 chunk of local memory so vertical pass has full resolution + uint read_index = gl_LocalInvocationID.x + gl_LocalInvocationID.y * 32 + 4; + vec4 color_top = vec4(0.0); + color_top += local_cache[read_index] * 0.174938; + color_top += local_cache[read_index + 1] * 0.165569; + color_top += local_cache[read_index + 2] * 0.140367; + color_top += local_cache[read_index + 3] * 0.106595; + color_top += local_cache[read_index - 1] * 0.165569; + color_top += local_cache[read_index - 2] * 0.140367; + color_top += local_cache[read_index - 3] * 0.106595; + + vec4 color_bottom = vec4(0.0); + color_bottom += local_cache[read_index + 16] * 0.174938; + color_bottom += local_cache[read_index + 1 + 16] * 0.165569; + color_bottom += local_cache[read_index + 2 + 16] * 0.140367; + color_bottom += local_cache[read_index + 3 + 16] * 0.106595; + color_bottom += local_cache[read_index - 1 + 16] * 0.165569; + color_bottom += local_cache[read_index - 2 + 16] * 0.140367; + color_bottom += local_cache[read_index - 3 + 16] * 0.106595; + + // rotate samples to take advantage of cache coherency + uint write_index = gl_LocalInvocationID.y * 2 + gl_LocalInvocationID.x * 16; + + temp_cache[write_index] = color_top; + temp_cache[write_index + 1] = color_bottom; + + memoryBarrierShared(); + barrier(); + + // Vertical pass + uint index = gl_LocalInvocationID.y + gl_LocalInvocationID.x * 16 + 4; vec4 color = vec4(0.0); - if (bool(params.flags & FLAG_HORIZONTAL)) { - ivec2 base_pos = ((pos + params.section.xy) << 1) + ivec2(1); - ivec2 section_begin = params.section.xy << 1; - ivec2 section_end = section_begin + (params.section.zw << 1); - - if (bool(params.flags & FLAG_HIGH_QUALITY_GLOW)) { - //Sample from two lines to capture single pixel features - GLOW_ADD(ivec2(0, 0), 0.152781); - GLOW_ADD(ivec2(1, 0), 0.144599); - GLOW_ADD(ivec2(2, 0), 0.122589); - GLOW_ADD(ivec2(3, 0), 0.093095); - GLOW_ADD(ivec2(4, 0), 0.063327); - GLOW_ADD(ivec2(-1, 0), 0.144599); - GLOW_ADD(ivec2(-2, 0), 0.122589); - GLOW_ADD(ivec2(-3, 0), 0.093095); - GLOW_ADD(ivec2(-4, 0), 0.063327); - - GLOW_ADD(ivec2(0, 1), 0.152781); - GLOW_ADD(ivec2(1, 1), 0.144599); - GLOW_ADD(ivec2(2, 1), 0.122589); - GLOW_ADD(ivec2(3, 1), 0.093095); - GLOW_ADD(ivec2(4, 1), 0.063327); - GLOW_ADD(ivec2(-1, 1), 0.144599); - GLOW_ADD(ivec2(-2, 1), 0.122589); - GLOW_ADD(ivec2(-3, 1), 0.093095); - GLOW_ADD(ivec2(-4, 1), 0.063327); - color *= 0.5; - } else { - GLOW_ADD(ivec2(0, 0), 0.174938); - GLOW_ADD(ivec2(1, 0), 0.165569); - GLOW_ADD(ivec2(2, 0), 0.140367); - GLOW_ADD(ivec2(3, 0), 0.106595); - GLOW_ADD(ivec2(-1, 0), 0.165569); - GLOW_ADD(ivec2(-2, 0), 0.140367); - GLOW_ADD(ivec2(-3, 0), 0.106595); - } - - color *= params.glow_strength; - } else { - ivec2 base_pos = pos + params.section.xy; - ivec2 section_begin = params.section.xy; - ivec2 section_end = section_begin + params.section.zw; - - GLOW_ADD(ivec2(0, 0), 0.288713); - GLOW_ADD(ivec2(0, 1), 0.233062); - GLOW_ADD(ivec2(0, 2), 0.122581); - GLOW_ADD(ivec2(0, -1), 0.233062); - GLOW_ADD(ivec2(0, -2), 0.122581); - color *= params.glow_strength; - } + color += temp_cache[index] * 0.174938; + color += temp_cache[index + 1] * 0.165569; + color += temp_cache[index + 2] * 0.140367; + color += temp_cache[index + 3] * 0.106595; + color += temp_cache[index - 1] * 0.165569; + color += temp_cache[index - 2] * 0.140367; + color += temp_cache[index - 3] * 0.106595; -#undef GLOW_ADD + color *= params.glow_strength; if (bool(params.flags & FLAG_GLOW_FIRST_PASS)) { #ifdef GLOW_USE_AUTO_EXPOSURE @@ -196,25 +206,24 @@ void main() { } color = textureLod(source_color, uv, 0.0); - if (bool(params.flags & FLAG_FORCE_LUMINANCE)) { - color.rgb = vec3(max(max(color.r, color.g), color.b)); - } - imageStore(dest_buffer, pos + params.target, color); - } else { color = texelFetch(source_color, pos + params.section.xy, 0); - if (bool(params.flags & FLAG_FORCE_LUMINANCE)) { - color.rgb = vec3(max(max(color.r, color.g), color.b)); - } - if (bool(params.flags & FLAG_FLIP_Y)) { pos.y = params.section.w - pos.y - 1; } + } - imageStore(dest_buffer, pos + params.target, color); + if (bool(params.flags & FLAG_FORCE_LUMINANCE)) { + color.rgb = vec3(max(max(color.r, color.g), color.b)); } + if (bool(params.flags & FLAG_ALPHA_TO_ONE)) { + color.a = 1.0; + } + + imageStore(dest_buffer, pos + params.target, color); + #endif #ifdef MODE_SIMPLE_COPY_DEPTH @@ -263,4 +272,8 @@ void main() { #endif imageStore(dest_buffer, pos + params.target, color); #endif + +#ifdef MODE_SET_COLOR + imageStore(dest_buffer, pos + params.target, params.set_color); +#endif } diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl index be34473892..da3c60af04 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl @@ -361,6 +361,65 @@ layout(location = 0) out vec4 frag_color; #endif // RENDER DEPTH +#ifdef ALPHA_HASH_USED + +float hash_2d(vec2 p) { + return fract(1.0e4 * sin(17.0 * p.x + 0.1 * p.y) * + (0.1 + abs(sin(13.0 * p.y + p.x)))); +} + +float hash_3d(vec3 p) { + return hash_2d(vec2(hash_2d(p.xy), p.z)); +} + +float compute_alpha_hash_threshold(vec3 pos, float hash_scale) { + vec3 dx = dFdx(pos); + vec3 dy = dFdx(pos); + float delta_max_sqr = max(length(dx), length(dy)); + float pix_scale = 1.0 / (hash_scale * delta_max_sqr); + + vec2 pix_scales = + vec2(exp2(floor(log2(pix_scale))), exp2(ceil(log2(pix_scale)))); + + vec2 a_thresh = vec2(hash_3d(floor(pix_scales.x * pos.xyz)), + hash_3d(floor(pix_scales.y * pos.xyz))); + + float lerp_factor = fract(log2(pix_scale)); + + float a_interp = (1.0 - lerp_factor) * a_thresh.x + lerp_factor * a_thresh.y; + + float min_lerp = min(lerp_factor, 1.0 - lerp_factor); + + vec3 cases = vec3(a_interp * a_interp / (2.0 * min_lerp * (1.0 - min_lerp)), + (a_interp - 0.5 * min_lerp) / (1.0 - min_lerp), + 1.0 - ((1.0 - a_interp) * (1.0 - a_interp) / + (2.0 * min_lerp * (1.0 - min_lerp)))); + + float alpha_hash_threshold = + (lerp_factor < (1.0 - min_lerp)) ? ((lerp_factor < min_lerp) ? cases.x : cases.y) : cases.z; + + return clamp(alpha_hash_threshold, 0.0, 1.0); +} + +#endif // ALPHA_HASH_USED + +#ifdef ALPHA_ANTIALIASING_EDGE_USED + +float calc_mip_level(vec2 texture_coord) { + vec2 dx = dFdx(texture_coord); + vec2 dy = dFdy(texture_coord); + float delta_max_sqr = max(dot(dx, dx), dot(dy, dy)); + return max(0.0, 0.5 * log2(delta_max_sqr)); +} + +float compute_alpha_antialiasing_edge(float input_alpha, vec2 texture_coord, float alpha_edge) { + input_alpha *= 1.0 + max(0, calc_mip_level(texture_coord)) * 0.25; // 0.25 mip scale, magic number + input_alpha = (input_alpha - alpha_edge) / max(fwidth(input_alpha), 0.0001) + 0.5; + return clamp(input_alpha, 0.0, 1.0); +} + +#endif // ALPHA_ANTIALIASING_USED + // This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. // We're dividing this factor off because the overall term we'll end up looks like // (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): @@ -1621,6 +1680,22 @@ vec4 volumetric_fog_process(vec2 screen_uv, float z) { vec4 fog_process(vec3 vertex) { vec3 fog_color = scene_data.fog_light_color; + if (scene_data.fog_aerial_perspective > 0.0) { + vec3 sky_fog_color = vec3(0.0); + vec3 cube_view = scene_data.radiance_inverse_xform * vertex; + // mip_level always reads from the second mipmap and higher so the fog is always slightly blurred + float mip_level = mix(1.0 / MAX_ROUGHNESS_LOD, 1.0, 1.0 - (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near)); +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + float lod, blend; + blend = modf(mip_level * MAX_ROUGHNESS_LOD, lod); + sky_fog_color = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(cube_view, lod)).rgb; + sky_fog_color = mix(sky_fog_color, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(cube_view, lod + 1)).rgb, blend); +#else + sky_fog_color = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_view, mip_level * MAX_ROUGHNESS_LOD).rgb; +#endif //USE_RADIANCE_CUBEMAP_ARRAY + fog_color = mix(fog_color, sky_fog_color, scene_data.fog_aerial_perspective); + } + if (scene_data.fog_sun_scatter > 0.001) { vec4 sun_scatter = vec4(0.0); float sun_total = 0.0; @@ -1676,6 +1751,15 @@ void main() { float clearcoat_gloss = 0.0; float anisotropy = 0.0; vec2 anisotropy_flow = vec2(1.0, 0.0); +#if defined(CUSTOM_FOG_USED) + vec4 custom_fog = vec4(0.0); +#endif +#if defined(CUSTOM_RADIANCE_USED) + vec4 custom_radiance = vec4(0.0); +#endif +#if defined(CUSTOM_IRRADIANCE_USED) + vec4 custom_irradiance = vec4(0.0); +#endif #if defined(AO_USED) float ao = 1.0; @@ -1684,10 +1768,6 @@ void main() { float alpha = 1.0; -#if defined(ALPHA_SCISSOR_USED) - float alpha_scissor = 0.5; -#endif - #if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) vec3 binormal = normalize(binormal_interp); vec3 tangent = normalize(tangent_interp); @@ -1724,6 +1804,19 @@ void main() { float sss_strength = 0.0; +#ifdef ALPHA_SCISSOR_USED + float alpha_scissor_threshold = 1.0; +#endif // ALPHA_SCISSOR_USED + +#ifdef ALPHA_HASH_USED + float alpha_hash_scale = 1.0; +#endif // ALPHA_HASH_USED + +#ifdef ALPHA_ANTIALIASING_EDGE_USED + float alpha_antialiasing_edge = 0.0; + vec2 alpha_texture_coordinate = vec2(0.0, 0.0); +#endif // ALPHA_ANTIALIASING_EDGE_USED + { /* clang-format off */ @@ -1732,7 +1825,7 @@ FRAGMENT_SHADER_CODE /* clang-format on */ } -#if defined(LIGHT_TRANSMITTANCE_USED) +#ifdef LIGHT_TRANSMITTANCE_USED #ifdef SSS_MODE_SKIN transmittance_color.a = sss_strength; #else @@ -1740,25 +1833,43 @@ FRAGMENT_SHADER_CODE #endif #endif -#if !defined(USE_SHADOW_TO_OPACITY) +#ifndef USE_SHADOW_TO_OPACITY -#if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { +#ifdef ALPHA_SCISSOR_USED + if (alpha < alpha_scissor_threshold) { discard; } #endif // ALPHA_SCISSOR_USED -#ifdef USE_OPAQUE_PREPASS +// alpha hash can be used in unison with alpha antialiasing +#ifdef ALPHA_HASH_USED + if (alpha < compute_alpha_hash_threshold(vertex, alpha_hash_scale)) { + discard; + } +#endif // ALPHA_HASH_USED +// If we are not edge antialiasing, we need to remove the output alpha channel from scissor and hash +#if (defined(ALPHA_SCISSOR_USED) || defined(ALPHA_HASH_USED)) && !defined(ALPHA_ANTIALIASING_EDGE_USED) + alpha = 1.0; +#endif + +#ifdef ALPHA_ANTIALIASING_EDGE_USED +// If alpha scissor is used, we must further the edge threshold, otherwise we wont get any edge feather +#ifdef ALPHA_SCISSOR_USED + alpha_antialiasing_edge = clamp(alpha_scissor_threshold + alpha_antialiasing_edge, 0.0, 1.0); +#endif + alpha = compute_alpha_antialiasing_edge(alpha, alpha_texture_coordinate, alpha_antialiasing_edge); +#endif // ALPHA_ANTIALIASING_EDGE_USED + +#ifdef USE_OPAQUE_PREPASS if (alpha < opaque_prepass_threshold) { discard; } - #endif // USE_OPAQUE_PREPASS #endif // !USE_SHADOW_TO_OPACITY -#if defined(NORMALMAP_USED) +#ifdef NORMALMAP_USED normalmap.xy = normalmap.xy * 2.0 - 1.0; normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. @@ -1767,7 +1878,7 @@ FRAGMENT_SHADER_CODE #endif -#if defined(LIGHT_ANISOTROPY_USED) +#ifdef LIGHT_ANISOTROPY_USED if (anisotropy > 0.01) { //rotation matrix @@ -1893,6 +2004,10 @@ FRAGMENT_SHADER_CODE specular_light *= scene_data.ambient_light_color_energy.a; } +#if defined(CUSTOM_RADIANCE_USED) + specular_light = mix(specular_light, custom_radiance.rgb, custom_radiance.a); +#endif + #ifndef USE_LIGHTMAP //lightmap overrides everything if (scene_data.use_ambient_light) { @@ -1910,7 +2025,9 @@ FRAGMENT_SHADER_CODE } } #endif // USE_LIGHTMAP - +#if defined(CUSTOM_IRRADIANCE_USED) + ambient_light = mix(specular_light, custom_irradiance.rgb, custom_irradiance.a); +#endif #endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) //radiance @@ -2739,6 +2856,11 @@ FRAGMENT_SHADER_CODE specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), fog.a); } +#if defined(CUSTOM_FOG_USED) + diffuse_buffer.rgb = mix(diffuse_buffer.rgb, custom_fog.rgb, custom_fog.a); + specular_buffer.rgb = mix(specular_buffer.rgb, vec3(0.0), custom_fog.a); +#endif //CUSTOM_FOG_USED + #else //MODE_MULTIPLE_RENDER_TARGETS #ifdef MODE_UNSHADED @@ -2759,6 +2881,10 @@ FRAGMENT_SHADER_CODE frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); } +#if defined(CUSTOM_FOG_USED) + frag_color.rgb = mix(frag_color.rgb, custom_fog.rgb, custom_fog.a); +#endif //CUSTOM_FOG_USED + #endif //MODE_MULTIPLE_RENDER_TARGETS #endif //MODE_RENDER_DEPTH diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl index 0cc2b90c53..e29a490ca1 100644 --- a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl @@ -43,12 +43,6 @@ layout(set = 0, binding = 3, std140) uniform SceneData { vec2 viewport_size; vec2 screen_pixel_size; - float time; - float reflection_multiplier; // one normally, zero when rendering reflections - - bool pancake_shadows; - uint pad; - //use vec4s because std140 doesnt play nice with vec2s, z and w are wasted vec4 directional_penumbra_shadow_kernel[32]; vec4 directional_soft_shadow_kernel[32]; @@ -108,6 +102,13 @@ layout(set = 0, binding = 3, std140) uniform SceneData { 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; } scene_data; diff --git a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl index a8ee33a664..06dc4b13de 100644 --- a/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl +++ b/servers/rendering/rasterizer_rd/shaders/screen_space_reflection.glsl @@ -155,18 +155,14 @@ void main() { depth = imageLoad(source_depth, ivec2(pos - 0.5)).r; - if (-depth >= params.camera_z_far) { //went beyond camera - break; - } - 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) { - // check the depth tolerance - //check that normal is valid + 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; } break; diff --git a/servers/rendering/rasterizer_rd/shaders/sky.glsl b/servers/rendering/rasterizer_rd/shaders/sky.glsl index 7711f683ae..6c985e1f5c 100644 --- a/servers/rendering/rasterizer_rd/shaders/sky.glsl +++ b/servers/rendering/rasterizer_rd/shaders/sky.glsl @@ -62,7 +62,8 @@ layout(set = 0, binding = 2, std140) uniform SceneData { bool volumetric_fog_enabled; float volumetric_fog_inv_length; float volumetric_fog_detail_spread; - uint volumetric_fog_pad; + + float fog_aerial_perspective; vec3 fog_light_color; float fog_sun_scatter; @@ -140,8 +141,8 @@ vec4 volumetric_fog_process(vec2 screen_uv) { return texture(sampler3D(volumetric_fog_texture, material_samplers[SAMPLER_LINEAR_CLAMP]), fog_pos); } -vec4 fog_process(vec3 view) { - vec3 fog_color = scene_data.fog_light_color; +vec4 fog_process(vec3 view, vec3 sky_color) { + vec3 fog_color = mix(scene_data.fog_light_color, sky_color, scene_data.fog_aerial_perspective); if (scene_data.fog_sun_scatter > 0.001) { vec4 sun_scatter = vec4(0.0); @@ -181,6 +182,7 @@ void main() { float alpha = 1.0; // Only available to subpasses vec4 half_res_color = vec4(1.0); vec4 quarter_res_color = vec4(1.0); + vec4 custom_fog = vec4(0.0); #ifdef USE_CUBEMAP_PASS vec3 inverted_cube_normal = cube_normal; @@ -225,7 +227,7 @@ FRAGMENT_SHADER_CODE // 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); + vec4 fog = fog_process(cube_normal, frag_color.rgb); frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); } @@ -234,6 +236,10 @@ FRAGMENT_SHADER_CODE frag_color.rgb = mix(frag_color.rgb, fog.rgb, fog.a); } + if (custom_fog.a > 0.0) { + frag_color.rgb = mix(frag_color.rgb, custom_fog.rgb, custom_fog.a); + } + #endif // DISABLE_FOG // Blending is disabled for Sky, so alpha doesn't blend diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl index b7c46a7d0e..4cc4fd3f64 100644 --- a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl +++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl @@ -37,16 +37,18 @@ layout(push_constant, binding = 1, std430) uniform Params { uvec2 glow_texture_size; float glow_intensity; - uint glow_level_flags; + uint pad3; uint glow_mode; + float glow_levels[7]; float exposure; float white; float auto_exposure_grey; + uint pad2; vec2 pixel_size; bool use_fxaa; - uint pad; + bool use_debanding; } params; @@ -155,6 +157,10 @@ vec3 tonemap_aces(vec3 color, float white) { } vec3 tonemap_reinhard(vec3 color, float white) { + // Ensure color values are positive. + // They can be negative in the case of negative lights, which leads to undesired behavior. + color = max(vec3(0.0), color); + return (white * color + color) / (color * white + white); } @@ -186,32 +192,32 @@ vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always o vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels vec3 glow = vec3(0.0f); - if (bool(params.glow_level_flags & (1 << 0))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb; + if (params.glow_levels[0] > 0.0001) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb * params.glow_levels[0]; } - if (bool(params.glow_level_flags & (1 << 1))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb; + if (params.glow_levels[1] > 0.0001) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb * params.glow_levels[1]; } - if (bool(params.glow_level_flags & (1 << 2))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb; + if (params.glow_levels[2] > 0.0001) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb * params.glow_levels[2]; } - if (bool(params.glow_level_flags & (1 << 3))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb; + if (params.glow_levels[3] > 0.0001) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb * params.glow_levels[3]; } - if (bool(params.glow_level_flags & (1 << 4))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb; + if (params.glow_levels[4] > 0.0001) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb * params.glow_levels[4]; } - if (bool(params.glow_level_flags & (1 << 5))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb; + if (params.glow_levels[5] > 0.0001) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb * params.glow_levels[5]; } - if (bool(params.glow_level_flags & (1 << 6))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb; + if (params.glow_levels[6] > 0.0001) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb * params.glow_levels[6]; } return glow; @@ -287,9 +293,8 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { dir * rcpDirMin)) * params.pixel_size; - vec3 rgbA = 0.5 * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz * exposure + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz) * exposure; - vec3 rgbB = rgbA * 0.5 + 0.25 * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz * exposure + - textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz * exposure); + vec3 rgbA = 0.5 * exposure * (textureLod(source_color, uv_interp + dir * (1.0 / 3.0 - 0.5), 0.0).xyz + textureLod(source_color, uv_interp + dir * (2.0 / 3.0 - 0.5), 0.0).xyz); + vec3 rgbB = rgbA * 0.5 + 0.25 * exposure * (textureLod(source_color, uv_interp + dir * -0.5, 0.0).xyz + textureLod(source_color, uv_interp + dir * 0.5, 0.0).xyz); float lumaB = dot(rgbB, luma); if ((lumaB < lumaMin) || (lumaB > lumaMax)) { @@ -299,6 +304,18 @@ vec3 do_fxaa(vec3 color, float exposure, vec2 uv_interp) { } } +// From http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf +// and https://www.shadertoy.com/view/MslGR8 (5th one starting from the bottom) +// NOTE: `frag_coord` is in pixels (i.e. not normalized UV). +vec3 screen_space_dither(vec2 frag_coord) { + // Iestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR. + vec3 dither = vec3(dot(vec2(171.0, 231.0), frag_coord)); + dither.rgb = fract(dither.rgb / vec3(103.0, 71.0, 97.0)); + + // Subtract 0.5 to avoid slightly brightening the whole viewport. + return (dither.rgb - 0.5) / 255.0; +} + void main() { vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb; @@ -322,6 +339,11 @@ void main() { if (params.use_fxaa) { color = do_fxaa(color, exposure, uv_interp); } + if (params.use_debanding) { + // For best results, debanding should be done before tonemapping. + // Otherwise, we're adding noise to an already-quantized image. + color += screen_space_dither(gl_FragCoord.xy); + } color = apply_tonemapping(color, params.white); color = linear_to_srgb(color); // regular linear -> SRGB conversion diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index 83cbfb85bd..1259b161bd 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "rendering_device.h" -#include "core/method_bind_ext.gen.inc" + #include "rendering_device_binds.h" RenderingDevice *RenderingDevice::singleton = nullptr; diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index 72afc7c621..f1f8b3cda0 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -31,8 +31,8 @@ #ifndef RENDERING_DEVICE_H #define RENDERING_DEVICE_H -#include "core/object.h" -#include "core/typed_array.h" +#include "core/object/class_db.h" +#include "core/variant/typed_array.h" #include "servers/display_server.h" class RDTextureFormat; diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp index b3d5b0ad83..4480b79f75 100644 --- a/servers/rendering/rendering_server_canvas.cpp +++ b/servers/rendering/rendering_server_canvas.cpp @@ -37,7 +37,7 @@ static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; -void RenderingServerCanvas::_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, RasterizerCanvas::Light *p_lights) { +void RenderingServerCanvas::_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, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_directional_lights, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel) { RENDER_TIMESTAMP("Cull CanvasItem Tree"); memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); @@ -68,7 +68,7 @@ void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Can RENDER_TIMESTAMP("Render Canvas Items"); - RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_transform); + RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_directional_lights, p_transform, p_default_filter, p_default_repeat, p_snap_2d_vertices_to_pixel); } void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transform2D p_transform, RenderingServerCanvas::Item *p_material_owner, RenderingServerCanvas::Item **r_items, int &r_index) { @@ -113,7 +113,12 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo } Rect2 rect = ci->get_rect(); - Transform2D xform = p_transform * ci->xform; + Transform2D xform = ci->xform; + if (snapping_2d_transforms_to_pixel) { + xform.elements[2].floor(); + } + xform = p_transform * xform; + Rect2 global_rect = xform.xform(rect); global_rect.position += p_clip_rect.position; @@ -167,8 +172,15 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo p_z = ci->z_index; } + RasterizerCanvas::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]; + } + for (int i = 0; i < child_item_count; i++) { - if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) { + if ((!child_items[i]->behind && !use_canvas_group) || (ci->sort_y && child_items[i]->sort_y)) { continue; } if (ci->sort_y) { @@ -182,6 +194,70 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); } + if (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]; + } else { + // there was a list before processing, so begin group from this one. + canvas_group_from = canvas_group_from->next; + } + + if (canvas_group_from) { + // Has a place to begin the group from! + + //compute a global rect (in global coords) for children in the same z layer + Rect2 rect_accum; + RasterizerCanvas::Item *c = canvas_group_from; + while (c) { + if (c == canvas_group_from) { + rect_accum = c->global_rect_cache; + } else { + rect_accum = rect_accum.merge(c->global_rect_cache); + } + + c = c->next; + } + + // We have two choices now, if user has drawn something, we must assume users wants to draw the "mask", so compute the size based on this. + // If nothing has been drawn, we just take it over and draw it ourselves. + if (ci->canvas_group->fit_empty && (ci->commands == nullptr || + (ci->commands->next == nullptr && ci->commands->type == Item::Command::TYPE_RECT && (static_cast<Item::CommandRect *>(ci->commands)->flags & RasterizerCanvas::CANVAS_RECT_IS_GROUP)))) { + // No commands, or sole command is the one used to draw, so we (re)create the draw command. + ci->clear(); + + if (rect_accum == Rect2()) { + rect_accum.size = Size2(1, 1); + } + + rect_accum = rect_accum.grow(ci->canvas_group->fit_margin); + + //draw it? + RasterizerCanvas::Item::CommandRect *crect = ci->alloc_command<RasterizerCanvas::Item::CommandRect>(); + + crect->flags = RasterizerCanvas::CANVAS_RECT_IS_GROUP; // so we can recognize it later + crect->rect = xform.affine_inverse().xform(rect_accum); + crect->modulate = Color(1, 1, 1, 1); + + //the global rect is used to do the copying, so update it + global_rect = rect_accum.grow(ci->canvas_group->clear_margin); //grow again by clear margin + global_rect.position += p_clip_rect.position; + } else { + global_rect.position -= p_clip_rect.position; + + global_rect = global_rect.merge(rect_accum); //must use both rects for this + global_rect = global_rect.grow(ci->canvas_group->clear_margin); //grow by clear margin + + global_rect.position += p_clip_rect.position; + } + + // Very important that this is cleared after used in RasterizerCanvas to avoid + // potential crashes. + canvas_group_from->canvas_group_owner = ci; + } + } + if (ci->update_when_visible) { RenderingServerRaster::redraw_request(); } @@ -211,7 +287,7 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo } for (int i = 0; i < child_item_count; i++) { - if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) { + if (child_items[i]->behind || use_canvas_group || (ci->sort_y && child_items[i]->sort_y)) { continue; } if (ci->sort_y) { @@ -222,30 +298,11 @@ void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transfo } } -void RenderingServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights) { - if (!p_masked_lights) { - return; - } - - RasterizerCanvas::Item *ci = p_canvas_item; - - while (ci) { - RasterizerCanvas::Light *light = p_masked_lights; - while (light) { - if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { - ci->light_masked = true; - } - - light = light->mask_next_ptr; - } - - ci = ci->next; - } -} - -void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect) { +void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::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) { RENDER_TIMESTAMP(">Render Canvas"); + snapping_2d_transforms_to_pixel = p_snap_2d_transforms_to_pixel; + if (p_canvas->children_order_dirty) { p_canvas->child_items.sort(); p_canvas->children_order_dirty = false; @@ -263,26 +320,26 @@ void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, } if (!has_mirror) { - _render_canvas_item_tree(p_render_target, ci, l, nullptr, p_transform, p_clip_rect, p_canvas->modulate, p_lights); + _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); } 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); + _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); //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); + _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); } 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); + _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); } 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); + _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); } } } @@ -451,18 +508,6 @@ void RenderingServerCanvas::canvas_item_set_update_when_visible(RID p_item, bool canvas_item->update_when_visible = p_update; } -void RenderingServerCanvas::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - canvas_item->texture_filter = p_filter; -} - -void RenderingServerCanvas::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) { - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - canvas_item->texture_repeat = p_repeat; -} - void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -484,7 +529,6 @@ void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_fro for (uint32_t i = 0; i < line->point_count; i++) { line->colors[i] = p_color; } - line->specular_shininess = Color(1, 1, 1, 1); } void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width) { @@ -495,8 +539,6 @@ void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Po Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!pline); - pline->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); - if (true || p_width <= 1) { #define TODO make thick lines possible Vector<int> indices; @@ -511,7 +553,6 @@ void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector<Po } pline->primitive = RS::PRIMITIVE_LINES; - pline->specular_shininess = Color(1, 1, 1, 1); pline->polygon.create(indices, p_points, p_colors); } else { #if 0 @@ -586,13 +627,10 @@ void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector<P Item::CommandPolygon *pline = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!pline); - pline->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); - if (true || p_width <= 1) { #define TODO make thick lines possible pline->primitive = RS::PRIMITIVE_LINES; - pline->specular_shininess = Color(1, 1, 1, 1); pline->polygon.create(Vector<int>(), p_points, p_colors); } else { } @@ -615,10 +653,7 @@ void RenderingServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_p Item::CommandPolygon *circle = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!circle); - circle->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); - circle->primitive = RS::PRIMITIVE_TRIANGLES; - circle->specular_shininess = Color(1, 1, 1, 1); Vector<int> indices; Vector<Vector2> points; @@ -645,7 +680,7 @@ void RenderingServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_p circle->polygon.create(indices, points, color); } -void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -672,11 +707,11 @@ void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; SWAP(rect->rect.size.x, rect->rect.size.y); } - rect->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - rect->specular_shininess = p_specular_color_shininess; + + rect->texture = p_texture; } -void RenderingServerCanvas::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, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, bool p_clip_uv, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::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.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -684,8 +719,9 @@ void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, cons ERR_FAIL_COND(!rect); rect->modulate = p_modulate; rect->rect = p_rect; - rect->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - rect->specular_shininess = p_specular_color_shininess; + + rect->texture = p_texture; + rect->source = p_src_rect; rect->flags = RasterizerCanvas::CANVAS_RECT_REGION; @@ -716,14 +752,15 @@ void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, cons } } -void RenderingServerCanvas::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::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::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::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); Item::CommandNinePatch *style = canvas_item->alloc_command<Item::CommandNinePatch>(); ERR_FAIL_COND(!style); - style->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - style->specular_shininess = p_specular_color_shininess; + + style->texture = p_texture; + style->rect = p_rect; style->source = p_source; style->draw_center = p_draw_center; @@ -736,7 +773,7 @@ void RenderingServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2 & style->axis_y = p_y_axis_mode; } -void RenderingServerCanvas::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, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::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) { uint32_t pc = p_points.size(); ERR_FAIL_COND(pc == 0 || pc > 4); @@ -762,11 +799,10 @@ void RenderingServerCanvas::canvas_item_add_primitive(RID p_item, const Vector<P prim->point_count = p_points.size(); - prim->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - prim->specular_shininess = p_specular_color_shininess; + prim->texture = p_texture; } -void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); #ifdef DEBUG_ENABLED @@ -783,12 +819,11 @@ void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Poi Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!polygon); polygon->primitive = RS::PRIMITIVE_TRIANGLES; - polygon->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - polygon->specular_shininess = p_specular_color_shininess; + polygon->texture = p_texture; polygon->polygon.create(indices, p_points, p_colors, p_uvs); } -void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, const Vector<int> &p_bones, const Vector<float> &p_weights, RID p_texture, int p_count) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -803,8 +838,9 @@ void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vec Item::CommandPolygon *polygon = canvas_item->alloc_command<Item::CommandPolygon>(); ERR_FAIL_COND(!polygon); - polygon->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - polygon->specular_shininess = p_specular_color_shininess; + + polygon->texture = p_texture; + polygon->polygon.create(indices, p_points, p_colors, p_uvs, p_bones, p_weights); polygon->primitive = RS::PRIMITIVE_TRIANGLES; @@ -819,42 +855,43 @@ void RenderingServerCanvas::canvas_item_add_set_transform(RID p_item, const Tran tr->xform = p_transform; } -void RenderingServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); Item::CommandMesh *m = canvas_item->alloc_command<Item::CommandMesh>(); ERR_FAIL_COND(!m); m->mesh = p_mesh; - m->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - m->specular_shininess = p_specular_color_shininess; + + m->texture = p_texture; + m->transform = p_transform; m->modulate = p_modulate; } -void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); Item::CommandParticles *part = canvas_item->alloc_command<Item::CommandParticles>(); ERR_FAIL_COND(!part); part->particles = p_particles; - part->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - part->specular_shininess = p_specular_color_shininess; + + part->texture = p_texture; //take the chance and request processing for them, at least once until they become visible again RSG::storage->particles_request_process(p_particles); } -void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { +void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); Item::CommandMultiMesh *mm = canvas_item->alloc_command<Item::CommandMultiMesh>(); ERR_FAIL_COND(!mm); mm->multimesh = p_mesh; - mm->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, mm->multimesh); - mm->specular_shininess = p_specular_color_shininess; + + mm->texture = p_texture; } void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { @@ -955,19 +992,65 @@ void RenderingServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool canvas_item->use_parent_material = p_enable; } +void RenderingServerCanvas::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) { + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + if (p_mode == RS::CANVAS_GROUP_MODE_DISABLED) { + if (canvas_item->canvas_group != nullptr) { + memdelete(canvas_item->canvas_group); + canvas_item->canvas_group = nullptr; + } + } else { + if (canvas_item->canvas_group == nullptr) { + canvas_item->canvas_group = memnew(RasterizerCanvas::Item::CanvasGroup); + } + canvas_item->canvas_group->mode = p_mode; + canvas_item->canvas_group->fit_empty = p_fit_empty; + canvas_item->canvas_group->fit_margin = p_fit_margin; + canvas_item->canvas_group->blur_mipmaps = p_blur_mipmaps; + canvas_item->canvas_group->clear_margin = p_clear_margin; + } +} + RID RenderingServerCanvas::canvas_light_create() { RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light); clight->light_internal = RSG::canvas_render->light_create(); return canvas_light_owner.make_rid(clight); } +void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) { + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + if (clight->mode == p_mode) { + return; + } + + RID canvas = clight->canvas; + + if (canvas.is_valid()) { + canvas_light_attach_to_canvas(p_light, RID()); + } + + clight->mode = p_mode; + + if (canvas.is_valid()) { + canvas_light_attach_to_canvas(p_light, canvas); + } +} + void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) { RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); if (clight->canvas.is_valid()) { Canvas *canvas = canvas_owner.getornull(clight->canvas); - canvas->lights.erase(clight); + if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) { + canvas->lights.erase(clight); + } else { + canvas->directional_lights.erase(clight); + } } if (!canvas_owner.owns(p_canvas)) { @@ -978,7 +1061,11 @@ void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_can if (clight->canvas.is_valid()) { Canvas *canvas = canvas_owner.getornull(clight->canvas); - canvas->lights.insert(clight); + if (clight->mode == RS::CANVAS_LIGHT_MODE_POINT) { + canvas->lights.insert(clight); + } else { + canvas->directional_lights.insert(clight); + } } } @@ -989,7 +1076,7 @@ void RenderingServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled clight->enabled = p_enabled; } -void RenderingServerCanvas::canvas_light_set_scale(RID p_light, float p_scale) { +void RenderingServerCanvas::canvas_light_set_texture_scale(RID p_light, float p_scale) { RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); @@ -1007,6 +1094,9 @@ void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); + if (clight->texture == p_texture) { + return; + } clight->texture = p_texture; clight->version++; RSG::canvas_render->light_set_texture(clight->light_internal, p_texture); @@ -1070,40 +1160,30 @@ void RenderingServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, clight->item_shadow_mask = p_mask; } -void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) { +void RenderingServerCanvas::canvas_light_set_directional_distance(RID p_light, float p_distance) { RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); - clight->mode = p_mode; + clight->directional_distance = p_distance; } -void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) { +void RenderingServerCanvas::canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode) { RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); - if (clight->use_shadow == p_enabled) { - return; - } - clight->use_shadow = p_enabled; - clight->version++; - RSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); + clight->blend_mode = p_mode; } -void RenderingServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size) { - ERR_FAIL_COND(p_size < 32 || p_size > 16384); - +void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) { RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); ERR_FAIL_COND(!clight); - int new_size = next_power_of_2(p_size); - if (new_size == clight->shadow_buffer_size) { + if (clight->use_shadow == p_enabled) { return; } - - clight->shadow_buffer_size = next_power_of_2(p_size); + clight->use_shadow = p_enabled; clight->version++; - - RSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); + RSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow); } void RenderingServerCanvas::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) { @@ -1271,6 +1351,41 @@ void RenderingServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder } } +void RenderingServerCanvas::canvas_set_shadow_texture_size(int p_size) { + RSG::canvas_render->set_shadow_texture_size(p_size); +} + +RID RenderingServerCanvas::canvas_texture_create() { + return RSG::storage->canvas_texture_create(); +} + +void RenderingServerCanvas::canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture) { + RSG::storage->canvas_texture_set_channel(p_canvas_texture, p_channel, p_texture); +} + +void RenderingServerCanvas::canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) { + RSG::storage->canvas_texture_set_shading_parameters(p_canvas_texture, p_base_color, p_shininess); +} + +void RenderingServerCanvas::canvas_texture_set_texture_filter(RID p_canvas_texture, RS::CanvasItemTextureFilter p_filter) { + RSG::storage->canvas_texture_set_texture_filter(p_canvas_texture, p_filter); +} + +void RenderingServerCanvas::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS::CanvasItemTextureRepeat p_repeat) { + RSG::storage->canvas_texture_set_texture_repeat(p_canvas_texture, p_repeat); +} + +void RenderingServerCanvas::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { + Item *ci = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!ci); + ci->texture_filter = p_filter; +} +void RenderingServerCanvas::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) { + Item *ci = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!ci); + ci->texture_repeat = p_repeat; +} + bool RenderingServerCanvas::free(RID p_rid) { if (canvas_owner.owns(p_rid)) { Canvas *canvas = canvas_owner.getornull(p_rid); diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h index cebe32fba0..36e2f77e95 100644 --- a/servers/rendering/rendering_server_canvas.h +++ b/servers/rendering/rendering_server_canvas.h @@ -52,8 +52,6 @@ public: Transform2D ysort_xform; Vector2 ysort_pos; int ysort_index; - RS::CanvasItemTextureFilter texture_filter; - RS::CanvasItemTextureRepeat texture_repeat; Vector<Item *> child_items; @@ -71,8 +69,6 @@ public: ysort_xform = Transform2D(); ysort_pos = Vector2(); ysort_index = 0; - texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; } }; @@ -120,6 +116,7 @@ public: }; Set<RasterizerCanvas::Light *> lights; + Set<RasterizerCanvas::Light *> directional_lights; Set<RasterizerCanvas::LightOccluderInstance *> occluders; @@ -156,17 +153,17 @@ public: RID_PtrOwner<RasterizerCanvas::Light> canvas_light_owner; bool disable_scale; + bool snapping_2d_transforms_to_pixel = false; 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, RasterizerCanvas::Light *p_lights); + 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, RasterizerCanvas::Light *p_lights, RasterizerCanvas::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, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner); - void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights); RasterizerCanvas::Item **z_list; RasterizerCanvas::Item **z_last_list; public: - void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect); + void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::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); RID canvas_create(); void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring); @@ -191,23 +188,20 @@ public: void canvas_item_set_update_when_visible(RID p_item, bool p_update); - void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter); - void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); - void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0); void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0); void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0); void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); - 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, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - 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, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), bool p_clip_uv = false, RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - 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), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - 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, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - 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(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + 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_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()); + void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1); + void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID()); + void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID()); + void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture); void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); @@ -223,10 +217,13 @@ public: void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false); + RID canvas_light_create(); + void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode); void canvas_light_attach_to_canvas(RID p_light, RID p_canvas); void canvas_light_set_enabled(RID p_light, bool p_enabled); - void canvas_light_set_scale(RID p_light, float p_scale); + void canvas_light_set_texture_scale(RID p_light, float p_scale); void canvas_light_set_transform(RID p_light, const Transform2D &p_transform); void canvas_light_set_texture(RID p_light, RID p_texture); void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset); @@ -237,11 +234,11 @@ public: void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer); void canvas_light_set_item_cull_mask(RID p_light, int p_mask); void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask); + void canvas_light_set_directional_distance(RID p_light, float p_distance); - void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode); + void canvas_light_set_blend_mode(RID p_light, RS::CanvasLightBlendMode p_mode); void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); - void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); void canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter); void canvas_light_set_shadow_color(RID p_light, const Color &p_color); void canvas_light_set_shadow_smooth(RID p_light, float p_smooth); @@ -259,6 +256,18 @@ public: void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode); + void canvas_set_shadow_texture_size(int p_size); + + RID canvas_texture_create(); + void canvas_texture_set_channel(RID p_canvas_texture, RS::CanvasTextureChannel p_channel, RID p_texture); + void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess); + + void canvas_texture_set_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter); + void canvas_texture_set_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); + + void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter); + void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); + bool free(RID p_rid); RenderingServerCanvas(); ~RenderingServerCanvas(); diff --git a/servers/rendering/rendering_server_raster.cpp b/servers/rendering/rendering_server_raster.cpp index cbc91497ba..94cfb6b752 100644 --- a/servers/rendering/rendering_server_raster.cpp +++ b/servers/rendering/rendering_server_raster.cpp @@ -30,10 +30,10 @@ #include "rendering_server_raster.h" +#include "core/config/project_settings.h" #include "core/io/marshalls.h" #include "core/os/os.h" -#include "core/project_settings.h" -#include "core/sort_array.h" +#include "core/templates/sort_array.h" #include "rendering_server_canvas.h" #include "rendering_server_globals.h" #include "rendering_server_scene.h" diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h index afb3d6f46f..daad706f8e 100644 --- a/servers/rendering/rendering_server_raster.h +++ b/servers/rendering/rendering_server_raster.h @@ -528,6 +528,11 @@ public: BIND2(viewport_remove_canvas, RID, RID) BIND3(viewport_set_canvas_transform, RID, RID, const Transform2D &) BIND2(viewport_set_transparent_background, RID, bool) + BIND2(viewport_set_snap_2d_transforms_to_pixel, RID, bool) + BIND2(viewport_set_snap_2d_vertices_to_pixel, RID, bool) + + BIND2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter) + BIND2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat) BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &) BIND4(viewport_set_canvas_stacking, RID, RID, int, int) @@ -535,6 +540,7 @@ public: BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) BIND2(viewport_set_msaa, RID, ViewportMSAA) BIND2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) + BIND2(viewport_set_use_debanding, RID, bool) BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo) BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw) @@ -581,7 +587,7 @@ public: BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) - BIND11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) + BIND11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) BIND1(environment_glow_set_use_bicubic_upscale, bool) BIND1(environment_glow_set_use_high_quality, bool) @@ -589,7 +595,7 @@ public: BIND6(environment_set_adjustment, RID, bool, float, float, float, RID) - BIND8(environment_set_fog, RID, bool, const Color &, float, float, float, float, float) + BIND9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) BIND9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter) BIND2(environment_set_volumetric_fog_volume_size, int, int) @@ -683,9 +689,19 @@ public: BIND3(canvas_set_parent, RID, RID, float) BIND1(canvas_set_disable_scale, bool) + BIND0R(RID, canvas_texture_create) + BIND3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID) + BIND3(canvas_texture_set_shading_parameters, RID, const Color &, float) + + BIND2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter) + BIND2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat) + BIND0R(RID, canvas_item_create) BIND2(canvas_item_set_parent, RID, RID) + BIND2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) + BIND2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) + BIND2(canvas_item_set_visible, RID, bool) BIND2(canvas_item_set_light_mask, RID, int) @@ -700,23 +716,20 @@ public: BIND2(canvas_item_set_draw_behind_parent, RID, bool) - BIND2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) - BIND2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) - BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) BIND4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float) BIND4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float) BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) - BIND11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND11(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND10(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND14(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) + BIND7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool) + BIND10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) + BIND6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float) + BIND5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID) + BIND9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int) + BIND5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID) + BIND3(canvas_item_add_multimesh, RID, RID, RID) + BIND3(canvas_item_add_particles, RID, RID, RID) BIND2(canvas_item_add_set_transform, RID, const Transform2D &) BIND2(canvas_item_add_clip_ignore, RID, bool) BIND2(canvas_item_set_sort_children_by_y, RID, bool) @@ -732,10 +745,15 @@ public: BIND2(canvas_item_set_use_parent_material, RID, bool) + BIND6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool) + BIND0R(RID, canvas_light_create) + + BIND2(canvas_light_set_mode, RID, CanvasLightMode) + BIND2(canvas_light_attach_to_canvas, RID, RID) BIND2(canvas_light_set_enabled, RID, bool) - BIND2(canvas_light_set_scale, RID, float) + BIND2(canvas_light_set_texture_scale, RID, float) BIND2(canvas_light_set_transform, RID, const Transform2D &) BIND2(canvas_light_set_texture, RID, RID) BIND2(canvas_light_set_texture_offset, RID, const Vector2 &) @@ -746,11 +764,11 @@ public: BIND3(canvas_light_set_layer_range, RID, int, int) BIND2(canvas_light_set_item_cull_mask, RID, int) BIND2(canvas_light_set_item_shadow_cull_mask, RID, int) + BIND2(canvas_light_set_directional_distance, RID, float) - BIND2(canvas_light_set_mode, RID, CanvasLightMode) + BIND2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode) BIND2(canvas_light_set_shadow_enabled, RID, bool) - BIND2(canvas_light_set_shadow_buffer_size, RID, int) BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) BIND2(canvas_light_set_shadow_color, RID, const Color &) BIND2(canvas_light_set_shadow_smooth, RID, float) @@ -768,6 +786,8 @@ public: BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) + BIND1(canvas_set_shadow_texture_size, int) + /* GLOBAL VARIABLES */ #undef BINDBASE diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h index 1b0a617627..a30aac3bb1 100644 --- a/servers/rendering/rendering_server_scene.h +++ b/servers/rendering/rendering_server_scene.h @@ -33,13 +33,13 @@ #include "servers/rendering/rasterizer.h" -#include "core/local_vector.h" #include "core/math/geometry_3d.h" #include "core/math/octree.h" #include "core/os/semaphore.h" #include "core/os/thread.h" -#include "core/rid_owner.h" -#include "core/self_list.h" +#include "core/templates/local_vector.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" #include "servers/xr/xr_interface.h" class RenderingServerScene { diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp index 48be6ca13b..c6682b1fcd 100644 --- a/servers/rendering/rendering_server_viewport.cpp +++ b/servers/rendering/rendering_server_viewport.cpp @@ -30,7 +30,7 @@ #include "rendering_server_viewport.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" #include "rendering_server_canvas.h" #include "rendering_server_globals.h" #include "rendering_server_scene.h" @@ -40,11 +40,21 @@ static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_vi float scale = 1.0; if (p_viewport->canvas_map.has(p_canvas->parent)) { - xf = xf * p_viewport->canvas_map[p_canvas->parent].transform; + Transform2D c_xform = p_viewport->canvas_map[p_canvas->parent].transform; + if (p_viewport->snap_2d_transforms_to_pixel) { + c_xform.elements[2] = c_xform.elements[2].floor(); + } + xf = xf * c_xform; scale = p_canvas->parent_scale; } - xf = xf * p_canvas_data->transform; + Transform2D c_xform = p_canvas_data->transform; + + if (p_viewport->snap_2d_transforms_to_pixel) { + c_xform.elements[2] = c_xform.elements[2].floor(); + } + + xf = xf * c_xform; if (scale != 1.0 && !RSG::canvas->disable_scale) { Vector2 pivot = p_vp_size * 0.5; @@ -115,7 +125,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) { //wants to draw 3D but there is no render buffer, create p_viewport->render_buffers = RSG::scene_render->render_buffers_create(); - RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa); + RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa, p_viewport->screen_space_aa, p_viewport->use_debanding); } RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor); @@ -132,10 +142,15 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); RasterizerCanvas::Light *lights = nullptr; RasterizerCanvas::Light *lights_with_shadow = nullptr; - RasterizerCanvas::Light *lights_with_mask = nullptr; + + RasterizerCanvas::Light *directional_lights = nullptr; + RasterizerCanvas::Light *directional_lights_with_shadow = nullptr; + Rect2 shadow_rect; int light_count = 0; + int shadow_count = 0; + int directional_light_count = 0; RENDER_TIMESTAMP("Cull Canvas Lights"); for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { @@ -175,10 +190,6 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: lights_with_shadow = cl; cl->radius_cache = cl->rect_cache.size.length(); } - if (cl->mode == RS::CANVAS_LIGHT_MODE_MASK) { - cl->mask_next_ptr = lights_with_mask; - lights_with_mask = cl; - } light_count++; } @@ -188,6 +199,26 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: } } + for (Set<RasterizerCanvas::Light *>::Element *F = canvas->directional_lights.front(); F; F = F->next()) { + RasterizerCanvas::Light *cl = F->get(); + if (cl->enabled) { + cl->filter_next_ptr = directional_lights; + directional_lights = cl; + cl->xform_cache = xf * cl->xform; + cl->xform_cache.elements[2] = Vector2(); //translation is pointless + if (cl->use_shadow) { + cl->shadows_next_ptr = directional_lights_with_shadow; + directional_lights_with_shadow = cl; + } + + directional_light_count++; + + if (directional_light_count == RS::MAX_2D_DIRECTIONAL_LIGHTS) { + break; + } + } + } + canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get(); } @@ -221,7 +252,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: while (light) { RENDER_TIMESTAMP("Render Shadow"); - RSG::canvas_render->light_update_shadow(light->light_internal, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders); + RSG::canvas_render->light_update_shadow(light->light_internal, shadow_count++, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders); light = light->shadows_next_ptr; } @@ -229,6 +260,90 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: RENDER_TIMESTAMP("<End rendering 2D Shadows"); } + if (directional_lights_with_shadow) { + //update shadows if any + RasterizerCanvas::Light *light = directional_lights_with_shadow; + while (light) { + Vector2 light_dir = -light->xform_cache.elements[1].normalized(); // Y is light direction + float cull_distance = light->directional_distance; + + Vector2 light_dir_sign; + light_dir_sign.x = (ABS(light_dir.x) < CMP_EPSILON) ? 0.0 : ((light_dir.x > 0.0) ? 1.0 : -1.0); + light_dir_sign.y = (ABS(light_dir.y) < CMP_EPSILON) ? 0.0 : ((light_dir.y > 0.0) ? 1.0 : -1.0); + + Vector2 points[6]; + int point_count = 0; + + for (int j = 0; j < 4; j++) { + static const Vector2 signs[4] = { Vector2(1, 1), Vector2(1, 0), Vector2(0, 0), Vector2(0, 1) }; + Vector2 sign_cmp = signs[j] * 2.0 - Vector2(1.0, 1.0); + Vector2 point = clip_rect.position + clip_rect.size * signs[j]; + + if (sign_cmp == light_dir_sign) { + //both point in same direction, plot offseted + points[point_count++] = point + light_dir * cull_distance; + } else if (sign_cmp.x == light_dir_sign.x || sign_cmp.y == light_dir_sign.y) { + int next_j = (j + 1) % 4; + Vector2 next_sign_cmp = signs[next_j] * 2.0 - Vector2(1.0, 1.0); + + //one point in the same direction, plot segment + + if (next_sign_cmp.x == light_dir_sign.x || next_sign_cmp.y == light_dir_sign.y) { + if (light_dir_sign.x != 0.0 || light_dir_sign.y != 0.0) { + points[point_count++] = point; + } + points[point_count++] = point + light_dir * cull_distance; + } else { + points[point_count++] = point + light_dir * cull_distance; + if (light_dir_sign.x != 0.0 || light_dir_sign.y != 0.0) { + points[point_count++] = point; + } + } + } else { + //plot normally + points[point_count++] = point; + } + } + + Vector2 xf_points[6]; + + RasterizerCanvas::LightOccluderInstance *occluders = nullptr; + + RENDER_TIMESTAMP(">Render Directional 2D Shadows"); + + //make list of occluders + int occ_cullded = 0; + for (Map<RID, Viewport::CanvasData>::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { + RenderingServerCanvas::Canvas *canvas = static_cast<RenderingServerCanvas::Canvas *>(E->get().canvas); + Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); + + for (Set<RasterizerCanvas::LightOccluderInstance *>::Element *F = canvas->occluders.front(); F; F = F->next()) { + if (!F->get()->enabled) { + continue; + } + F->get()->xform_cache = xf * F->get()->xform; + Transform2D localizer = F->get()->xform_cache.affine_inverse(); + + for (int j = 0; j < point_count; j++) { + xf_points[j] = localizer.xform(points[j]); + } + if (F->get()->aabb_cache.intersects_filled_polygon(xf_points, point_count)) { + F->get()->next = occluders; + occluders = F->get(); + occ_cullded++; + } + } + } + + RSG::canvas_render->light_update_directional_shadow(light->light_internal, shadow_count++, light->xform_cache, light->item_shadow_mask, cull_distance, clip_rect, occluders); + + light = light->shadows_next_ptr; + } + + //RSG::canvas_render->reset_canvas(); + RENDER_TIMESTAMP("<Render Directional 2D Shadows"); + } + if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().get_layer() > scenario_canvas_max_layer) { if (!can_draw_3d) { RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); @@ -244,6 +359,7 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size); RasterizerCanvas::Light *canvas_lights = nullptr; + RasterizerCanvas::Light *canvas_directional_lights = nullptr; RasterizerCanvas::Light *ptr = lights; while (ptr) { @@ -254,7 +370,16 @@ void RenderingServerViewport::_draw_viewport(Viewport *p_viewport, XRInterface:: ptr = ptr->filter_next_ptr; } - RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, lights_with_mask, clip_rect); + ptr = directional_lights; + while (ptr) { + if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) { + ptr->next_ptr = canvas_directional_lights; + canvas_directional_lights = ptr; + } + 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); i++; if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) { @@ -491,7 +616,7 @@ void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int RSG::scene_render->free(viewport->render_buffers); viewport->render_buffers = RID(); } else { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa); + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, viewport->use_debanding); } } } @@ -704,7 +829,7 @@ void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA } viewport->msaa = p_msaa; if (viewport->render_buffers.is_valid()) { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa); + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa, viewport->screen_space_aa, viewport->use_debanding); } } @@ -717,7 +842,20 @@ void RenderingServerViewport::viewport_set_screen_space_aa(RID p_viewport, RS::V } viewport->screen_space_aa = p_mode; if (viewport->render_buffers.is_valid()) { - RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode); + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, p_mode, viewport->use_debanding); + } +} + +void RenderingServerViewport::viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (viewport->use_debanding == p_use_debanding) { + return; + } + viewport->use_debanding = p_use_debanding; + if (viewport->render_buffers.is_valid()) { + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa, viewport->screen_space_aa, p_use_debanding); } } @@ -760,6 +898,33 @@ float RenderingServerViewport::viewport_get_measured_render_time_gpu(RID p_viewp return double((viewport->time_gpu_end - viewport->time_gpu_begin) / 1000) / 1000.0; } +void RenderingServerViewport::viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + viewport->snap_2d_transforms_to_pixel = p_enabled; +} + +void RenderingServerViewport::viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + viewport->snap_2d_vertices_to_pixel = p_enabled; +} + +void RenderingServerViewport::viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter) { + ERR_FAIL_COND_MSG(p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, "Viewport does not accept DEFAULT as texture filter (it's the topmost choice already).)"); + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->texture_filter = p_filter; +} +void RenderingServerViewport::viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat) { + ERR_FAIL_COND_MSG(p_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, "Viewport does not accept DEFAULT as texture repeat (it's the topmost choice already).)"); + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->texture_repeat = p_repeat; +} + bool RenderingServerViewport::free(RID p_rid) { if (viewport_owner.owns(p_rid)) { Viewport *viewport = viewport_owner.getornull(p_rid); diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h index 0b90646e4f..081f63690b 100644 --- a/servers/rendering/rendering_server_viewport.h +++ b/servers/rendering/rendering_server_viewport.h @@ -31,8 +31,8 @@ #ifndef VISUALSERVERVIEWPORT_H #define VISUALSERVERVIEWPORT_H -#include "core/rid_owner.h" -#include "core/self_list.h" +#include "core/templates/rid_owner.h" +#include "core/templates/self_list.h" #include "rasterizer.h" #include "servers/rendering_server.h" #include "servers/xr/xr_interface.h" @@ -59,6 +59,7 @@ public: RS::ViewportMSAA msaa; RS::ViewportScreenSpaceAA screen_space_aa; + bool use_debanding; DisplayServer::WindowID viewport_to_screen; Rect2 viewport_to_screen_rect; @@ -69,6 +70,9 @@ public: bool disable_environment; bool measure_render_time; + bool snap_2d_transforms_to_pixel; + bool snap_2d_vertices_to_pixel; + uint64_t time_cpu_begin; uint64_t time_cpu_end; @@ -85,6 +89,9 @@ public: RS::ViewportClearMode clear_mode; + RS::CanvasItemTextureFilter texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; + RS::CanvasItemTextureRepeat texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; + bool transparent_bg; struct CanvasKey { @@ -130,6 +137,10 @@ public: debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; msaa = RS::VIEWPORT_MSAA_DISABLED; screen_space_aa = RS::VIEWPORT_SCREEN_SPACE_AA_DISABLED; + use_debanding = false; + + snap_2d_transforms_to_pixel = false; + snap_2d_vertices_to_pixel = false; for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) { render_info[i] = 0; @@ -206,6 +217,7 @@ public: void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa); void viewport_set_screen_space_aa(RID p_viewport, RS::ViewportScreenSpaceAA p_mode); + void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding); virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info); virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw); @@ -214,6 +226,12 @@ public: float viewport_get_measured_render_time_cpu(RID p_viewport) const; float viewport_get_measured_render_time_gpu(RID p_viewport) const; + void viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled); + void viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled); + + void viewport_set_default_canvas_item_texture_filter(RID p_viewport, RS::CanvasItemTextureFilter p_filter); + void viewport_set_default_canvas_item_texture_repeat(RID p_viewport, RS::CanvasItemTextureRepeat p_repeat); + 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_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp index ab9856e06e..40ad228fd0 100644 --- a/servers/rendering/rendering_server_wrap_mt.cpp +++ b/servers/rendering/rendering_server_wrap_mt.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "rendering_server_wrap_mt.h" +#include "core/config/project_settings.h" #include "core/os/os.h" -#include "core/project_settings.h" #include "servers/display_server.h" void RenderingServerWrapMT::thread_exit() { diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h index 910acd74cb..d27b851d1d 100644 --- a/servers/rendering/rendering_server_wrap_mt.h +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -31,8 +31,8 @@ #ifndef RENDERING_SERVER_WRAP_MT_H #define RENDERING_SERVER_WRAP_MT_H -#include "core/command_queue_mt.h" #include "core/os/thread.h" +#include "core/templates/command_queue_mt.h" #include "servers/rendering_server.h" class RenderingServerWrapMT : public RenderingServer { @@ -431,6 +431,11 @@ public: FUNC2(viewport_remove_canvas, RID, RID) FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &) FUNC2(viewport_set_transparent_background, RID, bool) + FUNC2(viewport_set_snap_2d_transforms_to_pixel, RID, bool) + FUNC2(viewport_set_snap_2d_vertices_to_pixel, RID, bool) + + FUNC2(viewport_set_default_canvas_item_texture_filter, RID, CanvasItemTextureFilter) + FUNC2(viewport_set_default_canvas_item_texture_repeat, RID, CanvasItemTextureRepeat) FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &) FUNC4(viewport_set_canvas_stacking, RID, RID, int, int) @@ -438,6 +443,7 @@ public: FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) FUNC2(viewport_set_msaa, RID, ViewportMSAA) FUNC2(viewport_set_screen_space_aa, RID, ViewportScreenSpaceAA) + FUNC2(viewport_set_use_debanding, RID, bool) //this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) { @@ -492,7 +498,7 @@ public: FUNC1(environment_set_sdfgi_ray_count, EnvironmentSDFGIRayCount) FUNC1(environment_set_sdfgi_frames_to_converge, EnvironmentSDFGIFramesToConverge) - FUNC11(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) + FUNC11(environment_set_glow, RID, bool, Vector<float>, float, float, float, float, EnvironmentGlowBlendMode, float, float, float) FUNC1(environment_glow_set_use_bicubic_upscale, bool) FUNC1(environment_glow_set_use_high_quality, bool) @@ -500,7 +506,7 @@ public: FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID) - FUNC8(environment_set_fog, RID, bool, const Color &, float, float, float, float, float) + FUNC9(environment_set_fog, RID, bool, const Color &, float, float, float, float, float, float) FUNC9(environment_set_volumetric_fog, RID, bool, float, const Color &, float, float, float, float, EnvVolumetricFogShadowFilter) @@ -582,9 +588,19 @@ public: FUNC3(canvas_set_parent, RID, RID, float) FUNC1(canvas_set_disable_scale, bool) + FUNCRID(canvas_texture) + FUNC3(canvas_texture_set_channel, RID, CanvasTextureChannel, RID) + FUNC3(canvas_texture_set_shading_parameters, RID, const Color &, float) + + FUNC2(canvas_texture_set_texture_filter, RID, CanvasItemTextureFilter) + FUNC2(canvas_texture_set_texture_repeat, RID, CanvasItemTextureRepeat) + FUNCRID(canvas_item) FUNC2(canvas_item_set_parent, RID, RID) + FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) + FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) + FUNC2(canvas_item_set_visible, RID, bool) FUNC2(canvas_item_set_light_mask, RID, int) @@ -599,23 +615,20 @@ public: FUNC2(canvas_item_set_draw_behind_parent, RID, bool) - FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) - FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) - FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) FUNC4(canvas_item_add_polyline, RID, const Vector<Point2> &, const Vector<Color> &, float) FUNC4(canvas_item_add_multiline, RID, const Vector<Point2> &, const Vector<Color> &, float) FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) - FUNC11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC11(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC10(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC14(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + 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) + 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) + FUNC9(canvas_item_add_triangle_array, RID, const Vector<int> &, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, const Vector<int> &, const Vector<float> &, RID, int) + FUNC5(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID) + FUNC3(canvas_item_add_multimesh, RID, RID, RID) + FUNC3(canvas_item_add_particles, RID, RID, RID) FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) FUNC2(canvas_item_add_clip_ignore, RID, bool) FUNC2(canvas_item_set_sort_children_by_y, RID, bool) @@ -631,10 +644,15 @@ public: FUNC2(canvas_item_set_use_parent_material, RID, bool) + FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool) + FUNC0R(RID, canvas_light_create) + + FUNC2(canvas_light_set_mode, RID, CanvasLightMode) + FUNC2(canvas_light_attach_to_canvas, RID, RID) FUNC2(canvas_light_set_enabled, RID, bool) - FUNC2(canvas_light_set_scale, RID, float) + FUNC2(canvas_light_set_texture_scale, RID, float) FUNC2(canvas_light_set_transform, RID, const Transform2D &) FUNC2(canvas_light_set_texture, RID, RID) FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &) @@ -645,11 +663,11 @@ public: FUNC3(canvas_light_set_layer_range, RID, int, int) FUNC2(canvas_light_set_item_cull_mask, RID, int) FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int) + FUNC2(canvas_light_set_directional_distance, RID, float) - FUNC2(canvas_light_set_mode, RID, CanvasLightMode) + FUNC2(canvas_light_set_blend_mode, RID, CanvasLightBlendMode) FUNC2(canvas_light_set_shadow_enabled, RID, bool) - FUNC2(canvas_light_set_shadow_buffer_size, RID, int) FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) FUNC2(canvas_light_set_shadow_color, RID, const Color &) FUNC2(canvas_light_set_shadow_smooth, RID, float) @@ -667,6 +685,8 @@ public: FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) + FUNC1(canvas_set_shadow_texture_size, int) + /* GLOBAL VARIABLES */ FUNC3(global_variable_add, const StringName &, GlobalVariableType, const Variant &) diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index 1883b6b338..046c6ba580 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -30,7 +30,7 @@ #include "shader_language.h" #include "core/os/os.h" -#include "core/print_string.h" +#include "core/string/print_string.h" #include "servers/rendering_server.h" static bool _is_text_char(char32_t c) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 3c0a10809b..3a9f408dc0 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -31,13 +31,13 @@ #ifndef SHADER_LANGUAGE_H #define SHADER_LANGUAGE_H -#include "core/list.h" -#include "core/map.h" -#include "core/script_language.h" -#include "core/string_name.h" +#include "core/object/script_language.h" +#include "core/string/string_name.h" +#include "core/string/ustring.h" +#include "core/templates/list.h" +#include "core/templates/map.h" #include "core/typedefs.h" -#include "core/ustring.h" -#include "core/variant.h" +#include "core/variant/variant.h" class ShaderLanguage { public: diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp index f1209d9d6d..4d21807735 100644 --- a/servers/rendering/shader_types.cpp +++ b/servers/rendering/shader_types.cpp @@ -129,8 +129,16 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FOG"] = ShaderLanguage::TYPE_VEC4; // TODO consider adding to light shader + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RADIANCE"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["IRRADIANCE"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SPATIAL].functions["fragment"].can_discard = true; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR_THRESHOLD"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_HASH_SCALE"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_ANTIALIASING_EDGE"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_TEXTURE_COORDINATE"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); @@ -203,6 +211,9 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("alpha_to_coverage_and_one"); + /************ CANVAS ITEM **************************/ shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); @@ -353,6 +364,7 @@ ShaderTypes::ShaderTypes() { shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["HALF_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["QUARTER_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["FOG"] = ShaderLanguage::TYPE_VEC4; shader_modes[RS::SHADER_SKY].modes.push_back("use_half_res_pass"); shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass"); diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h index 7d8057a5c6..50f910babb 100644 --- a/servers/rendering/shader_types.h +++ b/servers/rendering/shader_types.h @@ -31,7 +31,7 @@ #ifndef SHADERTYPES_H #define SHADERTYPES_H -#include "core/ordered_hash_map.h" +#include "core/templates/ordered_hash_map.h" #include "servers/rendering_server.h" #include "shader_language.h" diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index 9434e377f8..cc959afdaa 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -30,8 +30,7 @@ #include "rendering_server.h" -#include "core/method_bind_ext.gen.inc" -#include "core/project_settings.h" +#include "core/config/project_settings.h" RenderingServer *RenderingServer::singleton = nullptr; RenderingServer *(*RenderingServer::create_func)() = nullptr; @@ -1735,6 +1734,8 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &RenderingServer::viewport_set_shadow_atlas_size); 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_use_debanding", "viewport", "enable"), &RenderingServer::viewport_set_use_debanding); + ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &RenderingServer::viewport_get_render_info); ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &RenderingServer::viewport_set_debug_draw); @@ -1747,12 +1748,12 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &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", "ao_color"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color())); - ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "level_flags", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap"), &RenderingServer::environment_set_glow); + 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"), &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_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &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", "bias", "light_affect", "ao_channel_affect", "blur", "bilateral_sharpness"), &RenderingServer::environment_set_ssao); - ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "light_color", "light_energy", "sun_scatter", "density", "height", "height_density"), &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"), &RenderingServer::environment_set_fog); ClassDB::bind_method(D_METHOD("scenario_create"), &RenderingServer::scenario_create); ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &RenderingServer::scenario_set_debug); @@ -1832,7 +1833,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_light_create"), &RenderingServer::canvas_light_create); ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &RenderingServer::canvas_light_attach_to_canvas); ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_enabled); - ClassDB::bind_method(D_METHOD("canvas_light_set_scale", "light", "scale"), &RenderingServer::canvas_light_set_scale); + ClassDB::bind_method(D_METHOD("canvas_light_set_texture_scale", "light", "scale"), &RenderingServer::canvas_light_set_texture_scale); ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &RenderingServer::canvas_light_set_transform); ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &RenderingServer::canvas_light_set_texture); ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &RenderingServer::canvas_light_set_texture_offset); @@ -1845,7 +1846,6 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_shadow_cull_mask); ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &RenderingServer::canvas_light_set_mode); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_shadow_enabled); - ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &RenderingServer::canvas_light_set_shadow_buffer_size); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &RenderingServer::canvas_light_set_shadow_filter); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &RenderingServer::canvas_light_set_shadow_color); ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &RenderingServer::canvas_light_set_shadow_smooth); @@ -2190,10 +2190,16 @@ void RenderingServer::_bind_methods() { BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MAX); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_ADD); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_SUB); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MIX); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK); + BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_DISABLED); + BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_OPAQUE); + BIND_ENUM_CONSTANT(CANVAS_GROUP_MODE_TRANSPARENT); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_POINT); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_DIRECTIONAL); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_BLEND_MODE_ADD); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_BLEND_MODE_SUB); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_BLEND_MODE_MIX); BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE); BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5); @@ -2334,6 +2340,8 @@ RenderingServer::RenderingServer() { GLOBAL_DEF("rendering/quality/shadows/soft_shadow_quality.mobile", 0); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/soft_shadow_quality", PropertyInfo(Variant::INT, "rendering/quality/shadows/soft_shadow_quality", PROPERTY_HINT_ENUM, "Hard (Fastest),Soft Low (Fast),Soft Medium (Average),Soft High (Slow),Soft Ultra (Slowest)")); + GLOBAL_DEF("rendering/quality/2d_shadow_atlas/size", 2048); + GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096); GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384")); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 7680dc1390..d676a1ba01 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -31,13 +31,13 @@ #ifndef RENDERING_SERVER_H #define RENDERING_SERVER_H -#include "core/image.h" +#include "core/io/image.h" #include "core/math/geometry_3d.h" #include "core/math/transform_2d.h" -#include "core/object.h" -#include "core/rid.h" -#include "core/typed_array.h" -#include "core/variant.h" +#include "core/object/class_db.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/rendering_device.h" #include "servers/rendering/shader_language.h" @@ -77,6 +77,7 @@ public: CANVAS_ITEM_Z_MAX = 4096, MAX_GLOW_LEVELS = 7, MAX_CURSORS = 8, + MAX_2D_DIRECTIONAL_LIGHTS = 8 }; /* TEXTURE API */ @@ -661,6 +662,25 @@ public: /* VIEWPORT TARGET API */ + enum CanvasItemTextureFilter { + CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_FILTER_NEAREST, + CANVAS_ITEM_TEXTURE_FILTER_LINEAR, + CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, + CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, + CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, + CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, + CANVAS_ITEM_TEXTURE_FILTER_MAX + }; + + enum CanvasItemTextureRepeat { + CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, + CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, + CANVAS_ITEM_TEXTURE_REPEAT_MIRROR, + CANVAS_ITEM_TEXTURE_REPEAT_MAX, + }; + virtual RID viewport_create() = 0; virtual void viewport_set_use_xr(RID p_viewport, bool p_use_xr) = 0; @@ -701,6 +721,11 @@ public: virtual void viewport_remove_canvas(RID p_viewport, RID p_canvas) = 0; virtual void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) = 0; virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0; + virtual void viewport_set_snap_2d_transforms_to_pixel(RID p_viewport, bool p_enabled) = 0; + virtual void viewport_set_snap_2d_vertices_to_pixel(RID p_viewport, bool p_enabled) = 0; + + virtual void viewport_set_default_canvas_item_texture_filter(RID p_viewport, CanvasItemTextureFilter p_filter) = 0; + virtual void viewport_set_default_canvas_item_texture_repeat(RID p_viewport, CanvasItemTextureRepeat p_repeat) = 0; virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0; virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0; @@ -727,6 +752,8 @@ public: virtual void viewport_set_screen_space_aa(RID p_viewport, ViewportScreenSpaceAA p_mode) = 0; + virtual void viewport_set_use_debanding(RID p_viewport, bool p_use_debanding) = 0; + enum ViewportRenderInfo { VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME, VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME, @@ -832,7 +859,7 @@ public: ENV_GLOW_BLEND_MODE_MIX, }; - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 0; + 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, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap) = 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; @@ -914,7 +941,7 @@ public: virtual void environment_set_sdfgi_frames_to_converge(EnvironmentSDFGIFramesToConverge p_frames) = 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) = 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; enum EnvVolumetricFogShadowFilter { ENV_VOLUMETRIC_FOG_SHADOW_FILTER_DISABLED, @@ -1090,9 +1117,26 @@ public: virtual void canvas_set_disable_scale(bool p_disable) = 0; + virtual RID canvas_texture_create() = 0; + + enum CanvasTextureChannel { + CANVAS_TEXTURE_CHANNEL_DIFFUSE, + CANVAS_TEXTURE_CHANNEL_NORMAL, + CANVAS_TEXTURE_CHANNEL_SPECULAR, + }; + virtual void canvas_texture_set_channel(RID p_canvas_texture, CanvasTextureChannel p_channel, RID p_texture) = 0; + virtual void canvas_texture_set_shading_parameters(RID p_canvas_texture, const Color &p_base_color, float p_shininess) = 0; + + //takes effect only for new draw commands + virtual void canvas_texture_set_texture_filter(RID p_canvas_texture, CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_texture_set_texture_repeat(RID p_canvas_texture, CanvasItemTextureRepeat p_repeat) = 0; + virtual RID canvas_item_create() = 0; virtual void canvas_item_set_parent(RID p_item, RID p_parent) = 0; + virtual void canvas_item_set_default_texture_filter(RID p_item, CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_item_set_default_texture_repeat(RID p_item, CanvasItemTextureRepeat p_repeat) = 0; + virtual void canvas_item_set_visible(RID p_item, bool p_visible) = 0; virtual void canvas_item_set_light_mask(RID p_item, int p_mask) = 0; @@ -1113,43 +1157,20 @@ public: NINE_PATCH_TILE_FIT, }; - enum CanvasItemTextureFilter { - CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item - CANVAS_ITEM_TEXTURE_FILTER_NEAREST, - CANVAS_ITEM_TEXTURE_FILTER_LINEAR, - CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, - CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, - CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, - CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, - CANVAS_ITEM_TEXTURE_FILTER_MAX - }; - - enum CanvasItemTextureRepeat { - CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item - CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, - CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, - CANVAS_ITEM_TEXTURE_REPEAT_MIRROR, - CANVAS_ITEM_TEXTURE_REPEAT_MAX, - }; - - //takes effect only for new draw commands - virtual void canvas_item_set_default_texture_filter(RID p_item, CanvasItemTextureFilter p_filter) = 0; - virtual void canvas_item_set_default_texture_repeat(RID p_item, CanvasItemTextureRepeat p_repeat) = 0; - virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0) = 0; virtual void canvas_item_add_polyline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0) = 0; virtual void canvas_item_add_multiline(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, float p_width = 1.0) = 0; virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; - 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, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 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, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), bool p_clip_uv = false, CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 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), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 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, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 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(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + 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_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; + virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int> &p_indices, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), const Vector<int> &p_bones = Vector<int>(), const Vector<float> &p_weights = Vector<float>(), RID p_texture = RID(), int p_count = -1) = 0; + virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID()) = 0; + virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID()) = 0; + virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture) = 0; virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0; virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0; virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0; @@ -1166,13 +1187,26 @@ public: virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable) = 0; + enum CanvasGroupMode { + CANVAS_GROUP_MODE_DISABLED, + CANVAS_GROUP_MODE_OPAQUE, + CANVAS_GROUP_MODE_TRANSPARENT, + }; + + virtual void canvas_item_set_canvas_group_mode(RID p_item, CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false) = 0; + virtual RID canvas_light_create() = 0; + + enum CanvasLightMode { + CANVAS_LIGHT_MODE_POINT, + CANVAS_LIGHT_MODE_DIRECTIONAL, + }; + + virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) = 0; + virtual void canvas_light_attach_to_canvas(RID p_light, RID p_canvas) = 0; virtual void canvas_light_set_enabled(RID p_light, bool p_enabled) = 0; - virtual void canvas_light_set_scale(RID p_light, float p_scale) = 0; virtual void canvas_light_set_transform(RID p_light, const Transform2D &p_transform) = 0; - virtual void canvas_light_set_texture(RID p_light, RID p_texture) = 0; - virtual void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) = 0; virtual void canvas_light_set_color(RID p_light, const Color &p_color) = 0; virtual void canvas_light_set_height(RID p_light, float p_height) = 0; virtual void canvas_light_set_energy(RID p_light, float p_energy) = 0; @@ -1181,14 +1215,19 @@ public: virtual void canvas_light_set_item_cull_mask(RID p_light, int p_mask) = 0; virtual void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) = 0; - enum CanvasLightMode { - CANVAS_LIGHT_MODE_ADD, - CANVAS_LIGHT_MODE_SUB, - CANVAS_LIGHT_MODE_MIX, - CANVAS_LIGHT_MODE_MASK, + virtual void canvas_light_set_directional_distance(RID p_light, float p_distance) = 0; + + virtual void canvas_light_set_texture_scale(RID p_light, float p_scale) = 0; + virtual void canvas_light_set_texture(RID p_light, RID p_texture) = 0; + virtual void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) = 0; + + enum CanvasLightBlendMode { + CANVAS_LIGHT_BLEND_MODE_ADD, + CANVAS_LIGHT_BLEND_MODE_SUB, + CANVAS_LIGHT_BLEND_MODE_MIX, }; - virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) = 0; + virtual void canvas_light_set_blend_mode(RID p_light, CanvasLightBlendMode p_mode) = 0; enum CanvasLightShadowFilter { CANVAS_LIGHT_FILTER_NONE, @@ -1198,7 +1237,6 @@ public: }; virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) = 0; - virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size) = 0; virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter) = 0; virtual void canvas_light_set_shadow_color(RID p_light, const Color &p_color) = 0; virtual void canvas_light_set_shadow_smooth(RID p_light, float p_smooth) = 0; @@ -1222,6 +1260,8 @@ public: virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, CanvasOccluderPolygonCullMode p_mode) = 0; + virtual void canvas_set_shadow_texture_size(int p_size) = 0; + /* GLOBAL VARIABLES */ enum GlobalVariableType { @@ -1405,7 +1445,9 @@ VARIANT_ENUM_CAST(RenderingServer::ShadowCastingSetting); VARIANT_ENUM_CAST(RenderingServer::NinePatchAxisMode); VARIANT_ENUM_CAST(RenderingServer::CanvasItemTextureFilter); VARIANT_ENUM_CAST(RenderingServer::CanvasItemTextureRepeat); +VARIANT_ENUM_CAST(RenderingServer::CanvasGroupMode); 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); diff --git a/servers/xr_server.cpp b/servers/xr_server.cpp index 09800443b7..45199edd24 100644 --- a/servers/xr_server.cpp +++ b/servers/xr_server.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "xr_server.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" #include "xr/xr_interface.h" #include "xr/xr_positional_tracker.h" diff --git a/servers/xr_server.h b/servers/xr_server.h index e04c7b3592..d66d4e778a 100644 --- a/servers/xr_server.h +++ b/servers/xr_server.h @@ -31,11 +31,11 @@ #ifndef XR_SERVER_H #define XR_SERVER_H +#include "core/object/reference.h" #include "core/os/os.h" #include "core/os/thread_safe.h" -#include "core/reference.h" -#include "core/rid.h" -#include "core/variant.h" +#include "core/templates/rid.h" +#include "core/variant/variant.h" class XRInterface; class XRPositionalTracker; |