diff options
Diffstat (limited to 'servers/visual/visual_server_raster.cpp')
-rw-r--r-- | servers/visual/visual_server_raster.cpp | 615 |
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 |