diff options
Diffstat (limited to 'drivers/gles2/rasterizer_gles2.cpp')
-rw-r--r-- | drivers/gles2/rasterizer_gles2.cpp | 211 |
1 files changed, 202 insertions, 9 deletions
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 59f844904e..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); @@ -1558,6 +1564,7 @@ void RasterizerGLES2::shader_set_default_texture_param(RID p_shader, const Strin 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) @@ -1565,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 */ @@ -4434,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); @@ -4443,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 + } } @@ -4458,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 @@ -4518,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); } @@ -4529,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++; } @@ -4888,7 +4961,7 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ keep=false; else if (old_mparams[E->key()].value.get_type()!=E->value().default_value.get_type()) { //type changed between old and new - /*if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { + /* 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()) @@ -5068,6 +5141,7 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material 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); @@ -7722,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) @@ -7739,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(); } @@ -7821,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; @@ -7829,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; } @@ -7845,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; @@ -8215,12 +8298,13 @@ 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; @@ -8231,6 +8315,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { } memdelete(ci->vp_render); ci->vp_render=NULL; + canvas_last_shader=RID(); } if (current_clip!=ci->final_clip_owner) { @@ -8248,10 +8333,116 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { 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) { @@ -8291,6 +8482,8 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { 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]; |