support for light and normal mapping in 2D
This commit is contained in:
parent
63165d80d5
commit
5ef3f7392f
|
@ -159,8 +159,8 @@ struct Vector2 {
|
|||
|
||||
operator String() const { return String::num(x)+","+String::num(y); }
|
||||
|
||||
inline Vector2(float p_x,float p_y) { x=p_x; y=p_y; }
|
||||
inline Vector2() { x=0; y=0; }
|
||||
_FORCE_INLINE_ Vector2(float p_x,float p_y) { x=p_x; y=p_y; }
|
||||
_FORCE_INLINE_ Vector2() { x=0; y=0; }
|
||||
};
|
||||
|
||||
_FORCE_INLINE_ Vector2 Vector2::plane_project(real_t p_d, const Vector2& p_vec) const {
|
||||
|
@ -198,6 +198,8 @@ Vector2 Vector2::linear_interpolate(const Vector2& p_a, const Vector2& p_b,float
|
|||
typedef Vector2 Size2;
|
||||
typedef Vector2 Point2;
|
||||
|
||||
struct Matrix32;
|
||||
|
||||
|
||||
struct Rect2 {
|
||||
|
||||
|
@ -224,6 +226,8 @@ struct Rect2 {
|
|||
return true;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ bool intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const;
|
||||
|
||||
bool intersects_segment(const Point2& p_from, const Point2& p_to, Point2* r_pos=NULL, Point2* r_normal=NULL) const;
|
||||
|
||||
inline bool encloses(const Rect2& p_rect) const {
|
||||
|
@ -597,6 +601,160 @@ struct Matrix32 {
|
|||
|
||||
};
|
||||
|
||||
bool Rect2::intersects_transformed(const Matrix32& p_xform, const Rect2& p_rect) const {
|
||||
|
||||
//SAT intersection between local and transformed rect2
|
||||
|
||||
Vector2 xf_points[4]={
|
||||
p_xform.xform(p_rect.pos),
|
||||
p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y)),
|
||||
p_xform.xform(Vector2(p_rect.pos.x,p_rect.pos.y+p_rect.size.y)),
|
||||
p_xform.xform(Vector2(p_rect.pos.x+p_rect.size.x,p_rect.pos.y+p_rect.size.y)),
|
||||
};
|
||||
|
||||
real_t low_limit;
|
||||
|
||||
//base rect2 first (faster)
|
||||
|
||||
if (xf_points[0].y>pos.y)
|
||||
goto next1;
|
||||
if (xf_points[1].y>pos.y)
|
||||
goto next1;
|
||||
if (xf_points[2].y>pos.y)
|
||||
goto next1;
|
||||
if (xf_points[3].y>pos.y)
|
||||
goto next1;
|
||||
|
||||
return false;
|
||||
|
||||
next1:
|
||||
|
||||
low_limit=pos.y+size.y;
|
||||
|
||||
if (xf_points[0].y<low_limit)
|
||||
goto next2;
|
||||
if (xf_points[1].y<low_limit)
|
||||
goto next2;
|
||||
if (xf_points[2].y<low_limit)
|
||||
goto next2;
|
||||
if (xf_points[3].y<low_limit)
|
||||
goto next2;
|
||||
|
||||
return false;
|
||||
|
||||
next2:
|
||||
|
||||
if (xf_points[0].x>pos.x)
|
||||
goto next3;
|
||||
if (xf_points[1].x>pos.x)
|
||||
goto next3;
|
||||
if (xf_points[2].x>pos.x)
|
||||
goto next3;
|
||||
if (xf_points[3].x>pos.x)
|
||||
goto next3;
|
||||
|
||||
return false;
|
||||
|
||||
next3:
|
||||
|
||||
low_limit=pos.x+size.x;
|
||||
|
||||
if (xf_points[0].x<low_limit)
|
||||
goto next4;
|
||||
if (xf_points[1].x<low_limit)
|
||||
goto next4;
|
||||
if (xf_points[2].x<low_limit)
|
||||
goto next4;
|
||||
if (xf_points[3].x<low_limit)
|
||||
goto next4;
|
||||
|
||||
return false;
|
||||
|
||||
next4:
|
||||
|
||||
Vector2 xf_points2[4]={
|
||||
pos,
|
||||
Vector2(pos.x+size.x,pos.y),
|
||||
Vector2(pos.x,pos.y+size.y),
|
||||
Vector2(pos.x+size.x,pos.y+size.y),
|
||||
};
|
||||
|
||||
real_t maxa=p_xform.elements[0].dot(xf_points2[0]);
|
||||
real_t mina=maxa;
|
||||
|
||||
real_t dp = p_xform.elements[0].dot(xf_points2[1]);
|
||||
maxa=MAX(dp,maxa);
|
||||
mina=MIN(dp,mina);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points2[2]);
|
||||
maxa=MAX(dp,maxa);
|
||||
mina=MIN(dp,mina);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points2[3]);
|
||||
maxa=MAX(dp,maxa);
|
||||
mina=MIN(dp,mina);
|
||||
|
||||
real_t maxb=p_xform.elements[0].dot(xf_points[0]);
|
||||
real_t minb=maxb;
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points[1]);
|
||||
maxb=MAX(dp,maxb);
|
||||
minb=MIN(dp,minb);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points[2]);
|
||||
maxb=MAX(dp,maxb);
|
||||
minb=MIN(dp,minb);
|
||||
|
||||
dp = p_xform.elements[0].dot(xf_points[3]);
|
||||
maxb=MAX(dp,maxb);
|
||||
minb=MIN(dp,minb);
|
||||
|
||||
|
||||
if ( mina > maxb )
|
||||
return false;
|
||||
if ( minb > maxa )
|
||||
return false;
|
||||
|
||||
maxa=p_xform.elements[1].dot(xf_points2[0]);
|
||||
mina=maxa;
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points2[1]);
|
||||
maxa=MAX(dp,maxa);
|
||||
mina=MIN(dp,mina);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points2[2]);
|
||||
maxa=MAX(dp,maxa);
|
||||
mina=MIN(dp,mina);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points2[3]);
|
||||
maxa=MAX(dp,maxa);
|
||||
mina=MIN(dp,mina);
|
||||
|
||||
maxb=p_xform.elements[1].dot(xf_points[0]);
|
||||
minb=maxb;
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points[1]);
|
||||
maxb=MAX(dp,maxb);
|
||||
minb=MIN(dp,minb);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points[2]);
|
||||
maxb=MAX(dp,maxb);
|
||||
minb=MIN(dp,minb);
|
||||
|
||||
dp = p_xform.elements[1].dot(xf_points[3]);
|
||||
maxb=MAX(dp,maxb);
|
||||
minb=MIN(dp,minb);
|
||||
|
||||
|
||||
if ( mina > maxb )
|
||||
return false;
|
||||
if ( minb > maxa )
|
||||
return false;
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
Vector2 Matrix32::basis_xform(const Vector2& v) const {
|
||||
|
||||
|
|
Binary file not shown.
|
@ -6409,7 +6409,7 @@ void RasterizerGLES2::_render_list_forward(RenderList *p_render_list,const Trans
|
|||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_SUB: {
|
||||
|
||||
glBlendEquation(GL_FUNC_SUBTRACT);
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_MUL: {
|
||||
|
@ -7824,8 +7824,10 @@ void RasterizerGLES2::canvas_begin() {
|
|||
//material_shader.unbind();
|
||||
canvas_shader.unbind();
|
||||
canvas_shader.set_custom_shader(0);
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false);
|
||||
canvas_shader.bind();
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0);
|
||||
canvas_use_modulate=false;
|
||||
_set_color_attrib(Color(1,1,1));
|
||||
canvas_transform=Transform();
|
||||
canvas_transform.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f);
|
||||
|
@ -7840,7 +7842,6 @@ void RasterizerGLES2::canvas_begin() {
|
|||
|
||||
canvas_opacity=1.0;
|
||||
canvas_blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
|
||||
|
||||
canvas_texscreen_used=false;
|
||||
uses_texpixel_size=false;
|
||||
canvas_last_shader=RID();
|
||||
|
@ -7876,7 +7877,7 @@ void RasterizerGLES2::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) {
|
|||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_SUB: {
|
||||
|
||||
glBlendEquation(GL_FUNC_SUBTRACT);
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_MUL: {
|
||||
|
@ -8325,216 +8326,21 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) {
|
|||
//canvas_transform = Variant(p_transform);
|
||||
}
|
||||
|
||||
void RasterizerGLES2::_canvas_normal_set_flip(const Vector2& p_flip) {
|
||||
|
||||
void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
|
||||
if (p_flip==normal_flip)
|
||||
return;
|
||||
normal_flip=p_flip;
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,normal_flip);
|
||||
}
|
||||
|
||||
|
||||
CanvasItem *current_clip=NULL;
|
||||
Shader *shader_cache=NULL;
|
||||
canvas_opacity=1.0;
|
||||
while(p_item_list) {
|
||||
template<bool use_normalmap>
|
||||
void RasterizerGLES2::_canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip) {
|
||||
|
||||
CanvasItem *ci=p_item_list;
|
||||
int cc=p_item->commands.size();
|
||||
CanvasItem::Command **commands = p_item->commands.ptr();
|
||||
|
||||
if (ci->vp_render) {
|
||||
if (draw_viewport_func) {
|
||||
draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
|
||||
}
|
||||
memdelete(ci->vp_render);
|
||||
ci->vp_render=NULL;
|
||||
canvas_last_shader=RID();
|
||||
}
|
||||
|
||||
if (current_clip!=ci->final_clip_owner) {
|
||||
|
||||
current_clip=ci->final_clip_owner;
|
||||
|
||||
//setup clip
|
||||
if (current_clip) {
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),
|
||||
current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height);
|
||||
} else {
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//begin rect
|
||||
CanvasItem *shader_owner = ci->shader_owner?ci->shader_owner:ci;
|
||||
|
||||
if (shader_owner->shader!=canvas_last_shader) {
|
||||
|
||||
Shader *shader = NULL;
|
||||
if (shader_owner->shader.is_valid()) {
|
||||
shader = this->shader_owner.get(shader_owner->shader);
|
||||
if (shader && !shader->valid) {
|
||||
shader=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
shader_cache=shader;
|
||||
|
||||
if (shader) {
|
||||
canvas_shader.set_custom_shader(shader->custom_code_id);
|
||||
if (canvas_shader.bind())
|
||||
rebind_texpixel_size=true;
|
||||
|
||||
if (shader_owner->shader_version!=shader->version) {
|
||||
//todo optimize uniforms
|
||||
shader_owner->shader_version=shader->version;
|
||||
}
|
||||
|
||||
if (shader->has_texscreen && framebuffer.active) {
|
||||
|
||||
int x = viewport.x;
|
||||
int y = window_size.height-(viewport.height+viewport.y);
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height));
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height));
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,max_texture_units-1);
|
||||
glActiveTexture(GL_TEXTURE0+max_texture_units-1);
|
||||
glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color);
|
||||
if (framebuffer.scale==1 && !canvas_texscreen_used) {
|
||||
#ifdef GLEW_ENABLED
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
#endif
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height);
|
||||
if (current_clip) {
|
||||
// print_line(" a clip ");
|
||||
}
|
||||
|
||||
canvas_texscreen_used=true;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
}
|
||||
|
||||
if (shader->has_screen_uv) {
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height));
|
||||
}
|
||||
|
||||
if (shader->uses_time) {
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0));
|
||||
draw_next_frame=true;
|
||||
}
|
||||
//if uses TIME - draw_next_frame=true
|
||||
|
||||
uses_texpixel_size=shader->uses_texpixel_size;
|
||||
|
||||
} else {
|
||||
shader_cache=NULL;
|
||||
canvas_shader.set_custom_shader(0);
|
||||
canvas_shader.bind();
|
||||
uses_texpixel_size=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
|
||||
canvas_last_shader=shader_owner->shader;
|
||||
}
|
||||
|
||||
if (shader_cache) {
|
||||
|
||||
Shader *shader = shader_cache;
|
||||
//this can be optimized..
|
||||
int tex_id=1;
|
||||
int idx=0;
|
||||
for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
|
||||
|
||||
Map<StringName,Variant>::Element *F=shader_owner->shader_param.find(E->key());
|
||||
|
||||
if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
|
||||
|
||||
RID rid;
|
||||
if (F) {
|
||||
rid=F->get();
|
||||
}
|
||||
|
||||
if (!rid.is_valid()) {
|
||||
|
||||
Map<StringName,RID>::Element *DT=shader->default_textures.find(E->key());
|
||||
if (DT) {
|
||||
rid=DT->get();
|
||||
}
|
||||
}
|
||||
|
||||
if (rid.is_valid()) {
|
||||
|
||||
int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic..
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+tex_id);
|
||||
Texture *t=texture_owner.get(rid);
|
||||
if (!t)
|
||||
glBindTexture(GL_TEXTURE_2D,white_tex);
|
||||
else
|
||||
glBindTexture(t->target,t->tex_id);
|
||||
|
||||
glUniform1i(loc,tex_id);
|
||||
tex_id++;
|
||||
}
|
||||
} else {
|
||||
Variant &v=F?F->get():E->get().default_value;
|
||||
canvas_shader.set_custom_uniform(idx,v);
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (tex_id>1) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
|
||||
|
||||
|
||||
bool reclip=false;
|
||||
|
||||
if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) {
|
||||
|
||||
switch(ci->blend_mode) {
|
||||
|
||||
case VS::MATERIAL_BLEND_MODE_MIX: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_ADD: {
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_SUB: {
|
||||
|
||||
glBlendEquation(GL_FUNC_SUBTRACT);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_MUL: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_DST_COLOR,GL_ZERO);
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
canvas_blend_mode=ci->blend_mode;
|
||||
}
|
||||
|
||||
int cc=ci->commands.size();
|
||||
CanvasItem::Command **commands = ci->commands.ptr();
|
||||
|
||||
canvas_opacity = ci->final_opacity;
|
||||
|
||||
for(int i=0;i<cc;i++) {
|
||||
|
||||
|
@ -8571,22 +8377,30 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
|
|||
|
||||
int flags=rect->flags;
|
||||
#endif
|
||||
if (use_normalmap)
|
||||
_canvas_normal_set_flip(Vector2((flags&CANVAS_RECT_FLIP_H)?-1:1,(flags&CANVAS_RECT_FLIP_V)?-1:1));
|
||||
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);
|
||||
if (use_normalmap)
|
||||
_canvas_normal_set_flip(Vector2(1,1));
|
||||
canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color);
|
||||
|
||||
} break;
|
||||
case CanvasItem::Command::TYPE_PRIMITIVE: {
|
||||
|
||||
if (use_normalmap)
|
||||
_canvas_normal_set_flip(Vector2(1,1));
|
||||
CanvasItem::CommandPrimitive* primitive = static_cast<CanvasItem::CommandPrimitive*>(c);
|
||||
canvas_draw_primitive(primitive->points,primitive->colors,primitive->uvs,primitive->texture,primitive->width);
|
||||
} break;
|
||||
case CanvasItem::Command::TYPE_POLYGON: {
|
||||
|
||||
if (use_normalmap)
|
||||
_canvas_normal_set_flip(Vector2(1,1));
|
||||
CanvasItem::CommandPolygon* polygon = static_cast<CanvasItem::CommandPolygon*>(c);
|
||||
canvas_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
|
||||
|
||||
|
@ -8594,6 +8408,8 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
|
|||
|
||||
case CanvasItem::Command::TYPE_POLYGON_PTR: {
|
||||
|
||||
if (use_normalmap)
|
||||
_canvas_normal_set_flip(Vector2(1,1));
|
||||
CanvasItem::CommandPolygonPtr* polygon = static_cast<CanvasItem::CommandPolygonPtr*>(c);
|
||||
canvas_draw_polygon(polygon->count,polygon->indices,polygon->points,polygon->uvs,polygon->colors,polygon->texture,false);
|
||||
} break;
|
||||
|
@ -8652,6 +8468,345 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RasterizerGLES2::_canvas_item_setup_shader_params(CanvasItem *shader_owner,Shader* shader) {
|
||||
|
||||
if (canvas_shader.bind())
|
||||
rebind_texpixel_size=true;
|
||||
|
||||
if (shader_owner->shader_version!=shader->version) {
|
||||
//todo optimize uniforms
|
||||
shader_owner->shader_version=shader->version;
|
||||
}
|
||||
|
||||
if (shader->has_texscreen && framebuffer.active) {
|
||||
|
||||
int x = viewport.x;
|
||||
int y = window_size.height-(viewport.height+viewport.y);
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height));
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(float(x)/framebuffer.width,float(y)/framebuffer.height,float(x+viewport.width)/framebuffer.width,float(y+viewport.height)/framebuffer.height));
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TEXSCREEN_TEX,max_texture_units-1);
|
||||
glActiveTexture(GL_TEXTURE0+max_texture_units-1);
|
||||
glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color);
|
||||
if (framebuffer.scale==1 && !canvas_texscreen_used) {
|
||||
#ifdef GLEW_ENABLED
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
#endif
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height);
|
||||
// if (current_clip) {
|
||||
// // print_line(" a clip ");
|
||||
// }
|
||||
|
||||
canvas_texscreen_used=true;
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
}
|
||||
|
||||
if (shader->has_screen_uv) {
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::SCREEN_UV_MULT,Vector2(1.0/viewport.width,1.0/viewport.height));
|
||||
}
|
||||
|
||||
if (shader->uses_time) {
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::TIME,Math::fmod(last_time,300.0));
|
||||
draw_next_frame=true;
|
||||
}
|
||||
//if uses TIME - draw_next_frame=true
|
||||
|
||||
uses_texpixel_size=shader->uses_texpixel_size;
|
||||
|
||||
}
|
||||
|
||||
void RasterizerGLES2::_canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* shader) {
|
||||
|
||||
//this can be optimized..
|
||||
int tex_id=1;
|
||||
int idx=0;
|
||||
for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
|
||||
|
||||
Map<StringName,Variant>::Element *F=shader_owner->shader_param.find(E->key());
|
||||
|
||||
if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) {
|
||||
|
||||
RID rid;
|
||||
if (F) {
|
||||
rid=F->get();
|
||||
}
|
||||
|
||||
if (!rid.is_valid()) {
|
||||
|
||||
Map<StringName,RID>::Element *DT=shader->default_textures.find(E->key());
|
||||
if (DT) {
|
||||
rid=DT->get();
|
||||
}
|
||||
}
|
||||
|
||||
if (rid.is_valid()) {
|
||||
|
||||
int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic..
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+tex_id);
|
||||
Texture *t=texture_owner.get(rid);
|
||||
if (!t)
|
||||
glBindTexture(GL_TEXTURE_2D,white_tex);
|
||||
else
|
||||
glBindTexture(t->target,t->tex_id);
|
||||
|
||||
glUniform1i(loc,tex_id);
|
||||
tex_id++;
|
||||
}
|
||||
} else {
|
||||
Variant &v=F?F->get():E->get().default_value;
|
||||
canvas_shader.set_custom_uniform(idx,v);
|
||||
}
|
||||
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (tex_id>1) {
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) {
|
||||
|
||||
|
||||
CanvasItem *current_clip=NULL;
|
||||
Shader *shader_cache=NULL;
|
||||
|
||||
bool rebind_shader=true;
|
||||
|
||||
canvas_opacity=1.0;
|
||||
canvas_use_modulate=p_modulate!=Color(1,1,1,1);
|
||||
canvas_modulate=p_modulate;
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
||||
|
||||
while(p_item_list) {
|
||||
|
||||
CanvasItem *ci=p_item_list;
|
||||
|
||||
if (ci->vp_render) {
|
||||
if (draw_viewport_func) {
|
||||
draw_viewport_func(ci->vp_render->owner,ci->vp_render->udata,ci->vp_render->rect);
|
||||
}
|
||||
memdelete(ci->vp_render);
|
||||
ci->vp_render=NULL;
|
||||
canvas_last_shader=RID();
|
||||
canvas_use_modulate=p_modulate!=Color(1,1,1,1);
|
||||
canvas_modulate=p_modulate;
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
||||
rebind_shader=true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (current_clip!=ci->final_clip_owner) {
|
||||
|
||||
current_clip=ci->final_clip_owner;
|
||||
|
||||
//setup clip
|
||||
if (current_clip) {
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(viewport.x+current_clip->final_clip_rect.pos.x,viewport.y+ (viewport.height-(current_clip->final_clip_rect.pos.y+current_clip->final_clip_rect.size.height)),
|
||||
current_clip->final_clip_rect.size.width,current_clip->final_clip_rect.size.height);
|
||||
} else {
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//begin rect
|
||||
CanvasItem *shader_owner = ci->shader_owner?ci->shader_owner:ci;
|
||||
|
||||
if (shader_owner->shader!=canvas_last_shader || rebind_shader) {
|
||||
|
||||
Shader *shader = NULL;
|
||||
if (shader_owner->shader.is_valid()) {
|
||||
shader = this->shader_owner.get(shader_owner->shader);
|
||||
if (shader && !shader->valid) {
|
||||
shader=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
shader_cache=shader;
|
||||
|
||||
if (shader) {
|
||||
canvas_shader.set_custom_shader(shader->custom_code_id);
|
||||
_canvas_item_setup_shader_params(shader_owner,shader);
|
||||
} else {
|
||||
shader_cache=NULL;
|
||||
canvas_shader.set_custom_shader(0);
|
||||
canvas_shader.bind();
|
||||
uses_texpixel_size=false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
|
||||
if (canvas_use_modulate)
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
|
||||
canvas_last_shader=shader_owner->shader;
|
||||
rebind_shader=false;
|
||||
}
|
||||
|
||||
if (shader_cache) {
|
||||
|
||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
||||
}
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
|
||||
|
||||
|
||||
bool reclip=false;
|
||||
|
||||
if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) {
|
||||
|
||||
switch(ci->blend_mode) {
|
||||
|
||||
case VS::MATERIAL_BLEND_MODE_MIX: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_ADD: {
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_SUB: {
|
||||
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_MUL: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_DST_COLOR,GL_ZERO);
|
||||
} break;
|
||||
case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: {
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
|
||||
} break;
|
||||
|
||||
}
|
||||
|
||||
canvas_blend_mode=ci->blend_mode;
|
||||
}
|
||||
|
||||
canvas_opacity = ci->final_opacity;
|
||||
|
||||
_canvas_item_render_commands<false>(ci,current_clip,reclip);
|
||||
|
||||
if (canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX && p_light) {
|
||||
|
||||
CanvasLight *light = p_light;
|
||||
bool light_used=false;
|
||||
bool subtract=false;
|
||||
|
||||
|
||||
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)) {
|
||||
|
||||
//intersects this light
|
||||
|
||||
if (!light_used || subtract!=light->subtract) {
|
||||
|
||||
subtract=light->subtract;
|
||||
|
||||
if (subtract) {
|
||||
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
|
||||
} else {
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!light_used) {
|
||||
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,true);
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,false);
|
||||
light_used=true;
|
||||
normal_flip=Vector2(1,1);
|
||||
|
||||
}
|
||||
bool light_rebind = canvas_shader.bind();
|
||||
|
||||
if (light_rebind) {
|
||||
|
||||
if (shader_owner && shader_cache) {
|
||||
_canvas_item_setup_shader_params(shader_owner,shader_cache);
|
||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
||||
}
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::PROJECTION_MATRIX,canvas_transform);
|
||||
if (canvas_use_modulate)
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::NORMAL_FLIP,Vector2(1,1));
|
||||
|
||||
|
||||
}
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_MATRIX,light->light_shader_xform);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS,light->light_shader_pos);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR,light->color);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT,light->height);
|
||||
glActiveTexture(GL_TEXTURE0+max_texture_units-2);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_TEXTURE,max_texture_units-2);
|
||||
Texture *t = texture_owner.get(light->texture);
|
||||
if (!t) {
|
||||
glBindTexture(GL_TEXTURE_2D,white_tex);
|
||||
} else {
|
||||
|
||||
glBindTexture(t->target,t->tex_id);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
_canvas_item_render_commands<true>(ci,current_clip,reclip); //redraw using light
|
||||
|
||||
}
|
||||
|
||||
light=light->next_ptr;
|
||||
}
|
||||
|
||||
if (light_used) {
|
||||
|
||||
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_LIGHTING,false);
|
||||
canvas_shader.set_conditional(CanvasShaderGLES2::USE_MODULATE,canvas_use_modulate);
|
||||
|
||||
canvas_shader.bind();
|
||||
|
||||
if (shader_owner && shader_cache) {
|
||||
_canvas_item_setup_shader_params(shader_owner,shader_cache);
|
||||
_canvas_item_setup_shader_uniforms(shader_owner,shader_cache);
|
||||
}
|
||||
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX,ci->final_transform);
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::EXTRA_MATRIX,Matrix32());
|
||||
if (canvas_use_modulate)
|
||||
canvas_shader.set_uniform(CanvasShaderGLES2::MODULATE,canvas_modulate);
|
||||
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (reclip) {
|
||||
|
||||
|
|
|
@ -1127,6 +1127,7 @@ class RasterizerGLES2 : public Rasterizer {
|
|||
bool active;
|
||||
|
||||
int blur_size;
|
||||
|
||||
struct Blur {
|
||||
|
||||
GLuint fbo;
|
||||
|
@ -1186,11 +1187,15 @@ class RasterizerGLES2 : public Rasterizer {
|
|||
GLuint white_tex;
|
||||
RID canvas_tex;
|
||||
float canvas_opacity;
|
||||
Color canvas_modulate;
|
||||
bool canvas_use_modulate;
|
||||
bool uses_texpixel_size;
|
||||
bool rebind_texpixel_size;
|
||||
Transform canvas_transform;
|
||||
RID canvas_last_shader;
|
||||
bool canvas_texscreen_used;
|
||||
Vector2 normal_flip;
|
||||
_FORCE_INLINE_ void _canvas_normal_set_flip(const Vector2& p_flip);
|
||||
|
||||
|
||||
_FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture);
|
||||
|
@ -1247,6 +1252,10 @@ class RasterizerGLES2 : public Rasterizer {
|
|||
GLuint tc0_id_cache;
|
||||
GLuint tc0_idx;
|
||||
|
||||
template<bool use_normalmap>
|
||||
_FORCE_INLINE_ void _canvas_item_render_commands(CanvasItem *p_item,CanvasItem *current_clip,bool &reclip);
|
||||
_FORCE_INLINE_ void _canvas_item_setup_shader_params(CanvasItem *shader_owner,Shader* p_shader);
|
||||
_FORCE_INLINE_ void _canvas_item_setup_shader_uniforms(CanvasItem *shader_owner,Shader* p_shader);
|
||||
public:
|
||||
|
||||
/* TEXTURE API */
|
||||
|
@ -1562,7 +1571,8 @@ 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);
|
||||
virtual void canvas_set_transform(const Matrix32& p_transform);
|
||||
|
||||
virtual void canvas_render_items(CanvasItem *p_item_list);
|
||||
virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light);
|
||||
|
||||
|
||||
/* ENVIRONMENT */
|
||||
|
||||
|
|
|
@ -261,6 +261,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a
|
|||
uses_light=true;
|
||||
}
|
||||
|
||||
if (vnode->name==vname_normal) {
|
||||
uses_normal=true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (vnode->name==vname_time) {
|
||||
|
@ -636,7 +641,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT
|
|||
r_flags.uses_light=uses_light;
|
||||
r_flags.uses_time=uses_time;
|
||||
r_flags.uses_normalmap=uses_normalmap;
|
||||
r_flags.uses_normal=uses_normalmap;
|
||||
r_flags.uses_normal=uses_normal;
|
||||
r_flags.uses_texpixel_size=uses_texpixel_size;
|
||||
r_flags.uses_worldvec=uses_worldvec;
|
||||
r_code_line=code;
|
||||
|
|
|
@ -26,7 +26,13 @@ uniform float time;
|
|||
#ifdef USE_LIGHTING
|
||||
|
||||
uniform highp mat4 light_matrix;
|
||||
varying vec4 light_tex_pos;
|
||||
uniform vec2 light_pos;
|
||||
varying vec4 light_uv_interp;
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
varying vec4 local_rot;
|
||||
uniform vec2 normal_flip;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -67,8 +73,13 @@ VERTEX_SHADER_CODE
|
|||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
light_tex_pos.xy = light_matrix * gl_Position;
|
||||
light_tex_pos.zw=outvec.xy - light_matrix[4].xy; //likely wrong
|
||||
light_uv_interp.xy = (light_matrix * outvec).xy;
|
||||
light_uv_interp.zw = outvec.xy-light_pos;
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
local_rot.xy=normalize( (modelview_matrix * ( extra_matrix * vec4(1.0,0.0,0.0,0.0) )).xy )*normal_flip.x;
|
||||
local_rot.zw=normalize( (modelview_matrix * ( extra_matrix * vec4(0.0,1.0,0.0,0.0) )).xy )*normal_flip.y;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -121,11 +132,22 @@ varying vec4 var2_interp;
|
|||
uniform float time;
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODULATE
|
||||
|
||||
uniform vec4 modulate;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
uniform sampler2D light_texture;
|
||||
varying vec4 light_tex_pos;
|
||||
uniform vec4 light_color;
|
||||
uniform float light_height;
|
||||
varying vec4 light_uv_interp;
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
varying vec4 local_rot;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHADOWS
|
||||
|
||||
|
@ -151,6 +173,11 @@ void main() {
|
|||
vec3 normal = vec3(0,0,1);
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODULATE
|
||||
|
||||
color*=modulate;
|
||||
#endif
|
||||
|
||||
color *= texture2D( texture, uv_interp );
|
||||
#if defined(ENABLE_SCREEN_UV)
|
||||
vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult;
|
||||
|
@ -166,9 +193,13 @@ FRAGMENT_SHADER_CODE
|
|||
|
||||
#ifdef USE_LIGHTING
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
normal.xy = mat2(local_rot.xy,local_rot.zw) * normal.xy;
|
||||
#endif
|
||||
|
||||
float att=1.0;
|
||||
|
||||
vec3 light = texture2D(light_texture,light_tex_pos).rgb;
|
||||
vec4 light = texture2D(light_texture,light_uv_interp.xy) * light_color;
|
||||
#ifdef USE_SHADOWS
|
||||
//this might not be that great on mobile?
|
||||
float light_dist = length(light_texture.zw);
|
||||
|
@ -183,18 +214,29 @@ FRAGMENT_SHADER_CODE
|
|||
#if defined(USE_LIGHT_SHADER_CODE)
|
||||
//light is written by the light shader
|
||||
{
|
||||
vec2 light_dir = normalize(light_tex_pos.zw);
|
||||
float light_distance = length(light_tex_pos.zw);
|
||||
vec2 light_dir = normalize(light_uv_interp.zw);
|
||||
float light_distance = length(light_uv_interp.zw);
|
||||
LIGHT_SHADER_CODE
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#if defined(NORMAL_USED)
|
||||
vec2 light_normal = normalize(light_tex_pos.zw);
|
||||
light = color.rgb * light * max(dot(light_normal,normal),0);
|
||||
vec3 light_normal = normalize(vec3(light_uv_interp.zw,-light_height));
|
||||
light*=max(dot(-light_normal,normal),0);
|
||||
#endif
|
||||
|
||||
color.rgb=light;
|
||||
color*=light;
|
||||
/*
|
||||
#ifdef USE_NORMAL
|
||||
color.xy=local_rot.xy;//normal.xy;
|
||||
color.zw=vec2(0.0,1.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=0.0; //invisible
|
||||
}
|
||||
|
||||
//light shader code
|
||||
#endif
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/*************************************************************************/
|
||||
#include "drivers/gles2/rasterizer_gles2.h"
|
||||
#include "drivers/gles1/rasterizer_gles1.h"
|
||||
#include "os_winrt.h"
|
||||
#include "drivers/nedmalloc/memory_pool_static_nedmalloc.h"
|
||||
#include "drivers/unix/memory_pool_static_malloc.h"
|
||||
|
@ -62,11 +61,11 @@ using namespace Microsoft::WRL;
|
|||
|
||||
int OSWinrt::get_video_driver_count() const {
|
||||
|
||||
return 2;
|
||||
return 1;
|
||||
}
|
||||
const char * OSWinrt::get_video_driver_name(int p_driver) const {
|
||||
|
||||
return p_driver==0?"GLES2":"GLES1";
|
||||
return "GLES2";
|
||||
}
|
||||
|
||||
OS::VideoMode OSWinrt::get_default_video_mode() const {
|
||||
|
|
|
@ -458,6 +458,16 @@ CanvasItem::BlendMode CanvasItem::get_blend_mode() const {
|
|||
return blend_mode;
|
||||
}
|
||||
|
||||
void CanvasItem::set_light_mask(int p_light_mask) {
|
||||
|
||||
light_mask=p_light_mask;
|
||||
VS::get_singleton()->canvas_item_set_light_mask(canvas_item,p_light_mask);
|
||||
}
|
||||
|
||||
int CanvasItem::get_light_mask() const{
|
||||
|
||||
return light_mask;
|
||||
}
|
||||
|
||||
|
||||
void CanvasItem::item_rect_changed() {
|
||||
|
@ -857,6 +867,9 @@ void CanvasItem::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_blend_mode","blend_mode"),&CanvasItem::set_blend_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_blend_mode"),&CanvasItem::get_blend_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_light_mask","light_mask"),&CanvasItem::set_light_mask);
|
||||
ObjectTypeDB::bind_method(_MD("get_light_mask"),&CanvasItem::get_light_mask);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_opacity","opacity"),&CanvasItem::set_opacity);
|
||||
ObjectTypeDB::bind_method(_MD("get_opacity"),&CanvasItem::get_opacity);
|
||||
ObjectTypeDB::bind_method(_MD("set_self_opacity","self_opacity"),&CanvasItem::set_self_opacity);
|
||||
|
@ -912,6 +925,7 @@ void CanvasItem::_bind_methods() {
|
|||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"visibility/on_top",PROPERTY_HINT_NONE,"",0), _SCS("_set_on_top"),_SCS("_is_on_top") ); //compatibility
|
||||
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/blend_mode",PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul,PMAlpha"), _SCS("set_blend_mode"),_SCS("get_blend_mode") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::INT,"visibility/light_mask",PROPERTY_HINT_ALL_FLAGS), _SCS("set_light_mask"),_SCS("get_light_mask") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::OBJECT,"shader/shader",PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemShader,CanvasItemShaderGraph"), _SCS("set_shader"),_SCS("get_shader") );
|
||||
ADD_PROPERTYNZ( PropertyInfo(Variant::BOOL,"shader/use_parent"), _SCS("set_use_parent_shader"),_SCS("get_use_parent_shader") );
|
||||
//exporting these two things doesn't really make much sense i think
|
||||
|
@ -992,6 +1006,7 @@ CanvasItem::CanvasItem() : xform_change(this) {
|
|||
canvas_layer=NULL;
|
||||
use_parent_shader=false;
|
||||
global_invalid=true;
|
||||
light_mask=1;
|
||||
|
||||
C=NULL;
|
||||
|
||||
|
|
|
@ -71,6 +71,7 @@ private:
|
|||
List<CanvasItem*>::Element *C;
|
||||
|
||||
BlendMode blend_mode;
|
||||
int light_mask;
|
||||
|
||||
bool first_draw;
|
||||
bool hidden;
|
||||
|
@ -80,8 +81,8 @@ private:
|
|||
bool drawing;
|
||||
bool block_transform_notify;
|
||||
bool behind;
|
||||
|
||||
bool use_parent_shader;
|
||||
|
||||
Ref<Shader> shader;
|
||||
|
||||
mutable Matrix32 global_transform;
|
||||
|
@ -158,6 +159,9 @@ public:
|
|||
void set_blend_mode(BlendMode p_blend_mode);
|
||||
BlendMode get_blend_mode() const;
|
||||
|
||||
void set_light_mask(int p_light_mask);
|
||||
int get_light_mask() const;
|
||||
|
||||
void set_opacity(float p_opacity);
|
||||
float get_opacity() const;
|
||||
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
#include "canvas_modulate.h"
|
||||
|
||||
|
||||
void CanvasModulate::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_CANVAS) {
|
||||
|
||||
VS::get_singleton()->canvas_set_modulate(get_canvas(),color);
|
||||
} else if (p_what==NOTIFICATION_EXIT_CANVAS) {
|
||||
|
||||
VS::get_singleton()->canvas_set_modulate(get_canvas(),Color(1,1,1,1));
|
||||
}
|
||||
}
|
||||
|
||||
void CanvasModulate::_bind_methods(){
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_color","color"),&CanvasModulate::set_color);
|
||||
ObjectTypeDB::bind_method(_MD("get_color"),&CanvasModulate::get_color);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::COLOR,"color"),_SCS("set_color"),_SCS("get_color"));
|
||||
}
|
||||
|
||||
|
||||
void CanvasModulate::set_color(const Color& p_color){
|
||||
|
||||
color=p_color;
|
||||
if (is_inside_tree()) {
|
||||
VS::get_singleton()->canvas_set_modulate(get_canvas(),color);
|
||||
}
|
||||
}
|
||||
Color CanvasModulate::get_color() const {
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
CanvasModulate::CanvasModulate()
|
||||
{
|
||||
color=Color(1,1,1,1);
|
||||
}
|
||||
|
||||
CanvasModulate::~CanvasModulate()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef CANVASMODULATE_H
|
||||
#define CANVASMODULATE_H
|
||||
|
||||
#include "scene/2d/node_2d.h"
|
||||
|
||||
class CanvasModulate : public Node2D {
|
||||
|
||||
OBJ_TYPE(CanvasModulate,Node2D);
|
||||
|
||||
Color color;
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
void set_color(const Color& p_color);
|
||||
Color get_color() const;
|
||||
|
||||
CanvasModulate();
|
||||
~CanvasModulate();
|
||||
};
|
||||
|
||||
#endif // CANVASMODULATE_H
|
|
@ -1,6 +1,39 @@
|
|||
#include "light_2d.h"
|
||||
#include "servers/visual_server.h"
|
||||
|
||||
void Light2D::edit_set_pivot(const Point2& p_pivot) {
|
||||
|
||||
set_texture_offset(p_pivot);
|
||||
|
||||
}
|
||||
|
||||
Point2 Light2D::edit_get_pivot() const {
|
||||
|
||||
return get_texture_offset();
|
||||
}
|
||||
bool Light2D::edit_has_pivot() const {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Rect2 Light2D::get_item_rect() const {
|
||||
|
||||
if (texture.is_null())
|
||||
return Rect2(0,0,1,1);
|
||||
|
||||
Size2i s;
|
||||
|
||||
s = texture->get_size();
|
||||
Point2i ofs=texture_offset;
|
||||
ofs-=s/2;
|
||||
|
||||
if (s==Size2(0,0))
|
||||
s=Size2(1,1);
|
||||
|
||||
return Rect2(ofs,s);
|
||||
}
|
||||
|
||||
|
||||
void Light2D::set_enabled( bool p_enabled) {
|
||||
|
||||
VS::get_singleton()->canvas_light_set_enabled(canvas_light,p_enabled);
|
||||
|
@ -81,6 +114,28 @@ int Light2D::get_z_range_max() const {
|
|||
return z_max;
|
||||
}
|
||||
|
||||
void Light2D::set_layer_range_min( int p_min_layer) {
|
||||
|
||||
layer_min=p_min_layer;
|
||||
VS::get_singleton()->canvas_light_set_layer_range(canvas_light,layer_min,layer_max);
|
||||
|
||||
}
|
||||
int Light2D::get_layer_range_min() const {
|
||||
|
||||
return layer_min;
|
||||
}
|
||||
|
||||
void Light2D::set_layer_range_max( int p_max_layer) {
|
||||
|
||||
layer_max=p_max_layer;
|
||||
VS::get_singleton()->canvas_light_set_layer_range(canvas_light,layer_min,layer_max);
|
||||
|
||||
}
|
||||
int Light2D::get_layer_range_max() const {
|
||||
|
||||
return layer_max;
|
||||
}
|
||||
|
||||
void Light2D::set_item_mask( int p_mask) {
|
||||
|
||||
item_mask=p_mask;
|
||||
|
@ -93,15 +148,15 @@ int Light2D::get_item_mask() const {
|
|||
return item_mask;
|
||||
}
|
||||
|
||||
void Light2D::set_blend_mode( LightBlendMode p_blend_mode ) {
|
||||
void Light2D::set_subtract_mode( bool p_enable ) {
|
||||
|
||||
blend_mode=p_blend_mode;
|
||||
VS::get_singleton()->canvas_light_set_blend_mode(canvas_light,VS::CanvasLightBlendMode(blend_mode));
|
||||
subtract_mode=p_enable;
|
||||
VS::get_singleton()->canvas_light_set_subtract_mode(canvas_light,p_enable);
|
||||
}
|
||||
|
||||
Light2D::LightBlendMode Light2D::get_blend_mode() const {
|
||||
bool Light2D::get_subtract_mode() const {
|
||||
|
||||
return blend_mode;
|
||||
return subtract_mode;
|
||||
}
|
||||
|
||||
void Light2D::set_shadow_enabled( bool p_enabled) {
|
||||
|
@ -115,6 +170,25 @@ bool Light2D::is_shadow_enabled() const {
|
|||
return shadow;
|
||||
}
|
||||
|
||||
void Light2D::_notification(int p_what) {
|
||||
|
||||
if (p_what==NOTIFICATION_ENTER_TREE) {
|
||||
|
||||
VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, get_canvas() );
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_TRANSFORM_CHANGED) {
|
||||
|
||||
VS::get_singleton()->canvas_light_set_transform( canvas_light, get_global_transform());
|
||||
}
|
||||
|
||||
if (p_what==NOTIFICATION_EXIT_TREE) {
|
||||
|
||||
VS::get_singleton()->canvas_light_attach_to_canvas( canvas_light, RID() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Light2D::_bind_methods() {
|
||||
|
||||
|
||||
|
@ -139,11 +213,18 @@ void Light2D::_bind_methods() {
|
|||
ObjectTypeDB::bind_method(_MD("set_z_range_max","z"),&Light2D::set_z_range_max);
|
||||
ObjectTypeDB::bind_method(_MD("get_z_range_max"),&Light2D::get_z_range_max);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_layer_range_min","layer"),&Light2D::set_layer_range_min);
|
||||
ObjectTypeDB::bind_method(_MD("get_layer_range_min"),&Light2D::get_layer_range_min);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_layer_range_max","layer"),&Light2D::set_layer_range_max);
|
||||
ObjectTypeDB::bind_method(_MD("get_layer_range_max"),&Light2D::get_layer_range_max);
|
||||
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_item_mask","item_mask"),&Light2D::set_item_mask);
|
||||
ObjectTypeDB::bind_method(_MD("get_item_mask"),&Light2D::get_item_mask);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_blend_mode","blend_mode"),&Light2D::set_blend_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_blend_mode"),&Light2D::get_blend_mode);
|
||||
ObjectTypeDB::bind_method(_MD("set_subtract_mode","enable"),&Light2D::set_subtract_mode);
|
||||
ObjectTypeDB::bind_method(_MD("get_subtract_mode"),&Light2D::get_subtract_mode);
|
||||
|
||||
ObjectTypeDB::bind_method(_MD("set_shadow_enabled","enabled"),&Light2D::set_shadow_enabled);
|
||||
ObjectTypeDB::bind_method(_MD("is_shadow_enabled"),&Light2D::is_shadow_enabled);
|
||||
|
@ -155,8 +236,10 @@ void Light2D::_bind_methods() {
|
|||
ADD_PROPERTY( PropertyInfo(Variant::REAL,"height"),_SCS("set_height"),_SCS("get_height"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"z_range_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,"z_range_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"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_min",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_min"),_SCS("get_layer_range_min"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"layer_range_max",PROPERTY_HINT_RANGE,"-512,512,1"),_SCS("set_layer_range_max"),_SCS("get_layer_range_max"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_mask"),_SCS("get_item_mask"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::INT,"blend_mode",PROPERTY_HINT_ENUM,"Add,Sub,Mul,Dodge,Burn,Lighten,Darken,Overlay,Screen"),_SCS("set_blend_mode"),_SCS("get_blend_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"subtract"),_SCS("set_subtract_mode"),_SCS("get_subtract_mode"));
|
||||
ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow_enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled"));
|
||||
|
||||
|
||||
|
@ -171,8 +254,10 @@ Light2D::Light2D() {
|
|||
height=0;
|
||||
z_min=-1024;
|
||||
z_max=1024;
|
||||
layer_min=0;
|
||||
layer_max=0;
|
||||
item_mask=1;
|
||||
blend_mode=LIGHT_BLEND_ADD;
|
||||
subtract_mode=false;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -6,20 +6,6 @@
|
|||
class Light2D : public Node2D {
|
||||
|
||||
OBJ_TYPE(Light2D,Node2D);
|
||||
public:
|
||||
|
||||
enum LightBlendMode {
|
||||
LIGHT_BLEND_ADD,
|
||||
LIGHT_BLEND_SUB,
|
||||
LIGHT_BLEND_MULTIPLY,
|
||||
LIGHT_BLEND_DODGE,
|
||||
LIGHT_BLEND_BURN,
|
||||
LIGHT_BLEND_LIGHTEN,
|
||||
LIGHT_BLEND_DARKEN,
|
||||
LIGHT_BLEND_OVERLAY,
|
||||
LIGHT_BLEND_SCREEN,
|
||||
};
|
||||
|
||||
private:
|
||||
RID canvas_light;
|
||||
bool enabled;
|
||||
|
@ -28,17 +14,24 @@ private:
|
|||
float height;
|
||||
int z_min;
|
||||
int z_max;
|
||||
int layer_min;
|
||||
int layer_max;
|
||||
int item_mask;
|
||||
LightBlendMode blend_mode;
|
||||
bool subtract_mode;
|
||||
Ref<Texture> texture;
|
||||
Vector2 texture_offset;
|
||||
|
||||
protected:
|
||||
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
public:
|
||||
|
||||
|
||||
virtual void edit_set_pivot(const Point2& p_pivot);
|
||||
virtual Point2 edit_get_pivot() const;
|
||||
virtual bool edit_has_pivot() const;
|
||||
|
||||
void set_enabled( bool p_enabled);
|
||||
bool is_enabled() const;
|
||||
|
||||
|
@ -60,21 +53,26 @@ public:
|
|||
void set_z_range_max( int p_max_z);
|
||||
int get_z_range_max() const;
|
||||
|
||||
void set_layer_range_min( int p_min_layer);
|
||||
int get_layer_range_min() const;
|
||||
|
||||
void set_layer_range_max( int p_max_layer);
|
||||
int get_layer_range_max() const;
|
||||
|
||||
void set_item_mask( int p_mask);
|
||||
int get_item_mask() const;
|
||||
|
||||
void set_blend_mode( LightBlendMode p_blend_mode );
|
||||
LightBlendMode get_blend_mode() const;
|
||||
void set_subtract_mode( bool p_enable );
|
||||
bool get_subtract_mode() const;
|
||||
|
||||
void set_shadow_enabled( bool p_enabled);
|
||||
bool is_shadow_enabled() const;
|
||||
|
||||
virtual Rect2 get_item_rect() const;
|
||||
|
||||
Light2D();
|
||||
~Light2D();
|
||||
};
|
||||
|
||||
|
||||
VARIANT_ENUM_CAST(Light2D::LightBlendMode);
|
||||
|
||||
#endif // LIGHT_2D_H
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
#include "scene/2d/remote_transform_2d.h"
|
||||
#include "scene/2d/y_sort.h"
|
||||
#include "scene/2d/navigation2d.h"
|
||||
#include "scene/2d/canvas_modulate.h"
|
||||
|
||||
#include "scene/2d/position_2d.h"
|
||||
#include "scene/2d/tile_map.h"
|
||||
|
@ -264,6 +265,7 @@ void register_scene_types() {
|
|||
ObjectTypeDB::register_virtual_type<RenderTargetTexture>();
|
||||
ObjectTypeDB::register_type<Timer>();
|
||||
ObjectTypeDB::register_type<CanvasLayer>();
|
||||
ObjectTypeDB::register_type<CanvasModulate>();
|
||||
ObjectTypeDB::register_type<ResourcePreloader>();
|
||||
|
||||
/* REGISTER GUI */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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){
|
||||
|
@ -4195,6 +4245,12 @@ 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++;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue