summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/visual/rasterizer.h67
-rw-r--r--servers/visual/visual_server_raster.cpp377
-rw-r--r--servers/visual/visual_server_raster.h61
-rw-r--r--servers/visual/visual_server_wrap_mt.h30
-rw-r--r--servers/visual_server.h33
5 files changed, 483 insertions, 85 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 4c9d0491b1..62ab8b3c56 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -572,8 +572,8 @@ public:
struct CanvasLight {
+
bool enabled;
- bool shadow;
Color color;
Matrix32 xform;
float height;
@@ -586,21 +586,26 @@ public:
RID texture;
Vector2 texture_offset;
RID canvas;
+ RID shadow_buffer;
+ int shadow_buffer_size;
+ float shadow_esm_mult;
void *texture_cache; // implementation dependent
Rect2 rect_cache;
Matrix32 xform_cache;
+ float radius_cache; //used for shadow far plane
+ CameraMatrix shadow_matrix_cache;
Matrix32 light_shader_xform;
Vector2 light_shader_pos;
+ CanvasLight *shadows_next_ptr;
CanvasLight *filter_next_ptr;
CanvasLight *next_ptr;
CanvasLight() {
- enabled=true;
- shadow=false;
+ enabled=true;
color=Color(1,1,1);
height=0;
z_min=-1024;
@@ -612,9 +617,24 @@ public:
texture_cache=NULL;
next_ptr=NULL;
filter_next_ptr=NULL;
+ shadow_buffer_size=2048;
+ shadow_esm_mult=80;
+
}
};
+ struct CanvasItem;
+
+ struct CanvasItemMaterial {
+
+ RID shader;
+ Map<StringName,Variant> shader_param;
+ uint32_t shader_version;
+ Set<CanvasItem*> owners;
+ bool unshaded;
+
+ CanvasItemMaterial() {unshaded=false; shader_version=0; }
+ };
struct CanvasItem {
@@ -744,16 +764,14 @@ public:
mutable bool rect_dirty;
mutable Rect2 rect;
CanvasItem*next;
- RID shader;
- Map<StringName,Variant> shader_param;
- uint32_t shader_version;
+ CanvasItemMaterial* material;
float final_opacity;
Matrix32 final_transform;
Rect2 final_clip_rect;
CanvasItem* final_clip_owner;
- CanvasItem* shader_owner;
+ CanvasItem* material_owner;
ViewportRender *vp_render;
Rect2 global_rect_cache;
@@ -881,8 +899,8 @@ public:
return rect;
}
- void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; shader_owner=NULL;}
- CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; shader_version=0; shader_owner=NULL;}
+ void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL;}
+ CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; }
virtual ~CanvasItem() { clear(); }
};
@@ -905,7 +923,36 @@ public:
virtual void canvas_set_transform(const Matrix32& p_transform)=0;
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0;
+ virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0;
+ /* LIGHT SHADOW MAPPING */
+
+ virtual RID canvas_light_occluder_create()=0;
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines)=0;
+
+
+ virtual RID canvas_light_shadow_buffer_create(int p_width)=0;
+ struct CanvasLightOccluderInstance {
+
+
+ bool enabled;
+ RID canvas;
+ RID polygon;
+ RID polygon_buffer;
+ Rect2 aabb_cache;
+ Matrix32 xform;
+ Matrix32 xform_cache;
+ int light_mask;
+ VS::CanvasOccluderPolygonCullMode cull_cache;
+
+ CanvasLightOccluderInstance *next;
+
+ CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0;
/* ENVIRONMENT */
@@ -945,6 +992,8 @@ public:
virtual bool is_environment(const RID& p_rid) const=0;
virtual bool is_shader(const RID& p_rid) const=0;
+ virtual bool is_canvas_light_occluder(const RID& p_rid) const=0;
+
virtual void free(const RID& p_rid)=0;
virtual void init()=0;
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index feb14d8a9d..3bcf0b8a3e 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -3765,55 +3765,32 @@ void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, boo
}
-void VisualServerRaster::canvas_item_set_use_parent_shader(RID p_item, bool p_enable) {
+void VisualServerRaster::canvas_item_set_use_parent_material(RID p_item, bool p_enable) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
- canvas_item->use_parent_shader=p_enable;
+ canvas_item->use_parent_material=p_enable;
}
-void VisualServerRaster::canvas_item_set_shader(RID p_item, RID p_shader) {
+void VisualServerRaster::canvas_item_set_material(RID p_item, RID p_material) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
- canvas_item->shader=p_shader;
-}
-
-RID VisualServerRaster::canvas_item_get_shader(RID p_item) const{
-
- CanvasItem *canvas_item = canvas_item_owner.get( p_item );
- ERR_FAIL_COND_V(!canvas_item,RID());
- return canvas_item->shader;
-}
+ if (canvas_item->material)
+ canvas_item->material->owners.erase(canvas_item);
-void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){
+ canvas_item->material=NULL;
- VS_CHANGED;
- CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
- ERR_FAIL_COND(!canvas_item);
- if (p_value.get_type()==Variant::NIL)
- canvas_item->shader_param.erase(p_param);
- else
- canvas_item->shader_param[p_param]=p_value;
-
-}
-Variant VisualServerRaster::canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const{
-
- CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
- ERR_FAIL_COND_V(!canvas_item,Variant());
- if (!canvas_item->shader_param.has(p_param)) {
- ERR_FAIL_COND_V(!canvas_item->shader.is_valid(),Variant());
- return rasterizer->shader_get_default_param(canvas_item->shader,p_param);
+ if (canvas_item_material_owner.owns(p_material)) {
+ canvas_item->material=canvas_item_material_owner.get(p_material);
+ canvas_item->material->owners.insert(canvas_item);
}
-
- return canvas_item->shader_param[p_param];
}
-
void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) {
VS_CHANGED;
@@ -3989,19 +3966,41 @@ void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_ena
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
- clight->shadow=p_enabled;
+
+ if (clight->shadow_buffer.is_valid()==p_enabled)
+ return;
+ if (p_enabled) {
+ clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ } else {
+ rasterizer->free(clight->shadow_buffer);
+ clight->shadow_buffer=RID();
+
+ }
}
+
void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
+ ERR_FAIL_COND(p_size<32 || p_size>16384);
+
+ clight->shadow_buffer_size=nearest_power_of_2(p_size);
+
+
+ if (clight->shadow_buffer.is_valid()) {
+ rasterizer->free(clight->shadow_buffer);
+ clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ }
+
}
-void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size){
+
+void VisualServerRaster::canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier) {
Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
ERR_FAIL_COND(!clight);
+ clight->shadow_esm_mult=p_multiplier;
}
@@ -4009,26 +4008,217 @@ void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size)
RID VisualServerRaster::canvas_light_occluder_create() {
- return RID();
+ Rasterizer::CanvasLightOccluderInstance *occluder = memnew( Rasterizer::CanvasLightOccluderInstance );
+
+ return canvas_light_occluder_owner.make_rid( occluder );
+
}
void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas) {
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.erase(occluder);
+ }
+
+ if (!canvas_owner.owns(p_canvas))
+ p_canvas=RID();
+
+ occluder->canvas=p_canvas;
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.insert(occluder);
+ }
}
void VisualServerRaster::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled){
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->enabled=p_enabled;
}
-void VisualServerRaster::canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape){
+void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->polygon.is_valid()) {
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+ }
+ occluder->polygon=p_polygon;
+ occluder->polygon_buffer=RID();
+
+ if (occluder->polygon.is_valid()) {
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (!occluder_poly)
+ occluder->polygon=RID();
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->owners.insert(occluder);
+ occluder->polygon_buffer=occluder_poly->occluder;
+ occluder->aabb_cache=occluder_poly->aabb;
+ occluder->cull_cache=occluder_poly->cull_mode;
+ }
}
+
+void VisualServerRaster::canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->xform=p_xform;
+
+}
+
+void VisualServerRaster::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->light_mask=p_mask;
+
+}
+
+
+RID VisualServerRaster::canvas_occluder_polygon_create() {
+
+ CanvasLightOccluderPolygon * occluder_poly = memnew( CanvasLightOccluderPolygon );
+ occluder_poly->occluder=rasterizer->canvas_light_occluder_create();
+ return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
+
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const DVector<Vector2>& p_shape, bool p_close){
+
+ if (p_shape.size()<3) {
+ canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape);
+ return;
+ }
+
+ DVector<Vector2> lines;
+ int lc = p_shape.size()*2;
+
+ lines.resize(lc-(p_close?0:2));
+ {
+ DVector<Vector2>::Write w = lines.write();
+ DVector<Vector2>::Read r = p_shape.read();
+
+ int max=lc/2;
+ if (!p_close) {
+ max--;
+ }
+ for(int i=0;i<max;i++) {
+
+ Vector2 a = r[i];
+ Vector2 b = r[(i+1)%(lc/2)];
+ w[i*2+0]=a;
+ w[i*2+1]=b;
+ }
+
+ }
+
+ canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines);
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape) {
+
+ CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ ERR_FAIL_COND(p_shape.size()&1);
+
+ int lc = p_shape.size();
+ occluder_poly->aabb=Rect2();
+ {
+ DVector<Vector2>::Read r = p_shape.read();
+ for(int i=0;i<lc;i++) {
+ if (i==0)
+ occluder_poly->aabb.pos=r[i];
+ else
+ occluder_poly->aabb.expand_to(r[i]);
+ }
+ }
+
+ rasterizer->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape);
+ for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->aabb_cache=occluder_poly->aabb;
+ }
+}
+
+void VisualServerRaster::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode) {
+
+ CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->cull_mode=p_mode;
+ for( Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->cull_cache=p_mode;
+ }
+
+}
+
+RID VisualServerRaster::canvas_item_material_create() {
+
+ Rasterizer::CanvasItemMaterial *material = memnew( Rasterizer::CanvasItemMaterial );
+ return canvas_item_material_owner.make_rid(material);
+
+}
+
+void VisualServerRaster::canvas_item_material_set_shader(RID p_material, RID p_shader){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ material->shader=p_shader;
+
+}
+void VisualServerRaster::canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ if (p_value.get_type()==Variant::NIL)
+ material->shader_param.erase(p_param);
+ else
+ material->shader_param[p_param]=p_value;
+
+
+}
+Variant VisualServerRaster::canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const{
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND_V(!material,Variant());
+ if (!material->shader_param.has(p_param)) {
+ ERR_FAIL_COND_V(!material->shader.is_valid(),Variant());
+ return rasterizer->shader_get_default_param(material->shader,p_param);
+ }
+
+ return material->shader_param[p_param];
+}
+
+void VisualServerRaster::canvas_item_material_set_unshaded(RID p_material, bool p_unshaded){
+
+ VS_CHANGED;
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material );
+ ERR_FAIL_COND(!material);
+ material->unshaded=p_unshaded;
+
+}
+
+
/******** CANVAS *********/
@@ -4285,6 +4475,10 @@ void VisualServerRaster::free( RID p_rid ) {
E->get()->canvas=RID();
}
+ for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) {
+
+ E->get()->canvas=RID();
+ }
canvas_owner.free( p_rid );
@@ -4314,10 +4508,26 @@ void VisualServerRaster::free( RID p_rid ) {
canvas_item->child_items[i]->parent=RID();
}
+ if (canvas_item->material) {
+ canvas_item->material->owners.erase(canvas_item);
+ }
+
canvas_item_owner.free( p_rid );
memdelete( canvas_item );
+ } else if (canvas_item_material_owner.owns(p_rid)) {
+
+ Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get(p_rid);
+ ERR_FAIL_COND(!material);
+ for(Set<Rasterizer::CanvasItem*>::Element *E=material->owners.front();E;E=E->next()) {
+
+ E->get()->material=NULL;
+ }
+
+ canvas_item_material_owner.free(p_rid);
+ memdelete(material);
+
} else if (canvas_light_owner.owns(p_rid)) {
Rasterizer::CanvasLight *canvas_light = canvas_light_owner.get(p_rid);
@@ -4329,9 +4539,44 @@ void VisualServerRaster::free( RID p_rid ) {
canvas->lights.erase(canvas_light);
}
+ if (canvas_light->shadow_buffer.is_valid())
+ rasterizer->free(canvas_light->shadow_buffer);
+
canvas_light_owner.free( p_rid );
memdelete( canvas_light );
+ } else if (canvas_light_occluder_owner.owns(p_rid)) {
+
+ Rasterizer::CanvasLightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->polygon.is_valid()) {
+
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+
+ }
+
+ canvas_light_occluder_owner.free( p_rid );
+ memdelete(occluder);
+
+ } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
+
+ CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid);
+ ERR_FAIL_COND(!occluder_poly);
+ rasterizer->free(occluder_poly->occluder);
+
+ while(occluder_poly->owners.size()) {
+
+ occluder_poly->owners.front()->get()->polygon=RID();
+ occluder_poly->owners.erase( occluder_poly->owners.front() );
+ }
+
+ canvas_light_occluder_polygon_owner.free( p_rid );
+ memdelete(occluder_poly);
+
} else if (scenario_owner.owns(p_rid)) {
Scenario *scenario=scenario_owner.get(p_rid);
@@ -6410,7 +6655,7 @@ void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void
}
-void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner) {
+void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_material_owner) {
CanvasItem *ci = p_canvas_item;
@@ -6455,11 +6700,11 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
ci->vp_render=NULL;
}
- if (ci->use_parent_shader && p_shader_owner)
- ci->shader_owner=p_shader_owner;
+ if (ci->use_parent_material && p_material_owner)
+ ci->material_owner=p_material_owner;
else {
- p_shader_owner=ci;
- ci->shader_owner=NULL;
+ p_material_owner=ci;
+ ci->material_owner=NULL;
}
@@ -6493,7 +6738,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
if (child_items[i]->ontop)
continue;
- _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
}
@@ -6524,7 +6769,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
if (!child_items[i]->ontop)
continue;
- _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_shader_owner);
+ _render_canvas_item(child_items[i],xform,p_clip_rect,opacity,p_z,z_list,z_last_list,(CanvasItem*)ci->final_clip_owner,p_material_owner);
}
}
@@ -6658,6 +6903,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
Rect2 clip_rect(0,0,viewport_rect.width,viewport_rect.height);
Rasterizer::CanvasLight *lights=NULL;
+ Rasterizer::CanvasLight *lights_with_shadow=NULL;
+ Rect2 shadow_rect;
for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
@@ -6676,6 +6923,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize);
cl->xform_cache=xf * cl->xform;
+
if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) {
cl->filter_next_ptr=lights;
lights=cl;
@@ -6685,16 +6933,55 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
scale.elements[2]=cl->rect_cache.pos;
cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
cl->light_shader_pos=cl->xform_cache[2];
+ if (cl->shadow_buffer.is_valid()) {
+ cl->shadows_next_ptr=lights_with_shadow;
+ if (lights_with_shadow==NULL) {
+ shadow_rect = cl->xform_cache.xform(cl->rect_cache);
+ } else {
+ shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) );
+ }
+ lights_with_shadow=cl;
+ cl->radius_cache=cl->rect_cache.size.length();
+
+ }
}
+ }
+ }
+
+ canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get();
+ }
+
+ if (lights_with_shadow) {
+ //update shadows if any
+
+ Rasterizer::CanvasLightOccluderInstance * occluders=NULL;
+
+ //make list of occluders
+ for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
+
+ Matrix32 xf = p_viewport->global_transform * E->get().transform;
+ for(Set<Rasterizer::CanvasLightOccluderInstance*>::Element *F=E->get().canvas->occluders.front();F;F=F->next()) {
+ F->get()->xform_cache = xf * F->get()->xform;
+ if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) {
+ F->get()->next=occluders;
+ occluders=F->get();
+
+ }
}
}
+ //update the light shadowmaps with them
+ Rasterizer::CanvasLight *light=lights_with_shadow;
+ while(light) {
- canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get();
+ rasterizer->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache);
+ light=light->shadows_next_ptr;
+ }
+ rasterizer->set_viewport(viewport_rect); //must reset viewport afterwards
}
for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) {
@@ -6719,6 +7006,8 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
i++;
}
+
+ rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
}
//capture
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 9b2b0c9c1a..b9a3f83364 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -371,7 +371,7 @@ class VisualServerRaster : public VisualServer {
-
+ mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner;
struct CanvasItem : public Rasterizer::CanvasItem {
@@ -384,7 +384,7 @@ class VisualServerRaster : public VisualServer {
bool sort_y;
float opacity;
float self_opacity;
- bool use_parent_shader;
+ bool use_parent_material;
Vector<CanvasItem*> child_items;
@@ -396,7 +396,7 @@ class VisualServerRaster : public VisualServer {
opacity=1;
self_opacity=1;
sort_y=false;
- use_parent_shader=false;
+ use_parent_material=false;
z_relative=true;
}
};
@@ -410,6 +410,24 @@ class VisualServerRaster : public VisualServer {
}
};
+ struct CanvasLightOccluder;
+
+ struct CanvasLightOccluderPolygon {
+
+ bool active;
+ Rect2 aabb;
+ CanvasOccluderPolygonCullMode cull_mode;
+ RID occluder;
+ Set<Rasterizer::CanvasLightOccluderInstance*> owners;
+
+ CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+ RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner;
+
+ RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner;
+
struct CanvasLight;
struct Canvas {
@@ -422,6 +440,7 @@ class VisualServerRaster : public VisualServer {
};
Set<Rasterizer::CanvasLight*> lights;
+ Set<Rasterizer::CanvasLightOccluderInstance*> occluders;
Vector<ChildItem> child_items;
Color modulate;
@@ -610,7 +629,7 @@ class VisualServerRaster : public VisualServer {
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
- void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner);
+ void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights);
Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
@@ -1131,15 +1150,8 @@ public:
virtual void canvas_item_set_z(RID p_item, int p_z);
virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
- virtual void canvas_item_set_shader(RID p_item, RID p_shader);
- virtual RID canvas_item_get_shader(RID p_item) const;
-
- virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable);
-
-
-
- virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value);
- virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const;
+ virtual void canvas_item_set_material(RID p_item, RID p_material);
+ virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
virtual RID canvas_light_create();
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas);
@@ -1156,17 +1168,36 @@ public:
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable);
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
- virtual void canvas_light_set_shadow_filter(RID p_light, int p_size);
+ virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier);
virtual RID canvas_light_occluder_create();
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas);
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled);
- virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape);
+ virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon);
+ virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform);
+ virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask);
+
+
+ virtual RID canvas_occluder_polygon_create();
+ virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_close);
+ virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape);
+ virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode);
+
+
virtual void canvas_item_clear(RID p_item);
virtual void canvas_item_raise(RID p_item);
+ /* CANVAS ITEM MATERIAL */
+
+ virtual RID canvas_item_material_create();
+ virtual void canvas_item_material_set_shader(RID p_material, RID p_shader);
+ virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value);
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
+ virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded);
+
+
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians
virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0);
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
index 6c95b6ed58..1890f7b760 100644
--- a/servers/visual/visual_server_wrap_mt.h
+++ b/servers/visual/visual_server_wrap_mt.h
@@ -1139,14 +1139,9 @@ public:
FUNC2(canvas_item_set_z,RID,int);
FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
- FUNC2(canvas_item_set_shader,RID, RID );
- FUNC1RC(RID,canvas_item_get_shader,RID );
+ FUNC2(canvas_item_set_material,RID, RID );
- FUNC2(canvas_item_set_use_parent_shader,RID, bool );
-
-
- FUNC3(canvas_item_set_shader_param,RID,const StringName&,const Variant&);
- FUNC2RC(Variant,canvas_item_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_set_use_parent_material,RID, bool );
FUNC1(canvas_item_clear,RID);
FUNC1(canvas_item_raise,RID);
@@ -1167,14 +1162,31 @@ public:
FUNC2(canvas_light_set_subtract_mode,RID,bool);
FUNC2(canvas_light_set_shadow_enabled,RID,bool);
FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
- FUNC2(canvas_light_set_shadow_filter,RID,int);
+ FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float);
+
/* CANVAS OCCLUDER */
FUNC0R(RID,canvas_light_occluder_create);
FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID);
FUNC2(canvas_light_occluder_set_enabled,RID,bool);
- FUNC2(canvas_light_occluder_set_shape,RID,const DVector<Vector2>&);
+ FUNC2(canvas_light_occluder_set_polygon,RID,RID);
+ FUNC2(canvas_light_occluder_set_transform,RID,const Matrix32&);
+ FUNC2(canvas_light_occluder_set_light_mask,RID,int);
+
+
+ FUNC0R(RID,canvas_occluder_polygon_create);
+ FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>&,bool);
+ FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&);
+ FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode);
+
+ /* CANVAS MATERIAL */
+
+ FUNC0R(RID,canvas_item_material_create);
+ FUNC2(canvas_item_material_set_shader,RID,RID);
+ FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&);
+ FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
+ FUNC2(canvas_item_material_set_unshaded,RID,bool);
/* CURSOR */
FUNC2(cursor_set_rotation,float , int ); // radians
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 37368e32f4..ccf6978ae3 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -998,13 +998,9 @@ public:
virtual void canvas_item_clear(RID p_item)=0;
virtual void canvas_item_raise(RID p_item)=0;
- virtual void canvas_item_set_shader(RID p_item, RID p_shader)=0;
- virtual RID canvas_item_get_shader(RID p_item) const=0;
+ virtual void canvas_item_set_material(RID p_item, RID p_material)=0;
- virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable)=0;
-
- virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0;
- virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=0;
+ virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable)=0;
virtual RID canvas_light_create()=0;
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0;
@@ -1021,13 +1017,34 @@ public:
virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0;
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, int p_size)=0;
+ virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0;
+
virtual RID canvas_light_occluder_create()=0;
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0;
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0;
- virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape)=0;
+ virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon)=0;
+ virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform)=0;
+ virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask)=0;
+
+ virtual RID canvas_occluder_polygon_create()=0;
+ virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed)=0;
+ virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape)=0;
+ enum CanvasOccluderPolygonCullMode {
+ CANVAS_OCCLUDER_POLYGON_CULL_DISABLED,
+ CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE,
+ CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE,
+ };
+ virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0;
+
+ /* CANVAS ITEM MATERIAL */
+
+ virtual RID canvas_item_material_create()=0;
+ virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0;
+ virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
+ virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0;
+ virtual void canvas_item_material_set_unshaded(RID p_material, bool p_unshaded)=0;
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians