diff options
author | Juan Linietsky <reduzio@gmail.com> | 2015-02-18 19:39:44 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2015-02-18 19:40:02 -0300 |
commit | 5ef3f7392faf0d2d9c136fc176f7a08cb774fe40 (patch) | |
tree | 78a763eebc9fc11ef1626a8bb93105aab88359c6 /servers | |
parent | 63165d80d5bbd6ecbd8a47e8f526db169cbb8dc7 (diff) |
support for light and normal mapping in 2D
Diffstat (limited to 'servers')
-rw-r--r-- | servers/visual/rasterizer.h | 29 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.cpp | 144 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 28 | ||||
-rw-r--r-- | servers/visual/visual_server_wrap_mt.h | 7 | ||||
-rw-r--r-- | servers/visual_server.h | 18 |
5 files changed, 175 insertions, 51 deletions
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 63ebdbc34a..2ae283f3b7 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -570,6 +570,7 @@ public: struct CanvasLight { + bool enabled; bool shadow; Color color; @@ -577,12 +578,23 @@ public: float height; int z_min; int z_max; + int layer_min; + int layer_max; int item_mask; - VS::CanvasLightBlendMode blend_mode; + bool subtract; RID texture; - void *texture_cache; // implementation dependent Vector2 texture_offset; + RID canvas; + + + void *texture_cache; // implementation dependent + Rect2 rect_cache; + Matrix32 xform_cache; + + Matrix32 light_shader_xform; + Vector2 light_shader_pos; + CanvasLight *filter_next_ptr; CanvasLight *next_ptr; CanvasLight() { @@ -592,10 +604,13 @@ public: height=0; z_min=-1024; z_max=1024; + layer_min=0; + layer_max=0; item_mask=1; - blend_mode=VS::CANVAS_LIGHT_BLEND_ADD; + subtract=false; texture_cache=NULL; next_ptr=NULL; + filter_next_ptr=NULL; } }; @@ -722,6 +737,7 @@ public: bool visible; bool ontop; VS::MaterialBlendMode blend_mode; + int light_mask; Vector<Command*> commands; mutable bool custom_rect; mutable bool rect_dirty; @@ -739,8 +755,9 @@ public: CanvasItem* shader_owner; ViewportRender *vp_render; - const Rect2& get_rect() const { + Rect2 global_rect_cache; + const Rect2& get_rect() const { if (custom_rect || !rect_dirty) return rect; @@ -864,7 +881,7 @@ public: } void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; shader_owner=NULL;} - CanvasItem() { vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; shader_version=0; shader_owner=NULL;} + CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; shader_version=0; shader_owner=NULL;} virtual ~CanvasItem() { clear(); } }; @@ -886,7 +903,7 @@ public: virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0; virtual void canvas_set_transform(const Matrix32& p_transform)=0; - virtual void canvas_render_items(CanvasItem *p_item_list)=0; + virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0; /* ENVIRONMENT */ diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index e8fa319f11..cef6fe567d 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -3195,6 +3195,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 +3221,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 +3314,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) @@ -3832,6 +3854,23 @@ 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){ @@ -3885,6 +3924,16 @@ void VisualServerRaster::canvas_light_set_z_range(RID p_light, int p_min_z,int p 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); @@ -3893,11 +3942,12 @@ void VisualServerRaster::canvas_light_set_item_mask(RID p_light, int 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->blend_mode=p_blend_mode; + clight->subtract=p_enable; } void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){ @@ -4194,7 +4244,13 @@ 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(); + } + + canvas_owner.free( p_rid ); memdelete( canvas ); @@ -4232,6 +4288,12 @@ void VisualServerRaster::free( RID 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); + } + canvas_light_owner.free( p_rid ); memdelete( canvas_light ); @@ -6280,7 +6342,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; @@ -6298,7 +6360,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); } } @@ -6404,7 +6466,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; @@ -6417,6 +6479,8 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat z_last_list[zidx]=ci; } + + ci->next=NULL; } @@ -6430,7 +6494,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat } -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(); @@ -6463,30 +6527,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); } } @@ -6549,7 +6613,43 @@ 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; + 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]; + } + + + + + } + } + canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get(); } @@ -6560,7 +6660,19 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_ // 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++; } diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index c15b6ebb26..eec677068e 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -410,6 +410,8 @@ class VisualServerRaster : public VisualServer { } }; + struct CanvasLight; + struct Canvas { Set<RID> viewports; @@ -419,8 +421,10 @@ class VisualServerRaster : public VisualServer { CanvasItem *item; }; + Set<Rasterizer::CanvasLight*> lights; Vector<ChildItem> child_items; + Color modulate; int find_item(CanvasItem *p_item) { for(int i=0;i<child_items.size();i++) { @@ -435,7 +439,7 @@ class VisualServerRaster : public VisualServer { child_items.remove(idx); } - Canvas() { } + Canvas() { modulate=Color(1,1,1,1); } }; @@ -603,9 +607,9 @@ class VisualServerRaster : public VisualServer { void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario); static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect); - void _render_canvas_item_tree(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect); + void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights); void _render_canvas_item(CanvasItem *p_canvas_item,const Matrix32& p_transform,const Rect2& p_clip_rect, float p_opacity,int p_z,Rasterizer::CanvasItem **z_list,Rasterizer::CanvasItem **z_last_list,CanvasItem *p_canvas_clip,CanvasItem *p_shader_owner); - void _render_canvas(Canvas *p_canvas,const Matrix32 &p_transform); + void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights); Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); Vector<Plane> _camera_generate_orthogonal_planes(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max); @@ -1075,6 +1079,8 @@ public: virtual RID canvas_create(); virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring); virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const; + virtual void canvas_set_modulate(RID p_canvas,const Color& p_color); + virtual RID canvas_item_create(); @@ -1085,6 +1091,8 @@ public: virtual bool canvas_item_is_visible(RID p_item) const; virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend); + virtual void canvas_item_set_light_mask(RID p_canvas_item,int p_mask); + //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect); @@ -1137,20 +1145,10 @@ public: virtual void canvas_light_set_color(RID p_light, const Color& p_color); virtual void canvas_light_set_height(RID p_light, float p_height); virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); + virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer); virtual void canvas_light_set_item_mask(RID p_light, int p_mask); - enum CanvasightBlendMode { - CANVAS_LIGHT_BLEND_ADD, - CANVAS_LIGHT_BLEND_SUB, - CANVAS_LIGHT_BLEND_MULTIPLY, - CANVAS_LIGHT_BLEND_DODGE, - CANVAS_LIGHT_BLEND_BURN, - CANVAS_LIGHT_BLEND_LIGHTEN, - CANVAS_LIGHT_BLEND_DARKEN, - CANVAS_LIGHT_BLEND_OVERLAY, - CANVAS_LIGHT_BLEND_SCREEN, - }; - virtual void canvas_light_set_blend_mode(RID p_light, CanvasLightBlendMode p_blend_mode); + virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable); virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); virtual void canvas_light_set_shadow_filter(RID p_light, int p_size); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index 9574dff018..c94425c586 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -1087,6 +1087,8 @@ public: FUNC0R(RID,canvas_create); FUNC3(canvas_set_item_mirroring,RID,RID,const Point2&); FUNC2RC(Point2,canvas_get_item_mirroring,RID,RID); + FUNC2(canvas_set_modulate,RID,const Color&); + FUNC0R(RID,canvas_item_create); @@ -1097,7 +1099,7 @@ public: FUNC1RC(bool,canvas_item_is_visible,RID); FUNC2(canvas_item_set_blend_mode,RID,MaterialBlendMode ); - + FUNC2(canvas_item_set_light_mask,RID,int ); //FUNC(canvas_item_set_rect,RID, const Rect2& p_rect); FUNC2(canvas_item_set_transform,RID, const Matrix32& ); @@ -1155,10 +1157,11 @@ public: FUNC2(canvas_light_set_texture_offset,RID,const Vector2&); FUNC2(canvas_light_set_color,RID,const Color&); FUNC2(canvas_light_set_height,RID,float); + FUNC3(canvas_light_set_layer_range,RID,int,int); FUNC3(canvas_light_set_z_range,RID,int,int); FUNC2(canvas_light_set_item_mask,RID,int); - FUNC2(canvas_light_set_blend_mode,RID,CanvasLightBlendMode); + FUNC2(canvas_light_set_subtract_mode,RID,bool); FUNC2(canvas_light_set_shadow_enabled,RID,bool); FUNC2(canvas_light_set_shadow_buffer_size,RID,int); FUNC2(canvas_light_set_shadow_filter,RID,int); diff --git a/servers/visual_server.h b/servers/visual_server.h index 49ae8ce4e6..e9bc97628f 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -944,6 +944,8 @@ public: virtual RID canvas_create()=0; virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring)=0; virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const=0; + virtual void canvas_set_modulate(RID p_canvas,const Color& p_color)=0; + virtual RID canvas_item_create()=0; @@ -953,6 +955,8 @@ public: virtual void canvas_item_set_visible(RID p_item,bool p_visible)=0; virtual bool canvas_item_is_visible(RID p_item) const=0; + virtual void canvas_item_set_light_mask(RID p_item,int p_mask)=0; + virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend)=0; virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport)=0; @@ -1008,20 +1012,10 @@ public: virtual void canvas_light_set_color(RID p_light, const Color& p_color)=0; virtual void canvas_light_set_height(RID p_light, float p_height)=0; virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0; + virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0; virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0; - enum CanvasLightBlendMode { - CANVAS_LIGHT_BLEND_ADD, - CANVAS_LIGHT_BLEND_SUB, - CANVAS_LIGHT_BLEND_MULTIPLY, - CANVAS_LIGHT_BLEND_DODGE, - CANVAS_LIGHT_BLEND_BURN, - CANVAS_LIGHT_BLEND_LIGHTEN, - CANVAS_LIGHT_BLEND_DARKEN, - CANVAS_LIGHT_BLEND_OVERLAY, - CANVAS_LIGHT_BLEND_SCREEN, - }; - virtual void canvas_light_set_blend_mode(RID p_light, CanvasLightBlendMode p_blend_mode)=0; + virtual void canvas_light_set_subtract_mode(RID p_light, bool p_enable)=0; virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0; virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0; virtual void canvas_light_set_shadow_filter(RID p_light, int p_size)=0; |