diff options
Diffstat (limited to 'drivers/gles2')
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 474 | ||||
-rw-r--r-- | drivers/gles2/rasterizer_gles2.h | 19 | ||||
-rw-r--r-- | drivers/gles2/shader_compiler_gles2.cpp | 94 | ||||
-rw-r--r-- | drivers/gles2/shader_compiler_gles2.h | 8 | ||||
-rw-r--r-- | drivers/gles2/shaders/canvas.glsl | 136 | ||||
-rw-r--r-- | drivers/gles2/shaders/material.glsl | 1 |
6 files changed, 690 insertions, 42 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index fdf73a6c21..9375532f07 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -1411,6 +1411,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { material_shader.free_custom_shader(shader->custom_code_id); } break; + case VS::SHADER_CANVAS_ITEM: { + canvas_shader.free_custom_shader(shader->custom_code_id); + } break; } shader->custom_code_id=0; @@ -1422,6 +1425,9 @@ void RasterizerGLES2::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) { case VS::SHADER_MATERIAL: { shader->custom_code_id=material_shader.create_custom_shader(); } break; + case VS::SHADER_CANVAS_ITEM: { + shader->custom_code_id=canvas_shader.create_custom_shader(); + } break; } _shader_make_dirty(shader); @@ -1545,17 +1551,20 @@ void RasterizerGLES2::shader_set_default_texture_param(RID p_shader, const Strin Shader *shader=shader_owner.get(p_shader); ERR_FAIL_COND(!shader); - ERR_FAIL_COND(!texture_owner.owns(p_texture)); + ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); if (p_texture.is_valid()) shader->default_textures[p_name]=p_texture; else shader->default_textures.erase(p_name); + _shader_make_dirty(shader); + } RID RasterizerGLES2::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,RID()); const Map<StringName,RID>::Element *E=shader->default_textures.find(p_name); if (!E) @@ -1563,6 +1572,22 @@ RID RasterizerGLES2::shader_get_default_texture_param(RID p_shader, const String return E->get(); } +Variant RasterizerGLES2::shader_get_default_param(RID p_shader, const StringName& p_name) { + + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,Variant()); + + //update shader params if necesary + //make sure the shader is compiled and everything + //so the actual parameters can be properly retrieved! + if (shader->dirty_list.in_list()) { + _update_shader(shader); + } + if (shader->valid && shader->uniforms.has(p_name)) + return shader->uniforms[p_name].default_value; + + return Variant(); +} /* COMMON MATERIAL API */ @@ -1606,6 +1631,7 @@ void RasterizerGLES2::material_set_param(RID p_material, const StringName& p_par material->shader_version=0; //get default! } else { E->get().value=p_value; + E->get().inuse=true; } } else { @@ -1613,6 +1639,7 @@ void RasterizerGLES2::material_set_param(RID p_material, const StringName& p_par ud.index=-1; ud.value=p_value; ud.istexture=p_value.get_type()==Variant::_RID; /// cache it being texture + ud.inuse=true; material->shader_params[p_param]=ud; //may be got at some point, or erased } @@ -1644,7 +1671,7 @@ Variant RasterizerGLES2::material_get_param(RID p_material, const StringName& p_ } - if (material->shader_params.has(p_param)) + if (material->shader_params.has(p_param) && material->shader_params[p_param].inuse) return material->shader_params[p_param].value; else return Variant(); @@ -4430,6 +4457,13 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (err) { return; //invalid } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + + Error err = shader_precompiler.compile(p_shader->vertex_code,ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX,vertex_code,vertex_globals,vertex_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } + } //print_line("compiled vertex: "+vertex_code); @@ -4439,9 +4473,16 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { String fragment_code; String fragment_globals; - Error err = shader_precompiler.compile(p_shader->fragment_code,(p_shader->mode==VS::SHADER_MATERIAL?ShaderLanguage::SHADER_MATERIAL_FRAGMENT:ShaderLanguage::SHADER_POST_PROCESS),fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); - if (err) { - return; //invalid + if (p_shader->mode==VS::SHADER_MATERIAL) { + Error err = shader_precompiler.compile(p_shader->fragment_code,ShaderLanguage::SHADER_MATERIAL_FRAGMENT,fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + Error err = shader_precompiler.compile(p_shader->fragment_code,ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT,fragment_code,fragment_globals,fragment_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } } @@ -4454,6 +4495,11 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { if (err) { return; //invalid } + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + Error err = shader_precompiler.compile(p_shader->light_code,(ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT),light_code,light_globals,light_flags,&p_shader->uniforms); + if (err) { + return; //invalid + } } fragment_globals+=light_globals; //both fragment anyway @@ -4514,7 +4560,36 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { } material_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); - } else { + } else if (p_shader->mode==VS::SHADER_CANVAS_ITEM) { + + Vector<const char*> enablers; + + if (light_flags.uses_time || fragment_flags.uses_time || vertex_flags.uses_time) { + enablers.push_back("#define USE_TIME\n"); + uses_time=true; + } + if (fragment_flags.uses_normal) { + enablers.push_back("#define NORMAL_USED\n"); + } + if (light_flags.uses_light) { + enablers.push_back("#define USE_LIGHT_SHADER_CODE\n"); + } + if (fragment_flags.use_var1_interp || vertex_flags.use_var1_interp) + enablers.push_back("#define ENABLE_VAR1_INTERP\n"); + if (fragment_flags.use_var2_interp || vertex_flags.use_var2_interp) + enablers.push_back("#define ENABLE_VAR2_INTERP\n"); + if (fragment_flags.uses_texscreen) { + enablers.push_back("#define ENABLE_TEXSCREEN\n"); + } + if (fragment_flags.uses_screen_uv) { + enablers.push_back("#define ENABLE_SCREEN_UV\n"); + } + if (fragment_flags.uses_texpixel_size) { + enablers.push_back("#define USE_TEXPIXEL_SIZE\n"); + } + + canvas_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); + //postprocess_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names); } @@ -4525,7 +4600,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { p_shader->has_texscreen=fragment_flags.uses_texscreen; p_shader->has_screen_uv=fragment_flags.uses_screen_uv; p_shader->can_zpass=!fragment_flags.uses_discard && !vertex_flags.vertex_code_writes_vertex; + p_shader->uses_normal=fragment_flags.uses_normal || light_flags.uses_normal; p_shader->uses_time=uses_time; + p_shader->uses_texpixel_size=fragment_flags.uses_texpixel_size; p_shader->version++; } @@ -4876,31 +4953,46 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ Material::UniformData ud; - bool keep=true; + bool keep=true; //keep material value + bool has_old = old_mparams.has(E->key()); + bool old_inuse=has_old && old_mparams[E->key()].inuse; - if (!old_mparams.has(E->key())) + if (!has_old || !old_inuse) keep=false; else if (old_mparams[E->key()].value.get_type()!=E->value().default_value.get_type()) { - - if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { + //type changed between old and new + /* if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { if (E->value().default_value.get_type()!=Variant::_RID) //hackfor textures keep=false; } else if (!old_mparams[E->key()].value.is_num() || !E->value().default_value.get_type()) + keep=false;*/ + + //value is invalid because type differs and default is not null + if (E->value().default_value.get_type()!=Variant::NIL) keep=false; } + ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); + if (keep) { ud.value=old_mparams[E->key()].value; + //print_line("KEEP: "+String(E->key())); } else { - ud.value=E->value().default_value; + if (ud.istexture && p_material->shader_cache->default_textures.has(E->key())) + ud.value=p_material->shader_cache->default_textures[E->key()]; + else + ud.value=E->value().default_value; + old_inuse=false; //if reverted to default, obviously did not work + //print_line("NEW: "+String(E->key())+" because: hasold-"+itos(old_mparams.has(E->key()))); //if (old_mparams.has(E->key())) // print_line(" told "+Variant::get_type_name(old_mparams[E->key()].value.get_type())+" tnew "+Variant::get_type_name(E->value().default_value.get_type())); } - ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); + ud.index=idx++; + ud.inuse=old_inuse; mparams[E->key()]=ud; } @@ -5021,23 +5113,8 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material E->get().value=RID(); //nullify, invalid texture rid=RID(); } - } else { - - - } - - if (!rid.is_valid()) { - //use from default textures - Map<StringName,RID>::Element *F=p_material->shader_cache->default_textures.find(E->key()); - if (F) { - t=texture_owner.get(F->get()); - if (!t) { - p_material->shader_cache->default_textures.erase(E->key()); - } - } } - glActiveTexture(GL_TEXTURE0+texcoord); glUniform1i(loc,texcoord); //TODO - this could happen automatically on compile... if (t) { @@ -5061,15 +5138,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material } - for (Map<StringName,RID>::Element *E=p_material->shader_cache->default_textures.front();E;E=E->next()) { - if (p_material->shader_params.has(E->key())) - continue; - - - } if (p_material->shader_cache->has_texscreen && framebuffer.active) { material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_MULT,Vector2(float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); + material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_SCREEN_CLAMP,Color(0,0,float(viewport.width)/framebuffer.width,float(viewport.height)/framebuffer.height)); material_shader.set_uniform(MaterialShaderGLES2::TEXSCREEN_TEX,texcoord); glActiveTexture(GL_TEXTURE0+texcoord); glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); @@ -7724,10 +7796,11 @@ void RasterizerGLES2::canvas_begin() { canvas_tex=RID(); //material_shader.unbind(); canvas_shader.unbind(); + canvas_shader.set_custom_shader(0); canvas_shader.bind(); canvas_shader.set_uniform(CanvasShaderGLES2::TEXTURE, 0); _set_color_attrib(Color(1,1,1)); - Transform canvas_transform; + canvas_transform=Transform(); canvas_transform.translate(-(viewport.width / 2.0f), -(viewport.height / 2.0f), 0.0f); float csy = 1.0; if (current_rt && current_rt_vflip) @@ -7741,6 +7814,9 @@ 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(); } @@ -7823,7 +7899,7 @@ void RasterizerGLES2::canvas_end_rect() { RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_texture) { - if (p_texture==canvas_tex) { + if (p_texture==canvas_tex && !rebind_texpixel_size) { if (canvas_tex.is_valid()) { Texture*texture=texture_owner.get(p_texture); return texture; @@ -7831,14 +7907,16 @@ RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_tex return NULL; } - + rebind_texpixel_size=false; if (p_texture.is_valid()) { + Texture*texture=texture_owner.get(p_texture); if (!texture) { canvas_tex=RID(); glBindTexture(GL_TEXTURE_2D,white_tex); + return NULL; } @@ -7847,6 +7925,9 @@ RasterizerGLES2::Texture* RasterizerGLES2::_bind_canvas_texture(const RID& p_tex glBindTexture(GL_TEXTURE_2D,texture->tex_id); canvas_tex=p_texture; + if (uses_texpixel_size) { + canvas_shader.set_uniform(CanvasShaderGLES2::TEXPIXEL_SIZE,Size2(1.0/texture->width,1.0/texture->height)); + } return texture; @@ -8217,6 +8298,327 @@ void RasterizerGLES2::canvas_set_transform(const Matrix32& p_transform) { //canvas_transform = Variant(p_transform); } + +void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { + + + CanvasItem *current_clip=NULL; + + canvas_opacity=1.0; + 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(); + } + + 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; + } + } + + 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; + } + //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()); + Variant &v=F?F->get():E->get().default_value; + if (v.get_type()==Variant::_RID || v.get_type()==Variant::OBJECT) { + int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. + + glActiveTexture(GL_TEXTURE0+tex_id); + RID tex = v; + Texture *t=texture_owner.get(tex); + if (!t) + glBindTexture(GL_TEXTURE_2D,white_tex); + else + glBindTexture(t->target,t->tex_id); + + glUniform1i(loc,tex_id); + tex_id++; + + } else { + canvas_shader.set_custom_uniform(idx,v); + } + + idx++; + } + + + 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,tex_id); + glActiveTexture(GL_TEXTURE0+tex_id); + 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; + } + tex_id++; + + } + + if (tex_id>1) { + 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 { + 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; + } + + 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++) { + + CanvasItem::Command *c=commands[i]; + + switch(c->type) { + case CanvasItem::Command::TYPE_LINE: { + + CanvasItem::CommandLine* line = static_cast<CanvasItem::CommandLine*>(c); + canvas_draw_line(line->from,line->to,line->color,line->width); + } break; + case CanvasItem::Command::TYPE_RECT: { + + CanvasItem::CommandRect* rect = static_cast<CanvasItem::CommandRect*>(c); +// canvas_draw_rect(rect->rect,rect->region,rect->source,rect->flags&CanvasItem::CommandRect::FLAG_TILE,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H,rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V,rect->texture,rect->modulate); +#if 0 + int flags=0; + + if (rect->flags&CanvasItem::CommandRect::FLAG_REGION) { + flags|=Rasterizer::CANVAS_RECT_REGION; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_TILE) { + flags|=Rasterizer::CANVAS_RECT_TILE; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_H) { + + flags|=Rasterizer::CANVAS_RECT_FLIP_H; + } + if (rect->flags&CanvasItem::CommandRect::FLAG_FLIP_V) { + + flags|=Rasterizer::CANVAS_RECT_FLIP_V; + } +#else + + int flags=rect->flags; +#endif + 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); + canvas_draw_style_box(style->rect,style->texture,style->margin,style->draw_center,style->color); + + } break; + case CanvasItem::Command::TYPE_PRIMITIVE: { + + 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: { + + 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); + + } break; + + case CanvasItem::Command::TYPE_POLYGON_PTR: { + + 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; + case CanvasItem::Command::TYPE_CIRCLE: { + + CanvasItem::CommandCircle* circle = static_cast<CanvasItem::CommandCircle*>(c); + static const int numpoints=32; + Vector2 points[numpoints+1]; + points[numpoints]=circle->pos; + int indices[numpoints*3]; + + for(int i=0;i<numpoints;i++) { + + points[i]=circle->pos+Vector2( Math::sin(i*Math_PI*2.0/numpoints),Math::cos(i*Math_PI*2.0/numpoints) )*circle->radius; + indices[i*3+0]=i; + indices[i*3+1]=(i+1)%numpoints; + indices[i*3+2]=numpoints; + } + canvas_draw_polygon(numpoints*3,indices,points,NULL,&circle->color,RID(),true); + //canvas_draw_circle(circle->indices.size(),circle->indices.ptr(),circle->points.ptr(),circle->uvs.ptr(),circle->colors.ptr(),circle->texture,circle->colors.size()==1); + } break; + case CanvasItem::Command::TYPE_TRANSFORM: { + + CanvasItem::CommandTransform* transform = static_cast<CanvasItem::CommandTransform*>(c); + canvas_set_transform(transform->xform); + } break; + case CanvasItem::Command::TYPE_BLEND_MODE: { + + CanvasItem::CommandBlendMode* bm = static_cast<CanvasItem::CommandBlendMode*>(c); + canvas_set_blend_mode(bm->blend_mode); + + } break; + case CanvasItem::Command::TYPE_CLIP_IGNORE: { + + CanvasItem::CommandClipIgnore* ci = static_cast<CanvasItem::CommandClipIgnore*>(c); + if (current_clip) { + + if (ci->ignore!=reclip) { + if (ci->ignore) { + + glDisable(GL_SCISSOR_TEST); + reclip=true; + } else { + + 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); + reclip=false; + } + } + } + + + + } break; + } + } + + + if (reclip) { + + 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); + } + + + + p_item_list=p_item_list->next; + } + + if (current_clip) { + glDisable(GL_SCISSOR_TEST); + } + +} + /* ENVIRONMENT */ RID RasterizerGLES2::environment_create() { diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index dc596f9f6c..0f77d18dee 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -191,6 +191,8 @@ class RasterizerGLES2 : public Rasterizer { bool writes_vertex; bool uses_discard; bool uses_time; + bool uses_normal; + bool uses_texpixel_size; Map<StringName,ShaderLanguage::Uniform> uniforms; StringName first_texture; @@ -214,6 +216,7 @@ class RasterizerGLES2 : public Rasterizer { writes_vertex=false; uses_discard=false; uses_time=false; + uses_normal=false; } @@ -241,8 +244,9 @@ class RasterizerGLES2 : public Rasterizer { struct UniformData { + bool inuse; bool istexture; - Variant value; + Variant value; int index; }; @@ -1168,6 +1172,13 @@ class RasterizerGLES2 : public Rasterizer { GLuint white_tex; RID canvas_tex; float canvas_opacity; + bool uses_texpixel_size; + bool rebind_texpixel_size; + Transform canvas_transform; + RID canvas_last_shader; + bool canvas_texscreen_used; + + _FORCE_INLINE_ Texture* _bind_canvas_texture(const RID& p_texture); VS::MaterialBlendMode canvas_blend_mode; @@ -1198,7 +1209,7 @@ class RasterizerGLES2 : public Rasterizer { RID overdraw_material; mutable MaterialShaderGLES2 material_shader; - CanvasShaderGLES2 canvas_shader; + mutable CanvasShaderGLES2 canvas_shader; BlurShaderGLES2 blur_shader; CopyShaderGLES2 copy_shader; @@ -1259,6 +1270,8 @@ public: virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; + virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name); + /* COMMON MATERIAL API */ virtual RID material_create(); @@ -1535,6 +1548,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); + /* ENVIRONMENT */ diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 50b63e1aa0..f1ddcf8009 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -131,6 +131,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a SL::BlockNode *bnode=(SL::BlockNode*)p_node; //variables + code+="{"ENDL; for(Map<StringName,SL::DataType>::Element *E=bnode->variables.front();E;E=E->next()) { code+=_mktab(p_level)+_typestr(E->value())+" "+replace_string(E->key())+";"ENDL; @@ -141,10 +142,12 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a code+=_mktab(p_level)+dump_node_code(bnode->statements[i],p_level)+";"ENDL; } + code+="}"ENDL; } break; case SL::Node::TYPE_VARIABLE: { SL::VariableNode *vnode=(SL::VariableNode*)p_node; + if (type==ShaderLanguage::SHADER_MATERIAL_VERTEX) { if (vnode->name==vname_vertex && p_assign_left) { @@ -171,6 +174,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } + + + if (type==ShaderLanguage::SHADER_MATERIAL_FRAGMENT) { if (vnode->name==vname_discard) { @@ -212,6 +218,47 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } } + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_VERTEX) { + + if (vnode->name==vname_var1_interp) { + flags->use_var1_interp=true; + } + if (vnode->name==vname_var2_interp) { + flags->use_var2_interp=true; + } + + } + + + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_FRAGMENT) { + + + if (vnode->name==vname_texpixel_size) { + uses_texpixel_size=true; + } + if (vnode->name==vname_normal) { + uses_normal=true; + } + + if (vnode->name==vname_screen_uv) { + uses_screen_uv=true; + } + + if (vnode->name==vname_var1_interp) { + flags->use_var1_interp=true; + } + if (vnode->name==vname_var2_interp) { + flags->use_var2_interp=true; + } + } + + if (type==ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT) { + + if (vnode->name==vname_light) { + uses_light=true; + } + + } if (vnode->name==vname_time) { uses_time=true; @@ -357,7 +404,7 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a } else if (callfunc=="texscreen") { //create the call to sample the screen, and clamp it uses_texscreen=true; - code="(texture2D( texscreen_tex, min(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_mult))).rgb"; + code="(texture2D( texscreen_tex, clamp(("+dump_node_code(onode->arguments[1],p_level)+").xy*texscreen_screen_mult,texscreen_screen_clamp.xy,texscreen_screen_clamp.zw))).rgb"; //code="(texture2D( screen_texture, ("+dump_node_code(onode->arguments[1],p_level)+").xy).rgb"; break; } else if (callfunc=="texpos") { @@ -550,6 +597,8 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT uses_light=false; uses_time=false; uses_normalmap=false; + uses_normal=false; + uses_texpixel_size=false; vertex_code_writes_vertex=false; uniforms=r_uniforms; flags=&r_flags; @@ -560,6 +609,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.use_var1_interp=false; r_flags.use_var2_interp=false; r_flags.uses_normalmap=false; + r_flags.uses_normal=false; String error; int errline,errcol; @@ -582,6 +632,8 @@ 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_texpixel_size=uses_texpixel_size; r_code_line=code; r_globals_line=global_code; @@ -638,6 +690,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { replace_table["cross" ]="cross"; replace_table["normalize"]= "normalize"; replace_table["reflect"]= "reflect"; + replace_table["refract"]= "refract"; replace_table["tex"]= "tex"; replace_table["texa"]= "texa"; replace_table["tex2"]= "tex2"; @@ -676,6 +729,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { //mode_replace_table[1]["POSITION"]="IN_POSITION"; mode_replace_table[1]["NORMAL"]="normal"; mode_replace_table[1]["TANGENT"]="tangent"; + mode_replace_table[1]["POSITION"]="gl_Position"; mode_replace_table[1]["BINORMAL"]="binormal"; mode_replace_table[1]["NORMALMAP"]="normalmap"; mode_replace_table[1]["NORMALMAP_DEPTH"]="normaldepth"; @@ -718,6 +772,42 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[2]["POINT_COORD"]="gl_PointCoord"; mode_replace_table[2]["TIME"]="time"; + mode_replace_table[3]["SRC_VERTEX"]="src_vtx"; + mode_replace_table[3]["VERTEX"]="outvec.xy"; + mode_replace_table[3]["UV"]="uv_interp"; + mode_replace_table[3]["COLOR"]="color_interp"; + mode_replace_table[3]["VAR1"]="var1_interp"; + mode_replace_table[3]["VAR2"]="var2_interp"; + mode_replace_table[3]["POINT_SIZE"]="gl_PointSize"; + mode_replace_table[3]["WORLD_MATRIX"]="modelview_matrix"; + mode_replace_table[3]["PROJECTION_MATRIX"]="projection_matrix"; + mode_replace_table[3]["EXTRA_MATRIX"]="extra_matrix"; + mode_replace_table[3]["TIME"]="time"; + + mode_replace_table[4]["POSITION"]="gl_Position"; + mode_replace_table[4]["NORMAL"]="normal"; + mode_replace_table[4]["UV"]="uv_interp"; + mode_replace_table[4]["SRC_COLOR"]="color_interp"; + mode_replace_table[4]["COLOR"]="color"; + mode_replace_table[4]["TEXTURE"]="texture"; + mode_replace_table[4]["TEXTURE_PIXEL_SIZE"]="texpixel_size"; + mode_replace_table[4]["VAR1"]="var1_interp"; + mode_replace_table[4]["VAR2"]="var2_interp"; + mode_replace_table[4]["SCREEN_UV"]="screen_uv"; + mode_replace_table[4]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[4]["TIME"]="time"; + + mode_replace_table[5]["SRC_COLOR"]="color"; + mode_replace_table[5]["COLOR"]="color"; + mode_replace_table[5]["NORMAL"]="normal"; + mode_replace_table[5]["LIGHT_DIR"]="light_dir"; + mode_replace_table[5]["LIGHT_DISTANCE"]="light_distance"; + mode_replace_table[5]["LIGHT"]="light"; + mode_replace_table[5]["POINT_COORD"]="gl_PointCoord"; + mode_replace_table[5]["TIME"]="time"; + + + //mode_replace_table[2]["SCREEN_POS"]="SCREEN_POS"; //mode_replace_table[2]["SCREEN_TEXEL_SIZE"]="SCREEN_TEXEL_SIZE"; @@ -738,5 +828,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_light="LIGHT"; vname_time="TIME"; vname_normalmap="NORMALMAP"; + vname_normal="NORMAL"; + vname_texpixel_size="TEXTURE_PIXEL_SIZE"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index 5012414c8b..a10fa6dfe0 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -51,6 +51,8 @@ private: bool uses_time; bool uses_screen_uv; bool uses_normalmap; + bool uses_normal; + bool uses_texpixel_size; bool vertex_code_writes_vertex; Flags *flags; @@ -68,6 +70,8 @@ private: StringName vname_light; StringName vname_time; StringName vname_normalmap; + StringName vname_normal; + StringName vname_texpixel_size; Map<StringName,ShaderLanguage::Uniform> *uniforms; @@ -79,7 +83,7 @@ private: String replace_string(const StringName& p_string); - Map<StringName,StringName> mode_replace_table[3]; + Map<StringName,StringName> mode_replace_table[9]; Map<StringName,StringName> replace_table; public: @@ -101,6 +105,8 @@ public: bool use_var2_interp; bool uses_light; bool uses_time; + bool uses_normal; + bool uses_texpixel_size; }; Error compile(const String& p_code, ShaderLanguage::ShaderType p_type, String& r_code_line, String& r_globals_line, Flags& r_flags, Map<StringName,ShaderLanguage::Uniform> *r_uniforms=NULL); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index f36741d586..464cb9e188 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -18,19 +18,56 @@ attribute highp vec2 uv_attrib; // attrib:4 varying vec2 uv_interp; varying vec4 color_interp; +#if defined(USE_TIME) +uniform float time; +#endif + + +#ifdef USE_LIGHTING + +uniform highp mat4 light_matrix; +varying vec4 light_tex_pos; + +#endif + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + //uniform bool snap_pixels; +VERTEX_SHADER_GLOBALS + void main() { color_interp = color_attrib; uv_interp = uv_attrib; highp vec4 outvec = vec4(vertex, 1.0); +{ + vec2 src_vtx=outvec.xy; +VERTEX_SHADER_CODE + +} outvec = extra_matrix * outvec; outvec = modelview_matrix * outvec; #ifdef USE_PIXEL_SNAP - outvec.xy=floor(outvec.xy+0.5); + outvec.xy=floor(outvec.xy+0.5); #endif + + +#ifdef USE_LIGHTING + + light_tex_pos.xy = light_matrix * outvec; + light_tex_pos.zw=outvec.xy - light_matrix[4].xy; //likely wrong + +#endif + + gl_Position = projection_matrix * outvec; } @@ -54,17 +91,112 @@ varying vec4 color_interp; #endif +#if defined(ENABLE_SCREEN_UV) + +uniform vec2 screen_uv_mult; + +#endif + +#if defined(ENABLE_TEXSCREEN) + +uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; +uniform sampler2D texscreen_tex; + +#endif + + +#if defined(ENABLE_VAR1_INTERP) +varying vec4 var1_interp; +#endif + +#if defined(ENABLE_VAR2_INTERP) +varying vec4 var2_interp; +#endif + +#if defined(USE_TIME) +uniform float time; +#endif + + +#ifdef USE_LIGHTING + +uniform sampler2D light_texture; +varying vec4 light_tex_pos; + +#ifdef USE_SHADOWS + +uniform sampler2D shadow_texture; +uniform float shadow_attenuation; + +#endif + +#endif + +#if defined(USE_TEXPIXEL_SIZE) +uniform vec2 texpixel_size; +#endif + + +FRAGMENT_SHADER_GLOBALS + + void main() { vec4 color = color_interp; - +#if defined(NORMAL_USED) + vec3 normal = vec3(0,0,1); +#endif + color *= texture2D( texture, uv_interp ); +#if defined(ENABLE_SCREEN_UV) + vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; +#endif +{ +FRAGMENT_SHADER_CODE +} #ifdef DEBUG_ENCODED_32 highp float enc32 = dot( color,highp vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1) ); color = vec4(vec3(enc32),1.0); #endif +#ifdef USE_LIGHTING + + float att=1.0; + + vec3 light = texture2D(light_texture,light_tex_pos).rgb; +#ifdef USE_SHADOWS + //this might not be that great on mobile? + float light_dist = length(light_texture.zw); + float light_angle = atan2(light_texture.x,light_texture.z) + 1.0 * 0.5; + float shadow_dist = texture2D(shadow_texture,vec2(light_angle,0)); + if (light_dist>shadow_dist) { + light*=shadow_attenuation; + } +//use shadows +#endif + +#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); +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); +#endif + + color.rgb=light; +//light shader code +#endif + +//use lighting +#endif // color.rgb*=color.a; gl_FragColor = color; diff --git a/drivers/gles2/shaders/material.glsl b/drivers/gles2/shaders/material.glsl index 718dd56249..38fb03ab5c 100644 --- a/drivers/gles2/shaders/material.glsl +++ b/drivers/gles2/shaders/material.glsl @@ -779,6 +779,7 @@ uniform highp mat4 camera_inverse_transform; #if defined(ENABLE_TEXSCREEN) uniform vec2 texscreen_screen_mult; +uniform vec4 texscreen_screen_clamp; uniform sampler2D texscreen_tex; #endif |