-New mask mode for lights, makes using masks MUCH easier.
This commit is contained in:
parent
88c653a9e5
commit
428984ec0c
8 changed files with 71 additions and 18 deletions
|
@ -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) {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ public:
|
|||
MODE_ADD,
|
||||
MODE_SUB,
|
||||
MODE_MIX,
|
||||
MODE_MASK,
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -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); }
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue