Browse Source

2D Shaders are working again using the new syntax, though all is buggy in general

Juan Linietsky 8 years ago
parent
commit
1527cf8c0d

+ 2 - 1
core/error_macros.h

@@ -49,7 +49,8 @@
 enum ErrorHandlerType {
 enum ErrorHandlerType {
 	ERR_HANDLER_ERROR,
 	ERR_HANDLER_ERROR,
 	ERR_HANDLER_WARNING,
 	ERR_HANDLER_WARNING,
-	ERR_HANDLER_SCRIPT
+	ERR_HANDLER_SCRIPT,
+	ERR_HANDLER_SHADER,
 };
 };
 
 
 typedef void (*ErrorHandlerFunc)(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type);
 typedef void (*ErrorHandlerFunc)(void*,const char*,const char*,int p_line,const char *, const char *,ErrorHandlerType p_type);

+ 1 - 0
core/os/os.cpp

@@ -68,6 +68,7 @@ void OS::print_error(const char* p_function,const char* p_file,int p_line,const
 		case ERR_ERROR: err_type="**ERROR**"; break;
 		case ERR_ERROR: err_type="**ERROR**"; break;
 		case ERR_WARNING: err_type="**WARNING**"; break;
 		case ERR_WARNING: err_type="**WARNING**"; break;
 		case ERR_SCRIPT: err_type="**SCRIPT ERROR**"; break;
 		case ERR_SCRIPT: err_type="**SCRIPT ERROR**"; break;
+		case ERR_SHADER: err_type="**SHADER ERROR**"; break;
 	}
 	}
 
 
 	if (p_rationale && *p_rationale)
 	if (p_rationale && *p_rationale)

+ 2 - 1
core/os/os.h

@@ -120,7 +120,8 @@ public:
 	enum ErrorType {
 	enum ErrorType {
 		ERR_ERROR,
 		ERR_ERROR,
 		ERR_WARNING,
 		ERR_WARNING,
-		ERR_SCRIPT
+		ERR_SCRIPT,
+		ERR_SHADER
 	};
 	};
 
 
 	virtual void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type=ERR_ERROR);
 	virtual void print_error(const char* p_function,const char* p_file,int p_line,const char *p_code,const char*p_rationale,ErrorType p_type=ERR_ERROR);

+ 3 - 0
core/pair.h

@@ -34,6 +34,9 @@ struct Pair {
 
 
 	F first;
 	F first;
 	S second;
 	S second;
+
+	Pair() {}
+	Pair( F p_first,  S p_second) { first=p_first; second=p_second; }
 };
 };
 
 
 #endif // PAIR_H
 #endif // PAIR_H

+ 88 - 55
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_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD,false);
 
 
 
 
+	state.canvas_shader.set_custom_shader(0);
 	state.canvas_shader.bind();
 	state.canvas_shader.bind();
 	state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,Color(1,1,1,1));
 	state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,Color(1,1,1,1));
 	state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Matrix32());
 	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..
 						//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(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);
 					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 );
 				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 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)
 #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);
 				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) {
 				if (primitive->colors.size()==1 && primitive->points.size()>1) {
 
 
 					Color c = primitive->colors[0];
 					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);
 				Item::CommandPolygon* polygon = static_cast<Item::CommandPolygon*>(c);
 				_set_texture_rect_mode(false);
 				_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);
 				_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1);
 
 
 			} break;
 			} 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);
 	glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex);
 
 
 
 
+	int last_blend_mode=-1;
+
 	RID canvas_last_material;
 	RID canvas_last_material;
 
 
 	bool prev_distance_field=false;
 	bool prev_distance_field=false;
 
 
+
+
 	while(p_item_list) {
 	while(p_item_list) {
 
 
 		Item *ci=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;
 		RID material = material_owner->material;
 
 
 		if (material!=canvas_last_material || rebind_shader) {
 		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;
 			canvas_last_material=material;
 			rebind_shader=false;
 			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;
 		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);
 					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);
 						glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 					}
 					}
 					else {
 					else {
@@ -932,33 +972,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
 					}
 					}
 
 
 				 } break;
 				 } break;
-				 case VS::MATERIAL_BLEND_MODE_ADD: {
+				 case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: {
 
 
 					glBlendEquation(GL_FUNC_ADD);
 					glBlendEquation(GL_FUNC_ADD);
 					glBlendFunc(GL_SRC_ALPHA,GL_ONE);
 					glBlendFunc(GL_SRC_ALPHA,GL_ONE);
 
 
 				 } break;
 				 } break;
-				 case VS::MATERIAL_BLEND_MODE_SUB: {
+				 case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: {
 
 
 					glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
 					glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
 					glBlendFunc(GL_SRC_ALPHA,GL_ONE);
 					glBlendFunc(GL_SRC_ALPHA,GL_ONE);
 				 } break;
 				 } break;
-				case VS::MATERIAL_BLEND_MODE_MUL: {
+				case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: {
 					glBlendEquation(GL_FUNC_ADD);
 					glBlendEquation(GL_FUNC_ADD);
 					glBlendFunc(GL_DST_COLOR,GL_ZERO);
 					glBlendFunc(GL_DST_COLOR,GL_ZERO);
 				} break;
 				} break;
-				case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: {
+				case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: {
 					glBlendEquation(GL_FUNC_ADD);
 					glBlendEquation(GL_FUNC_ADD);
 					glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
 					glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
 				} break;
 				} 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(
 		state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
 					ci->final_modulate.r * p_modulate.r,
 					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);
 		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);
 			_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;
 			Light *light = p_light;
 			bool light_used=false;
 			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();
 					bool light_rebind = state.canvas_shader.bind();
 
 
 					if (light_rebind) {
 					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::FINAL_MODULATE,state.canvas_item_modulate);
 						state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform);
 						state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform);
 						state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32());
 						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_PCF9,false);
 				state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false);
 				state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false);
 
 
-
 				state.canvas_shader.bind();
 				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(
 				state.canvas_item_modulate = unshaded ? ci->final_modulate : Color(
 							ci->final_modulate.r * p_modulate.r,
 							ci->final_modulate.r * p_modulate.r,
 							ci->final_modulate.g * p_modulate.g,
 							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::EXTRA_MATRIX,Matrix32());
 				state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate);
 				state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate);
 
 
-
 				glBlendEquation(GL_FUNC_ADD);
 				glBlendEquation(GL_FUNC_ADD);
 
 
 				if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) {
 				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
 				//@TODO RESET canvas_blend_mode
+				*/
 			}
 			}
 
 
 
 
@@ -1380,6 +1409,9 @@ void RasterizerCanvasGLES3::reset_canvas() {
 	state.vp=canvas_transform;
 	state.vp=canvas_transform;
 
 
 	store_transform(canvas_transform,state.canvas_item_ubo_data.projection_matrix);
 	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);
 	glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo);
 	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data);
 	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data);
@@ -1442,6 +1474,7 @@ void RasterizerCanvasGLES3::initialize() {
 	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 
 	state.canvas_shader.init();
 	state.canvas_shader.init();
+	state.canvas_shader.set_base_material_tex_index(1);
 	state.canvas_shadow_shader.init();
 	state.canvas_shadow_shader.init();
 
 
 	state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS,storage->config.use_rgba_2d_shadows);
 	state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS,storage->config.use_rgba_2d_shadows);

+ 2 - 0
drivers/gles3/rasterizer_canvas_gles3.h

@@ -5,12 +5,14 @@
 #include "rasterizer_storage_gles3.h"
 #include "rasterizer_storage_gles3.h"
 #include "shaders/canvas_shadow.glsl.h"
 #include "shaders/canvas_shadow.glsl.h"
 
 
+
 class RasterizerCanvasGLES3 : public RasterizerCanvas {
 class RasterizerCanvasGLES3 : public RasterizerCanvas {
 public:
 public:
 
 
 	struct CanvasItemUBO {
 	struct CanvasItemUBO {
 
 
 		float projection_matrix[16];
 		float projection_matrix[16];
+		float time[4];
 
 
 	};
 	};
 
 

+ 10 - 0
drivers/gles3/rasterizer_gles3.cpp

@@ -115,8 +115,17 @@ void RasterizerGLES3::initialize() {
 
 
 void RasterizerGLES3::begin_frame(){
 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){
 void RasterizerGLES3::set_current_render_target(RID p_render_target){
 
 
 	if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
 	if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
@@ -257,6 +266,7 @@ RasterizerGLES3::RasterizerGLES3()
 	storage = memnew( RasterizerStorageGLES3 );
 	storage = memnew( RasterizerStorageGLES3 );
 	canvas = memnew( RasterizerCanvasGLES3 );
 	canvas = memnew( RasterizerCanvasGLES3 );
 	canvas->storage=storage;
 	canvas->storage=storage;
+	storage->canvas=canvas;
 
 
 
 
 }
 }

+ 892 - 7
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -1,4 +1,5 @@
 #include "rasterizer_storage_gles3.h"
 #include "rasterizer_storage_gles3.h"
+#include "rasterizer_canvas_gles3.h"
 #include "globals.h"
 #include "globals.h"
 
 
 /* TEXTURE API */
 /* 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){
 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){
 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 {
 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){
 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{
 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{
 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){
 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{
 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 */
 /* 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(){
 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();
 	return RID();
 }
 }
 
 
 void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value){
 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{
 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();
 	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 */
 /* MESH API */
 
 
 RID RasterizerStorageGLES3::mesh_create(){
 RID RasterizerStorageGLES3::mesh_create(){
@@ -1950,6 +2792,49 @@ bool RasterizerStorageGLES3::free(RID p_rid){
 		info.texture_mem-=texture->total_data_size;
 		info.texture_mem-=texture->total_data_size;
 		texture_owner.free(p_rid);
 		texture_owner.free(p_rid);
 		memdelete(texture);
 		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)) {
 	} else if (canvas_occluder_owner.owns(p_rid)) {
 
 
 
 

+ 105 - 4
drivers/gles3/rasterizer_storage_gles3.h

@@ -2,16 +2,21 @@
 #define RASTERIZERSTORAGEGLES3_H
 #define RASTERIZERSTORAGEGLES3_H
 
 
 #include "servers/visual/rasterizer.h"
 #include "servers/visual/rasterizer.h"
+#include "servers/visual/shader_language.h"
 #include "shader_gles3.h"
 #include "shader_gles3.h"
 #include "shaders/copy.glsl.h"
 #include "shaders/copy.glsl.h"
 #include "shaders/canvas.glsl.h"
 #include "shaders/canvas.glsl.h"
+#include "self_list.h"
+#include "shader_compiler_gles3.h"
 
 
-
+class RasterizerCanvasGLES3;
 
 
 
 
 class RasterizerStorageGLES3 : public RasterizerStorage {
 class RasterizerStorageGLES3 : public RasterizerStorage {
 public:
 public:
 
 
+	RasterizerCanvasGLES3 *canvas;
+
 	enum FBOFormat {
 	enum FBOFormat {
 		FBO_FORMAT_16_BITS,
 		FBO_FORMAT_16_BITS,
 		FBO_FORMAT_32_BITS,
 		FBO_FORMAT_32_BITS,
@@ -47,9 +52,13 @@ public:
 		Set<String> extensions;
 		Set<String> extensions;
 	} config;
 	} config;
 
 
-	struct Shaders {
+	mutable struct Shaders {
 
 
 		CopyShaderGLES3 copy;
 		CopyShaderGLES3 copy;
+
+		ShaderCompilerGLES3 compiler;
+
+		ShaderCompilerGLES3::IdentifierActions actions_canvas;
 	} shaders;
 	} shaders;
 
 
 	struct Resources {
 	struct Resources {
@@ -169,11 +178,71 @@ public:
 
 
 	/* SHADER API */
 	/* SHADER API */
 
 
+	struct Material;
+
 	struct Shader : public RID_Data {
 	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);
 	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 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 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 */
 	/* 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 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 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;
 	virtual Variant material_get_param(RID p_material, const StringName& p_param) const;
 
 
+	void _update_material(Material* material);
+
+	void update_dirty_materials();
+
 	/* MESH API */
 	/* MESH API */
 
 
 	virtual RID mesh_create();
 	virtual RID mesh_create();
@@ -432,6 +532,7 @@ public:
 		bool clear_request;
 		bool clear_request;
 		Color clear_request_color;
 		Color clear_request_color;
 		int canvas_draw_commands;
 		int canvas_draw_commands;
+		float time[4];
 	} frame;
 	} frame;
 
 
 	void initialize();
 	void initialize();

+ 528 - 0
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());
+	}
+}

+ 67 - 0
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

+ 65 - 18
drivers/gles3/shader_gles3.cpp

@@ -214,6 +214,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
 
 
 	}
 	}
 
 
+
+
 	v.ok=false;
 	v.ok=false;
 	/* SETUP CONDITIONALS */
 	/* SETUP CONDITIONALS */
 	
 	
@@ -245,6 +247,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
 	CharString code_string;
 	CharString code_string;
 	CharString code_string2;
 	CharString code_string2;
 	CharString code_globals;
 	CharString code_globals;
+	CharString material_string;
 
 
 
 
 	//print_line("code version? "+itos(conditional_version.code_version));
 	//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];
 		cc=&custom_code_map[conditional_version.code_version];
 		v.code_version=cc->version;
 		v.code_version=cc->version;
 		define_line_ofs+=2;
 		define_line_ofs+=2;
+
 	}
 	}
 
 
 
 
@@ -273,7 +277,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
 	if (cc) {
 	if (cc) {
 		for(int i=0;i<cc->custom_defines.size();i++) {
 		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]));
 			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();
 		code_globals=cc->vertex_globals.ascii();
 		strings.push_back(code_globals.get_data());
 		strings.push_back(code_globals.get_data());
 	}
 	}
+
 	strings.push_back(vertex_code1.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) {
 	if (cc) {
 		code_string=cc->vertex.ascii();
 		code_string=cc->vertex.ascii();
 		strings.push_back(code_string.get_data());
 		strings.push_back(code_string.get_data());
 	}
 	}
 
 
-	strings.push_back(vertex_code2.get_data());
+	strings.push_back(vertex_code3.get_data());
 #ifdef DEBUG_SHADER
 #ifdef DEBUG_SHADER
 
 
 	DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data()));
 	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);
 		ERR_FAIL_V(NULL);
 	}	
 	}	
-	
+
+
 	/* FRAGMENT SHADER */
 	/* FRAGMENT SHADER */
 
 
 	strings.resize(strings_base_size);
 	strings.resize(strings_base_size);
@@ -396,21 +409,29 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
 		code_globals=cc->fragment_globals.ascii();
 		code_globals=cc->fragment_globals.ascii();
 		strings.push_back(code_globals.get_data());
 		strings.push_back(code_globals.get_data());
 	}
 	}
+
 	strings.push_back(fragment_code1.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) {
 	if (cc) {
 		code_string=cc->fragment.ascii();
 		code_string=cc->fragment.ascii();
 		strings.push_back(code_string.get_data());
 		strings.push_back(code_string.get_data());
 	}
 	}
 
 
-	strings.push_back(fragment_code2.get_data());
+	strings.push_back(fragment_code3.get_data());
 
 
 	if (cc) {
 	if (cc) {
 		code_string2=cc->light.ascii();
 		code_string2=cc->light.ascii();
 		strings.push_back(code_string2.get_data());
 		strings.push_back(code_string2.get_data());
 	}
 	}
 
 
-	strings.push_back(fragment_code3.get_data());
+	strings.push_back(fragment_code4.get_data());
 
 
 #ifdef DEBUG_SHADER
 #ifdef DEBUG_SHADER
 	DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data()));
 	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 );
 		ERR_FAIL_V( NULL );
 	}		
 	}		
-	
+
 	glAttachShader(v.id,v.frag_id);
 	glAttachShader(v.id,v.frag_id);
 	glAttachShader(v.id,v.vert_id);
 	glAttachShader(v.id,v.vert_id);
 
 
@@ -552,10 +573,11 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
 
 
 	if ( cc ) {
 	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).
 	//split vertex and shader code (thank you, retarded shader compiler programmers from you know what company).
 	{
 	{
 		String globals_tag="\nVERTEX_SHADER_GLOBALS";
 		String globals_tag="\nVERTEX_SHADER_GLOBALS";
+		String material_tag="\nMATERIAL_UNIFORMS";
 		String code_tag="\nVERTEX_SHADER_CODE";
 		String code_tag="\nVERTEX_SHADER_CODE";
 		String code =  vertex_code;
 		String code =  vertex_code;
 		int cpos = code.find(globals_tag);
 		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();
 			vertex_code0=code.substr(0,cpos).ascii();
 			code = code.substr(cpos+globals_tag.length(),code.length());
 			code = code.substr(cpos+globals_tag.length(),code.length());
 
 
-			cpos = code.find(code_tag);
+			cpos = code.find(material_tag);
 
 
 			if (cpos==-1) {
 			if (cpos==-1) {
 				vertex_code1=code.ascii();
 				vertex_code1=code.ascii();
 			} else {
 			} else {
 
 
 				vertex_code1=code.substr(0,cpos).ascii();
 				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 globals_tag="\nFRAGMENT_SHADER_GLOBALS";
+		String material_tag="\nMATERIAL_UNIFORMS";
 		String code_tag="\nFRAGMENT_SHADER_CODE";
 		String code_tag="\nFRAGMENT_SHADER_CODE";
 		String light_code_tag="\nLIGHT_SHADER_CODE";
 		String light_code_tag="\nLIGHT_SHADER_CODE";
 		String code =  fragment_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();
 			fragment_code0=code.substr(0,cpos).ascii();
 			code = code.substr(cpos+globals_tag.length(),code.length());
 			code = code.substr(cpos+globals_tag.length(),code.length());
 
 
-			cpos = code.find(code_tag);
+			cpos = code.find(material_tag);
 
 
 			if (cpos==-1) {
 			if (cpos==-1) {
 				fragment_code1=code.ascii();
 				fragment_code1=code.ascii();
 			} else {
 			} else {
 
 
 				fragment_code1=code.substr(0,cpos).ascii();
 				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) {
 				if (cpos==-1) {
 					fragment_code2=code2.ascii();
 					fragment_code2=code2.ascii();
 				} else {
 				} else {
 
 
 					fragment_code2=code2.substr(0,cpos).ascii();
 					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++;
 	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));
 	ERR_FAIL_COND(!custom_code_map.has(p_code_id));
 	CustomCode *cc=&custom_code_map[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=p_fragment;
 	cc->fragment_globals=p_fragment_globals;
 	cc->fragment_globals=p_fragment_globals;
 	cc->light=p_light;
 	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->custom_defines=p_custom_defines;
 	cc->version++;
 	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() {
 ShaderGLES3::ShaderGLES3() {
 	version=NULL;
 	version=NULL;
 	last_custom_code=1;
 	last_custom_code=1;
 	uniforms_dirty = true;
 	uniforms_dirty = true;
-
+	base_material_tex_index=0;
 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units);
 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units);
 }
 }
 
 

+ 17 - 10
drivers/gles3/shader_gles3.h

@@ -105,9 +105,10 @@ private:
 		String fragment;
 		String fragment;
 		String fragment_globals;
 		String fragment_globals;
 		String light;
 		String light;
+		String uniforms;
 		uint32_t version;
 		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 vert_id;
 		GLuint frag_id;					
 		GLuint frag_id;					
 		GLint *uniform_location;
 		GLint *uniform_location;
-		Vector<GLint> custom_uniform_locations;
+		Vector<GLint> texture_uniform_locations;
 		uint32_t code_version;
 		uint32_t code_version;
 		bool ok;
 		bool ok;
 		Version() { code_version=0; ok=false; uniform_location=NULL; }
 		Version() { code_version=0; ok=false; uniform_location=NULL; }
@@ -166,10 +167,14 @@ private:
 	CharString fragment_code1;
 	CharString fragment_code1;
 	CharString fragment_code2;
 	CharString fragment_code2;
 	CharString fragment_code3;
 	CharString fragment_code3;
+	CharString fragment_code4;
 
 
 	CharString vertex_code0;
 	CharString vertex_code0;
 	CharString vertex_code1;
 	CharString vertex_code1;
 	CharString vertex_code2;
 	CharString vertex_code2;
+	CharString vertex_code3;
+
+	int base_material_tex_index;
 
 
 	Version * get_current_version();
 	Version * get_current_version();
 	
 	
@@ -308,7 +313,7 @@ public:
 	void clear_caches();
 	void clear_caches();
 
 
 	uint32_t create_custom_shader();
 	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 set_custom_shader(uint32_t p_id);
 	void free_custom_shader(uint32_t p_id);
 	void free_custom_shader(uint32_t p_id);
 
 
@@ -332,23 +337,25 @@ public:
 		uniforms_dirty = true;
 		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_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_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;
 	virtual void init()=0;
 	void finish();
 	void finish();
 
 
+	void set_base_material_tex_index(int p_idx);
+
 	virtual ~ShaderGLES3();
 	virtual ~ShaderGLES3();
 
 
 };
 };

+ 50 - 22
drivers/gles3/shaders/canvas.glsl

@@ -1,7 +1,7 @@
 [vertex]
 [vertex]
 
 
 
 
-layout(location=0) in highp vec3 vertex;
+layout(location=0) in highp vec2 vertex;
 layout(location=3) in vec4 color_attrib;
 layout(location=3) in vec4 color_attrib;
 
 
 #ifdef USE_TEXTURE_RECT
 #ifdef USE_TEXTURE_RECT
@@ -20,6 +20,7 @@ layout(location=4) in highp vec2 uv_attrib;
 layout(std140) uniform CanvasItemData { //ubo:0
 layout(std140) uniform CanvasItemData { //ubo:0
 
 
 	highp mat4 projection_matrix;
 	highp mat4 projection_matrix;
+	highp vec4 time;
 };
 };
 
 
 uniform highp mat4 modelview_matrix;
 uniform highp mat4 modelview_matrix;
@@ -29,10 +30,6 @@ uniform highp mat4 extra_matrix;
 out mediump vec2 uv_interp;
 out mediump vec2 uv_interp;
 out mediump vec4 color_interp;
 out mediump vec4 color_interp;
 
 
-#if defined(USE_TIME)
-uniform float time;
-#endif
-
 #ifdef USE_LIGHTING
 #ifdef USE_LIGHTING
 
 
 layout(std140) uniform LightData { //ubo:1
 layout(std140) uniform LightData { //ubo:1
@@ -51,6 +48,7 @@ layout(std140) uniform LightData { //ubo:1
 	highp float shadow_distance_mult;
 	highp float shadow_distance_mult;
 };
 };
 
 
+
 out vec4 light_uv_interp;
 out vec4 light_uv_interp;
 
 
 #if defined(NORMAL_USED)
 #if defined(NORMAL_USED)
@@ -66,20 +64,30 @@ out highp vec2 pos;
 
 
 VERTEX_SHADER_GLOBALS
 VERTEX_SHADER_GLOBALS
 
 
+#if defined(USE_MATERIAL)
+
+layout(std140) uniform UniformData { //ubo:2
+
+MATERIAL_UNIFORMS
+
+};
+
+#endif
+
 void main() {
 void main() {
 
 
-	color_interp = color_attrib;
+	vec4 vertex_color = color_attrib;
 
 
 
 
 #ifdef USE_TEXTURE_RECT
 #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
 #else
 	uv_interp = uv_attrib;
 	uv_interp = uv_attrib;
-	highp vec4 outvec = vec4(vertex, 1.0);
+	highp vec4 outvec = vec4(vertex,0.0,1.0);
 #endif
 #endif
 
 
 
 
@@ -90,16 +98,16 @@ VERTEX_SHADER_CODE
 
 
 }
 }
 
 
-#if !defined(USE_WORLD_VEC)
+#if !defined(SKIP_TRANSFORM_USED)
 	outvec = extra_matrix * outvec;
 	outvec = extra_matrix * outvec;
 	outvec = modelview_matrix * outvec;
 	outvec = modelview_matrix * outvec;
 #endif
 #endif
 
 
-
+	color_interp = vertex_color;
 
 
 #ifdef USE_PIXEL_SNAP
 #ifdef USE_PIXEL_SNAP
 
 
-	outvec.xy=floor(outvec.xy+0.5);
+	outvec.xy=floor(outvec+0.5);
 #endif
 #endif
 
 
 
 
@@ -132,20 +140,24 @@ VERTEX_SHADER_CODE
 
 
 
 
 uniform mediump sampler2D color_texture; // texunit:0
 uniform mediump sampler2D color_texture; // texunit:0
+uniform highp vec2 color_texpixel_size;
 
 
 in mediump vec2 uv_interp;
 in mediump vec2 uv_interp;
 in mediump vec4 color_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
 #endif
 
 
-#if defined(USE_TIME)
-uniform float time;
-#endif
+layout(std140) uniform CanvasItemData {
+
+	highp mat4 projection_matrix;
+	highp vec4 time;
+};
+
 
 
 #ifdef USE_LIGHTING
 #ifdef USE_LIGHTING
 
 
@@ -188,6 +200,17 @@ FRAGMENT_SHADER_GLOBALS
 
 
 layout(location=0) out mediump vec4 frag_color;
 layout(location=0) out mediump vec4 frag_color;
 
 
+
+#if defined(USE_MATERIAL)
+
+layout(std140) uniform UniformData {
+
+MATERIAL_UNIFORMS
+
+};
+
+#endif
+
 void main() {
 void main() {
 
 
 	vec4 color = color_interp;
 	vec4 color = color_interp;
@@ -195,6 +218,9 @@ void main() {
 	vec3 normal = vec3(0.0,0.0,1.0);
 	vec3 normal = vec3(0.0,0.0,1.0);
 #endif
 #endif
 
 
+#if !defined(COLOR_USED)
+//default behavior, texture by color
+
 #ifdef USE_DISTANCE_FIELD
 #ifdef USE_DISTANCE_FIELD
 	const float smoothing = 1.0/32.0;
 	const float smoothing = 1.0/32.0;
 	float distance = texture(color_texture, uv_interp).a;
 	float distance = texture(color_texture, uv_interp).a;
@@ -204,6 +230,7 @@ void main() {
 
 
 #endif
 #endif
 
 
+#endif
 
 
 #if defined(ENABLE_SCREEN_UV)
 #if defined(ENABLE_SCREEN_UV)
 	vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult;
 	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;
 	float normal_depth=1.0;
+
+#if defined(NORMALMAP_USED)
+	vec3 normal_map=vec3(0.0,0.0,1.0);
 #endif
 #endif
 
 
 FRAGMENT_SHADER_CODE
 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 );
 	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
 #endif
 
 
@@ -246,7 +274,7 @@ FRAGMENT_SHADER_CODE
 
 
 	vec2 light_uv = light_uv_interp.xy;
 	vec2 light_uv = light_uv_interp.xy;
 	vec4 light = texture(light_texture,light_uv) * light_color;
 	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);
 	vec4 shadow_color=vec4(0.0,0.0,0.0,0.0);
 #endif
 #endif
 
 
@@ -409,7 +437,7 @@ LIGHT_SHADER_CODE
 #endif
 #endif
 
 
 
 
-#if defined(USE_OUTPUT_SHADOW_COLOR)
+#if defined(SHADOW_COLOR_USED)
 	color=mix(shadow_color,color,shadow_attenuation);
 	color=mix(shadow_color,color,shadow_attenuation);
 #else
 #else
 	//color*=shadow_attenuation;
 	//color*=shadow_attenuation;

+ 4 - 0
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[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);
 			print("\E[0;35m   At: %s:%i.\E[0m\n",p_file,p_line);
 			break;
 			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;
 	}
 	}
 }
 }
 
 

+ 9 - 0
platform/windows/os_windows.cpp

@@ -1727,6 +1727,10 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
 				print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
 				print("SCRIPT ERROR: %s: %s\n", p_function, err_details);
 				print("          At: %s:%i\n", p_file, p_line);
 				print("          At: %s:%i\n", p_file, p_line);
 				break;
 				break;
+			case ERR_SHADER:
+				print("SHADER ERROR: %s: %s\n", p_function, err_details);
+				print("          At: %s:%i\n", p_file, p_line);
+				break;
 		}
 		}
 
 
 	} else {
 	} else {
@@ -1742,6 +1746,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
 			case ERR_ERROR: basecol = FOREGROUND_RED; break;
 			case ERR_ERROR: basecol = FOREGROUND_RED; break;
 			case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
 			case ERR_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break;
 			case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
 			case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break;
+			case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break;
 		}
 		}
 
 
 		basecol |= current_bg;
 		basecol |= current_bg;
@@ -1753,6 +1758,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
 				case ERR_ERROR: print("ERROR: "); break;
 				case ERR_ERROR: print("ERROR: "); break;
 				case ERR_WARNING: print("WARNING: "); break;
 				case ERR_WARNING: print("WARNING: "); break;
 				case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
 				case ERR_SCRIPT: print("SCRIPT ERROR: "); break;
+				case ERR_SCRIPT: print("SHADER ERROR: "); break;
 			}
 			}
 
 
 			SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
 			SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
@@ -1763,6 +1769,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
 				case ERR_ERROR: print("   At: "); break;
 				case ERR_ERROR: print("   At: "); break;
 				case ERR_WARNING: print("     At: "); break;
 				case ERR_WARNING: print("     At: "); break;
 				case ERR_SCRIPT: print("          At: "); break;
 				case ERR_SCRIPT: print("          At: "); break;
+				case ERR_SHADER: print("          At: "); break;
 			}
 			}
 
 
 			SetConsoleTextAttribute(hCon, current_fg | current_bg);
 			SetConsoleTextAttribute(hCon, current_fg | current_bg);
@@ -1775,6 +1782,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
 				case ERR_ERROR: print("ERROR: %s: ", p_function); break;
 				case ERR_ERROR: print("ERROR: %s: ", p_function); break;
 				case ERR_WARNING: print("WARNING: %s: ", p_function); break;
 				case ERR_WARNING: print("WARNING: %s: ", p_function); break;
 				case ERR_SCRIPT: print("SCRIPT ERROR: %s: ", p_function); break;
 				case ERR_SCRIPT: print("SCRIPT ERROR: %s: ", p_function); break;
+				case ERR_SHADER: print("SCRIPT ERROR: %s: ", p_function); break;
 			}
 			}
 
 
 			SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
 			SetConsoleTextAttribute(hCon, current_fg | current_bg | FOREGROUND_INTENSITY);
@@ -1785,6 +1793,7 @@ void OS_Windows::print_error(const char* p_function, const char* p_file, int p_l
 				case ERR_ERROR: print("   At: "); break;
 				case ERR_ERROR: print("   At: "); break;
 				case ERR_WARNING: print("     At: "); break;
 				case ERR_WARNING: print("     At: "); break;
 				case ERR_SCRIPT: print("          At: "); break;
 				case ERR_SCRIPT: print("          At: "); break;
+				case ERR_SHADER: print("          At: "); break;
 			}
 			}
 
 
 			SetConsoleTextAttribute(hCon, current_fg | current_bg);
 			SetConsoleTextAttribute(hCon, current_fg | current_bg);

+ 5 - 9
scene/2d/canvas_item.cpp

@@ -55,7 +55,7 @@ bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value)
 				}
 				}
 			}
 			}
 			if (pr) {
 			if (pr) {
-				VisualServer::get_singleton()->material_set_param(material,pr,p_value);
+				VisualServer::get_singleton()->material_set_param(_get_material(),pr,p_value);
 				return true;
 				return true;
 			}
 			}
 		}
 		}
@@ -78,7 +78,7 @@ bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const {
 
 
 			StringName pr = shader->remap_param(p_name);
 			StringName pr = shader->remap_param(p_name);
 			if (pr) {
 			if (pr) {
-				r_ret=VisualServer::get_singleton()->material_get_param(material,pr);
+				r_ret=VisualServer::get_singleton()->material_get_param(_get_material(),pr);
 				return true;
 				return true;
 			}
 			}
 		}
 		}
@@ -111,7 +111,7 @@ void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) {
 	if (shader.is_valid())
 	if (shader.is_valid())
 		rid=shader->get_rid();
 		rid=shader->get_rid();
 
 
-	VS::get_singleton()->material_set_shader(material,rid);
+	VS::get_singleton()->material_set_shader(_get_material(),rid);
 	_change_notify(); //properties for shader exposed
 	_change_notify(); //properties for shader exposed
 	emit_changed();
 	emit_changed();
 }
 }
@@ -123,18 +123,14 @@ Ref<Shader> CanvasItemMaterial::get_shader() const{
 
 
 void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){
 void CanvasItemMaterial::set_shader_param(const StringName& p_param,const Variant& p_value){
 
 
-	VS::get_singleton()->material_set_param(material,p_param,p_value);
+	VS::get_singleton()->material_set_param(_get_material(),p_param,p_value);
 }
 }
 
 
 Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
 Variant CanvasItemMaterial::get_shader_param(const StringName& p_param) const{
 
 
-	return VS::get_singleton()->material_get_param(material,p_param);
+	return VS::get_singleton()->material_get_param(_get_material(),p_param);
 }
 }
 
 
-RID CanvasItemMaterial::get_rid() const {
-
-	return material;
-}
 
 
 
 
 void CanvasItemMaterial::_bind_methods() {
 void CanvasItemMaterial::_bind_methods() {

+ 1 - 3
scene/2d/canvas_item.h

@@ -41,10 +41,9 @@ class Font;
 
 
 class StyleBox;
 class StyleBox;
 
 
-class CanvasItemMaterial : public Material{
+class CanvasItemMaterial : public Material {
 
 
 	OBJ_TYPE(CanvasItemMaterial,Material);
 	OBJ_TYPE(CanvasItemMaterial,Material);
-	RID material;
 	Ref<Shader> shader;
 	Ref<Shader> shader;
 public:
 public:
 	/*enum ShadingMode {
 	/*enum ShadingMode {
@@ -70,7 +69,6 @@ public:
 	void set_shader_param(const StringName& p_param,const Variant& p_value);
 	void set_shader_param(const StringName& p_param,const Variant& p_value);
 	Variant get_shader_param(const StringName& p_param) const;
 	Variant get_shader_param(const StringName& p_param) const;
 
 
-	virtual RID get_rid() const;
 	CanvasItemMaterial();
 	CanvasItemMaterial();
 	~CanvasItemMaterial();
 	~CanvasItemMaterial();
 };
 };

+ 0 - 37
scene/gui/color_picker.cpp

@@ -34,31 +34,12 @@
 #include "os/input.h"
 #include "os/input.h"
 #include "os/keyboard.h"
 #include "os/keyboard.h"
 
 
-void update_material(Ref<CanvasItemMaterial>mat,const Color& p_color,float h,float s,float v) {
-	if (!mat.is_valid())
-		return;
-	Ref<Shader> sdr = mat->get_shader();
-	if (!sdr.is_valid())
-		return;
-
-	mat->set_shader_param("R",p_color.r);
-	mat->set_shader_param("G",p_color.g);
-	mat->set_shader_param("B",p_color.b);
-	mat->set_shader_param("H",h);
-	mat->set_shader_param("S",s);
-	mat->set_shader_param("V",v);
-	mat->set_shader_param("A",p_color.a);
-}
 
 
 void ColorPicker::_notification(int p_what) {
 void ColorPicker::_notification(int p_what) {
 
 
 
 
 	switch(p_what) {
 	switch(p_what) {
 		case NOTIFICATION_THEME_CHANGED: {
 		case NOTIFICATION_THEME_CHANGED: {
-			uv_material->set_shader(get_shader("uv_editor"));
-			w_material->set_shader(get_shader("w_editor"));
-			update_material(uv_material,color,h,s,v);
-			update_material(w_material,color,h,s,v);
 			uv_edit->set_texture(get_icon("color_main"));
 			uv_edit->set_texture(get_icon("color_main"));
 			w_edit->set_texture(get_icon("color_hue"));
 			w_edit->set_texture(get_icon("color_hue"));
 			sample->set_texture(get_icon("color_sample"));
 			sample->set_texture(get_icon("color_sample"));
@@ -68,8 +49,6 @@ void ColorPicker::_notification(int p_what) {
 
 
 		case NOTIFICATION_ENTER_TREE: {
 		case NOTIFICATION_ENTER_TREE: {
 			btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
 			btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
-			update_material(uv_material, color,h,s,v);
-			update_material(w_material, color,h,s,v);
 
 
 			uv_edit->get_child(0)->cast_to<Control>()->update();
 			uv_edit->get_child(0)->cast_to<Control>()->update();
 			w_edit->get_child(0)->cast_to<Control>()->update();
 			w_edit->get_child(0)->cast_to<Control>()->update();
@@ -113,8 +92,6 @@ void ColorPicker::set_color(const Color& p_color) {
 	if (!is_inside_tree())
 	if (!is_inside_tree())
 		return;
 		return;
 
 
-	update_material(uv_material, color,h,s,v);
-	update_material(w_material, color,h,s,v);
 
 
 	uv_edit->get_child(0)->cast_to<Control>()->update();
 	uv_edit->get_child(0)->cast_to<Control>()->update();
 	w_edit->get_child(0)->cast_to<Control>()->update();
 	w_edit->get_child(0)->cast_to<Control>()->update();
@@ -509,7 +486,6 @@ ColorPicker::ColorPicker() :
 	uv_edit->add_child(c);
 	uv_edit->add_child(c);
 	c->set_area_as_parent_rect();
 	c->set_area_as_parent_rect();
 	c->set_stop_mouse(false);
 	c->set_stop_mouse(false);
-	c->set_material(memnew ( CanvasItemMaterial ));
 	Vector<Variant> args=Vector<Variant>();
 	Vector<Variant> args=Vector<Variant>();
 	args.push_back(0);
 	args.push_back(0);
 	args.push_back(c);
 	args.push_back(c);
@@ -525,7 +501,6 @@ ColorPicker::ColorPicker() :
 	w_edit->add_child(c);
 	w_edit->add_child(c);
 	c->set_area_as_parent_rect();
 	c->set_area_as_parent_rect();
 	c->set_stop_mouse(false);
 	c->set_stop_mouse(false);
-	c->set_material(memnew ( CanvasItemMaterial ));
 	args.clear();
 	args.clear();
 	args.push_back(1);
 	args.push_back(1);
 	args.push_back(c);
 	args.push_back(c);
@@ -593,18 +568,6 @@ ColorPicker::ColorPicker() :
 	//_update_color();
 	//_update_color();
 	updating=false;
 	updating=false;
 
 
-	uv_material.instance();
-	Ref<Shader> s_uv = get_shader("uv_editor");
-	uv_material->set_shader(s_uv);
-
-	w_material.instance();
-
-	Ref<Shader> s_w = get_shader("w_editor");
-	w_material->set_shader(s_w);
-
-	uv_edit->set_material(uv_material);
-	w_edit->set_material(w_material);
-
 	set_color(Color(1,1,1));
 	set_color(Color(1,1,1));
 
 
 
 

+ 0 - 2
scene/gui/color_picker.h

@@ -57,8 +57,6 @@ private:
 	List<Color> presets;
 	List<Color> presets;
 	ToolButton *btn_pick;
 	ToolButton *btn_pick;
 	CheckButton *btn_mode;
 	CheckButton *btn_mode;
-	Ref<CanvasItemMaterial> uv_material;
-	Ref<CanvasItemMaterial> w_material;
 	HSlider *scroll[4];
 	HSlider *scroll[4];
 	SpinBox *values[4];
 	SpinBox *values[4];
 	Label *labels[4];
 	Label *labels[4];

+ 3 - 0
scene/resources/material.h

@@ -46,6 +46,9 @@ class Material : public Resource {
 	OBJ_SAVE_TYPE( Material );
 	OBJ_SAVE_TYPE( Material );
 
 
 	RID material;
 	RID material;
+protected:
+
+	_FORCE_INLINE_  RID _get_material() const { return material; }
 public:
 public:
 
 
 	virtual RID get_rid() const;
 	virtual RID get_rid() const;

+ 51 - 2
servers/visual/shader_language.cpp

@@ -712,6 +712,8 @@ bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
 
 
 void ShaderLanguage::clear() {
 void ShaderLanguage::clear() {
 
 
+	current_function=StringName();
+
 	completion_type=COMPLETION_NONE;
 	completion_type=COMPLETION_NONE;
 	completion_block=NULL;
 	completion_block=NULL;
 	completion_function=StringName();
 	completion_function=StringName();
@@ -2096,6 +2098,12 @@ bool ShaderLanguage::is_scalar_type(DataType p_type) {
 	return p_type==TYPE_BOOL || p_type==TYPE_INT || p_type==TYPE_UINT || p_type==TYPE_FLOAT;
 	return p_type==TYPE_BOOL || p_type==TYPE_INT || p_type==TYPE_UINT || p_type==TYPE_FLOAT;
 }
 }
 
 
+bool ShaderLanguage::is_sampler_type(DataType p_type) {
+
+	return p_type==TYPE_SAMPLER2D || p_type==TYPE_ISAMPLER2D || p_type==TYPE_USAMPLER2D || p_type==TYPE_SAMPLERCUBE;
+
+}
+
 void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
 void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
 
 
 	Set<String> kws;
 	Set<String> kws;
@@ -2122,6 +2130,27 @@ void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
 	}
 	}
 }
 }
 
 
+void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
+
+
+	Set<String> kws;
+
+	int idx=0;
+
+	while (builtin_func_defs[idx].name) {
+
+		kws.insert(builtin_func_defs[idx].name);
+
+		idx++;
+	}
+
+	for(Set<String>::Element *E=kws.front();E;E=E->next()) {
+		r_keywords->push_back(E->get());
+	}
+}
+
+
+
 ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
 ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
 
 
 	static const DataType scalar_types[]={
 	static const DataType scalar_types[]={
@@ -2342,6 +2371,12 @@ ShaderLanguage::Node* ShaderLanguage::_parse_expression(BlockNode* p_block,const
 
 
 				bool ok =_parse_function_arguments(p_block,p_builtin_types,func,&carg);
 				bool ok =_parse_function_arguments(p_block,p_builtin_types,func,&carg);
 
 
+				for(int i=0;i<shader->functions.size();i++) {
+					if (shader->functions[i].name==name) {
+						shader->functions[i].uses_function.insert(name);
+					}
+				}
+
 
 
 
 
 				if (carg>=0) {
 				if (carg>=0) {
@@ -3140,6 +3175,9 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
 
 
 	Token tk = _get_token();
 	Token tk = _get_token();
 
 
+	int texture_uniforms = 0;
+	int uniforms =0;
+
 	while(tk.type!=TK_EOF) {
 	while(tk.type!=TK_EOF) {
 
 
 		switch(tk.type) {
 		switch(tk.type) {
@@ -3160,12 +3198,12 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
 
 
-					if (shader->render_modes.has(tk.text)) {
+					if (shader->render_modes.find(tk.text)!=-1) {
 						_set_error("Duplicate render mode: '"+String(tk.text)+"'");
 						_set_error("Duplicate render mode: '"+String(tk.text)+"'");
 						return ERR_PARSE_ERROR;
 						return ERR_PARSE_ERROR;
 					}
 					}
 
 
-					shader->render_modes.insert(tk.text);
+					shader->render_modes.push_back(tk.text);
 
 
 					tk = _get_token();
 					tk = _get_token();
 					if (tk.type==TK_COMMA) {
 					if (tk.type==TK_COMMA) {
@@ -3225,6 +3263,13 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
 
 
 					ShaderNode::Uniform uniform;
 					ShaderNode::Uniform uniform;
 					uniform.order=shader->uniforms.size();
 					uniform.order=shader->uniforms.size();
+					if (is_sampler_type(type)) {
+						uniform.texture_order=texture_uniforms++;
+						uniform.order=-1;
+					} else {
+						uniform.texture_order=-1;
+						uniform.order=uniforms++;
+					}
 					uniform.type=type;
 					uniform.type=type;
 					uniform.precission=precision;
 					uniform.precission=precision;
 
 
@@ -3520,9 +3565,13 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
 					return ERR_PARSE_ERROR;
 					return ERR_PARSE_ERROR;
 				}
 				}
 
 
+				current_function = name;
+
 				Error err = _parse_block(func_node->body,builtin_types);
 				Error err = _parse_block(func_node->body,builtin_types);
 				if (err)
 				if (err)
 					return err;
 					return err;
+
+				current_function=StringName();
 			}
 			}
 		}
 		}
 
 

+ 7 - 1
servers/visual/shader_language.h

@@ -370,6 +370,7 @@ public:
 		struct Function {
 		struct Function {
 			StringName name;
 			StringName name;
 			FunctionNode*function;
 			FunctionNode*function;
+			Set<StringName> uses_function;
 			bool callable;
 			bool callable;
 		};
 		};
 
 
@@ -391,6 +392,7 @@ public:
 			};
 			};
 
 
 			int order;
 			int order;
+			int texture_order;
 			DataType type;
 			DataType type;
 			DataPrecision precission;
 			DataPrecision precission;
 			Vector<ConstantNode::Value> default_value;
 			Vector<ConstantNode::Value> default_value;
@@ -403,7 +405,7 @@ public:
 
 
 		Map<StringName,Varying> varyings;
 		Map<StringName,Varying> varyings;
 		Map<StringName,Uniform> uniforms;
 		Map<StringName,Uniform> uniforms;
-		Set<StringName> render_modes;
+		Vector<StringName> render_modes;
 
 
 		Vector<Function> functions;
 		Vector<Function> functions;
 
 
@@ -461,8 +463,10 @@ public:
 	static bool convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value=NULL);
 	static bool convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value=NULL);
 	static DataType get_scalar_type(DataType p_type);
 	static DataType get_scalar_type(DataType p_type);
 	static bool is_scalar_type(DataType p_type);
 	static bool is_scalar_type(DataType p_type);
+	static bool is_sampler_type(DataType p_type);
 
 
 	static void get_keyword_list(List<String> *r_keywords);
 	static void get_keyword_list(List<String> *r_keywords);
+	static void get_builtin_funcs(List<String> *r_keywords);
 private:
 private:
 
 
 	struct KeyWord { TokenType token; const char *text;};
 	struct KeyWord { TokenType token; const char *text;};
@@ -476,6 +480,8 @@ private:
 	int char_idx;
 	int char_idx;
 	int tk_line;
 	int tk_line;
 
 
+	StringName current_function;
+
 	struct TkPos {
 	struct TkPos {
 		int char_idx;
 		int char_idx;
 		int tk_line;
 		int tk_line;

+ 62 - 0
servers/visual/shader_types.cpp

@@ -18,6 +18,7 @@ ShaderTypes::ShaderTypes()
 {
 {
 	singleton=this;
 	singleton=this;
 
 
+	/*************** SPATIAL ***********************/
 
 
 	shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC3;
 	shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC3;
 	shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_NORMAL"]=ShaderLanguage::TYPE_VEC3;
 	shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_NORMAL"]=ShaderLanguage::TYPE_VEC3;
@@ -96,4 +97,65 @@ ShaderTypes::ShaderTypes()
 	shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_model_space");
 	shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_model_space");
 	shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_camera_space");
 	shader_modes[VS::SHADER_SPATIAL].modes.insert("vertex_camera_space");
 
 
+	/************ CANVAS ITEM **************************/
+
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX_COLOR"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT;
+
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["EXTRA_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["UV"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR1"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR2"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_VEC"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_HEIGHT"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_COLOR"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_UV"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_SHADOW"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SHADOW"]=ShaderLanguage::TYPE_VEC4;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_transform");
+
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix");
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add");
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub");
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mul");
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_premul_alpha");
+
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded");
+	shader_modes[VS::SHADER_SPATIAL].modes.insert("light_only");
+
+
+
+
+
+
 }
 }

+ 1 - 0
servers/visual_server.h

@@ -140,6 +140,7 @@ public:
 		SHADER_SPATIAL,
 		SHADER_SPATIAL,
 		SHADER_CANVAS_ITEM,
 		SHADER_CANVAS_ITEM,
 		SHADER_LIGHT,
 		SHADER_LIGHT,
+		SHADER_MAX
 	};
 	};
 
 
 
 

+ 4 - 0
tools/editor/editor_log.cpp

@@ -67,6 +67,10 @@ void EditorLog::_error_handler(void *p_self, const char*p_func, const char*p_fil
 
 
 			icon = self->get_icon("ScriptError","EditorIcons");
 			icon = self->get_icon("ScriptError","EditorIcons");
 		} break;
 		} break;
+		case ERR_HANDLER_SHADER: {
+
+			icon = self->get_icon("Shader","EditorIcons");
+		} break;
 
 
 	}
 	}