summaryrefslogtreecommitdiff
path: root/servers/visual/visual_server_raster.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/visual_server_raster.cpp')
-rw-r--r--servers/visual/visual_server_raster.cpp615
1 files changed, 554 insertions, 61 deletions
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index fc32702a12..3bcf0b8a3e 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -1576,6 +1576,15 @@ void VisualServerRaster::viewport_set_render_target_vflip(RID p_viewport,bool p_
}
+void VisualServerRaster::viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable) {
+
+ Viewport *viewport = viewport_owner.get( p_viewport );
+ ERR_FAIL_COND(!viewport);
+
+ viewport->render_target_clear_on_new_frame=p_enable;
+
+}
+
void VisualServerRaster::viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect) {
Viewport *viewport = viewport_owner.get( p_viewport );
@@ -1594,6 +1603,23 @@ bool VisualServerRaster::viewport_get_render_target_vflip(RID p_viewport) const{
}
+bool VisualServerRaster::viewport_get_render_target_clear_on_new_frame(RID p_viewport) const{
+
+ const Viewport *viewport = viewport_owner.get( p_viewport );
+ ERR_FAIL_COND_V(!viewport,false);
+
+ return viewport->render_target_clear_on_new_frame;
+
+}
+
+void VisualServerRaster::viewport_render_target_clear(RID p_viewport) {
+
+ Viewport *viewport = viewport_owner.get( p_viewport );
+ ERR_FAIL_COND(!viewport);
+
+ viewport->render_target_clear=true;
+
+}
void VisualServerRaster::viewport_queue_screen_capture(RID p_viewport) {
@@ -3195,6 +3221,7 @@ RID VisualServerRaster::canvas_create() {
return rid;
}
+
void VisualServerRaster::canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring) {
Canvas * canvas = canvas_owner.get(p_canvas);
@@ -3220,6 +3247,14 @@ Point2 VisualServerRaster::canvas_get_item_mirroring(RID p_canvas,RID p_item) co
return canvas->child_items[idx].mirror;
}
+void VisualServerRaster::canvas_set_modulate(RID p_canvas,const Color& p_color) {
+
+ Canvas * canvas = canvas_owner.get(p_canvas);
+ ERR_FAIL_COND(!canvas);
+ canvas->modulate=p_color;
+}
+
+
RID VisualServerRaster::canvas_item_create() {
@@ -3305,14 +3340,27 @@ bool VisualServerRaster::canvas_item_is_visible(RID p_item) const {
}
+void VisualServerRaster::canvas_item_set_light_mask(RID p_canvas_item,int p_mask) {
+
+ VS_CHANGED;
+
+ CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ if (canvas_item->light_mask==p_mask)
+ return;
+ VS_CHANGED;
+
+ canvas_item->light_mask=p_mask;
+
+}
+
+
void VisualServerRaster::canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_canvas_item );
- if (!canvas_item) {
- printf("!canvas_item\n");
- };
ERR_FAIL_COND(!canvas_item);
if (canvas_item->blend_mode==p_blend)
@@ -3470,7 +3518,7 @@ void VisualServerRaster::canvas_item_add_circle(RID p_item, const Point2& p_pos,
}
-void VisualServerRaster::canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile,const Color& p_modulate) {
+void VisualServerRaster::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) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
@@ -3493,12 +3541,16 @@ void VisualServerRaster::canvas_item_add_texture_rect(RID p_item, const Rect2& p
rect->flags|=Rasterizer::CANVAS_RECT_FLIP_V;
rect->rect.size.y = -rect->rect.size.y;
}
+ if (p_transpose) {
+ rect->flags|=Rasterizer::CANVAS_RECT_TRANSPOSE;
+ SWAP(rect->rect.size.x, rect->rect.size.y);
+ }
rect->texture=p_texture;
canvas_item->rect_dirty=true;
canvas_item->commands.push_back(rect);
}
-void VisualServerRaster::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) {
+void VisualServerRaster::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) {
VS_CHANGED;
CanvasItem *canvas_item = canvas_item_owner.get( p_item );
ERR_FAIL_COND(!canvas_item);
@@ -3521,12 +3573,17 @@ void VisualServerRaster::canvas_item_add_texture_rect_region(RID p_item, const R
rect->flags|=Rasterizer::CANVAS_RECT_FLIP_V;
rect->rect.size.y = -rect->rect.size.y;
}
+ if (p_transpose) {
+ rect->flags|=Rasterizer::CANVAS_RECT_TRANSPOSE;
+ SWAP(rect->rect.size.x, rect->rect.size.y);
+ }
canvas_item->rect_dirty=true;
canvas_item->commands.push_back(rect);
}
+
void VisualServerRaster::canvas_item_add_style_box(RID p_item, const Rect2& p_rect, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center,const Color& p_modulate) {
VS_CHANGED;
@@ -3708,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{
+ if (canvas_item->material)
+ canvas_item->material->owners.erase(canvas_item);
- CanvasItem *canvas_item = canvas_item_owner.get( p_item );
- ERR_FAIL_COND_V(!canvas_item,RID());
- return canvas_item->shader;
+ canvas_item->material=NULL;
-}
-
-void VisualServerRaster::canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value){
-
- 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;
@@ -3823,60 +3857,150 @@ void VisualServerRaster::canvas_item_raise(RID p_item) {
RID VisualServerRaster::canvas_light_create() {
- return RID();
+ Rasterizer::CanvasLight *clight = memnew( Rasterizer::CanvasLight );
+ return canvas_light_owner.make_rid(clight);
}
void VisualServerRaster::canvas_light_attach_to_canvas(RID p_light,RID p_canvas){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ if (clight->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(clight->canvas);
+ canvas->lights.erase(clight);
+ }
+
+ if (!canvas_owner.owns(p_canvas))
+ p_canvas=RID();
+ clight->canvas=p_canvas;
+
+ if (clight->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(clight->canvas);
+ canvas->lights.insert(clight);
+ }
+
+
}
void VisualServerRaster::canvas_light_set_enabled(RID p_light, bool p_enabled){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->enabled=p_enabled;
}
void VisualServerRaster::canvas_light_set_transform(RID p_light, const Matrix32& p_transform){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->xform=p_transform;
}
void VisualServerRaster::canvas_light_set_texture(RID p_light, RID p_texture){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->texture=p_texture;
}
void VisualServerRaster::canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->texture_offset=p_offset;
}
void VisualServerRaster::canvas_light_set_color(RID p_light, const Color& p_color){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->color=p_color;
+
}
void VisualServerRaster::canvas_light_set_height(RID p_light, float p_height){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->height=p_height;
}
void VisualServerRaster::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->z_min=p_min_z;
+ clight->z_max=p_max_z;
+
+}
+
+void VisualServerRaster::canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer) {
+
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->layer_min=p_min_layer;
+ clight->layer_max=p_max_layer;
}
+
void VisualServerRaster::canvas_light_set_item_mask(RID p_light, int p_mask){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->item_mask=p_mask;
}
-void VisualServerRaster::canvas_light_set_blend_mode(RID p_light, CanvasLightBlendMode p_blend_mode){
+void VisualServerRaster::canvas_light_set_subtract_mode(RID p_light, bool p_enable) {
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+ clight->subtract=p_enable;
+
}
void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){
+ Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ 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;
}
@@ -3884,24 +4008,215 @@ 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_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_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape){
+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 *********/
@@ -4154,7 +4469,17 @@ void VisualServerRaster::free( RID p_rid ) {
canvas->child_items[i].item->parent=RID();
}
-
+
+ for (Set<Rasterizer::CanvasLight*>::Element *E=canvas->lights.front();E;E=E->next()) {
+
+ 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 );
memdelete( canvas );
@@ -4183,9 +4508,75 @@ 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);
+ ERR_FAIL_COND(!canvas_light);
+
+ if (canvas_light->canvas.is_valid()) {
+ Canvas* canvas = canvas_owner.get(canvas_light->canvas);
+ if (canvas)
+ 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);
@@ -6231,7 +6622,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
}
-void VisualServerRaster::_render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect) {
+void VisualServerRaster::_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) {
static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1;
@@ -6249,7 +6640,7 @@ void VisualServerRaster::_render_canvas_item_tree(CanvasItem *p_canvas_item,cons
for(int i=0;i<z_range;i++) {
if (!z_list[i])
continue;
- rasterizer->canvas_render_items(z_list[i]);
+ rasterizer->canvas_render_items(z_list[i],CANVAS_ITEM_Z_MIN+i,p_modulate,p_lights);
}
}
@@ -6264,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;
@@ -6309,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;
}
@@ -6347,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);
}
@@ -6355,7 +6746,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
//something to draw?
ci->final_transform=xform;
ci->final_opacity=opacity * ci->self_opacity;
-
+ ci->global_rect_cache=global_rect;
int zidx = p_z-CANVAS_ITEM_Z_MIN;
@@ -6368,6 +6759,8 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
z_last_list[zidx]=ci;
}
+
+
ci->next=NULL;
}
@@ -6376,12 +6769,12 @@ 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);
}
}
-void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform) {
+void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform,Rasterizer::CanvasLight *p_lights) {
rasterizer->canvas_begin();
@@ -6414,30 +6807,30 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans
for(int i=0;i<z_range;i++) {
if (!z_list[i])
continue;
- rasterizer->canvas_render_items(z_list[i]);
+ rasterizer->canvas_render_items(z_list[i],CANVAS_ITEM_Z_MIN+i,p_canvas->modulate,p_lights);
}
} else {
for(int i=0;i<l;i++) {
Canvas::ChildItem& ci=p_canvas->child_items[i];
- _render_canvas_item_tree(ci.item,p_transform,clip_rect);
+ _render_canvas_item_tree(ci.item,p_transform,clip_rect,p_canvas->modulate,p_lights);
//mirroring (useful for scrolling backgrounds)
if (ci.mirror.x!=0) {
Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0));
- _render_canvas_item_tree(ci.item,xform2,clip_rect);
+ _render_canvas_item_tree(ci.item,xform2,clip_rect,p_canvas->modulate,p_lights);
}
if (ci.mirror.y!=0) {
Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y));
- _render_canvas_item_tree(ci.item,xform2,clip_rect);
+ _render_canvas_item_tree(ci.item,xform2,clip_rect,p_canvas->modulate,p_lights);
}
if (ci.mirror.y!=0 && ci.mirror.x!=0) {
Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror);
- _render_canvas_item_tree(ci.item,xform2,clip_rect);
+ _render_canvas_item_tree(ci.item,xform2,clip_rect,p_canvas->modulate,p_lights);
}
}
@@ -6492,7 +6885,15 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
} else if (true /*|| !p_viewport->canvas_list.empty()*/){
//clear the viewport black because of no camera? i seriously should..
- rasterizer->clear_viewport(clear_color);
+ if (p_viewport->render_target_clear_on_new_frame || p_viewport->render_target_clear) {
+ if (p_viewport->transparent_bg) {
+ rasterizer->clear_viewport(Color(0,0,0,0));
+ }
+ else {
+ rasterizer->clear_viewport(clear_color);
+ }
+ p_viewport->render_target_clear=false;
+ }
}
if (!p_viewport->hide_canvas) {
@@ -6500,21 +6901,113 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
Map<Viewport::CanvasKey,Viewport::CanvasData*> canvas_map;
+ 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()) {
+
+ Matrix32 xf = p_viewport->global_transform * E->get().transform;
+
+ //find lights in canvas
+
+
+ for(Set<Rasterizer::CanvasLight*>::Element *F=E->get().canvas->lights.front();F;F=F->next()) {
+
+ Rasterizer::CanvasLight* cl=F->get();
+ if (cl->enabled && cl->texture.is_valid()) {
+ //not super efficient..
+ Size2 tsize(rasterizer->texture_get_width(cl->texture),rasterizer->texture_get_height(cl->texture));
+ Vector2 offset=tsize/2.0;
+ 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;
+ cl->texture_cache=NULL;
+ Matrix32 scale;
+ scale.scale(cl->rect_cache.size);
+ 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) {
+
+ 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()) {
// print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size()));
//print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform);
Matrix32 xform = p_viewport->global_transform * E->get()->transform;
- _render_canvas( E->get()->canvas,xform );
+
+ Rasterizer::CanvasLight *canvas_lights=NULL;
+
+ Rasterizer::CanvasLight *ptr=lights;
+ while(ptr) {
+ if (E->get()->layer>=ptr->layer_min && E->get()->layer<=ptr->layer_max) {
+ ptr->next_ptr=canvas_lights;
+ canvas_lights=ptr;
+ }
+ ptr=ptr->filter_next_ptr;
+ }
+
+ _render_canvas( E->get()->canvas,xform,canvas_lights );
i++;
}
+
+ rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
}
//capture