summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp6
-rw-r--r--drivers/gles2/shaders/canvas.glsl23
-rw-r--r--scene/2d/light_2d.cpp3
-rw-r--r--scene/2d/light_2d.h1
-rw-r--r--servers/visual/rasterizer.h7
-rw-r--r--servers/visual/visual_server_raster.cpp44
-rw-r--r--servers/visual/visual_server_raster.h4
-rw-r--r--servers/visual_server.h1
8 files changed, 71 insertions, 18 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index d0f2f88ee6..83b71fd5ff 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -9540,7 +9540,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_opacity = ci->final_opacity;
- if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT)))
+ if (unshaded || (p_modulate.a>0.001 && (!material || material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT) && !ci->light_masked ))
_canvas_item_render_commands<false>(ci,current_clip,reclip);
if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light && !unshaded) {
@@ -9572,7 +9572,8 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
} break;
- case VS::CANVAS_LIGHT_MODE_MIX: {
+ case VS::CANVAS_LIGHT_MODE_MIX:
+ case VS::CANVAS_LIGHT_MODE_MASK: {
glBlendEquation(GL_FUNC_ADD);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@@ -9620,6 +9621,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,Color(light->color.r*light->energy,light->color.g*light->energy,light->color.b*light->energy,light->color.a));
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_LOCAL_MATRIX,light->xform_cache.affine_inverse());
+ canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA,light->mode==VS::CANVAS_LIGHT_MODE_MASK?1.0:0.0);
if (has_shadow) {
diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl
index e297b328cd..259e82d704 100644
--- a/drivers/gles2/shaders/canvas.glsl
+++ b/drivers/gles2/shaders/canvas.glsl
@@ -155,6 +155,7 @@ uniform vec4 light_color;
uniform vec4 light_shadow_color;
uniform float light_height;
varying vec4 light_uv_interp;
+uniform float light_outside_alpha;
#if defined(NORMAL_USED)
varying vec4 local_rot;
@@ -247,22 +248,27 @@ FRAGMENT_SHADER_CODE
vec4 shadow_color=vec4(0.0,0.0,0.0,0.0);
#endif
+ if (any(lessThan(light_uv_interp.xy,vec2(0.0,0.0))) || any(greaterThanEqual(light_uv_interp.xy,vec2(1.0,1.0)))) {
+ color.a*=light_outside_alpha; //invisible
+
+ } else {
+
#if defined(USE_LIGHT_SHADER_CODE)
//light is written by the light shader
-{
- vec4 light_out=light*color;
+ {
+ vec4 light_out=light*color;
LIGHT_SHADER_CODE
- color=light_out;
-}
+ color=light_out;
+ }
#else
#if defined(NORMAL_USED)
- vec3 light_normal = normalize(vec3(light_vec,-light_height));
- light*=max(dot(-light_normal,normal),0.0);
+ vec3 light_normal = normalize(vec3(light_vec,-light_height));
+ light*=max(dot(-light_normal,normal),0.0);
#endif
- color*=light;
+ color*=light;
/*
#ifdef USE_NORMAL
color.xy=local_rot.xy;//normal.xy;
@@ -273,9 +279,6 @@ LIGHT_SHADER_CODE
//light shader code
#endif
- if (any(lessThan(light_uv_interp.xy,vec2(0.0,0.0))) || any(greaterThanEqual(light_uv_interp.xy,vec2(1.0,1.0)))) {
- color.a=0.0; //invisible
- } else {
#ifdef USE_SHADOWS
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 852a6fb46b..a2112c7d37 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -333,7 +333,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY( PropertyInfo(Variant::REAL,"scale",PROPERTY_HINT_RANGE,"0.01,4096,0.01"),_SCS("set_texture_scale"),_SCS("get_texture_scale"));
ADD_PROPERTY( PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"energy"),_SCS("set_energy"),_SCS("get_energy"));
- ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix"),_SCS("set_mode"),_SCS("get_mode"));
+ ADD_PROPERTY( PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Add,Sub,Mix,Mask"),_SCS("set_mode"),_SCS("get_mode"));
ADD_PROPERTY( PropertyInfo(Variant::REAL,"range/height"),_SCS("set_height"),_SCS("get_height"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_min",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_min"),_SCS("get_z_range_min"));
ADD_PROPERTY( PropertyInfo(Variant::INT,"range/z_max",PROPERTY_HINT_RANGE,itos(VS::CANVAS_ITEM_Z_MIN)+","+itos(VS::CANVAS_ITEM_Z_MAX)+",1"),_SCS("set_z_range_max"),_SCS("get_z_range_max"));
@@ -349,6 +349,7 @@ void Light2D::_bind_methods() {
BIND_CONSTANT( MODE_ADD );
BIND_CONSTANT( MODE_SUB );
BIND_CONSTANT( MODE_MIX );
+ BIND_CONSTANT( MODE_MASK );
}
diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h
index bf61868bac..0828d9ac33 100644
--- a/scene/2d/light_2d.h
+++ b/scene/2d/light_2d.h
@@ -11,6 +11,7 @@ public:
MODE_ADD,
MODE_SUB,
MODE_MIX,
+ MODE_MASK,
};
private:
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 50407f1b0f..d94067961f 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -610,6 +610,7 @@ public:
CanvasLight *shadows_next_ptr;
CanvasLight *filter_next_ptr;
CanvasLight *next_ptr;
+ CanvasLight *mask_next_ptr;
CanvasLight() {
enabled=true;
@@ -627,6 +628,7 @@ public:
mode=VS::CANVAS_LIGHT_MODE_ADD;
texture_cache=NULL;
next_ptr=NULL;
+ mask_next_ptr=NULL;
filter_next_ptr=NULL;
shadow_buffer_size=2048;
shadow_esm_mult=80;
@@ -792,6 +794,7 @@ public:
CanvasItem* material_owner;
ViewportRender *vp_render;
bool distance_field;
+ bool light_masked;
Rect2 global_rect_cache;
@@ -918,8 +921,8 @@ public:
return rect;
}
- void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL;}
- CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; }
+ void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL; light_masked=false; }
+ CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; }
virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
};
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index a94d4f64c7..79911121f5 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -6777,6 +6777,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_material_owner) {
CanvasItem *ci = p_canvas_item;
@@ -6878,6 +6879,7 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
ci->final_opacity=opacity * ci->self_opacity;
ci->global_rect_cache=global_rect;
ci->global_rect_cache.pos-=p_clip_rect.pos;
+ ci->light_masked=false;
int zidx = p_z-CANVAS_ITEM_Z_MIN;
@@ -6905,7 +6907,34 @@ void VisualServerRaster::_render_canvas_item(CanvasItem *p_canvas_item,const Mat
}
-void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform,Rasterizer::CanvasLight *p_lights) {
+void VisualServerRaster::_light_mask_canvas_items(int p_z,Rasterizer::CanvasItem *p_canvas_item,Rasterizer::CanvasLight *p_masked_lights) {
+
+ if (!p_masked_lights)
+ return;
+
+ Rasterizer::CanvasItem *ci=p_canvas_item;
+
+ while(ci) {
+
+ Rasterizer::CanvasLight *light=p_masked_lights;
+ while(light) {
+
+ if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) {
+ ci->light_masked=true;
+ }
+
+ light=light->mask_next_ptr;
+ }
+
+ ci=ci->next;
+ }
+
+
+
+
+}
+
+void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_transform,Rasterizer::CanvasLight *p_lights,Rasterizer::CanvasLight *p_masked_lights) {
rasterizer->canvas_begin();
@@ -6938,6 +6967,11 @@ void VisualServerRaster::_render_canvas(Canvas *p_canvas,const Matrix32 &p_trans
for(int i=0;i<z_range;i++) {
if (!z_list[i])
continue;
+
+ if (p_masked_lights) {
+ _light_mask_canvas_items(CANVAS_ITEM_Z_MIN+i,z_list[i],p_masked_lights);
+ }
+
rasterizer->canvas_render_items(z_list[i],CANVAS_ITEM_Z_MIN+i,p_canvas->modulate,p_lights);
}
} else {
@@ -7072,6 +7106,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
Rect2 clip_rect(0,0,viewport_rect.width,viewport_rect.height);
Rasterizer::CanvasLight *lights=NULL;
Rasterizer::CanvasLight *lights_with_shadow=NULL;
+ Rasterizer::CanvasLight *lights_with_mask=NULL;
Rect2 shadow_rect;
int light_count=0;
@@ -7119,9 +7154,14 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
cl->radius_cache=cl->rect_cache.size.length();
}
+ if (cl->mode==CANVAS_LIGHT_MODE_MASK) {
+ cl->mask_next_ptr=lights_with_mask;
+ lights_with_mask=cl;
+ }
light_count++;
}
+
}
}
@@ -7190,7 +7230,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
ptr=ptr->filter_next_ptr;
}
- _render_canvas( E->get()->canvas,xform,canvas_lights );
+ _render_canvas( E->get()->canvas,xform,canvas_lights,lights_with_mask );
i++;
if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) {
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index b6a5ca6308..e0127faf41 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -633,7 +633,9 @@ class VisualServerRaster : public VisualServer {
static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
- void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights);
+ void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights, Rasterizer::CanvasLight *p_masked_lights);
+ void _light_mask_canvas_items(int p_z,Rasterizer::CanvasItem *p_canvas_item,Rasterizer::CanvasLight *p_masked_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);
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 96c3e15cde..c5100b8d30 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -1041,6 +1041,7 @@ public:
CANVAS_LIGHT_MODE_ADD,
CANVAS_LIGHT_MODE_SUB,
CANVAS_LIGHT_MODE_MIX,
+ CANVAS_LIGHT_MODE_MASK,
};
virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0;