diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.cpp | 143 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_canvas_gles3.h | 2 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_gles3.cpp | 10 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 899 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 109 | ||||
-rw-r--r-- | drivers/gles3/shader_compiler_gles3.cpp | 528 | ||||
-rw-r--r-- | drivers/gles3/shader_compiler_gles3.h | 67 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.cpp | 83 | ||||
-rw-r--r-- | drivers/gles3/shader_gles3.h | 27 | ||||
-rw-r--r-- | drivers/gles3/shaders/canvas.glsl | 72 | ||||
-rw-r--r-- | drivers/unix/os_unix.cpp | 4 |
11 files changed, 1828 insertions, 116 deletions
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index a1e755cb4a..b2228a6cfa 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -138,6 +138,7 @@ void RasterizerCanvasGLES3::canvas_begin(){ state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD,false); + state.canvas_shader.set_custom_shader(0); state.canvas_shader.bind(); state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,Color(1,1,1,1)); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Matrix32()); @@ -520,6 +521,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr //err.. } + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + glVertexAttrib4f(1,rect->rect.pos.x,rect->rect.pos.y,rect->rect.size.x,rect->rect.size.y); glVertexAttrib4f(2,src_rect.pos.x,src_rect.pos.y,src_rect.size.x,src_rect.size.y); @@ -567,6 +570,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + #define DSTRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(1,m_x,m_y,m_w,m_h) #define SRCRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(2,(m_x)*texpixel_size.x,(m_y)*texpixel_size.y,(m_w)*texpixel_size.x,(m_h)*texpixel_size.y) @@ -634,8 +639,13 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr ERR_CONTINUE( primitive->points.size()<1); - _bind_canvas_texture(primitive->texture); + RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(primitive->texture); + + if (texture ) { + Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + } if (primitive->colors.size()==1 && primitive->points.size()>1) { Color c = primitive->colors[0]; @@ -652,6 +662,14 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr Item::CommandPolygon* polygon = static_cast<Item::CommandPolygon*>(c); _set_texture_rect_mode(false); + + RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(polygon->texture); + + if (texture ) { + Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); + + } _draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); } break; @@ -800,10 +818,14 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + int last_blend_mode=-1; + RID canvas_last_material; bool prev_distance_field=false; + + while(p_item_list) { Item *ci=p_item_list; @@ -878,53 +900,71 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const RID material = material_owner->material; if (material!=canvas_last_material || rebind_shader) { -#if 0 - Shader *shader = NULL; - if (material && material->shader.is_valid()) { - shader = shader_owner.get(material->shader); - if (shader && !shader->valid) { - shader=NULL; + + RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.getornull(material); + RasterizerStorageGLES3::Shader *shader_ptr = NULL; + + if (material_ptr) { + + shader_ptr = material_ptr->shader; + + if (shader_ptr && shader_ptr->mode!=VS::SHADER_CANVAS_ITEM) { + shader_ptr=NULL; //do not use non canvasitem shader } } - shader_cache=shader; - if (shader) { - canvas_shader.set_custom_shader(shader->custom_code_id); - _canvas_item_setup_shader_params(material,shader); - } else { - shader_cache=NULL; - canvas_shader.set_custom_shader(0); - canvas_shader.bind(); - uses_texpixel_size=false; + if (shader_ptr && shader_ptr!=shader_cache) { + + state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); + state.canvas_shader.bind(); + + if (material_ptr->ubo_id) { + glBindBufferBase(GL_UNIFORM_BUFFER,2,material_ptr->ubo_id); + } + + int tc = material_ptr->textures.size(); + RID* textures = material_ptr->textures.ptr(); + + for(int i=0;i<tc;i++) { + + glActiveTexture(GL_TEXTURE1+i); + + RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull( textures[i] ); + if (!t) { + //check hints + glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); + continue; + } + + glBindTexture(t->target,t->tex_id); + } + + + } else if (!shader_ptr) { + state.canvas_shader.set_custom_shader(0); + state.canvas_shader.bind(); } + shader_cache=shader_ptr; - canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,canvas_transform); - if (canvas_use_modulate) - reset_modulate=true; canvas_last_material=material; rebind_shader=false; -#endif - } - if (material.is_valid() && shader_cache) { -#if 0 - _canvas_item_setup_shader_uniforms(material,shader_cache); -#endif } - bool unshaded = false; //(material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX; + int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; + bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode==RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode!=RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX); bool reclip=false; -#if 0 - if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) { - switch(ci->blend_mode) { + if (last_blend_mode!=blend_mode) { + + switch(blend_mode) { - case VS::MATERIAL_BLEND_MODE_MIX: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); - if (current_rt && current_rt_transparent) { + if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } else { @@ -932,33 +972,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const } } break; - case VS::MATERIAL_BLEND_MODE_ADD: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA,GL_ONE); } break; - case VS::MATERIAL_BLEND_MODE_SUB: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: { glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_SRC_ALPHA,GL_ONE); } break; - case VS::MATERIAL_BLEND_MODE_MUL: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_DST_COLOR,GL_ZERO); } break; - case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { + case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); } break; } - canvas_blend_mode=ci->blend_mode; + last_blend_mode=blend_mode; } -#endif - -// canvas_shader.set_uniform(CanvasShaderGLES3::CANVAS_MODULATE,unshaded ? Color(1,1,1,1) : p_modulate); state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( ci->final_modulate.r * p_modulate.r, @@ -974,10 +1011,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,state.extra_matrix); - if (unshaded || (state.canvas_item_modulate.a>0.001 && (!material.is_valid() /*|| material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT*/) && !ci->light_masked )) + if (unshaded || (state.canvas_item_modulate.a>0.001 && (!shader_cache || shader_cache->canvas_item.light_mode!=RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked )) _canvas_item_render_commands(ci,current_clip,reclip); - if (/*canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX &&*/ p_light && !unshaded) { + if ((blend_mode==RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) { Light *light = p_light; bool light_used=false; @@ -1046,12 +1083,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const bool light_rebind = state.canvas_shader.bind(); if (light_rebind) { -#if 0 - if (material && shader_cache) { - _canvas_item_setup_shader_params(material,shader_cache); - _canvas_item_setup_shader_uniforms(material,shader_cache); - } -#endif + state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32()); @@ -1100,15 +1132,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9,false); state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false); - state.canvas_shader.bind(); -#if 0 - if (material && shader_cache) { - _canvas_item_setup_shader_params(material,shader_cache); - _canvas_item_setup_shader_uniforms(material,shader_cache); - } -#endif + last_blend_mode=-1; + + /* + //this is set again, so it should not be needed anyway? state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( ci->final_modulate.r * p_modulate.r, ci->final_modulate.g * p_modulate.g, @@ -1120,7 +1149,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32()); state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate); - glBlendEquation(GL_FUNC_ADD); if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { @@ -1130,6 +1158,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const } //@TODO RESET canvas_blend_mode + */ } @@ -1380,6 +1409,9 @@ void RasterizerCanvasGLES3::reset_canvas() { state.vp=canvas_transform; store_transform(canvas_transform,state.canvas_item_ubo_data.projection_matrix); + for(int i=0;i<4;i++) { + state.canvas_item_ubo_data.time[i]=storage->frame.time[i]; + } glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data); @@ -1442,6 +1474,7 @@ void RasterizerCanvasGLES3::initialize() { glBindBuffer(GL_UNIFORM_BUFFER, 0); state.canvas_shader.init(); + state.canvas_shader.set_base_material_tex_index(1); state.canvas_shadow_shader.init(); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS,storage->config.use_rgba_2d_shadows); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 1f72a8dbcf..8f34f07d06 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -5,12 +5,14 @@ #include "rasterizer_storage_gles3.h" #include "shaders/canvas_shadow.glsl.h" + class RasterizerCanvasGLES3 : public RasterizerCanvas { public: struct CanvasItemUBO { float projection_matrix[16]; + float time[4]; }; diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 27b0690645..eaa9825605 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -115,8 +115,17 @@ void RasterizerGLES3::initialize() { void RasterizerGLES3::begin_frame(){ + double time_total = double(OS::get_singleton()->get_ticks_usec())/1000000.0; + storage->frame.time[0]=time_total; + storage->frame.time[1]=Math::fmod(time_total,3600); + storage->frame.time[2]=Math::fmod(time_total,900); + storage->frame.time[3]=Math::fmod(time_total,60); + + storage->update_dirty_shaders(); + storage->update_dirty_materials(); } + void RasterizerGLES3::set_current_render_target(RID p_render_target){ if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { @@ -257,6 +266,7 @@ RasterizerGLES3::RasterizerGLES3() storage = memnew( RasterizerStorageGLES3 ); canvas = memnew( RasterizerCanvasGLES3 ); canvas->storage=storage; + storage->canvas=canvas; } diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index b4d65080a4..74b7d72652 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1,4 +1,5 @@ #include "rasterizer_storage_gles3.h" +#include "rasterizer_canvas_gles3.h" #include "globals.h" /* TEXTURE API */ @@ -1000,65 +1001,906 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable RID RasterizerStorageGLES3::shader_create(VS::ShaderMode p_mode){ - return RID(); + Shader *shader = memnew( Shader ); + shader->mode=p_mode; + RID rid = shader_owner.make_rid(shader); + shader_set_mode(rid,p_mode); + _shader_make_dirty(shader); + shader->self=rid; + + return rid; +} + +void RasterizerStorageGLES3::_shader_make_dirty(Shader* p_shader) { + + if (p_shader->dirty_list.in_list()) + return; + + _shader_dirty_list.add(&p_shader->dirty_list); } void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode){ + ERR_FAIL_INDEX(p_mode,VS::SHADER_MAX); + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + + if (shader->custom_code_id && p_mode==shader->mode) + return; + + + if (shader->custom_code_id) { + + shader->shader->free_custom_shader(shader->custom_code_id); + shader->custom_code_id=0; + } + + shader->mode=p_mode; + + ShaderGLES3* shaders[VS::SHADER_MAX]={ + &canvas->state.canvas_shader, + &canvas->state.canvas_shader, + &canvas->state.canvas_shader, + + }; + + shader->shader=shaders[p_mode]; + + shader->custom_code_id = shader->shader->create_custom_shader(); + + _shader_make_dirty(shader); } VS::ShaderMode RasterizerStorageGLES3::shader_get_mode(RID p_shader) const { - return VS::SHADER_SPATIAL; + const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,VS::SHADER_MAX); + + return shader->mode; } void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String& p_code){ + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + shader->code=p_code; + _shader_make_dirty(shader); } String RasterizerStorageGLES3::shader_get_code(RID p_shader) const{ - return String(); + const Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND_V(!shader,String()); + + + return shader->code; } + +void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { + + + _shader_dirty_list.remove( &p_shader->dirty_list ); + + p_shader->valid=false; + + p_shader->uniforms.clear(); + + ShaderCompilerGLES3::GeneratedCode gen_code; + ShaderCompilerGLES3::IdentifierActions *actions=NULL; + + + + switch(p_shader->mode) { + case VS::SHADER_CANVAS_ITEM: { + + p_shader->canvas_item.light_mode=Shader::CanvasItem::LIGHT_MODE_NORMAL; + p_shader->canvas_item.blend_mode=Shader::CanvasItem::BLEND_MODE_MIX; + + shaders.actions_canvas.render_mode_values["blend_add"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_ADD); + shaders.actions_canvas.render_mode_values["blend_mix"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MIX); + shaders.actions_canvas.render_mode_values["blend_sub"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_SUB); + shaders.actions_canvas.render_mode_values["blend_mul"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MUL); + shaders.actions_canvas.render_mode_values["blend_premul_alpha"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_PMALPHA); + + shaders.actions_canvas.render_mode_values["unshaded"]=Pair<int*,int>(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_UNSHADED); + shaders.actions_canvas.render_mode_values["light_only"]=Pair<int*,int>(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); + + actions=&shaders.actions_canvas; + actions->uniforms=&p_shader->uniforms; + + } break; + } + + + Error err = shaders.compiler.compile(p_shader->mode,p_shader->code,actions,p_shader->path,gen_code); + + ERR_FAIL_COND(err!=OK); + + p_shader->shader->set_custom_shader_code(p_shader->custom_code_id,gen_code.vertex,gen_code.vertex_global,gen_code.fragment,gen_code.light,gen_code.fragment_global,gen_code.uniforms,gen_code.texture_uniforms,gen_code.defines); + + p_shader->ubo_size=gen_code.uniform_total_size; + p_shader->ubo_offsets=gen_code.uniform_offsets; + p_shader->texture_count=gen_code.texture_uniforms.size(); + + //all materials using this shader will have to be invalidated, unfortunately + + for (SelfList<Material>* E = p_shader->materials.first();E;E=E->next() ) { + + _material_make_dirty(E->self()); + } + + p_shader->valid=true; + p_shader->version++; + +} + +void RasterizerStorageGLES3::update_dirty_shaders() { + + while( _shader_dirty_list.first() ) { + _update_shader(_shader_dirty_list.first()->self() ); + } +} + void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const{ + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + + + if (shader->dirty_list.in_list()) + _update_shader(shader); // ok should be not anymore dirty + + + Map<int,StringName> order; + + for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { + + + order[E->get().order]=E->key(); + } + + + for(Map<int,StringName>::Element *E=order.front();E;E=E->next()) { + + PropertyInfo pi; + ShaderLanguage::ShaderNode::Uniform &u=shader->uniforms[E->get()]; + pi.name=E->get(); + switch(u.type) { + case ShaderLanguage::TYPE_VOID: pi.type=Variant::NIL; break; + case ShaderLanguage::TYPE_BOOL: pi.type=Variant::BOOL; break; + case ShaderLanguage::TYPE_BVEC2: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y"; break; + case ShaderLanguage::TYPE_BVEC3: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z"; break; + case ShaderLanguage::TYPE_BVEC4: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z,w"; break; + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_INT: { + pi.type=Variant::INT; + if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { + pi.hint=PROPERTY_HINT_RANGE; + pi.hint_string=rtos(u.hint_range[0])+","+rtos(u.hint_range[1]); + } + + } break; + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_UVEC4: { + + pi.type=Variant::INT_ARRAY; + } break; + case ShaderLanguage::TYPE_FLOAT: { + pi.type=Variant::REAL; + if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { + pi.hint=PROPERTY_HINT_RANGE; + pi.hint_string=rtos(u.hint_range[0])+","+rtos(u.hint_range[1])+","+rtos(u.hint_range[2]); + } + + } break; + case ShaderLanguage::TYPE_VEC2: pi.type=Variant::VECTOR2; break; + case ShaderLanguage::TYPE_VEC3: pi.type=Variant::VECTOR3; break; + case ShaderLanguage::TYPE_VEC4: { + if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + pi.type=Variant::COLOR; + } else { + pi.type=Variant::PLANE; + } + } break; + case ShaderLanguage::TYPE_MAT2: pi.type=Variant::MATRIX32; break; + case ShaderLanguage::TYPE_MAT3: pi.type=Variant::MATRIX3; break; + case ShaderLanguage::TYPE_MAT4: pi.type=Variant::TRANSFORM; break; + case ShaderLanguage::TYPE_SAMPLER2D: + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER2D: { + + pi.type=Variant::OBJECT; + pi.hint=PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string="Texture"; + } break; + case ShaderLanguage::TYPE_SAMPLERCUBE: { + + pi.type=Variant::OBJECT; + pi.hint=PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string="CubeMap"; + } break; + }; + + p_param_list->push_back(pi); + + } } void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture){ + Shader *shader=shader_owner.get(p_shader); + ERR_FAIL_COND(!shader); + 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 RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ - return RID(); + 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) + return RID(); + return E->get(); } /* COMMON MATERIAL API */ +void RasterizerStorageGLES3::_material_make_dirty(Material* p_material) const { + + if (p_material->dirty_list.in_list()) + return; + + _material_dirty_list.add(&p_material->dirty_list); +} + RID RasterizerStorageGLES3::material_create(){ - return RID(); + Material *material = memnew( Material ); + + return material_owner.make_rid(material); } -void RasterizerStorageGLES3::material_set_shader(RID p_shader_material, RID p_shader){ +void RasterizerStorageGLES3::material_set_shader(RID p_material, RID p_shader){ + + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND(!material); + + Shader *shader=shader_owner.getornull(p_shader); + + if (material->shader) { + //if shader, remove from previous shader material list + material->shader->materials.remove( &material->list ); + } + material->shader=shader; + + if (shader) { + shader->materials.add(&material->list); + } + _material_make_dirty(material); } -RID RasterizerStorageGLES3::material_get_shader(RID p_shader_material) const{ + +RID RasterizerStorageGLES3::material_get_shader(RID p_material) const{ + + const Material *material = material_owner.get( p_material ); + ERR_FAIL_COND_V(!material,RID()); + + if (material->shader) + return material->shader->self; return RID(); } void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value){ + Material *material = material_owner.get( p_material ); + ERR_FAIL_COND(!material); + + if (p_value.get_type()==Variant::NIL) + material->params.erase(p_param); + else + material->params[p_param]=p_value; + + _material_make_dirty(material); } Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName& p_param) const{ + const Material *material = material_owner.get( p_material ); + ERR_FAIL_COND_V(!material,RID()); + + if (material->params.has(p_param)) + return material->params[p_param]; + return Variant(); } +_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data) { + switch(type) { + case ShaderLanguage::TYPE_BOOL: { + + bool v = value; + + GLuint *gui = (GLuint*)data; + *gui = v ? GL_TRUE : GL_FALSE; + } break; + case ShaderLanguage::TYPE_BVEC2: { + + int v = value; + GLuint *gui = (GLuint*)data; + gui[0]=v&1 ? GL_TRUE : GL_FALSE; + gui[1]=v&2 ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_BVEC3: { + + int v = value; + GLuint *gui = (GLuint*)data; + gui[0]=v&1 ? GL_TRUE : GL_FALSE; + gui[1]=v&2 ? GL_TRUE : GL_FALSE; + gui[2]=v&4 ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_BVEC4: { + + int v = value; + GLuint *gui = (GLuint*)data; + gui[0]=v&1 ? GL_TRUE : GL_FALSE; + gui[1]=v&2 ? GL_TRUE : GL_FALSE; + gui[2]=v&4 ? GL_TRUE : GL_FALSE; + gui[3]=v&8 ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_INT: { + + int v = value; + GLint *gui = (GLint*)data; + gui[0]=v; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + + DVector<int> iv = value; + int s = iv.size(); + GLint *gui = (GLint*)data; + + DVector<int>::Read r = iv.read(); + + for(int i=0;i<2;i++) { + if (i<s) + gui[i]=r[i]; + else + gui[i]=0; + + } + + } break; + case ShaderLanguage::TYPE_IVEC3: { + + DVector<int> iv = value; + int s = iv.size(); + GLint *gui = (GLint*)data; + + DVector<int>::Read r = iv.read(); + + for(int i=0;i<3;i++) { + if (i<s) + gui[i]=r[i]; + else + gui[i]=0; + + } + } break; + case ShaderLanguage::TYPE_IVEC4: { + + + DVector<int> iv = value; + int s = iv.size(); + GLint *gui = (GLint*)data; + + DVector<int>::Read r = iv.read(); + + for(int i=0;i<4;i++) { + if (i<s) + gui[i]=r[i]; + else + gui[i]=0; + + } + } break; + case ShaderLanguage::TYPE_UINT: { + + int v = value; + GLuint *gui = (GLuint*)data; + gui[0]=v; + + } break; + case ShaderLanguage::TYPE_UVEC2: { + + DVector<int> iv = value; + int s = iv.size(); + GLuint *gui = (GLuint*)data; + + DVector<int>::Read r = iv.read(); + + for(int i=0;i<2;i++) { + if (i<s) + gui[i]=r[i]; + else + gui[i]=0; + + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + DVector<int> iv = value; + int s = iv.size(); + GLuint *gui = (GLuint*)data; + + DVector<int>::Read r = iv.read(); + + for(int i=0;i<3;i++) { + if (i<s) + gui[i]=r[i]; + else + gui[i]=0; + } + + } break; + case ShaderLanguage::TYPE_UVEC4: { + DVector<int> iv = value; + int s = iv.size(); + GLuint *gui = (GLuint*)data; + + DVector<int>::Read r = iv.read(); + + for(int i=0;i<4;i++) { + if (i<s) + gui[i]=r[i]; + else + gui[i]=0; + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + float v = value; + GLfloat *gui = (GLfloat*)data; + gui[0]=v; + + } break; + case ShaderLanguage::TYPE_VEC2: { + Vector2 v = value; + GLfloat *gui = (GLfloat*)data; + gui[0]=v.x; + gui[1]=v.y; + + } break; + case ShaderLanguage::TYPE_VEC3: { + Vector3 v = value; + GLfloat *gui = (GLfloat*)data; + gui[0]=v.x; + gui[1]=v.y; + gui[2]=v.z; + + } break; + case ShaderLanguage::TYPE_VEC4: { + + GLfloat *gui = (GLfloat*)data; + + if (value.get_type()==Variant::COLOR) { + Color v=value; + + gui[0]=v.r; + gui[1]=v.g; + gui[3]=v.b; + gui[4]=v.a; + } else if (value.get_type()==Variant::RECT2) { + Rect2 v=value; + + gui[0]=v.pos.x; + gui[1]=v.pos.y; + gui[3]=v.size.x; + gui[4]=v.size.y; + } else if (value.get_type()==Variant::QUAT) { + Quat v=value; + + gui[0]=v.x; + gui[1]=v.y; + gui[3]=v.z; + gui[4]=v.w; + } else { + Plane v=value; + + gui[0]=v.normal.x; + gui[1]=v.normal.y; + gui[3]=v.normal.x; + gui[4]=v.d; + + } + } break; + case ShaderLanguage::TYPE_MAT2: { + Matrix32 v = value; + GLfloat *gui = (GLfloat*)data; + + gui[ 0]=v.elements[0][0]; + gui[ 1]=v.elements[0][1]; + gui[ 2]=v.elements[1][0]; + gui[ 3]=v.elements[1][1]; + } break; + case ShaderLanguage::TYPE_MAT3: { + + + Matrix3 v = value; + GLfloat *gui = (GLfloat*)data; + + gui[ 0]=v.elements[0][0]; + gui[ 1]=v.elements[1][0]; + gui[ 2]=v.elements[2][0]; + gui[ 3]=0; + gui[ 4]=v.elements[0][1]; + gui[ 5]=v.elements[1][1]; + gui[ 6]=v.elements[2][1]; + gui[ 7]=0; + gui[ 8]=v.elements[0][2]; + gui[ 9]=v.elements[1][2]; + gui[10]=v.elements[2][2]; + gui[11]=0; + } break; + case ShaderLanguage::TYPE_MAT4: { + + Transform v = value; + GLfloat *gui = (GLfloat*)data; + + gui[ 0]=v.basis.elements[0][0]; + gui[ 1]=v.basis.elements[1][0]; + gui[ 2]=v.basis.elements[2][0]; + gui[ 3]=0; + gui[ 4]=v.basis.elements[0][1]; + gui[ 5]=v.basis.elements[1][1]; + gui[ 6]=v.basis.elements[2][1]; + gui[ 7]=0; + gui[ 8]=v.basis.elements[0][2]; + gui[ 9]=v.basis.elements[1][2]; + gui[10]=v.basis.elements[2][2]; + gui[11]=0; + gui[12]=v.origin.x; + gui[13]=v.origin.y; + gui[14]=v.origin.z; + gui[15]=1; + } break; + default: {} + } + +} + +_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value>& value, uint8_t *data) { + + switch(type) { + case ShaderLanguage::TYPE_BOOL: { + + GLuint *gui = (GLuint*)data; + *gui = value[0].boolean ? GL_TRUE : GL_FALSE; + } break; + case ShaderLanguage::TYPE_BVEC2: { + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; + gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_BVEC3: { + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; + gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; + gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_BVEC4: { + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; + gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; + gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE; + gui[3]=value[3].boolean ? GL_TRUE : GL_FALSE; + + } break; + case ShaderLanguage::TYPE_INT: { + + GLint *gui = (GLint*)data; + gui[0]=value[0].sint; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].sint; + + } + + } break; + case ShaderLanguage::TYPE_IVEC3: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<3;i++) { + gui[i]=value[i].sint; + + } + + } break; + case ShaderLanguage::TYPE_IVEC4: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<4;i++) { + gui[i]=value[i].sint; + + } + + } break; + case ShaderLanguage::TYPE_UINT: { + + + GLuint *gui = (GLuint*)data; + gui[0]=value[0].uint; + + } break; + case ShaderLanguage::TYPE_UVEC2: { + + GLint *gui = (GLint*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].uint; + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + GLint *gui = (GLint*)data; + + for(int i=0;i<3;i++) { + gui[i]=value[i].uint; + } + + } break; + case ShaderLanguage::TYPE_UVEC4: { + GLint *gui = (GLint*)data; + + for(int i=0;i<4;i++) { + gui[i]=value[i].uint; + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + + GLfloat *gui = (GLfloat*)data; + gui[0]=value[0].real; + + } break; + case ShaderLanguage::TYPE_VEC2: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC3: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<3;i++) { + gui[i]=value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC4: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<4;i++) { + gui[i]=value[i].real; + } + } break; + case ShaderLanguage::TYPE_MAT2: { + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<2;i++) { + gui[i]=value[i].real; + } + } break; + case ShaderLanguage::TYPE_MAT3: { + + + + GLfloat *gui = (GLfloat*)data; + + gui[ 0]=value[0].real; + gui[ 1]=value[1].real; + gui[ 2]=value[2].real; + gui[ 3]=0; + gui[ 4]=value[3].real; + gui[ 5]=value[4].real; + gui[ 6]=value[5].real; + gui[ 7]=0; + gui[ 8]=value[6].real; + gui[ 9]=value[7].real; + gui[10]=value[8].real; + gui[11]=0; + } break; + case ShaderLanguage::TYPE_MAT4: { + + GLfloat *gui = (GLfloat*)data; + + for(int i=0;i<16;i++) { + gui[i]=value[i].real; + } + } break; + default: {} + } + +} + + +_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) { + + switch(type) { + + case ShaderLanguage::TYPE_BOOL: + case ShaderLanguage::TYPE_INT: + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_FLOAT: { + zeromem(data,4); + } break; + case ShaderLanguage::TYPE_BVEC2: + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_VEC2: { + zeromem(data,8); + } break; + case ShaderLanguage::TYPE_BVEC3: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_VEC3: + case ShaderLanguage::TYPE_BVEC4: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC4: + case ShaderLanguage::TYPE_VEC4: + case ShaderLanguage::TYPE_MAT2:{ + + zeromem(data,16); + } break; + case ShaderLanguage::TYPE_MAT3:{ + + zeromem(data,48); + } break; + case ShaderLanguage::TYPE_MAT4:{ + zeromem(data,64); + } break; + + default: {} + } + +} + +void RasterizerStorageGLES3::_update_material(Material* material) { + + if (material->dirty_list.in_list()) + _material_dirty_list.remove( &material->dirty_list ); + + //clear ubo if it needs to be cleared + if (material->ubo_size) { + + if (!material->shader || material->shader->ubo_size!=material->ubo_size) { + //by by ubo + glDeleteBuffers(1,&material->ubo_id); + material->ubo_id=0; + material->ubo_size=0; + } + } + + //create ubo if it needs to be created + if (material->ubo_size==0 && material->shader && material->shader->ubo_size) { + + glGenBuffers(1, &material->ubo_id); + glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id); + glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + material->ubo_size=material->shader->ubo_size; + } + + //fill up the UBO if it needs to be filled + if (material->shader && material->ubo_size) { + uint8_t* local_ubo = (uint8_t*)alloca(material->ubo_size); + + for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=material->shader->uniforms.front();E;E=E->next()) { + + if (E->get().order<0) + continue; // texture, does not go here + + //regular uniform + uint8_t *data = &local_ubo[ material->shader->ubo_offsets[E->get().order] ]; + + Map<StringName,Variant>::Element *V = material->params.find(E->key()); + + if (V) { + //user provided + _fill_std140_variant_ubo_value(E->get().type,V->get(),data); + } else if (E->get().default_value.size()){ + //default value + _fill_std140_ubo_value(E->get().type,E->get().default_value,data); + //value=E->get().default_value; + } else { + //zero because it was not provided + _fill_std140_ubo_empty(E->get().type,data); + } + + + } + + glBindBuffer(GL_UNIFORM_BUFFER,material->ubo_id); + glBufferSubData(GL_UNIFORM_BUFFER, 0, material->ubo_size, local_ubo); + glBindBuffer(GL_UNIFORM_BUFFER, 0); + } + + //set up the texture array, for easy access when it needs to be drawn + if (material->shader && material->shader->texture_count) { + + material->textures.resize(material->shader->texture_count); + + for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=material->shader->uniforms.front();E;E=E->next()) { + + if (E->get().texture_order<0) + continue; // not a texture, does not go here + + RID texture; + + Map<StringName,Variant>::Element *V = material->params.find(E->key()); + if (V) { + texture=V->get(); + } + + if (!texture.is_valid()) { + Map<StringName,RID>::Element *W = material->shader->default_textures.find(E->key()); + if (W) { + texture=W->get(); + } + } + + material->textures[ E->get().texture_order ]=texture; + + + } + + + } else { + material->textures.clear(); + } + +} + +void RasterizerStorageGLES3::update_dirty_materials() { + + while( _material_dirty_list.first() ) { + + Material *material = _material_dirty_list.first()->self(); + + _update_material(material); + } +} + /* MESH API */ RID RasterizerStorageGLES3::mesh_create(){ @@ -1950,6 +2792,49 @@ bool RasterizerStorageGLES3::free(RID p_rid){ info.texture_mem-=texture->total_data_size; texture_owner.free(p_rid); memdelete(texture); + + } else if (shader_owner.owns(p_rid)) { + + // delete the texture + Shader *shader = shader_owner.get(p_rid); + + if (shader->shader) + shader->shader->free_custom_shader(shader->custom_code_id); + + if (shader->dirty_list.in_list()) + _shader_dirty_list.remove(&shader->dirty_list); + + while (shader->materials.first()) { + + Material *mat = shader->materials.first()->self(); + + mat->shader=NULL; + _material_make_dirty(mat); + + shader->materials.remove( shader->materials.first() ); + } + + //material_shader.free_custom_shader(shader->custom_code_id); + shader_owner.free(p_rid); + memdelete(shader); + + } else if (material_owner.owns(p_rid)) { + + // delete the texture + Material *material = material_owner.get(p_rid); + + if (material->shader) { + material->shader->materials.remove( & material->list ); + } + + if (material->ubo_id) { + glDeleteBuffers(1,&material->ubo_id); + } + + material_owner.free(p_rid); + memdelete(material); + + } else if (canvas_occluder_owner.owns(p_rid)) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 9820fbc941..b7b3e607c6 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -2,16 +2,21 @@ #define RASTERIZERSTORAGEGLES3_H #include "servers/visual/rasterizer.h" +#include "servers/visual/shader_language.h" #include "shader_gles3.h" #include "shaders/copy.glsl.h" #include "shaders/canvas.glsl.h" +#include "self_list.h" +#include "shader_compiler_gles3.h" - +class RasterizerCanvasGLES3; class RasterizerStorageGLES3 : public RasterizerStorage { public: + RasterizerCanvasGLES3 *canvas; + enum FBOFormat { FBO_FORMAT_16_BITS, FBO_FORMAT_32_BITS, @@ -47,9 +52,13 @@ public: Set<String> extensions; } config; - struct Shaders { + mutable struct Shaders { CopyShaderGLES3 copy; + + ShaderCompilerGLES3 compiler; + + ShaderCompilerGLES3::IdentifierActions actions_canvas; } shaders; struct Resources { @@ -169,11 +178,71 @@ public: /* SHADER API */ + struct Material; + struct Shader : public RID_Data { + RID self; + + VS::ShaderMode mode; + ShaderGLES3 *shader; + String code; + SelfList<Material>::List materials; + + + + Map<StringName,ShaderLanguage::ShaderNode::Uniform> uniforms; + Vector<uint32_t> ubo_offsets; + uint32_t ubo_size; + + uint32_t texture_count; + + uint32_t custom_code_id; + uint32_t version; + + SelfList<Shader> dirty_list; + + Map<StringName,RID> default_textures; + + bool valid; + + String path; + + struct CanvasItem { + + enum BlendMode { + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_PMALPHA, + }; + + int blend_mode; + enum LightMode { + LIGHT_MODE_NORMAL, + LIGHT_MODE_UNSHADED, + LIGHT_MODE_LIGHT_ONLY + }; + + int light_mode; + + } canvas_item; + + Shader() : dirty_list(this) { + + shader=NULL; + valid=false; + custom_code_id=0; + version=1; + } }; + mutable SelfList<Shader>::List _shader_dirty_list; + void _shader_make_dirty(Shader* p_shader); + + mutable RID_Owner<Shader> shader_owner; virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL); @@ -187,17 +256,48 @@ 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; + void _update_shader(Shader* p_shader) const; + + void update_dirty_shaders(); /* COMMON MATERIAL API */ + struct Material : public RID_Data { + + Shader *shader; + GLuint ubo_id; + uint32_t ubo_size; + Map<StringName,Variant> params; + SelfList<Material> list; + SelfList<Material> dirty_list; + Vector<RID> textures; + + Material() : list(this), dirty_list(this) { + shader=NULL; + ubo_id=0; + ubo_size=0; + } + + }; + + mutable SelfList<Material>::List _material_dirty_list; + void _material_make_dirty(Material *p_material) const; + + + mutable RID_Owner<Material> material_owner; + virtual RID material_create(); - virtual void material_set_shader(RID p_shader_material, RID p_shader); - virtual RID material_get_shader(RID p_shader_material) const; + virtual void material_set_shader(RID p_material, RID p_shader); + virtual RID material_get_shader(RID p_material) const; virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); virtual Variant material_get_param(RID p_material, const StringName& p_param) const; + void _update_material(Material* material); + + void update_dirty_materials(); + /* MESH API */ virtual RID mesh_create(); @@ -432,6 +532,7 @@ public: bool clear_request; Color clear_request_color; int canvas_draw_commands; + float time[4]; } frame; void initialize(); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp new file mode 100644 index 0000000000..49707400ca --- /dev/null +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -0,0 +1,528 @@ +#include "shader_compiler_gles3.h" +#include "os/os.h" + +#define SL ShaderLanguage + +static String _mktab(int p_level) { + + String tb; + for(int i=0;i<p_level;i++) { + tb+="\t"; + } + + return tb; +} + +static String _typestr(SL::DataType p_type) { + + return ShaderLanguage::get_datatype_name(p_type); +} + +static int _get_datatype_size(SL::DataType p_type) { + + switch(p_type) { + + case SL::TYPE_VOID: return 0; + case SL::TYPE_BOOL: return 4; + case SL::TYPE_BVEC2: return 8; + case SL::TYPE_BVEC3: return 16; + case SL::TYPE_BVEC4: return 16; + case SL::TYPE_INT: return 4; + case SL::TYPE_IVEC2: return 8; + case SL::TYPE_IVEC3: return 16; + case SL::TYPE_IVEC4: return 16; + case SL::TYPE_UINT: return 4; + case SL::TYPE_UVEC2: return 8; + case SL::TYPE_UVEC3: return 16; + case SL::TYPE_UVEC4: return 16; + case SL::TYPE_FLOAT: return 4; + case SL::TYPE_VEC2: return 8; + case SL::TYPE_VEC3: return 16; + case SL::TYPE_VEC4: return 16; + case SL::TYPE_MAT2: return 16; + case SL::TYPE_MAT3: return 48; + case SL::TYPE_MAT4: return 64; + case SL::TYPE_SAMPLER2D: return 16; + case SL::TYPE_ISAMPLER2D: return 16; + case SL::TYPE_USAMPLER2D: return 16; + case SL::TYPE_SAMPLERCUBE: return 16; + } + + +} + + +static String _prestr(SL::DataPrecision p_pres) { + + + switch(p_pres) { + case SL::PRECISION_LOWP: return "lowp "; + case SL::PRECISION_MEDIUMP: return "mediump "; + case SL::PRECISION_HIGHP: return "highp "; + case SL::PRECISION_DEFAULT: return ""; + } + return ""; +} + + +static String _opstr(SL::Operator p_op) { + + return SL::get_operator_text(p_op); +} + +static String _mkid(const String& p_id) { + + return "m_"+p_id; +} + +static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value>& p_values) { + + switch(p_type) { + case SL::TYPE_BOOL: return p_values[0].boolean?"true":"false"; + case SL::TYPE_BVEC2: return String()+"bvec2("+(p_values[0].boolean?"true":"false")+(p_values[1].boolean?"true":"false")+")"; + case SL::TYPE_BVEC3: return String()+"bvec3("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+")"; + case SL::TYPE_BVEC4: return String()+"bvec4("+(p_values[0].boolean?"true":"false")+","+(p_values[1].boolean?"true":"false")+","+(p_values[2].boolean?"true":"false")+","+(p_values[3].boolean?"true":"false")+")"; + case SL::TYPE_INT: return rtos(p_values[0].sint); + case SL::TYPE_IVEC2: return String()+"ivec2("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+")"; + case SL::TYPE_IVEC3: return String()+"ivec3("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+")"; + case SL::TYPE_IVEC4: return String()+"ivec4("+rtos(p_values[0].sint)+","+rtos(p_values[1].sint)+","+rtos(p_values[2].sint)+","+rtos(p_values[3].sint)+")"; + case SL::TYPE_UINT: return rtos(p_values[0].real); + case SL::TYPE_UVEC2: return String()+"uvec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")"; + case SL::TYPE_UVEC3: return String()+"uvec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")"; + case SL::TYPE_UVEC4: return String()+"uvec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")"; + case SL::TYPE_FLOAT: return rtos(p_values[0].real); + case SL::TYPE_VEC2: return String()+"vec2("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+")"; + case SL::TYPE_VEC3: return String()+"vec3("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+")"; + case SL::TYPE_VEC4: return String()+"vec4("+rtos(p_values[0].real)+","+rtos(p_values[1].real)+","+rtos(p_values[2].real)+","+rtos(p_values[3].real)+")"; + default: ERR_FAIL_V(String()); + } +} + +void ShaderCompilerGLES3::_dump_function_deps(SL::ShaderNode* p_node, const StringName& p_for_func, const Map<StringName,String>& p_func_code, String& r_to_add, Set<StringName> &added) { + + int fidx=-1; + + for(int i=0;i<p_node->functions.size();i++) { + if (p_node->functions[i].name==p_for_func) { + fidx=i; + break; + } + } + + ERR_FAIL_COND(fidx==-1); + + for (Set<StringName>::Element *E=p_node->functions[fidx].uses_function.front();E;E=E->next()) { + + if (added.has(E->get())) { + continue; //was added already + } + + _dump_function_deps(p_node,E->get(),p_func_code,r_to_add,added); + + SL::FunctionNode *fnode=NULL; + + for(int i=0;i<p_node->functions.size();i++) { + if (p_node->functions[i].name==E->get()) { + fnode=p_node->functions[i].function; + break; + } + } + + ERR_FAIL_COND(!fnode); + + r_to_add+="\n"; + + String header; + header=_typestr(fnode->return_type)+" "+_mkid(fnode->name)+"("; + for(int i=0;i<fnode->arguments.size();i++) { + + if (i>0) + header+=", "; + header+=_prestr(fnode->arguments[i].precision)+_typestr(fnode->arguments[i].type)+" "+_mkid(fnode->arguments[i].name); + } + + header+=")\n"; + r_to_add+=header; + r_to_add+=p_func_code[E->get()]; + + added.insert(E->get()); + } +} + +String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, GeneratedCode& r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions) { + + String code; + + switch(p_node->type) { + + case SL::Node::TYPE_SHADER: { + + SL::ShaderNode *pnode=(SL::ShaderNode*)p_node; + + for(int i=0;i<pnode->render_modes.size();i++) { + + if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) { + + r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]].utf8()); + used_rmode_defines.insert(pnode->render_modes[i]); + } + + if (p_actions.render_mode_flags.has(pnode->render_modes[i])) { + *p_actions.render_mode_flags[pnode->render_modes[i]]=true; + } + + if (p_actions.render_mode_values.has(pnode->render_modes[i])) { + Pair<int*,int> &p = p_actions.render_mode_values[pnode->render_modes[i]]; + *p.first=p.second; + } + } + + + int max_texture_uniforms=0; + int max_uniforms=0; + + for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) { + if (SL::is_sampler_type(E->get().type)) + max_texture_uniforms++; + else + max_uniforms++; + } + + r_gen_code.texture_uniforms.resize(max_texture_uniforms); + + Vector<int> uniform_sizes; + uniform_sizes.resize(max_uniforms); + + for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) { + + String ucode="uniform "; + ucode+=_prestr(E->get().precission); + ucode+=_typestr(E->get().type); + ucode+=" "+_mkid(E->key()); + ucode+=";\n"; + if (SL::is_sampler_type(E->get().type)) { + r_gen_code.vertex_global+=ucode; + r_gen_code.fragment_global+=ucode; + r_gen_code.texture_uniforms[E->get().texture_order]=_mkid(E->key()); + } else { + if (r_gen_code.uniforms.empty()) { + + r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii()); + } + r_gen_code.uniforms+=ucode; + uniform_sizes[E->get().order]=_get_datatype_size(E->get().type); + } + + p_actions.uniforms->insert(E->key(),E->get()); + + } + + // add up + for(int i=0;i<uniform_sizes.size();i++) { + + if (i>0) + uniform_sizes[i]=uniform_sizes[i]+uniform_sizes[i-1]; + } + //offset + r_gen_code.uniform_offsets.resize(uniform_sizes.size()); + for(int i=0;i<uniform_sizes.size();i++) { + + if (i>0) + r_gen_code.uniform_offsets[i]=uniform_sizes[i]-1; + else + r_gen_code.uniform_offsets[i]=0; + } + + if (uniform_sizes.size()) { + r_gen_code.uniform_total_size=uniform_sizes[ uniform_sizes.size() -1 ]; + } else { + r_gen_code.uniform_total_size=0; + } + + for(Map<StringName,SL::ShaderNode::Varying>::Element *E=pnode->varyings.front();E;E=E->next()) { + + String vcode; + vcode+=_prestr(E->get().precission); + vcode+=_typestr(E->get().type); + vcode+=" "+String(E->key()); + vcode+=";\n"; + r_gen_code.vertex_global+="out "+vcode; + r_gen_code.fragment_global+="in "+vcode; + } + + Map<StringName,String> function_code; + + //code for functions + for(int i=0;i<pnode->functions.size();i++) { + SL::FunctionNode *fnode=pnode->functions[i].function; + function_code[fnode->name]=_dump_node_code(fnode->body,p_level+1,r_gen_code,p_actions,p_default_actions); + } + + //place functions in actual code + + Set<StringName> added_vtx; + Set<StringName> added_fragment; //share for light + + for(int i=0;i<pnode->functions.size();i++) { + + SL::FunctionNode *fnode=pnode->functions[i].function; + + + if (fnode->name=="vertex") { + + _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.vertex_global,added_vtx); + r_gen_code.vertex=function_code["vertex"]; + } + + if (fnode->name=="fragment") { + + _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.fragment_global,added_fragment); + r_gen_code.fragment=function_code["fragment"]; + } + + if (fnode->name=="light") { + + _dump_function_deps(pnode,fnode->name,function_code,r_gen_code.fragment_global,added_fragment); + r_gen_code.light=function_code["light"]; + } + } + + //code+=dump_node_code(pnode->body,p_level); + } break; + case SL::Node::TYPE_FUNCTION: { + + } break; + case SL::Node::TYPE_BLOCK: { + SL::BlockNode *bnode=(SL::BlockNode*)p_node; + + //variables + code+=_mktab(p_level-1)+"{\n"; + for(Map<StringName,SL::BlockNode::Variable>::Element *E=bnode->variables.front();E;E=E->next()) { + + code+=_mktab(p_level)+_prestr(E->get().precision)+_typestr(E->get().type)+" "+_mkid(E->key())+";\n"; + } + + for(int i=0;i<bnode->statements.size();i++) { + + String scode = _dump_node_code(bnode->statements[i],p_level,r_gen_code,p_actions,p_default_actions); + + if (bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW || bnode->statements[i]->type==SL::Node::TYPE_CONTROL_FLOW) { + code+=scode; //use directly + } else { + code+=_mktab(p_level)+scode+";\n"; + } + } + code+=_mktab(p_level-1)+"}\n"; + + + } break; + case SL::Node::TYPE_VARIABLE: { + SL::VariableNode *vnode=(SL::VariableNode*)p_node; + + if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) { + r_gen_code.defines.push_back(p_default_actions.usage_defines[vnode->name].utf8()); + used_name_defines.insert(vnode->name); + } + + if (p_actions.usage_flag_pointers.has(vnode->name) && !used_name_defines.has(vnode->name)) { + *p_actions.usage_flag_pointers[vnode->name]=true; + used_name_defines.insert(vnode->name); + } + + if (p_default_actions.renames.has(vnode->name)) + code=p_default_actions.renames[vnode->name]; + else + code=_mkid(vnode->name); + + + } break; + case SL::Node::TYPE_CONSTANT: { + SL::ConstantNode *cnode=(SL::ConstantNode*)p_node; + return get_constant_text(cnode->datatype,cnode->values); + + } break; + case SL::Node::TYPE_OPERATOR: { + SL::OperatorNode *onode=(SL::OperatorNode*)p_node; + + + switch(onode->op) { + + case SL::OP_ASSIGN: + case SL::OP_ASSIGN_ADD: + case SL::OP_ASSIGN_SUB: + case SL::OP_ASSIGN_MUL: + case SL::OP_ASSIGN_DIV: + case SL::OP_ASSIGN_SHIFT_LEFT: + case SL::OP_ASSIGN_SHIFT_RIGHT: + case SL::OP_ASSIGN_MOD: + case SL::OP_ASSIGN_BIT_AND: + case SL::OP_ASSIGN_BIT_OR: + case SL::OP_ASSIGN_BIT_XOR: + code=_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op)+_dump_node_code(onode->arguments[1],p_level,r_gen_code,p_actions,p_default_actions); + break; + case SL::OP_BIT_INVERT: + case SL::OP_NEGATE: + case SL::OP_NOT: + case SL::OP_DECREMENT: + case SL::OP_INCREMENT: + code=_opstr(onode->op)+_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions); + break; + case SL::OP_POST_DECREMENT: + case SL::OP_POST_INCREMENT: + code=_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op); + break; + case SL::OP_CALL: + case SL::OP_CONSTRUCT: { + + ERR_FAIL_COND_V(onode->arguments[0]->type!=SL::Node::TYPE_VARIABLE,String()); + + SL::VariableNode *vnode=(SL::VariableNode*)onode->arguments[0]; + + if (onode->op==SL::OP_CONSTRUCT) { + code+=String(vnode->name); + } else { + + if (internal_functions.has(vnode->name)) { + code+=vnode->name; + } else if (p_default_actions.renames.has(vnode->name)) { + code+=p_default_actions.renames[vnode->name]; + } else { + code+=_mkid(vnode->name); + } + } + + code+="("; + + for(int i=1;i<onode->arguments.size();i++) { + if (i>1) + code+=", "; + code+=_dump_node_code(onode->arguments[i],p_level,r_gen_code,p_actions,p_default_actions); + } + code+=")"; + } break; + default: { + + code="("+_dump_node_code(onode->arguments[0],p_level,r_gen_code,p_actions,p_default_actions)+_opstr(onode->op)+_dump_node_code(onode->arguments[1],p_level,r_gen_code,p_actions,p_default_actions)+")"; + break; + + } + } + + } break; + case SL::Node::TYPE_CONTROL_FLOW: { + SL::ControlFlowNode *cfnode=(SL::ControlFlowNode*)p_node; + if (cfnode->flow_op==SL::FLOW_OP_IF) { + + code+=_mktab(p_level)+"if ("+_dump_node_code(cfnode->expressions[0],p_level,r_gen_code,p_actions,p_default_actions)+")\n"; + code+=_dump_node_code(cfnode->blocks[0],p_level+1,r_gen_code,p_actions,p_default_actions); + if (cfnode->blocks.size()==2) { + + code+=_mktab(p_level)+"else\n"; + code+=_dump_node_code(cfnode->blocks[1],p_level+1,r_gen_code,p_actions,p_default_actions); + } + + + } else if (cfnode->flow_op==SL::FLOW_OP_RETURN) { + + if (cfnode->blocks.size()) { + code="return "+_dump_node_code(cfnode->blocks[0],p_level,r_gen_code,p_actions,p_default_actions); + } else { + code="return"; + } + } + + } break; + case SL::Node::TYPE_MEMBER: { + SL::MemberNode *mnode=(SL::MemberNode*)p_node; + code=_dump_node_code(mnode->owner,p_level,r_gen_code,p_actions,p_default_actions)+"."+mnode->name; + + } break; + } + + return code; + +} + + +Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code, IdentifierActions* p_actions, const String &p_path,GeneratedCode& r_gen_code) { + + + + Error err = parser.compile(p_code,ShaderTypes::get_singleton()->get_functions(p_mode),ShaderTypes::get_singleton()->get_modes(p_mode)); + + if (err!=OK) { + _err_print_error(NULL,p_path.utf8().get_data(),parser.get_error_line(),parser.get_error_text().utf8().get_data(),ERR_HANDLER_SHADER); + return err; + } + + r_gen_code.defines.clear(); + r_gen_code.vertex=String(); + r_gen_code.vertex_global=String(); + r_gen_code.fragment=String(); + r_gen_code.fragment_global=String(); + r_gen_code.light=String(); + + + + used_name_defines.clear(); + used_rmode_defines.clear(); + + _dump_node_code(parser.get_shader(),1,r_gen_code,*p_actions,actions[p_mode]); + + return OK; + +} + + +ShaderCompilerGLES3::ShaderCompilerGLES3() { + + /** CANVAS ITEM SHADER **/ + + actions[VS::SHADER_CANVAS_ITEM].renames["SRC_VERTEX"]="vertex"; + actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"]="outvec.xy"; + actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX_COLOR"]="vertex_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["UV"]="uv_interp"; + actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"]="gl_PointSize"; + + actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"]="modelview_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"]="projection_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"]=="extra_matrix"; + actions[VS::SHADER_CANVAS_ITEM].renames["TIME"]="time"; + + actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"]="color"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"]="normal"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"]="normal_map"; + actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"]="normal_depth"; + actions[VS::SHADER_CANVAS_ITEM].renames["UV"]="uv_interp"; + actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"]="color"; + actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"]="color_texture"; + actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"]="color_texpixel_size"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"]="screen_uv"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"]="screen_texture"; + actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"]="gl_PointCoord"; + + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"]="light_vec"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"]="light_height"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"]="light_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"]="light_uv"; + //actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_SHADOW_COLOR"]="light_shadow_color"; + actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"]="light"; + actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"]="shadow_color"; + + actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"]="#define COLOR_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"]="#define SCREEN_TEXTURE_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"]="#define SCREEN_UV_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"]="#define NORMAL_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"]="#define NORMALMAP_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"]="#define SHADOW_COLOR_USED\n"; + + actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_transform"]="#define SKIP_TRANSFORM_USED\n"; + + List<String> func_list; + + ShaderLanguage::get_builtin_funcs(&func_list); + + for (List<String>::Element *E=func_list.front();E;E=E->next()) { + internal_functions.insert(E->get()); + } +} diff --git a/drivers/gles3/shader_compiler_gles3.h b/drivers/gles3/shader_compiler_gles3.h new file mode 100644 index 0000000000..ad51b99927 --- /dev/null +++ b/drivers/gles3/shader_compiler_gles3.h @@ -0,0 +1,67 @@ +#ifndef SHADERCOMPILERGLES3_H +#define SHADERCOMPILERGLES3_H + +#include "servers/visual/shader_language.h" +#include "servers/visual/shader_types.h" +#include "servers/visual_server.h" +#include "pair.h" + +class ShaderCompilerGLES3 { +public: + struct IdentifierActions { + + Map<StringName,Pair<int*,int> > render_mode_values; + Map<StringName,bool*> render_mode_flags; + Map<StringName,bool*> usage_flag_pointers; + + Map<StringName,ShaderLanguage::ShaderNode::Uniform> *uniforms; + }; + + struct GeneratedCode { + + Vector<CharString> defines; + Vector<StringName> texture_uniforms; + Vector<uint32_t> uniform_offsets; + uint32_t uniform_total_size; + String uniforms; + String vertex_global; + String vertex; + String fragment_global; + String fragment; + String light; + + }; + +private: + + ShaderLanguage parser; + + struct DefaultIdentifierActions { + + Map<StringName,String> renames; + Map<StringName,String> render_mode_defines; + Map<StringName,String> usage_defines; + }; + + void _dump_function_deps(ShaderLanguage::ShaderNode *p_node, const StringName& p_for_func, const Map<StringName, String> &p_func_code, String& r_to_add,Set<StringName> &added); + String _dump_node_code(ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions& p_actions, const DefaultIdentifierActions& p_default_actions); + + + + Set<StringName> used_name_defines; + Set<StringName> used_rmode_defines; + Set<StringName> internal_functions; + + + DefaultIdentifierActions actions[VS::SHADER_MAX]; + +public: + + + Error compile(VS::ShaderMode p_mode, const String& p_code, IdentifierActions* p_actions, const String& p_path, GeneratedCode& r_gen_code); + + + ShaderCompilerGLES3(); +}; + +#endif // SHADERCOMPILERGLES3_H diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index f8c0234943..35191fecf7 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -214,6 +214,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { } + + v.ok=false; /* SETUP CONDITIONALS */ @@ -245,6 +247,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { CharString code_string; CharString code_string2; CharString code_globals; + CharString material_string; //print_line("code version? "+itos(conditional_version.code_version)); @@ -258,6 +261,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { cc=&custom_code_map[conditional_version.code_version]; v.code_version=cc->version; define_line_ofs+=2; + } @@ -273,7 +277,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { if (cc) { for(int i=0;i<cc->custom_defines.size();i++) { - strings.push_back(cc->custom_defines[i]); + strings.push_back(cc->custom_defines[i].get_data()); DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i])); } } @@ -305,14 +309,22 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { code_globals=cc->vertex_globals.ascii(); strings.push_back(code_globals.get_data()); } + strings.push_back(vertex_code1.get_data()); if (cc) { + material_string=cc->uniforms.ascii(); + strings.push_back(material_string.get_data()); + } + + strings.push_back(vertex_code2.get_data()); + + if (cc) { code_string=cc->vertex.ascii(); strings.push_back(code_string.get_data()); } - strings.push_back(vertex_code2.get_data()); + strings.push_back(vertex_code3.get_data()); #ifdef DEBUG_SHADER DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data())); @@ -367,7 +379,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { ERR_FAIL_V(NULL); } - + + /* FRAGMENT SHADER */ strings.resize(strings_base_size); @@ -396,21 +409,29 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { code_globals=cc->fragment_globals.ascii(); strings.push_back(code_globals.get_data()); } + strings.push_back(fragment_code1.get_data()); if (cc) { + material_string=cc->uniforms.ascii(); + strings.push_back(material_string.get_data()); + } + + strings.push_back(fragment_code2.get_data()); + + if (cc) { code_string=cc->fragment.ascii(); strings.push_back(code_string.get_data()); } - strings.push_back(fragment_code2.get_data()); + strings.push_back(fragment_code3.get_data()); if (cc) { code_string2=cc->light.ascii(); strings.push_back(code_string2.get_data()); } - strings.push_back(fragment_code3.get_data()); + strings.push_back(fragment_code4.get_data()); #ifdef DEBUG_SHADER DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data())); @@ -463,7 +484,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { ERR_FAIL_V( NULL ); } - + glAttachShader(v.id,v.frag_id); glAttachShader(v.id,v.vert_id); @@ -552,10 +573,11 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { if ( cc ) { - v.custom_uniform_locations.resize(cc->custom_uniforms.size()); - for(int i=0;i<cc->custom_uniforms.size();i++) { + v.texture_uniform_locations.resize(cc->texture_uniforms.size()); + for(int i=0;i<cc->texture_uniforms.size();i++) { - v.custom_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->custom_uniforms[i]).ascii().get_data()); + v.texture_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->texture_uniforms[i]).ascii().get_data()); + glUniform1i(v.texture_uniform_locations[i],i+base_material_tex_index); } } @@ -597,6 +619,7 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co //split vertex and shader code (thank you, retarded shader compiler programmers from you know what company). { String globals_tag="\nVERTEX_SHADER_GLOBALS"; + String material_tag="\nMATERIAL_UNIFORMS"; String code_tag="\nVERTEX_SHADER_CODE"; String code = vertex_code; int cpos = code.find(globals_tag); @@ -606,20 +629,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co vertex_code0=code.substr(0,cpos).ascii(); code = code.substr(cpos+globals_tag.length(),code.length()); - cpos = code.find(code_tag); + cpos = code.find(material_tag); if (cpos==-1) { vertex_code1=code.ascii(); } else { vertex_code1=code.substr(0,cpos).ascii(); - vertex_code2=code.substr(cpos+code_tag.length(),code.length()).ascii(); + String code2 = code.substr(cpos+material_tag.length(),code.length()); + + cpos = code2.find(code_tag); + if (cpos==-1) { + vertex_code2=code2.ascii(); + } else { + + vertex_code2=code2.substr(0,cpos).ascii(); + vertex_code3 = code2.substr(cpos+code_tag.length(),code2.length()).ascii(); + } + } } } { String globals_tag="\nFRAGMENT_SHADER_GLOBALS"; + String material_tag="\nMATERIAL_UNIFORMS"; String code_tag="\nFRAGMENT_SHADER_CODE"; String light_code_tag="\nLIGHT_SHADER_CODE"; String code = fragment_code; @@ -630,22 +664,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co fragment_code0=code.substr(0,cpos).ascii(); code = code.substr(cpos+globals_tag.length(),code.length()); - cpos = code.find(code_tag); + cpos = code.find(material_tag); if (cpos==-1) { fragment_code1=code.ascii(); } else { fragment_code1=code.substr(0,cpos).ascii(); - String code2 = code.substr(cpos+code_tag.length(),code.length()); + String code2 = code.substr(cpos+material_tag.length(),code.length()); - cpos = code2.find(light_code_tag); + cpos = code2.find(code_tag); if (cpos==-1) { fragment_code2=code2.ascii(); } else { fragment_code2=code2.substr(0,cpos).ascii(); - fragment_code3 = code2.substr(cpos+light_code_tag.length(),code2.length()).ascii(); + String code3 = code2.substr(cpos+code_tag.length(),code2.length()); + + cpos = code3.find(light_code_tag); + if (cpos==-1) { + fragment_code3=code3.ascii(); + } else { + + fragment_code3=code3.substr(0,cpos).ascii(); + fragment_code4 = code3.substr(cpos+light_code_tag.length(),code3.length()).ascii(); + } } } } @@ -697,7 +740,7 @@ uint32_t ShaderGLES3::create_custom_shader() { return last_custom_code++; } -void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_light, const String& p_fragment_globals,const Vector<StringName>& p_uniforms,const Vector<const char*> &p_custom_defines) { +void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals, const String& p_fragment, const String& p_light, const String& p_fragment_globals, const String &p_uniforms, const Vector<StringName> &p_texture_uniforms, const Vector<CharString> &p_custom_defines) { ERR_FAIL_COND(!custom_code_map.has(p_code_id)); CustomCode *cc=&custom_code_map[p_code_id]; @@ -707,7 +750,8 @@ void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_ver cc->fragment=p_fragment; cc->fragment_globals=p_fragment_globals; cc->light=p_light; - cc->custom_uniforms=p_uniforms; + cc->texture_uniforms=p_texture_uniforms; + cc->uniforms=p_uniforms; cc->custom_defines=p_custom_defines; cc->version++; } @@ -734,13 +778,16 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { } +void ShaderGLES3::set_base_material_tex_index(int p_idx) { + base_material_tex_index=p_idx; +} ShaderGLES3::ShaderGLES3() { version=NULL; last_custom_code=1; uniforms_dirty = true; - + base_material_tex_index=0; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units); } diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 7aaf65d450..176a2282fd 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -105,9 +105,10 @@ private: String fragment; String fragment_globals; String light; + String uniforms; uint32_t version; - Vector<StringName> custom_uniforms; - Vector<const char*> custom_defines; + Vector<StringName> texture_uniforms; + Vector<CharString> custom_defines; }; @@ -118,7 +119,7 @@ private: GLuint vert_id; GLuint frag_id; GLint *uniform_location; - Vector<GLint> custom_uniform_locations; + Vector<GLint> texture_uniform_locations; uint32_t code_version; bool ok; Version() { code_version=0; ok=false; uniform_location=NULL; } @@ -166,10 +167,14 @@ private: CharString fragment_code1; CharString fragment_code2; CharString fragment_code3; + CharString fragment_code4; CharString vertex_code0; CharString vertex_code1; CharString vertex_code2; + CharString vertex_code3; + + int base_material_tex_index; Version * get_current_version(); @@ -308,7 +313,7 @@ public: void clear_caches(); uint32_t create_custom_shader(); - void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const Vector<StringName>& p_uniforms,const Vector<const char*> &p_custom_defines); + void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const String& p_uniforms,const Vector<StringName>& p_texture_uniforms,const Vector<CharString> &p_custom_defines); void set_custom_shader(uint32_t p_id); void free_custom_shader(uint32_t p_id); @@ -332,23 +337,25 @@ public: uniforms_dirty = true; }; - _FORCE_INLINE_ void set_custom_uniform(int p_idx, const Variant& p_value) { + _FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant& p_value) { ERR_FAIL_COND(!version); - ERR_FAIL_INDEX(p_idx,version->custom_uniform_locations.size()); - _set_uniform_variant( version->custom_uniform_locations[p_idx], p_value ); + ERR_FAIL_INDEX(p_idx,version->texture_uniform_locations.size()); + _set_uniform_variant( version->texture_uniform_locations[p_idx], p_value ); } - _FORCE_INLINE_ GLint get_custom_uniform_location(int p_idx) { + _FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) { ERR_FAIL_COND_V(!version,-1); - ERR_FAIL_INDEX_V(p_idx,version->custom_uniform_locations.size(),-1); - return version->custom_uniform_locations[p_idx]; + ERR_FAIL_INDEX_V(p_idx,version->texture_uniform_locations.size(),-1); + return version->texture_uniform_locations[p_idx]; } virtual void init()=0; void finish(); + void set_base_material_tex_index(int p_idx); + virtual ~ShaderGLES3(); }; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index eed2239ec9..cf2e0f776f 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -1,7 +1,7 @@ [vertex] -layout(location=0) in highp vec3 vertex; +layout(location=0) in highp vec2 vertex; layout(location=3) in vec4 color_attrib; #ifdef USE_TEXTURE_RECT @@ -20,6 +20,7 @@ layout(location=4) in highp vec2 uv_attrib; layout(std140) uniform CanvasItemData { //ubo:0 highp mat4 projection_matrix; + highp vec4 time; }; uniform highp mat4 modelview_matrix; @@ -29,10 +30,6 @@ uniform highp mat4 extra_matrix; out mediump vec2 uv_interp; out mediump vec4 color_interp; -#if defined(USE_TIME) -uniform float time; -#endif - #ifdef USE_LIGHTING layout(std140) uniform LightData { //ubo:1 @@ -51,6 +48,7 @@ layout(std140) uniform LightData { //ubo:1 highp float shadow_distance_mult; }; + out vec4 light_uv_interp; #if defined(NORMAL_USED) @@ -66,20 +64,30 @@ out highp vec2 pos; VERTEX_SHADER_GLOBALS +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { //ubo:2 + +MATERIAL_UNIFORMS + +}; + +#endif + void main() { - color_interp = color_attrib; + vec4 vertex_color = color_attrib; #ifdef USE_TEXTURE_RECT - uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.xy; - highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex.xy,vec2(1.0,1.0)-vertex.xy,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0); + uv_interp = src_rect.xy + abs(src_rect.zw) * vertex; + highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex,vec2(1.0,1.0)-vertex,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0); #else uv_interp = uv_attrib; - highp vec4 outvec = vec4(vertex, 1.0); + highp vec4 outvec = vec4(vertex,0.0,1.0); #endif @@ -90,16 +98,16 @@ VERTEX_SHADER_CODE } -#if !defined(USE_WORLD_VEC) +#if !defined(SKIP_TRANSFORM_USED) outvec = extra_matrix * outvec; outvec = modelview_matrix * outvec; #endif - + color_interp = vertex_color; #ifdef USE_PIXEL_SNAP - outvec.xy=floor(outvec.xy+0.5); + outvec.xy=floor(outvec+0.5); #endif @@ -132,20 +140,24 @@ VERTEX_SHADER_CODE uniform mediump sampler2D color_texture; // texunit:0 +uniform highp vec2 color_texpixel_size; in mediump vec2 uv_interp; in mediump vec4 color_interp; -#if defined(ENABLE_TEXSCREEN) +#if defined(SCREEN_TEXTURE_USED) -uniform sampler2D texscreen_tex; // texunit:-3 +uniform sampler2D screen_texture; // texunit:-3 #endif -#if defined(USE_TIME) -uniform float time; -#endif +layout(std140) uniform CanvasItemData { + + highp mat4 projection_matrix; + highp vec4 time; +}; + #ifdef USE_LIGHTING @@ -188,6 +200,17 @@ FRAGMENT_SHADER_GLOBALS layout(location=0) out mediump vec4 frag_color; + +#if defined(USE_MATERIAL) + +layout(std140) uniform UniformData { + +MATERIAL_UNIFORMS + +}; + +#endif + void main() { vec4 color = color_interp; @@ -195,6 +218,9 @@ void main() { vec3 normal = vec3(0.0,0.0,1.0); #endif +#if !defined(COLOR_USED) +//default behavior, texture by color + #ifdef USE_DISTANCE_FIELD const float smoothing = 1.0/32.0; float distance = texture(color_texture, uv_interp).a; @@ -204,6 +230,7 @@ void main() { #endif +#endif #if defined(ENABLE_SCREEN_UV) vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; @@ -211,14 +238,15 @@ void main() { { -#if defined(USE_NORMALMAP) - vec3 normal_map=vec3(0.0,0.0,1.0); float normal_depth=1.0; + +#if defined(NORMALMAP_USED) + vec3 normal_map=vec3(0.0,0.0,1.0); #endif FRAGMENT_SHADER_CODE -#if defined(USE_NORMALMAP) +#if defined(NORMALMAP_USED) normal = mix(vec3(0.0,0.0,1.0), normal_map * vec3(2.0,-2.0,1.0) - vec3( 1.0, -1.0, 0.0 ), normal_depth ); #endif @@ -246,7 +274,7 @@ FRAGMENT_SHADER_CODE vec2 light_uv = light_uv_interp.xy; vec4 light = texture(light_texture,light_uv) * light_color; -#if defined(USE_OUTPUT_SHADOW_COLOR) +#if defined(SHADOW_COLOR_USED) vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); #endif @@ -409,7 +437,7 @@ LIGHT_SHADER_CODE #endif -#if defined(USE_OUTPUT_SHADOW_COLOR) +#if defined(SHADOW_COLOR_USED) color=mix(shadow_color,color,shadow_attenuation); #else //color*=shadow_attenuation; diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 271cf302ef..b9ee6178f0 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -88,6 +88,10 @@ void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,c print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details); print("\E[0;35m At: %s:%i.\E[0m\n",p_file,p_line); break; + case ERR_SHADER: + print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details); + print("\E[0;36m At: %s:%i.\E[0m\n",p_file,p_line); + break; } } |