diff options
author | Juan Linietsky <reduzio@gmail.com> | 2015-03-02 00:54:10 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2015-03-02 00:54:43 -0300 |
commit | a1f715a4da71fbc2b7d6fad68624bf8b22c6da17 (patch) | |
tree | 5cd305c8f8858504f0b5efb804b2c291b1dc5089 /scene/2d | |
parent | 0e732637d07d908daf64526f222e71fea402f3db (diff) |
support for 2D shadow casters
Added support for 2D shadow casters.
*DANGER* Shaders in CanvasItem CHANGED, if you are using shader in a
CanvasItem and pull this, you will lose them. Shaders now work through a
2D material system similar to 3D. If you don't want to lose the 2D
shader code, save the shader as a .shd, then create a material in
CanvasItem and re-assign the shader.
Diffstat (limited to 'scene/2d')
-rw-r--r-- | scene/2d/canvas_item.cpp | 309 | ||||
-rw-r--r-- | scene/2d/canvas_item.h | 59 | ||||
-rw-r--r-- | scene/2d/light_2d.cpp | 49 | ||||
-rw-r--r-- | scene/2d/light_2d.h | 8 | ||||
-rw-r--r-- | scene/2d/light_occluder_2d.cpp | 201 | ||||
-rw-r--r-- | scene/2d/light_occluder_2d.h | 73 |
6 files changed, 571 insertions, 128 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 223adaf9bb..4a1842100a 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -36,6 +36,192 @@ #include "scene/resources/texture.h" #include "scene/resources/style_box.h" + +bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value) { + + if (p_name==SceneStringNames::get_singleton()->shader_shader) { + set_shader(p_value); + return true; + } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) { + set_unshaded(p_value); + print_line("set unshaded"); + return true; + } else { + + if (shader.is_valid()) { + + + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/")==0) { //backwards compatibility + pr = n.substr(6,n.length()); + } + } + if (pr) { + VisualServer::get_singleton()->canvas_item_material_set_shader_param(material,pr,p_value); + return true; + } + } + } + + return false; +} + +bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const { + + + if (p_name==SceneStringNames::get_singleton()->shader_shader) { + + r_ret=get_shader(); + return true; + } else if (p_name==SceneStringNames::get_singleton()->shader_unshaded) { + + + r_ret=unshaded; + return true; + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret=VisualServer::get_singleton()->canvas_item_material_get_shader_param(material,pr); + return true; + } + } + + } + + + return false; +} + + +void CanvasItemMaterial::_get_property_list( List<PropertyInfo> *p_list) const { + + p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"CanvasItemShader,CanvasItemShaderGraph" ) ); + p_list->push_back( PropertyInfo( Variant::BOOL, "shader/unshaded") ); + + if (!shader.is_null()) { + + shader->get_param_list(p_list); + } + +} + +void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) { + + ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM); +#ifdef TOOLS_ENABLED + + if (shader.is_valid()) { + shader->disconnect("changed",this,"_shader_changed"); + } +#endif + shader=p_shader; + +#ifdef TOOLS_ENABLED + + if (shader.is_valid()) { + shader->connect("changed",this,"_shader_changed"); + } +#endif + + RID rid; + if (shader.is_valid()) + rid=shader->get_rid(); + + VS::get_singleton()->canvas_item_material_set_shader(material,rid); + _change_notify(); //properties for shader exposed + emit_changed(); +} + +Ref<Shader> CanvasItemMaterial::get_shader() const{ + + return shader; +} + +void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){ + + VS::get_singleton()->canvas_item_material_set_shader_param(material,p_param,p_value); +} + +Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{ + + return VS::get_singleton()->canvas_item_material_get_shader_param(material,p_param); +} + +void CanvasItemMaterial::_shader_changed() { + + +} + +RID CanvasItemMaterial::get_rid() const { + + return material; +} + +void CanvasItemMaterial::set_unshaded(bool p_unshaded) { + + unshaded=p_unshaded; + VS::get_singleton()->canvas_item_material_set_unshaded(material,p_unshaded); +} + +bool CanvasItemMaterial::is_unshaded() const{ + + return unshaded; +} + +void CanvasItemMaterial::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_shader","shader:Shader"),&CanvasItemMaterial::set_shader); + ObjectTypeDB::bind_method(_MD("get_shader:Shader"),&CanvasItemMaterial::get_shader); + ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItemMaterial::set_shader_param); + ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItemMaterial::get_shader_param); + ObjectTypeDB::bind_method(_MD("set_unshaded","unshaded"),&CanvasItemMaterial::set_unshaded); + ObjectTypeDB::bind_method(_MD("is_unshaded"),&CanvasItemMaterial::is_unshaded); + +} + +void CanvasItemMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String f = p_function.operator String(); + if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) { + + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\""); + } + } + } + Resource::get_argument_options(p_function,p_idx,r_options); +} + +CanvasItemMaterial::CanvasItemMaterial() { + + material=VS::get_singleton()->canvas_item_material_create(); + unshaded=false; +} + +CanvasItemMaterial::~CanvasItemMaterial(){ + + VS::get_singleton()->free(material); +} + + + + + + + + +/////////////////////////////////////////////////////////////////// + + + bool CanvasItem::is_visible() const { if (!is_inside_tree()) @@ -730,111 +916,35 @@ bool CanvasItem::is_draw_behind_parent_enabled() const{ return behind; } -void CanvasItem::set_shader(const Ref<Shader>& p_shader) { - - ERR_FAIL_COND(p_shader.is_valid() && p_shader->get_mode()!=Shader::MODE_CANVAS_ITEM); - -#ifdef TOOLS_ENABLED - - if (shader.is_valid()) { - shader->disconnect("changed",this,"_shader_changed"); - } -#endif - shader=p_shader; - -#ifdef TOOLS_ENABLED +void CanvasItem::set_material(const Ref<CanvasItemMaterial>& p_material) { - if (shader.is_valid()) { - shader->connect("changed",this,"_shader_changed"); - } -#endif + material=p_material; RID rid; - if (shader.is_valid()) - rid=shader->get_rid(); - VS::get_singleton()->canvas_item_set_shader(canvas_item,rid); - _change_notify(); //properties for shader exposed -} - -void CanvasItem::set_use_parent_shader(bool p_use_parent_shader) { - - use_parent_shader=p_use_parent_shader; - VS::get_singleton()->canvas_item_set_use_parent_shader(canvas_item,p_use_parent_shader); + if (material.is_valid()) + rid=material->get_rid(); + VS::get_singleton()->canvas_item_set_material(canvas_item,rid); + _change_notify(); //properties for material exposed } -bool CanvasItem::get_use_parent_shader() const{ +void CanvasItem::set_use_parent_material(bool p_use_parent_material) { - return use_parent_shader; + use_parent_material=p_use_parent_material; + VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item,p_use_parent_material); } -Ref<Shader> CanvasItem::get_shader() const{ +bool CanvasItem::get_use_parent_material() const{ - return shader; + return use_parent_material; } -void CanvasItem::set_shader_param(const StringName& p_param,const Variant& p_value) { +Ref<CanvasItemMaterial> CanvasItem::get_material() const{ - VS::get_singleton()->canvas_item_set_shader_param(canvas_item,p_param,p_value); + return material; } -Variant CanvasItem::get_shader_param(const StringName& p_param) const { - - return VS::get_singleton()->canvas_item_get_shader_param(canvas_item,p_param); -} - -bool CanvasItem::_set(const StringName& p_name, const Variant& p_value) { - - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); - if (pr) { - set_shader_param(pr,p_value); - return true; - } - } - return false; -} -bool CanvasItem::_get(const StringName& p_name,Variant &r_ret) const{ - if (shader.is_valid()) { - StringName pr = shader->remap_param(p_name); - if (pr) { - r_ret=get_shader_param(pr); - return true; - } - } - return false; - -} -void CanvasItem::_get_property_list( List<PropertyInfo> *p_list) const{ - - if (shader.is_valid()) { - shader->get_param_list(p_list); - } -} - -#ifdef TOOLS_ENABLED -void CanvasItem::_shader_changed() { - - _change_notify(); -} -#endif - -void CanvasItem::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { - - if (p_idx==0 && shader.is_valid() && (p_function.operator String()=="get_shader_param" || p_function.operator String()=="set_shader_param")) { - - List<PropertyInfo> pl; - shader->get_param_list(&pl); - for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { - r_options->push_back("\""+E->get().name.replace_first("shader_param/","")+"\""); - } - - return; - } - - Node::get_argument_options(p_function,p_idx,r_options); -} void CanvasItem::_bind_methods() { @@ -880,9 +990,6 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("_set_on_top","on_top"),&CanvasItem::_set_on_top); ObjectTypeDB::bind_method(_MD("_is_on_top"),&CanvasItem::_is_on_top); -#ifdef TOOLS_ENABLED - ObjectTypeDB::bind_method(_MD("_shader_changed"),&CanvasItem::_shader_changed); -#endif //ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); ObjectTypeDB::bind_method(_MD("draw_line","from","to","color","width"),&CanvasItem::draw_line,DEFVAL(1.0)); @@ -901,20 +1008,18 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("draw_set_transform","pos","rot","scale"),&CanvasItem::draw_set_transform); ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); ObjectTypeDB::bind_method(_MD("get_global_transform"),&CanvasItem::get_global_transform); + ObjectTypeDB::bind_method(_MD("get_global_transform_with_canvas"),&CanvasItem::get_global_transform_with_canvas); ObjectTypeDB::bind_method(_MD("get_viewport_transform"),&CanvasItem::get_viewport_transform); ObjectTypeDB::bind_method(_MD("get_viewport_rect"),&CanvasItem::get_viewport_rect); ObjectTypeDB::bind_method(_MD("get_canvas"),&CanvasItem::get_canvas); ObjectTypeDB::bind_method(_MD("get_world_2d"),&CanvasItem::get_world_2d); //ObjectTypeDB::bind_method(_MD("get_viewport"),&CanvasItem::get_viewport); - ObjectTypeDB::bind_method(_MD("set_shader","shader"),&CanvasItem::set_shader); - ObjectTypeDB::bind_method(_MD("get_shader"),&CanvasItem::get_shader); - ObjectTypeDB::bind_method(_MD("set_use_parent_shader","enable"),&CanvasItem::set_use_parent_shader); - ObjectTypeDB::bind_method(_MD("get_use_parent_shader"),&CanvasItem::get_use_parent_shader); - - ObjectTypeDB::bind_method(_MD("set_shader_param","param","value"),&CanvasItem::set_shader_param); - ObjectTypeDB::bind_method(_MD("get_shader_param","param"),&CanvasItem::get_shader_param); + ObjectTypeDB::bind_method(_MD("set_material","material:CanvasItemMaterial"),&CanvasItem::set_material); + ObjectTypeDB::bind_method(_MD("get_material:CanvasItemMaterial"),&CanvasItem::get_material); + ObjectTypeDB::bind_method(_MD("set_use_parent_material","enable"),&CanvasItem::set_use_parent_material); + ObjectTypeDB::bind_method(_MD("get_use_parent_material"),&CanvasItem::get_use_parent_material); BIND_VMETHOD(MethodInfo("_draw")); @@ -926,8 +1031,8 @@ void CanvasItem::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") ); ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") ); - ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") ); - ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"material/material",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial"), _SCS("set_material"),_SCS("get_material") ); + ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"material/use_parent"), _SCS("set_use_parent_material"),_SCS("get_use_parent_material") ); //exporting these two things doesn't really make much sense i think //ADD_PROPERTY( PropertyInfo(Variant::BOOL,"transform/toplevel"), _SCS("set_as_toplevel"),_SCS("is_set_as_toplevel") ); //ADD_PROPERTY(PropertyInfo(Variant::BOOL,"transform/notify"),_SCS("set_transform_notify"),_SCS("is_transform_notify_enabled")); @@ -1004,7 +1109,7 @@ CanvasItem::CanvasItem() : xform_change(this) { block_transform_notify=false; // viewport=NULL; canvas_layer=NULL; - use_parent_shader=false; + use_parent_material=false; global_invalid=true; light_mask=1; diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 2441d205ce..0c7be261ab 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -40,6 +40,41 @@ class Font; class StyleBox; +class CanvasItemMaterial : public Resource{ + + OBJ_TYPE(CanvasItemMaterial,Resource); + RID material; + Ref<Shader> shader; + bool unshaded; + +protected: + + bool _set(const StringName& p_name, const Variant& p_value); + bool _get(const StringName& p_name,Variant &r_ret) const; + void _get_property_list( List<PropertyInfo> *p_list) const; + + void _shader_changed(); + static void _bind_methods(); + + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; + +public: + + void set_shader(const Ref<Shader>& p_shader); + Ref<Shader> get_shader() const; + + void set_shader_param(const StringName& p_param,const Variant& p_value); + Variant get_shader_param(const StringName& p_param) const; + + void set_unshaded(bool p_unshaded); + bool is_unshaded() const; + + virtual RID get_rid() const; + CanvasItemMaterial(); + ~CanvasItemMaterial(); +}; + + class CanvasItem : public Node { OBJ_TYPE( CanvasItem, Node ); @@ -81,9 +116,9 @@ private: bool drawing; bool block_transform_notify; bool behind; - bool use_parent_shader; + bool use_parent_material; - Ref<Shader> shader; + Ref<CanvasItemMaterial> material; mutable Matrix32 global_transform; mutable bool global_invalid; @@ -104,9 +139,6 @@ private: void _queue_sort_children(); void _sort_children(); -#ifdef TOOLS_ENABLED - void _shader_changed(); -#endif void _notify_transform(CanvasItem *p_node); void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); } @@ -114,11 +146,6 @@ private: protected: - bool _set(const StringName& p_name, const Variant& p_value); - bool _get(const StringName& p_name,Variant &r_ret) const; - void _get_property_list( List<PropertyInfo> *p_list) const; - - _FORCE_INLINE_ void _notify_transform() { if (!is_inside_tree()) return; _notify_transform(this); if (!block_transform_notify) notification(NOTIFICATION_LOCAL_TRANSFORM_CHANGED); } void item_rect_changed(); @@ -216,16 +243,12 @@ public: RID get_canvas() const; Ref<World2D> get_world_2d() const; - void set_shader(const Ref<Shader>& p_shader); - Ref<Shader> get_shader() const; + void set_material(const Ref<CanvasItemMaterial>& p_material); + Ref<CanvasItemMaterial> get_material() const; - void set_use_parent_shader(bool p_use_parent_shader); - bool get_use_parent_shader() const; + void set_use_parent_material(bool p_use_parent_material); + bool get_use_parent_material() const; - void set_shader_param(const StringName& p_param,const Variant& p_value); - Variant get_shader_param(const StringName& p_param) const; - - void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; CanvasItem(); ~CanvasItem(); diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index cea8c06d3f..93be0c397f 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -170,6 +170,29 @@ bool Light2D::is_shadow_enabled() const { return shadow; } +void Light2D::set_shadow_buffer_size( int p_size ) { + + shadow_buffer_size=p_size; + VS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light,shadow_buffer_size); +} + +int Light2D::get_shadow_buffer_size() const { + + return shadow_buffer_size; +} + +void Light2D::set_shadow_esm_multiplier( float p_multiplier) { + + shadow_esm_multiplier=p_multiplier; + VS::get_singleton()->canvas_light_set_shadow_esm_multiplier(canvas_light,p_multiplier); +} + +float Light2D::get_shadow_esm_multiplier() const{ + + return shadow_esm_multiplier; +} + + void Light2D::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { @@ -229,18 +252,26 @@ void Light2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled); ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled); + ObjectTypeDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size); + ObjectTypeDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size); + + ObjectTypeDB::bind_method(_MD("set_shadow_esm_multiplier","multiplier"),&Light2D::set_shadow_esm_multiplier); + ObjectTypeDB::bind_method(_MD("get_shadow_esm_multiplier"),&Light2D::get_shadow_esm_multiplier); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture")); - ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"texture_offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset")); + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"offset"),_SCS("set_texture_offset"),_SCS("get_texture_offset")); ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color")); - ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),_SCS("set_height"),_SCS("get_height")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max")); - ADD_PROPERTY( PropertyInfo(Variant::INT,"item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask")); ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode")); - ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/layer_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"range/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size")); + ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier")); } @@ -258,6 +289,8 @@ Light2D::Light2D() { layer_max=0; item_mask=1; subtract_mode=false; + shadow_buffer_size=2048; + shadow_esm_multiplier=80; } diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index dbfd233d39..89f351c3cd 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -17,6 +17,8 @@ private: int layer_min; int layer_max; int item_mask; + int shadow_buffer_size; + float shadow_esm_multiplier; bool subtract_mode; Ref<Texture> texture; Vector2 texture_offset; @@ -68,6 +70,12 @@ public: void set_shadow_enabled( bool p_enabled); bool is_shadow_enabled() const; + void set_shadow_buffer_size( int p_size ); + int get_shadow_buffer_size() const; + + void set_shadow_esm_multiplier( float p_multiplier); + float get_shadow_esm_multiplier() const; + virtual Rect2 get_item_rect() const; Light2D(); diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp new file mode 100644 index 0000000000..186ea2e248 --- /dev/null +++ b/scene/2d/light_occluder_2d.cpp @@ -0,0 +1,201 @@ +#include "light_occluder_2d.h" + + +void OccluderPolygon2D::set_polygon(const DVector<Vector2>& p_polygon) { + + polygon=p_polygon; + VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,p_polygon,closed); + emit_changed(); +} + +DVector<Vector2> OccluderPolygon2D::get_polygon() const{ + + return polygon; +} + +void OccluderPolygon2D::set_closed(bool p_closed) { + + if (closed==p_closed) + return; + closed=p_closed; + VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon,polygon,closed); + emit_changed(); +} + +bool OccluderPolygon2D::is_closed() const{ + + return closed; +} + +void OccluderPolygon2D::set_cull_mode(CullMode p_mode){ + + cull=p_mode; + VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon,VS::CanvasOccluderPolygonCullMode(p_mode)); +} + +OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const{ + + return cull; +} + + +RID OccluderPolygon2D::get_rid() const { + + return occ_polygon; +} + +void OccluderPolygon2D::_bind_methods() { + + + ObjectTypeDB::bind_method(_MD("set_closed","closed"),&OccluderPolygon2D::set_closed); + ObjectTypeDB::bind_method(_MD("is_closed"),&OccluderPolygon2D::is_closed); + + ObjectTypeDB::bind_method(_MD("set_cull_mode","cull_mode"),&OccluderPolygon2D::set_cull_mode); + ObjectTypeDB::bind_method(_MD("get_cull_mode"),&OccluderPolygon2D::get_cull_mode); + + ObjectTypeDB::bind_method(_MD("set_polygon","polygon"),&OccluderPolygon2D::set_polygon); + ObjectTypeDB::bind_method(_MD("get_polygon"),&OccluderPolygon2D::get_polygon); + + ADD_PROPERTY( PropertyInfo(Variant::VECTOR2_ARRAY,"polygon"),_SCS("set_polygon"),_SCS("get_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"closed"),_SCS("set_closed"),_SCS("is_closed")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"cull_mode",PROPERTY_HINT_ENUM,"Disabled,ClockWise,CounterClockWise"),_SCS("set_cull_mode"),_SCS("get_cull_mode")); + + BIND_CONSTANT(CULL_DISABLED); + BIND_CONSTANT(CULL_CLOCKWISE); + BIND_CONSTANT(CULL_COUNTER_CLOCKWISE); +} + + +OccluderPolygon2D::OccluderPolygon2D() { + + occ_polygon=VS::get_singleton()->canvas_occluder_polygon_create(); + closed=true; + cull=CULL_DISABLED; +} + +OccluderPolygon2D::~OccluderPolygon2D() { + + VS::get_singleton()->free(occ_polygon); +} + +#ifdef DEBUG_ENABLED +void LightOccluder2D::_poly_changed() { + + update(); +} +#endif + + +void LightOccluder2D::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_CANVAS) { + + VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,get_canvas()); + VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform()); + + } + if (p_what==NOTIFICATION_TRANSFORM_CHANGED) { + + VS::get_singleton()->canvas_light_occluder_set_transform(occluder,get_global_transform()); + } + + if (p_what==NOTIFICATION_DRAW) { + + if (get_tree()->is_editor_hint()) { + + if (occluder_polygon.is_valid()) { + + DVector<Vector2> poly = occluder_polygon->get_polygon(); + + if (poly.size()) { + if (occluder_polygon->is_closed()) { + Vector<Color> color; + color.push_back(Color(0,0,0,0.6)); + draw_polygon(Variant(poly),color); + } else { + + int ps=poly.size(); + DVector<Vector2>::Read r = poly.read(); + for(int i=0;i<ps-1;i++) { + + draw_line(r[i],r[i+1],Color(0,0,0,0.6),3); + } + } + } + } + } + } + + + if (p_what==NOTIFICATION_EXIT_CANVAS) { + + VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder,RID()); + } + + +} + +void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon) { + +#ifdef DEBUG_ENABLED + if (occluder_polygon.is_valid()) + occluder_polygon->disconnect("changed",this,"_poly_changed"); +#endif + occluder_polygon=p_polygon; + + if (occluder_polygon.is_valid()) + VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,occluder_polygon->get_rid()); + else + VS::get_singleton()->canvas_light_occluder_set_polygon(occluder,RID()); + +#ifdef DEBUG_ENABLED + if (occluder_polygon.is_valid()) + occluder_polygon->connect("changed",this,"_poly_changed"); + update(); +#endif + +} + +Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const { + + return occluder_polygon; +} + +void LightOccluder2D::set_occluder_light_mask(int p_mask) { + + mask=p_mask; + VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder,mask); +} + +int LightOccluder2D::get_occluder_light_mask() const{ + + return mask; +} + +void LightOccluder2D::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("set_occluder_polygon","polygon:OccluderPolygon2D"),&LightOccluder2D::set_occluder_polygon); + ObjectTypeDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"),&LightOccluder2D::get_occluder_polygon); + + ObjectTypeDB::bind_method(_MD("set_occluder_light_mask","mask"),&LightOccluder2D::set_occluder_light_mask); + ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"),&LightOccluder2D::get_occluder_light_mask); + +#ifdef DEBUG_ENABLED + ObjectTypeDB::bind_method("_poly_changed",&LightOccluder2D::_poly_changed); +#endif + + ADD_PROPERTY( PropertyInfo(Variant::OBJECT,"occluder",PROPERTY_HINT_RESOURCE_TYPE,"OccluderPolygon2D"),_SCS("set_occluder_polygon"),_SCS("get_occluder_polygon")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"light_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_occluder_light_mask"),_SCS("get_occluder_light_mask")); +} + +LightOccluder2D::LightOccluder2D() { + + occluder=VS::get_singleton()->canvas_light_occluder_create(); + mask=1; +} + +LightOccluder2D::~LightOccluder2D() { + + VS::get_singleton()->free(occluder); +} + diff --git a/scene/2d/light_occluder_2d.h b/scene/2d/light_occluder_2d.h new file mode 100644 index 0000000000..0343e3697e --- /dev/null +++ b/scene/2d/light_occluder_2d.h @@ -0,0 +1,73 @@ +#ifndef LIGHTOCCLUDER2D_H +#define LIGHTOCCLUDER2D_H + +#include "scene/2d/node_2d.h" + +class OccluderPolygon2D : public Resource { + + OBJ_TYPE(OccluderPolygon2D,Resource); +public: + + enum CullMode { + CULL_DISABLED, + CULL_CLOCKWISE, + CULL_COUNTER_CLOCKWISE + }; +private: + + + RID occ_polygon; + DVector<Vector2> polygon; + bool closed; + CullMode cull; + +protected: + + static void _bind_methods(); +public: + + void set_polygon(const DVector<Vector2>& p_polygon); + DVector<Vector2> get_polygon() const; + + void set_closed(bool p_closed); + bool is_closed() const; + + void set_cull_mode(CullMode p_mode); + CullMode get_cull_mode() const; + + virtual RID get_rid() const; + OccluderPolygon2D(); + ~OccluderPolygon2D(); + +}; + +VARIANT_ENUM_CAST(OccluderPolygon2D::CullMode); + +class LightOccluder2D : public Node2D { + OBJ_TYPE(LightOccluder2D,Node2D); + + RID occluder; + bool enabled; + int mask; + Ref<OccluderPolygon2D> occluder_polygon; + +#ifdef DEBUG_ENABLED + void _poly_changed(); +#endif + +protected: + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_occluder_polygon(const Ref<OccluderPolygon2D>& p_polygon); + Ref<OccluderPolygon2D> get_occluder_polygon() const; + + void set_occluder_light_mask(int p_mask); + int get_occluder_light_mask() const; + + LightOccluder2D(); + ~LightOccluder2D(); +}; + +#endif // LIGHTOCCLUDER2D_H |