diff options
Diffstat (limited to 'servers/visual/visual_server_raster.cpp')
| -rw-r--r-- | servers/visual/visual_server_raster.cpp | 1345 |
1 files changed, 1043 insertions, 302 deletions
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index af50b9b592..a94d4f64c7 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -112,6 +112,21 @@ void VisualServerRaster::texture_set_reload_hook(RID p_texture,ObjectID p_owner, rasterizer->texture_set_reload_hook(p_texture,p_owner,p_function); } +void VisualServerRaster::texture_set_path(RID p_texture,const String& p_path) { + + rasterizer->texture_set_path(p_texture,p_path); +} + +String VisualServerRaster::texture_get_path(RID p_texture) const{ + + return rasterizer->texture_get_path(p_texture); +} + +void VisualServerRaster::texture_debug_usage(List<TextureInfo> *r_info){ + + rasterizer->texture_debug_usage(r_info); +} + /* SHADER API */ RID VisualServerRaster::shader_create(ShaderMode p_mode) { @@ -157,6 +172,16 @@ void VisualServerRaster::shader_get_param_list(RID p_shader, List<PropertyInfo> } +void VisualServerRaster::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) { + + rasterizer->shader_set_default_texture_param(p_shader,p_name,p_texture); +} + +RID VisualServerRaster::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ + + return rasterizer->shader_get_default_texture_param(p_shader,p_name); +} + /* Material */ @@ -444,6 +469,14 @@ AABB VisualServerRaster::mesh_get_custom_aabb(RID p_mesh) const { return rasterizer->mesh_get_custom_aabb(p_mesh); } +void VisualServerRaster::mesh_clear(RID p_mesh) { + + ERR_FAIL_COND(!rasterizer->is_mesh(p_mesh)); + while(rasterizer->mesh_get_surface_count(p_mesh)) { + rasterizer->mesh_remove_surface(p_mesh,0); + } +} + /* MULTIMESH */ @@ -1357,7 +1390,7 @@ void VisualServerRaster::_update_baked_light_sampler_dp_cache(BakedLightSampler void VisualServerRaster::baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution){ - ERR_FAIL_COND(p_resolution<4 && p_resolution>64); + ERR_FAIL_COND(p_resolution<4 || p_resolution>64); VS_CHANGED; BakedLightSampler * blsamp = baked_light_sampler_owner.get(p_baked_light_sampler); ERR_FAIL_COND(!blsamp); @@ -1566,6 +1599,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 ); @@ -1584,6 +1626,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) { @@ -1657,6 +1716,17 @@ void VisualServerRaster::viewport_set_hide_canvas(RID p_viewport,bool p_hide) { } +void VisualServerRaster::viewport_set_disable_environment(RID p_viewport,bool p_disable) { + + VS_CHANGED; + + Viewport *viewport=NULL; + viewport = viewport_owner.get( p_viewport ); + ERR_FAIL_COND(!viewport); + viewport->disable_environment=p_disable; + +} + void VisualServerRaster::viewport_attach_camera(RID p_viewport,RID p_camera) { VS_CHANGED; @@ -3185,6 +3255,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); @@ -3210,6 +3281,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() { @@ -3295,14 +3374,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) @@ -3342,130 +3434,15 @@ void VisualServerRaster::canvas_item_set_clip(RID p_item, bool p_clip) { canvas_item->clip=p_clip; } -const Rect2& VisualServerRaster::CanvasItem::get_rect() const { - - if (custom_rect || !rect_dirty) - return rect; - - //must update rect - int s=commands.size(); - if (s==0) { - - rect=Rect2(); - rect_dirty=false; - return rect; - } - - Matrix32 xf; - bool found_xform=false; - bool first=true; - - const CanvasItem::Command * const *cmd = &commands[0]; - - - for (int i=0;i<s;i++) { - - const CanvasItem::Command *c=cmd[i]; - Rect2 r; - - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { - - const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c); - r.pos=line->from; - r.expand_to(line->to); - } break; - case CanvasItem::Command::TYPE_RECT: { - - const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c); - r=crect->rect; - - } break; - case CanvasItem::Command::TYPE_STYLE: { - - const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c); - r=style->rect; - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { - - const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c); - r.pos=primitive->points[0]; - for(int i=1;i<primitive->points.size();i++) { - - r.expand_to(primitive->points[i]); - - } - } break; - case CanvasItem::Command::TYPE_POLYGON: { - - const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c); - int l = polygon->points.size(); - const Point2*pp=&polygon->points[0]; - r.pos=pp[0]; - for(int i=1;i<l;i++) { - - r.expand_to(pp[i]); - - } - } break; - - case CanvasItem::Command::TYPE_POLYGON_PTR: { - - const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c); - int l = polygon->count; - if (polygon->indices != NULL) { - - r.pos=polygon->points[polygon->indices[0]]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[polygon->indices[i]]); - }; - } else { - r.pos=polygon->points[0]; - for (int i=1; i<polygon->count; i++) { - - r.expand_to(polygon->points[i]); - }; - }; - } break; - case CanvasItem::Command::TYPE_CIRCLE: { - - const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c); - r.pos=Point2(-circle->radius,-circle->radius)+circle->pos; - r.size=Point2(circle->radius*2.0,circle->radius*2.0); - } break; - case CanvasItem::Command::TYPE_TRANSFORM: { - - const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c); - xf=transform->xform; - found_xform=true; - continue; - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - } break; - } - - if (found_xform) { - r = xf.xform(r); - found_xform=false; - } - - - if (first) { - rect=r; - first=false; - } else - rect=rect.merge(r); - } +void VisualServerRaster::canvas_item_set_distance_field_mode(RID p_item, bool p_distance_field) { + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); - rect_dirty=false; - return rect; + canvas_item->distance_field=p_distance_field; } + void VisualServerRaster::canvas_item_set_transform(RID p_item, const Matrix32& p_transform) { VS_CHANGED; @@ -3583,7 +3560,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); @@ -3606,12 +3583,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); @@ -3634,12 +3615,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; @@ -3802,6 +3788,72 @@ void VisualServerRaster::canvas_item_add_set_blend_mode(RID p_item, MaterialBlen canvas_item->commands.push_back(bm); }; +void VisualServerRaster::canvas_item_set_z(RID p_item, int p_z) { + + ERR_FAIL_COND(p_z<CANVAS_ITEM_Z_MIN || p_z>CANVAS_ITEM_Z_MAX); + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z=p_z; + +} + +void VisualServerRaster::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + canvas_item->z_relative=p_enable; + +} + +void VisualServerRaster::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2& p_rect) { + + VS_CHANGED; + CanvasItem *canvas_item = canvas_item_owner.get( p_item ); + ERR_FAIL_COND(!canvas_item); + if (bool(canvas_item->copy_back_buffer!=NULL) !=p_enable) { + if (p_enable) { + canvas_item->copy_back_buffer = memnew( Rasterizer::CanvasItem::CopyBackBuffer ); + } else { + memdelete(canvas_item->copy_back_buffer); + canvas_item->copy_back_buffer=NULL; + } + } + + if (p_enable) { + canvas_item->copy_back_buffer->rect=p_rect; + canvas_item->copy_back_buffer->full=p_rect==Rect2(); + } + +} + +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_material=p_enable; + +} + +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); + + if (canvas_item->material) + canvas_item->material->owners.erase(canvas_item); + + canvas_item->material=NULL; + + 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); + } +} + void VisualServerRaster::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { VS_CHANGED; @@ -3864,6 +3916,408 @@ void VisualServerRaster::canvas_item_raise(RID p_item) { } +/***** CANVAS LIGHT *******/ + +RID VisualServerRaster::canvas_light_create() { + + 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_scale(RID p_light, float p_scale) { + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->scale=p_scale; + +} + + +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_energy(RID p_light, float p_energy){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->energy=p_energy; + +} + +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_item_shadow_mask(RID p_light, int p_mask){ + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->item_shadow_mask=p_mask; + +} + + +void VisualServerRaster::canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) { + + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->mode=p_mode; + +} +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_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; + +} + +void VisualServerRaster::canvas_light_set_shadow_color(RID p_light, const Color& p_color) { + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->shadow_color=p_color; + +} + + +/****** CANVAS LIGHT OCCLUDER ******/ + +RID VisualServerRaster::canvas_light_occluder_create() { + + 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_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_shading_mode(RID p_material, CanvasItemShadingMode p_mode) { + + VS_CHANGED; + Rasterizer::CanvasItemMaterial *material = canvas_item_material_owner.get( p_material ); + ERR_FAIL_COND(!material); + material->shading_mode=p_mode; + +} + + /******** CANVAS *********/ @@ -3971,7 +4425,7 @@ void VisualServerRaster::free( RID p_rid ) { VS_CHANGED; - if (rasterizer->is_texture(p_rid) || rasterizer->is_material(p_rid) || rasterizer->is_shader(p_rid)) { + if (rasterizer->is_texture(p_rid) || rasterizer->is_material(p_rid) || rasterizer->is_shader(p_rid) || rasterizer->is_environment(p_rid)) { rasterizer->free(p_rid); } else if (rasterizer->is_skeleton(p_rid)) { @@ -3988,7 +4442,7 @@ void VisualServerRaster::free( RID p_rid ) { } rasterizer->free(p_rid); - } else if (rasterizer->is_mesh(p_rid) || rasterizer->is_multimesh(p_rid) || rasterizer->is_light(p_rid) || rasterizer->is_particles(p_rid) ) { + } else if (rasterizer->is_mesh(p_rid) || rasterizer->is_multimesh(p_rid) || rasterizer->is_light(p_rid) || rasterizer->is_particles(p_rid) || rasterizer->is_immediate(p_rid)) { //delete the resource _free_attached_instances(p_rid); @@ -4114,7 +4568,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 ); @@ -4143,9 +4607,82 @@ 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); + } + + } + + if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) { + + Canvas *canvas = canvas_owner.get(occluder->canvas); + canvas->occluders.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); @@ -4697,7 +5234,6 @@ void VisualServerRaster::_light_instance_update_lispsm_shadow(Instance *p_light, AABB proj_space_aabb; - float max_d,min_d; { @@ -5790,6 +6326,20 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan } +void VisualServerRaster::_render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { + RID environment; + if (p_scenario->environment.is_valid()) + environment=p_scenario->environment; + else + environment=p_scenario->fallback_environment; + + rasterizer->set_camera(Transform(),CameraMatrix(),false); + rasterizer->begin_scene(p_viewport->viewport_data,environment,p_scenario->debug); + rasterizer->set_viewport(viewport_rect); + rasterizer->end_scene(); +} + + void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario) { @@ -5799,7 +6349,8 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S /* STEP 1 - SETUP CAMERA */ CameraMatrix camera_matrix; - + bool ortho=false; + switch(p_camera->type) { case Camera::ORTHOGONAL: { @@ -5811,6 +6362,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S p_camera->vaspect ); + ortho=true; } break; case Camera::PERSPECTIVE: { @@ -5822,12 +6374,13 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S p_camera->vaspect ); + ortho=false; } break; } - rasterizer->set_camera(p_camera->transform, camera_matrix); + rasterizer->set_camera(p_camera->transform, camera_matrix,ortho); Vector<Plane> planes = camera_matrix.get_projection_planes(p_camera->transform); @@ -6190,7 +6743,41 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S rasterizer->end_scene(); } -void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity) { + +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; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; + + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + + + _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,1.0,0,z_list,z_last_list,NULL,NULL); + + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + rasterizer->canvas_render_items(z_list[i],CANVAS_ITEM_Z_MIN+i,p_modulate,p_lights); + } + +} + + +void VisualServerRaster::_render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect) { + + VisualServerRaster *self=(VisualServerRaster*)(p_self); + Viewport *vp=(Viewport*)p_vp; + self->_draw_viewport(vp,p_rect.pos.x,p_rect.pos.y,p_rect.size.x,p_rect.size.y); + self->rasterizer->canvas_begin(); + +} + +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; @@ -6209,24 +6796,39 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat if (global_rect.intersects(p_clip_rect) && ci->viewport.is_valid() && viewport_owner.owns(ci->viewport)) { - Viewport *vp = viewport_owner.get(ci->viewport); + Viewport *vp = viewport_owner.get(ci->viewport); Point2i from = xform.get_origin() + Point2(viewport_rect.x,viewport_rect.y); Point2i size = rect.size; size.x *= xform[0].length(); size.y *= xform[1].length(); + ci->vp_render = memnew( Rasterizer::CanvasItem::ViewportRender ); + ci->vp_render->owner=this; + ci->vp_render->udata=vp; + ci->vp_render->rect=Rect2(from.x, + from.y, + size.x, + size.y); +/* _draw_viewport(vp, from.x, from.y, size.x, size.y); +*/ + //rasterizer->canvas_begin(); + } else { + ci->vp_render=NULL; + } - rasterizer->canvas_begin(); + if (ci->use_parent_material && p_material_owner) + ci->material_owner=p_material_owner; + else { + p_material_owner=ci; + ci->material_owner=NULL; } - int s = ci->commands.size(); - bool reclip=false; float opacity = ci->opacity * p_opacity; @@ -6236,8 +6838,15 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(CanvasItem*)); if (ci->clip) { - rasterizer->canvas_set_clip(true,global_rect); - canvas_clip=global_rect; + if (p_canvas_clip != NULL) { + ci->final_clip_rect=p_canvas_clip->final_clip_rect.clip(global_rect); + } else { + ci->final_clip_rect=global_rect; + } + ci->final_clip_owner=ci; + + } else { + ci->final_clip_owner=p_canvas_clip; } if (ci->sort_y) { @@ -6246,197 +6855,138 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat sorter.sort(child_items,child_item_count); } + if (ci->z_relative) + p_z=CLAMP(p_z+ci->z,CANVAS_ITEM_Z_MIN,CANVAS_ITEM_Z_MAX); + else + p_z=ci->z; for(int i=0;i<child_item_count;i++) { if (child_items[i]->ontop) continue; - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity); + _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); } + if (ci->copy_back_buffer) { - if (s!=0) { - - //Rect2 rect( ci->rect.pos + p_ofs, ci->rect.size); - - if (p_clip_rect.intersects(global_rect)) { - - rasterizer->canvas_begin_rect(xform); - rasterizer->canvas_set_opacity( opacity * ci->self_opacity ); - rasterizer->canvas_set_blend_mode( ci->blend_mode ); - - CanvasItem::Command **commands = &ci->commands[0]; - - for (int i=0;i<s;i++) { - - CanvasItem::Command *c=commands[i]; - - switch(c->type) { - case CanvasItem::Command::TYPE_LINE: { + ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); + } - CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c); - rasterizer->canvas_draw_line(line->from,line->to,line->color,line->width); - } break; - case CanvasItem::Command::TYPE_RECT: { + if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) { + //something to draw? + ci->final_transform=xform; + ci->final_opacity=opacity * ci->self_opacity; + ci->global_rect_cache=global_rect; + ci->global_rect_cache.pos-=p_clip_rect.pos; - CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c); -// rasterizer->canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); -#if 0 - int flags=0; + int zidx = p_z-CANVAS_ITEM_Z_MIN; - if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { - flags|=Rasterizer::CANVAS_RECT_REGION; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { - flags|=Rasterizer::CANVAS_RECT_TILE; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { - - flags|=Rasterizer::CANVAS_RECT_FLIP_H; - } - if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { + if (z_last_list[zidx]) { + z_last_list[zidx]->next=ci; + z_last_list[zidx]=ci; - flags|=Rasterizer::CANVAS_RECT_FLIP_V; - } -#else + } else { + z_list[zidx]=ci; + z_last_list[zidx]=ci; + } - int flags=rect->flags; -#endif - rasterizer->canvas_draw_rect(rect->rect,flags,rect->source,rect->texture,rect->modulate); - } break; - case CanvasItem::Command::TYPE_STYLE: { - CanvasItem::CommandStyle* style = static_cast<CanvasItem::CommandStyle*>(c); - rasterizer->canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); + ci->next=NULL; - } break; - case CanvasItem::Command::TYPE_PRIMITIVE: { + } - CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c); - rasterizer->canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width); - } break; - case CanvasItem::Command::TYPE_POLYGON: { + for(int i=0;i<child_item_count;i++) { - CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); + 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_material_owner); + } - } break; +} - case CanvasItem::Command::TYPE_POLYGON_PTR: { +void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform,Rasterizer::CanvasLight *p_lights) { - CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c); - rasterizer->canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false); - } break; - case CanvasItem::Command::TYPE_CIRCLE: { + rasterizer->canvas_begin(); - CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c); - static const int numpoints=32; - Vector2 points[numpoints+1]; - points[numpoints]=circle->pos; - int indices[numpoints*3]; + int l = p_canvas->child_items.size(); + Canvas::ChildItem *ci=p_canvas->child_items.ptr(); - for(int i=0;i<numpoints;i++) { + bool has_mirror=false; + for(int i=0;i<l;i++) { + if (ci[i].mirror.x || ci[i].mirror.y) { + has_mirror=true; + break; + } + } - points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius; - indices[i*3+0]=i; - indices[i*3+1]=(i+1)%numpoints; - indices[i*3+2]=numpoints; - } - rasterizer->canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); - //rasterizer->canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); - } break; - case CanvasItem::Command::TYPE_TRANSFORM: { - - CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c); - rasterizer->canvas_set_transform(transform->xform); - } break; - case CanvasItem::Command::TYPE_BLEND_MODE: { - - CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c); - rasterizer->canvas_set_blend_mode(bm->blend_mode); - - } break; - case CanvasItem::Command::TYPE_CLIP_IGNORE: { - - CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c); - if (canvas_clip!=Rect2()) { - - if (ci->ignore!=reclip) { - if (ci->ignore) { - - rasterizer->canvas_set_clip(false,Rect2()); - reclip=true; - } else { - rasterizer->canvas_set_clip(true,canvas_clip); - reclip=false; - } - } - } + Rect2 clip_rect(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height); + if (!has_mirror) { + static const int z_range = CANVAS_ITEM_Z_MAX-CANVAS_ITEM_Z_MIN+1; + Rasterizer::CanvasItem *z_list[z_range]; + Rasterizer::CanvasItem *z_last_list[z_range]; + for(int i=0;i<z_range;i++) { + z_list[i]=NULL; + z_last_list[i]=NULL; + } + for(int i=0;i<l;i++) { + _render_canvas_item(ci[i].item,p_transform,clip_rect,1.0,0,z_list,z_last_list,NULL,NULL); + } - } break; - } - } - rasterizer->canvas_end_rect(); + for(int i=0;i<z_range;i++) { + if (!z_list[i]) + continue; + 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++) { - if (reclip) { + Canvas::ChildItem& ci=p_canvas->child_items[i]; + _render_canvas_item_tree(ci.item,p_transform,clip_rect,p_canvas->modulate,p_lights); - rasterizer->canvas_set_clip(true,canvas_clip); - } + //mirroring (useful for scrolling backgrounds) + if (ci.mirror.x!=0) { - for(int i=0;i<child_item_count;i++) { + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); + _render_canvas_item_tree(ci.item,xform2,clip_rect,p_canvas->modulate,p_lights); + } + if (ci.mirror.y!=0) { - if (!child_items[i]->ontop) - continue; - _render_canvas_item(child_items[i],xform,p_clip_rect,opacity); - } + Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); + _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,p_canvas->modulate,p_lights); + } - if (ci->clip) { - rasterizer->canvas_set_clip(false,Rect2()); - canvas_clip=Rect2(); + } } } -void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform) { - rasterizer->canvas_begin(); +void VisualServerRaster::_draw_viewport_camera(Viewport *p_viewport,bool p_ignore_camera) { - int l = p_canvas->child_items.size(); - for(int i=0;i<l;i++) { + Camera *camera=NULL; + if (camera_owner.owns( p_viewport->camera )) + camera=camera_owner.get( p_viewport->camera ); + Scenario *scenario = scenario_owner.get( p_viewport->scenario ); - Canvas::ChildItem& ci=p_canvas->child_items[i]; - _render_canvas_item(ci.item,p_transform,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); + _update_instances(); // check dirty instances before rendering - //mirroring (useful for scrolling backgrounds) - if (ci.mirror.x!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(ci.mirror.x,0)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); - } - if (ci.mirror.y!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,Vector2(0,ci.mirror.y)); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); - } - if (ci.mirror.y!=0 && ci.mirror.x!=0) { - - Matrix32 xform2 = p_transform * Matrix32(0,ci.mirror); - _render_canvas_item(ci.item,xform2,Rect2(viewport_rect.x,viewport_rect.y,viewport_rect.width,viewport_rect.height),1); - } - - } + if (p_ignore_camera) + _render_no_camera(p_viewport, camera,scenario ); + else + _render_camera(p_viewport, camera,scenario ); } - void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ofs_y,int p_parent_w,int p_parent_h) { ViewportRect desired_rect=p_viewport->rect; @@ -6471,19 +7021,47 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ /* Camera should always be BEFORE any other 3D */ - if (!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario)) { + bool scenario_draw_canvas_bg=false; + int scenario_canvas_max_layer=0; - Camera *camera = camera_owner.get( p_viewport->camera ); - Scenario *scenario = scenario_owner.get( p_viewport->scenario ); + if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) { - _update_instances(); // check dirty instances before rendering + Scenario *scenario=scenario_owner.get(p_viewport->scenario); + if (scenario->environment.is_valid()) { + if (rasterizer->is_environment(scenario->environment)) { + scenario_draw_canvas_bg=rasterizer->environment_get_background(scenario->environment)==VS::ENV_BG_CANVAS; + scenario_canvas_max_layer=rasterizer->environment_get_background_param(scenario->environment,VS::ENV_BG_PARAM_CANVAS_MAX_LAYER); + } + } + } - _render_camera(p_viewport, camera,scenario ); + bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario); + + + if (scenario_draw_canvas_bg) { + + rasterizer->begin_canvas_bg(); + } + + if (!scenario_draw_canvas_bg && can_draw_3d) { + + _draw_viewport_camera(p_viewport,false); } 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 { + Color cc=clear_color; + if (scenario_draw_canvas_bg) + cc.a=0; + rasterizer->clear_viewport(cc); + } + p_viewport->render_target_clear=false; + } } if (!p_viewport->hide_canvas) { @@ -6491,21 +7069,145 @@ 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; + + int light_count=0; + 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)); + tsize*=cl->scale; + + 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(); + + } + + light_count++; + } + } + } + + //print_line("lights: "+itos(light_count)); 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 + } + + + + + if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer>scenario_canvas_max_layer) { + + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + + } + 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++; + if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } + + } + + if (scenario_draw_canvas_bg) { + _draw_viewport_camera(p_viewport,!can_draw_3d); + scenario_draw_canvas_bg=false; + } + + +// rasterizer->canvas_debug_viewport_shadows(lights_with_shadow); } //capture @@ -6594,7 +7296,7 @@ void VisualServerRaster::_draw_viewports() { rasterizer->set_viewport(viewport_rect); } - rasterizer->canvas_begin(); + rasterizer->canvas_begin(); rasterizer->canvas_disable_blending(); rasterizer->canvas_begin_rect(Matrix32()); rasterizer->canvas_draw_rect(E->get()->rt_to_screen_rect,0,Rect2(Point2(),E->get()->rt_to_screen_rect.size),E->get()->render_target_texture,Color(1,1,1)); @@ -6617,7 +7319,7 @@ void VisualServerRaster::_draw_viewports() { if (r.size.width==0) r.size.width=window_w; if (r.size.height==0) - r.size.height=window_w; + r.size.height=window_h; _draw_viewport(vp,r.pos.x,r.pos.y,r.size.width,r.size.height); @@ -6675,6 +7377,8 @@ void VisualServerRaster::_draw_cursors_and_margins() { rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), 0, Rect2(), tex, Color(1, 1, 1, 1)); }; + + if (black_image[MARGIN_LEFT].is_valid()) { Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_LEFT]),rasterizer->texture_get_height(black_image[MARGIN_LEFT])); rasterizer->canvas_draw_rect(Rect2(0,0,black_margin[MARGIN_LEFT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_LEFT],Color(1,1,1)); @@ -6686,15 +7390,27 @@ void VisualServerRaster::_draw_cursors_and_margins() { rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_RIGHT],Color(1,1,1)); } else if (black_margin[MARGIN_RIGHT]) rasterizer->canvas_draw_rect(Rect2(window_w-black_margin[MARGIN_RIGHT],0,black_margin[MARGIN_RIGHT],window_h),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); - if (black_margin[MARGIN_TOP]) + + if (black_image[MARGIN_TOP].is_valid()) { + Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_TOP]),rasterizer->texture_get_height(black_image[MARGIN_TOP])); + rasterizer->canvas_draw_rect(Rect2(0,0,window_w,black_margin[MARGIN_TOP]),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_TOP],Color(1,1,1)); + + } else if (black_margin[MARGIN_TOP]) { rasterizer->canvas_draw_rect(Rect2(0,0,window_w,black_margin[MARGIN_TOP]),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); - if (black_margin[MARGIN_BOTTOM]) + } + + if (black_image[MARGIN_BOTTOM].is_valid()) { + + Size2 sz(rasterizer->texture_get_width(black_image[MARGIN_BOTTOM]),rasterizer->texture_get_height(black_image[MARGIN_BOTTOM])); + rasterizer->canvas_draw_rect(Rect2(0,window_h-black_margin[MARGIN_BOTTOM],window_w,black_margin[MARGIN_BOTTOM]),0,Rect2(0,0,sz.x,sz.y),black_image[MARGIN_BOTTOM],Color(1,1,1)); + } else if (black_margin[MARGIN_BOTTOM]) { rasterizer->canvas_draw_rect(Rect2(0,window_h-black_margin[MARGIN_BOTTOM],window_w,black_margin[MARGIN_BOTTOM]),0,Rect2(0,0,1,1),RID(),Color(0,0,0)); + } rasterizer->canvas_end_rect(); }; -void VisualServerRaster::flush() { +void VisualServerRaster::sync() { //do none } @@ -6732,11 +7448,13 @@ void VisualServerRaster::set_default_clear_color(const Color& p_color) { clear_color=p_color; } -void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_color) { +void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_color,bool p_scale) { if (p_image.empty()) return; + rasterizer->restore_framebuffer(); + rasterizer->begin_frame(); int window_w = OS::get_singleton()->get_video_mode(0).width; @@ -6754,9 +7472,27 @@ void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_col texture_set_data(texture,p_image); rasterizer->canvas_begin_rect(Matrix32()); Rect2 imgrect(0,0,p_image.get_width(),p_image.get_height()); - Rect2 screenrect=imgrect; - screenrect.pos+=((Size2(vr.width,vr.height)-screenrect.size)/2.0).floor(); - rasterizer->canvas_draw_rect(screenrect,0,imgrect,texture,Color(1,1,1,0)); + Rect2 screenrect; + if (p_scale) { + + if (window_w > window_h) { + //scale horizontally + screenrect.size.y = window_h; + screenrect.size.x = imgrect.size.x * window_h / imgrect.size.y; + screenrect.pos.x = (window_w - screenrect.size.x)/2; + + } else { + //scale vertically + screenrect.size.x = window_w; + screenrect.size.y = imgrect.size.y * window_w / imgrect.size.x; + screenrect.pos.y = (window_h - screenrect.size.y)/2; + } + } else { + + screenrect=imgrect; + screenrect.pos+=((Size2(vr.width,vr.height)-screenrect.size)/2.0).floor(); + + } rasterizer->canvas_draw_rect(screenrect,0,imgrect,texture,Color(1,1,1,1)); rasterizer->canvas_end_rect(); @@ -6811,6 +7547,10 @@ void VisualServerRaster::finish() { free(default_cursor_texture); + if (test_cube.is_valid()) + free(test_cube); + + _free_internal_rids(); _clean_up_owner( &room_owner,"Room" ); _clean_up_owner( &portal_owner,"Portal" ); @@ -6828,7 +7568,7 @@ void VisualServerRaster::finish() { octree_allocator.clear(); if (instance_dependency_map.size()) { - print_line("base resources missing "+itos(instance_dependency_map.size())); + print_line("Base resources missing amount: "+itos(instance_dependency_map.size())); } ERR_FAIL_COND( instance_dependency_map.size() ); } @@ -6849,6 +7589,7 @@ RID VisualServerRaster::get_test_cube() { VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) { rasterizer=p_rasterizer; + rasterizer->draw_viewport_func=_render_canvas_item_viewport; instance_update_list=NULL; render_pass=0; clear_color=Color(0.3,0.3,0.3,1.0); |