mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +00:00 
			
		
		
		
	2D Shaders are working again using the new syntax, though all is buggy in general
This commit is contained in:
		
							parent
							
								
									850eaf7ed7
								
							
						
					
					
						commit
						1527cf8c0d
					
				
					 26 changed files with 1980 additions and 173 deletions
				
			
		|  | @ -49,7 +49,8 @@ | |||
| enum ErrorHandlerType { | ||||
| 	ERR_HANDLER_ERROR, | ||||
| 	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); | ||||
|  |  | |||
|  | @ -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_WARNING: err_type="**WARNING**"; break; | ||||
| 		case ERR_SCRIPT: err_type="**SCRIPT ERROR**"; break; | ||||
| 		case ERR_SHADER: err_type="**SHADER ERROR**"; break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (p_rationale && *p_rationale) | ||||
|  |  | |||
|  | @ -120,7 +120,8 @@ public: | |||
| 	enum ErrorType { | ||||
| 		ERR_ERROR, | ||||
| 		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); | ||||
|  |  | |||
|  | @ -34,6 +34,9 @@ struct Pair { | |||
| 
 | ||||
| 	F first; | ||||
| 	S second; | ||||
| 
 | ||||
| 	Pair() {} | ||||
| 	Pair( F p_first,  S p_second) { first=p_first; second=p_second; } | ||||
| }; | ||||
| 
 | ||||
| #endif // PAIR_H
 | ||||
|  |  | |||
|  | @ -138,6 +138,7 @@ void RasterizerCanvasGLES3::canvas_begin(){ | |||
| 	state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD,false); | ||||
| 
 | ||||
| 
 | ||||
| 	state.canvas_shader.set_custom_shader(0); | ||||
| 	state.canvas_shader.bind(); | ||||
| 	state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,Color(1,1,1,1)); | ||||
| 	state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Matrix32()); | ||||
|  | @ -520,6 +521,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr | |||
| 						//err..
 | ||||
| 					} | ||||
| 
 | ||||
| 					state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); | ||||
| 
 | ||||
| 
 | ||||
| 					glVertexAttrib4f(1,rect->rect.pos.x,rect->rect.pos.y,rect->rect.size.x,rect->rect.size.y); | ||||
| 					glVertexAttrib4f(2,src_rect.pos.x,src_rect.pos.y,src_rect.size.x,src_rect.size.y); | ||||
|  | @ -567,6 +570,8 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr | |||
| 
 | ||||
| 				Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); | ||||
| 
 | ||||
| 				state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); | ||||
| 
 | ||||
| #define DSTRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(1,m_x,m_y,m_w,m_h) | ||||
| #define SRCRECT(m_x,m_y,m_w,m_h) glVertexAttrib4f(2,(m_x)*texpixel_size.x,(m_y)*texpixel_size.y,(m_w)*texpixel_size.x,(m_h)*texpixel_size.y) | ||||
| 
 | ||||
|  | @ -634,8 +639,13 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr | |||
| 
 | ||||
| 				ERR_CONTINUE( primitive->points.size()<1); | ||||
| 
 | ||||
| 				_bind_canvas_texture(primitive->texture); | ||||
| 				RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(primitive->texture); | ||||
| 
 | ||||
| 				if (texture ) { | ||||
| 					Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); | ||||
| 					state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); | ||||
| 
 | ||||
| 				} | ||||
| 				if (primitive->colors.size()==1 && primitive->points.size()>1) { | ||||
| 
 | ||||
| 					Color c = primitive->colors[0]; | ||||
|  | @ -652,6 +662,14 @@ void RasterizerCanvasGLES3::_canvas_item_render_commands(Item *p_item,Item *curr | |||
| 
 | ||||
| 				Item::CommandPolygon* polygon = static_cast<Item::CommandPolygon*>(c); | ||||
| 				_set_texture_rect_mode(false); | ||||
| 
 | ||||
| 				RasterizerStorageGLES3::Texture* texture = _bind_canvas_texture(polygon->texture); | ||||
| 
 | ||||
| 				if (texture ) { | ||||
| 					Size2 texpixel_size( 1.0/texture->width, 1.0/texture->height ); | ||||
| 					state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE,texpixel_size); | ||||
| 
 | ||||
| 				} | ||||
| 				_draw_polygon(polygon->count,polygon->indices.ptr(),polygon->points.ptr(),polygon->uvs.ptr(),polygon->colors.ptr(),polygon->texture,polygon->colors.size()==1); | ||||
| 
 | ||||
| 			} break; | ||||
|  | @ -800,10 +818,14 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 	glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); | ||||
| 
 | ||||
| 
 | ||||
| 	int last_blend_mode=-1; | ||||
| 
 | ||||
| 	RID canvas_last_material; | ||||
| 
 | ||||
| 	bool prev_distance_field=false; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	while(p_item_list) { | ||||
| 
 | ||||
| 		Item *ci=p_item_list; | ||||
|  | @ -878,53 +900,71 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 		RID material = material_owner->material; | ||||
| 
 | ||||
| 		if (material!=canvas_last_material || rebind_shader) { | ||||
| #if 0 | ||||
| 			Shader *shader = NULL; | ||||
| 			if (material && material->shader.is_valid()) { | ||||
| 				shader = shader_owner.get(material->shader); | ||||
| 				if (shader && !shader->valid) { | ||||
| 					shader=NULL; | ||||
| 
 | ||||
| 			RasterizerStorageGLES3::Material *material_ptr = storage->material_owner.getornull(material); | ||||
| 			RasterizerStorageGLES3::Shader *shader_ptr = NULL; | ||||
| 
 | ||||
| 			if (material_ptr) { | ||||
| 
 | ||||
| 				shader_ptr = material_ptr->shader; | ||||
| 
 | ||||
| 				if (shader_ptr && shader_ptr->mode!=VS::SHADER_CANVAS_ITEM) { | ||||
| 					shader_ptr=NULL; //do not use non canvasitem shader
 | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			shader_cache=shader; | ||||
| 
 | ||||
| 			if (shader) { | ||||
| 				canvas_shader.set_custom_shader(shader->custom_code_id); | ||||
| 				_canvas_item_setup_shader_params(material,shader); | ||||
| 			} else { | ||||
| 				shader_cache=NULL; | ||||
| 				canvas_shader.set_custom_shader(0); | ||||
| 				canvas_shader.bind(); | ||||
| 				uses_texpixel_size=false; | ||||
| 			if (shader_ptr && shader_ptr!=shader_cache) { | ||||
| 
 | ||||
| 				state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); | ||||
| 				state.canvas_shader.bind(); | ||||
| 
 | ||||
| 				if (material_ptr->ubo_id) { | ||||
| 					glBindBufferBase(GL_UNIFORM_BUFFER,2,material_ptr->ubo_id); | ||||
| 				} | ||||
| 
 | ||||
| 				int tc = material_ptr->textures.size(); | ||||
| 				RID* textures = material_ptr->textures.ptr(); | ||||
| 
 | ||||
| 				for(int i=0;i<tc;i++) { | ||||
| 
 | ||||
| 					glActiveTexture(GL_TEXTURE1+i); | ||||
| 
 | ||||
| 					RasterizerStorageGLES3::Texture *t = storage->texture_owner.getornull( textures[i] ); | ||||
| 					if (!t) { | ||||
| 						//check hints
 | ||||
| 						glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex); | ||||
| 						continue; | ||||
| 					} | ||||
| 
 | ||||
| 					glBindTexture(t->target,t->tex_id); | ||||
| 				} | ||||
| 
 | ||||
| 
 | ||||
| 			} else if (!shader_ptr) { | ||||
| 				state.canvas_shader.set_custom_shader(0); | ||||
| 				state.canvas_shader.bind(); | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 			shader_cache=shader_ptr; | ||||
| 
 | ||||
| 			canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,canvas_transform); | ||||
| 			if (canvas_use_modulate) | ||||
| 				reset_modulate=true; | ||||
| 			canvas_last_material=material; | ||||
| 			rebind_shader=false; | ||||
| #endif | ||||
| 
 | ||||
| 		} | ||||
| 
 | ||||
| 		if (material.is_valid() && shader_cache) { | ||||
| #if 0 | ||||
| 			_canvas_item_setup_shader_uniforms(material,shader_cache); | ||||
| #endif | ||||
| 		} | ||||
| 
 | ||||
| 		bool unshaded = false; //(material && material->shading_mode==VS::CANVAS_ITEM_SHADING_UNSHADED) || ci->blend_mode!=VS::MATERIAL_BLEND_MODE_MIX;
 | ||||
| 		int blend_mode = shader_cache ? shader_cache->canvas_item.blend_mode : RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX; | ||||
| 		bool unshaded = shader_cache && (shader_cache->canvas_item.light_mode==RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_UNSHADED || blend_mode!=RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX); | ||||
| 		bool reclip=false; | ||||
| #if 0 | ||||
| 		if (ci==p_item_list || ci->blend_mode!=canvas_blend_mode) { | ||||
| 
 | ||||
| 			switch(ci->blend_mode) { | ||||
| 		if (last_blend_mode!=blend_mode) { | ||||
| 
 | ||||
| 				 case VS::MATERIAL_BLEND_MODE_MIX: { | ||||
| 			switch(blend_mode) { | ||||
| 
 | ||||
| 				 case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX: { | ||||
| 					glBlendEquation(GL_FUNC_ADD); | ||||
| 					if (current_rt && current_rt_transparent) { | ||||
| 					if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { | ||||
| 						glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); | ||||
| 					} | ||||
| 					else { | ||||
|  | @ -932,33 +972,30 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 					} | ||||
| 
 | ||||
| 				 } break; | ||||
| 				 case VS::MATERIAL_BLEND_MODE_ADD: { | ||||
| 				 case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_ADD: { | ||||
| 
 | ||||
| 					glBlendEquation(GL_FUNC_ADD); | ||||
| 					glBlendFunc(GL_SRC_ALPHA,GL_ONE); | ||||
| 
 | ||||
| 				 } break; | ||||
| 				 case VS::MATERIAL_BLEND_MODE_SUB: { | ||||
| 				 case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_SUB: { | ||||
| 
 | ||||
| 					glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); | ||||
| 					glBlendFunc(GL_SRC_ALPHA,GL_ONE); | ||||
| 				 } break; | ||||
| 				case VS::MATERIAL_BLEND_MODE_MUL: { | ||||
| 				case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MUL: { | ||||
| 					glBlendEquation(GL_FUNC_ADD); | ||||
| 					glBlendFunc(GL_DST_COLOR,GL_ZERO); | ||||
| 				} break; | ||||
| 				case VS::MATERIAL_BLEND_MODE_PREMULT_ALPHA: { | ||||
| 				case RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA: { | ||||
| 					glBlendEquation(GL_FUNC_ADD); | ||||
| 					glBlendFunc(GL_ONE,GL_ONE_MINUS_SRC_ALPHA); | ||||
| 				} break; | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 			canvas_blend_mode=ci->blend_mode; | ||||
| 			last_blend_mode=blend_mode; | ||||
| 		} | ||||
| #endif | ||||
| 
 | ||||
| //		canvas_shader.set_uniform(CanvasShaderGLES3::CANVAS_MODULATE,unshaded ? Color(1,1,1,1) : p_modulate);
 | ||||
| 
 | ||||
| 		state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( | ||||
| 					ci->final_modulate.r * p_modulate.r, | ||||
|  | @ -974,10 +1011,10 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 		state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,state.extra_matrix); | ||||
| 
 | ||||
| 
 | ||||
| 		if (unshaded || (state.canvas_item_modulate.a>0.001 && (!material.is_valid() /*|| material->shading_mode!=VS::CANVAS_ITEM_SHADING_ONLY_LIGHT*/) && !ci->light_masked )) | ||||
| 		if (unshaded || (state.canvas_item_modulate.a>0.001 && (!shader_cache || shader_cache->canvas_item.light_mode!=RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked )) | ||||
| 			_canvas_item_render_commands(ci,current_clip,reclip); | ||||
| 
 | ||||
| 		if (/*canvas_blend_mode==VS::MATERIAL_BLEND_MODE_MIX &&*/ p_light && !unshaded) { | ||||
| 		if ((blend_mode==RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_MIX || RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_PMALPHA) && p_light && !unshaded) { | ||||
| 
 | ||||
| 			Light *light = p_light; | ||||
| 			bool light_used=false; | ||||
|  | @ -1046,12 +1083,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 					bool light_rebind = state.canvas_shader.bind(); | ||||
| 
 | ||||
| 					if (light_rebind) { | ||||
| #if 0 | ||||
| 						if (material && shader_cache) { | ||||
| 							_canvas_item_setup_shader_params(material,shader_cache); | ||||
| 							_canvas_item_setup_shader_uniforms(material,shader_cache); | ||||
| 						} | ||||
| #endif | ||||
| 
 | ||||
| 						state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate); | ||||
| 						state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,state.final_transform); | ||||
| 						state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32()); | ||||
|  | @ -1100,15 +1132,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 				state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9,false); | ||||
| 				state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13,false); | ||||
| 
 | ||||
| 
 | ||||
| 				state.canvas_shader.bind(); | ||||
| #if 0 | ||||
| 				if (material && shader_cache) { | ||||
| 					_canvas_item_setup_shader_params(material,shader_cache); | ||||
| 					_canvas_item_setup_shader_uniforms(material,shader_cache); | ||||
| 				} | ||||
| #endif | ||||
| 
 | ||||
| 				last_blend_mode=-1; | ||||
| 
 | ||||
| 				/*
 | ||||
| 				//this is set again, so it should not be needed anyway?
 | ||||
| 				state.canvas_item_modulate = unshaded ? ci->final_modulate : Color( | ||||
| 							ci->final_modulate.r * p_modulate.r, | ||||
| 							ci->final_modulate.g * p_modulate.g, | ||||
|  | @ -1120,7 +1149,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 				state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX,Matrix32()); | ||||
| 				state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE,state.canvas_item_modulate); | ||||
| 
 | ||||
| 
 | ||||
| 				glBlendEquation(GL_FUNC_ADD); | ||||
| 
 | ||||
| 				if (storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { | ||||
|  | @ -1130,6 +1158,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const | |||
| 				} | ||||
| 
 | ||||
| 				//@TODO RESET canvas_blend_mode
 | ||||
| 				*/ | ||||
| 			} | ||||
| 
 | ||||
| 
 | ||||
|  | @ -1380,6 +1409,9 @@ void RasterizerCanvasGLES3::reset_canvas() { | |||
| 	state.vp=canvas_transform; | ||||
| 
 | ||||
| 	store_transform(canvas_transform,state.canvas_item_ubo_data.projection_matrix); | ||||
| 	for(int i=0;i<4;i++) { | ||||
| 		state.canvas_item_ubo_data.time[i]=storage->frame.time[i]; | ||||
| 	} | ||||
| 
 | ||||
| 	glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); | ||||
| 	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data); | ||||
|  | @ -1442,6 +1474,7 @@ void RasterizerCanvasGLES3::initialize() { | |||
| 	glBindBuffer(GL_UNIFORM_BUFFER, 0); | ||||
| 
 | ||||
| 	state.canvas_shader.init(); | ||||
| 	state.canvas_shader.set_base_material_tex_index(1); | ||||
| 	state.canvas_shadow_shader.init(); | ||||
| 
 | ||||
| 	state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS,storage->config.use_rgba_2d_shadows); | ||||
|  |  | |||
|  | @ -5,12 +5,14 @@ | |||
| #include "rasterizer_storage_gles3.h" | ||||
| #include "shaders/canvas_shadow.glsl.h" | ||||
| 
 | ||||
| 
 | ||||
| class RasterizerCanvasGLES3 : public RasterizerCanvas { | ||||
| public: | ||||
| 
 | ||||
| 	struct CanvasItemUBO { | ||||
| 
 | ||||
| 		float projection_matrix[16]; | ||||
| 		float time[4]; | ||||
| 
 | ||||
| 	}; | ||||
| 
 | ||||
|  |  | |||
|  | @ -115,8 +115,17 @@ void RasterizerGLES3::initialize() { | |||
| 
 | ||||
| void RasterizerGLES3::begin_frame(){ | ||||
| 
 | ||||
| 	double time_total = double(OS::get_singleton()->get_ticks_usec())/1000000.0; | ||||
| 
 | ||||
| 	storage->frame.time[0]=time_total; | ||||
| 	storage->frame.time[1]=Math::fmod(time_total,3600); | ||||
| 	storage->frame.time[2]=Math::fmod(time_total,900); | ||||
| 	storage->frame.time[3]=Math::fmod(time_total,60); | ||||
| 
 | ||||
| 	storage->update_dirty_shaders(); | ||||
| 	storage->update_dirty_materials(); | ||||
| } | ||||
| 
 | ||||
| void RasterizerGLES3::set_current_render_target(RID p_render_target){ | ||||
| 
 | ||||
| 	if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) { | ||||
|  | @ -257,6 +266,7 @@ RasterizerGLES3::RasterizerGLES3() | |||
| 	storage = memnew( RasterizerStorageGLES3 ); | ||||
| 	canvas = memnew( RasterizerCanvasGLES3 ); | ||||
| 	canvas->storage=storage; | ||||
| 	storage->canvas=canvas; | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| #include "rasterizer_storage_gles3.h" | ||||
| #include "rasterizer_canvas_gles3.h" | ||||
| #include "globals.h" | ||||
| 
 | ||||
| /* TEXTURE API */ | ||||
|  | @ -1000,65 +1001,906 @@ void RasterizerStorageGLES3::texture_set_shrink_all_x2_on_set_data(bool p_enable | |||
| 
 | ||||
| RID RasterizerStorageGLES3::shader_create(VS::ShaderMode p_mode){ | ||||
| 
 | ||||
| 	return RID(); | ||||
| 	Shader *shader = memnew( Shader ); | ||||
| 	shader->mode=p_mode; | ||||
| 	RID rid = shader_owner.make_rid(shader); | ||||
| 	shader_set_mode(rid,p_mode); | ||||
| 	_shader_make_dirty(shader); | ||||
| 	shader->self=rid; | ||||
| 
 | ||||
| 	return rid; | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::_shader_make_dirty(Shader* p_shader) { | ||||
| 
 | ||||
| 	if (p_shader->dirty_list.in_list()) | ||||
| 		return; | ||||
| 
 | ||||
| 	_shader_dirty_list.add(&p_shader->dirty_list); | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::shader_set_mode(RID p_shader,VS::ShaderMode p_mode){ | ||||
| 
 | ||||
| 	ERR_FAIL_INDEX(p_mode,VS::SHADER_MAX); | ||||
| 	Shader *shader=shader_owner.get(p_shader); | ||||
| 	ERR_FAIL_COND(!shader); | ||||
| 
 | ||||
| 	if (shader->custom_code_id && p_mode==shader->mode) | ||||
| 		return; | ||||
| 
 | ||||
| 
 | ||||
| 	if (shader->custom_code_id) { | ||||
| 
 | ||||
| 		shader->shader->free_custom_shader(shader->custom_code_id); | ||||
| 		shader->custom_code_id=0; | ||||
| 	} | ||||
| 
 | ||||
| 	shader->mode=p_mode; | ||||
| 
 | ||||
| 	ShaderGLES3* shaders[VS::SHADER_MAX]={ | ||||
| 		&canvas->state.canvas_shader, | ||||
| 		&canvas->state.canvas_shader, | ||||
| 		&canvas->state.canvas_shader, | ||||
| 
 | ||||
| 	}; | ||||
| 
 | ||||
| 	shader->shader=shaders[p_mode]; | ||||
| 
 | ||||
| 	shader->custom_code_id = shader->shader->create_custom_shader(); | ||||
| 
 | ||||
| 	_shader_make_dirty(shader); | ||||
| 
 | ||||
| } | ||||
| VS::ShaderMode RasterizerStorageGLES3::shader_get_mode(RID p_shader) const { | ||||
| 
 | ||||
| 	return VS::SHADER_SPATIAL; | ||||
| 	const Shader *shader=shader_owner.get(p_shader); | ||||
| 	ERR_FAIL_COND_V(!shader,VS::SHADER_MAX); | ||||
| 
 | ||||
| 	return shader->mode; | ||||
| } | ||||
| void RasterizerStorageGLES3::shader_set_code(RID p_shader, const String& p_code){ | ||||
| 
 | ||||
| 	Shader *shader=shader_owner.get(p_shader); | ||||
| 	ERR_FAIL_COND(!shader); | ||||
| 
 | ||||
| 	shader->code=p_code; | ||||
| 	_shader_make_dirty(shader); | ||||
| } | ||||
| String RasterizerStorageGLES3::shader_get_code(RID p_shader) const{ | ||||
| 
 | ||||
| 	return String(); | ||||
| 	const Shader *shader=shader_owner.get(p_shader); | ||||
| 	ERR_FAIL_COND_V(!shader,String()); | ||||
| 
 | ||||
| 
 | ||||
| 	return shader->code; | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::_update_shader(Shader* p_shader) const { | ||||
| 
 | ||||
| 
 | ||||
| 	_shader_dirty_list.remove( &p_shader->dirty_list ); | ||||
| 
 | ||||
| 	p_shader->valid=false; | ||||
| 
 | ||||
| 	p_shader->uniforms.clear(); | ||||
| 
 | ||||
| 	ShaderCompilerGLES3::GeneratedCode gen_code; | ||||
| 	ShaderCompilerGLES3::IdentifierActions *actions=NULL; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	switch(p_shader->mode) { | ||||
| 		case VS::SHADER_CANVAS_ITEM: { | ||||
| 
 | ||||
| 			p_shader->canvas_item.light_mode=Shader::CanvasItem::LIGHT_MODE_NORMAL; | ||||
| 			p_shader->canvas_item.blend_mode=Shader::CanvasItem::BLEND_MODE_MIX; | ||||
| 
 | ||||
| 			shaders.actions_canvas.render_mode_values["blend_add"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_ADD); | ||||
| 			shaders.actions_canvas.render_mode_values["blend_mix"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MIX); | ||||
| 			shaders.actions_canvas.render_mode_values["blend_sub"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_SUB); | ||||
| 			shaders.actions_canvas.render_mode_values["blend_mul"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_MUL); | ||||
| 			shaders.actions_canvas.render_mode_values["blend_premul_alpha"]=Pair<int*,int>(&p_shader->canvas_item.blend_mode,Shader::CanvasItem::BLEND_MODE_PMALPHA); | ||||
| 
 | ||||
| 			shaders.actions_canvas.render_mode_values["unshaded"]=Pair<int*,int>(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_UNSHADED); | ||||
| 			shaders.actions_canvas.render_mode_values["light_only"]=Pair<int*,int>(&p_shader->canvas_item.light_mode,Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); | ||||
| 
 | ||||
| 			actions=&shaders.actions_canvas; | ||||
| 			actions->uniforms=&p_shader->uniforms; | ||||
| 
 | ||||
| 		} break; | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	Error err = shaders.compiler.compile(p_shader->mode,p_shader->code,actions,p_shader->path,gen_code); | ||||
| 
 | ||||
| 	ERR_FAIL_COND(err!=OK); | ||||
| 
 | ||||
| 	p_shader->shader->set_custom_shader_code(p_shader->custom_code_id,gen_code.vertex,gen_code.vertex_global,gen_code.fragment,gen_code.light,gen_code.fragment_global,gen_code.uniforms,gen_code.texture_uniforms,gen_code.defines); | ||||
| 
 | ||||
| 	p_shader->ubo_size=gen_code.uniform_total_size; | ||||
| 	p_shader->ubo_offsets=gen_code.uniform_offsets; | ||||
| 	p_shader->texture_count=gen_code.texture_uniforms.size(); | ||||
| 
 | ||||
| 	//all materials using this shader will have to be invalidated, unfortunately
 | ||||
| 
 | ||||
| 	for (SelfList<Material>* E = p_shader->materials.first();E;E=E->next() ) { | ||||
| 
 | ||||
| 		_material_make_dirty(E->self()); | ||||
| 	} | ||||
| 
 | ||||
| 	p_shader->valid=true; | ||||
| 	p_shader->version++; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::update_dirty_shaders() { | ||||
| 
 | ||||
| 	while( _shader_dirty_list.first() ) { | ||||
| 		_update_shader(_shader_dirty_list.first()->self() ); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const{ | ||||
| 
 | ||||
| 	Shader *shader=shader_owner.get(p_shader); | ||||
| 	ERR_FAIL_COND(!shader); | ||||
| 
 | ||||
| 
 | ||||
| 	if (shader->dirty_list.in_list()) | ||||
| 		_update_shader(shader); // ok should be not anymore dirty
 | ||||
| 
 | ||||
| 
 | ||||
| 	Map<int,StringName> order; | ||||
| 
 | ||||
| 
 | ||||
| 	for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { | ||||
| 
 | ||||
| 
 | ||||
| 		order[E->get().order]=E->key(); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	for(Map<int,StringName>::Element *E=order.front();E;E=E->next()) { | ||||
| 
 | ||||
| 		PropertyInfo pi; | ||||
| 		ShaderLanguage::ShaderNode::Uniform &u=shader->uniforms[E->get()]; | ||||
| 		pi.name=E->get(); | ||||
| 		switch(u.type) { | ||||
| 			case ShaderLanguage::TYPE_VOID: pi.type=Variant::NIL; break; | ||||
| 			case ShaderLanguage::TYPE_BOOL: pi.type=Variant::BOOL; break; | ||||
| 			case ShaderLanguage::TYPE_BVEC2: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y"; break; | ||||
| 			case ShaderLanguage::TYPE_BVEC3: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z"; break; | ||||
| 			case ShaderLanguage::TYPE_BVEC4: pi.type=Variant::INT; pi.hint=PROPERTY_HINT_FLAGS; pi.hint_string="x,y,z,w"; break; | ||||
| 			case ShaderLanguage::TYPE_UINT: | ||||
| 			case ShaderLanguage::TYPE_INT: { | ||||
| 				pi.type=Variant::INT; | ||||
| 				if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { | ||||
| 					pi.hint=PROPERTY_HINT_RANGE; | ||||
| 					pi.hint_string=rtos(u.hint_range[0])+","+rtos(u.hint_range[1]); | ||||
| 				} | ||||
| 
 | ||||
| 			} break; | ||||
| 			case ShaderLanguage::TYPE_IVEC2: | ||||
| 			case ShaderLanguage::TYPE_IVEC3: | ||||
| 			case ShaderLanguage::TYPE_IVEC4: | ||||
| 			case ShaderLanguage::TYPE_UVEC2: | ||||
| 			case ShaderLanguage::TYPE_UVEC3: | ||||
| 			case ShaderLanguage::TYPE_UVEC4: { | ||||
| 
 | ||||
| 				pi.type=Variant::INT_ARRAY; | ||||
| 			} break; | ||||
| 			case ShaderLanguage::TYPE_FLOAT: { | ||||
| 				pi.type=Variant::REAL; | ||||
| 				if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { | ||||
| 					pi.hint=PROPERTY_HINT_RANGE; | ||||
| 					pi.hint_string=rtos(u.hint_range[0])+","+rtos(u.hint_range[1])+","+rtos(u.hint_range[2]); | ||||
| 				} | ||||
| 
 | ||||
| 			} break; | ||||
| 			case ShaderLanguage::TYPE_VEC2: pi.type=Variant::VECTOR2; break; | ||||
| 			case ShaderLanguage::TYPE_VEC3: pi.type=Variant::VECTOR3; break; | ||||
| 			case ShaderLanguage::TYPE_VEC4: { | ||||
| 				if (u.hint==ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { | ||||
| 					pi.type=Variant::COLOR; | ||||
| 				} else { | ||||
| 					pi.type=Variant::PLANE; | ||||
| 				} | ||||
| 			} break; | ||||
| 			case ShaderLanguage::TYPE_MAT2: pi.type=Variant::MATRIX32; break; | ||||
| 			case ShaderLanguage::TYPE_MAT3: pi.type=Variant::MATRIX3; break; | ||||
| 			case ShaderLanguage::TYPE_MAT4: pi.type=Variant::TRANSFORM; break; | ||||
| 			case ShaderLanguage::TYPE_SAMPLER2D: | ||||
| 			case ShaderLanguage::TYPE_ISAMPLER2D: | ||||
| 			case ShaderLanguage::TYPE_USAMPLER2D: { | ||||
| 
 | ||||
| 				 pi.type=Variant::OBJECT; | ||||
| 				 pi.hint=PROPERTY_HINT_RESOURCE_TYPE; | ||||
| 				 pi.hint_string="Texture"; | ||||
| 			} break; | ||||
| 			case ShaderLanguage::TYPE_SAMPLERCUBE: { | ||||
| 
 | ||||
| 				pi.type=Variant::OBJECT; | ||||
| 				pi.hint=PROPERTY_HINT_RESOURCE_TYPE; | ||||
| 				pi.hint_string="CubeMap"; | ||||
| 			} break; | ||||
| 		}; | ||||
| 
 | ||||
| 		p_param_list->push_back(pi); | ||||
| 
 | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture){ | ||||
| 
 | ||||
| 	Shader *shader=shader_owner.get(p_shader); | ||||
| 	ERR_FAIL_COND(!shader); | ||||
| 	ERR_FAIL_COND(p_texture.is_valid() && !texture_owner.owns(p_texture)); | ||||
| 
 | ||||
| 	if (p_texture.is_valid()) | ||||
| 		shader->default_textures[p_name]=p_texture; | ||||
| 	else | ||||
| 		shader->default_textures.erase(p_name); | ||||
| 
 | ||||
| 	_shader_make_dirty(shader); | ||||
| } | ||||
| RID RasterizerStorageGLES3::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const{ | ||||
| 
 | ||||
| 	return RID(); | ||||
| 	const Shader *shader=shader_owner.get(p_shader); | ||||
| 	ERR_FAIL_COND_V(!shader,RID()); | ||||
| 
 | ||||
| 	const Map<StringName,RID>::Element *E=shader->default_textures.find(p_name); | ||||
| 	if (!E) | ||||
| 		return RID(); | ||||
| 	return E->get(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* COMMON MATERIAL API */ | ||||
| 
 | ||||
| void RasterizerStorageGLES3::_material_make_dirty(Material* p_material) const { | ||||
| 
 | ||||
| 	if (p_material->dirty_list.in_list()) | ||||
| 		return; | ||||
| 
 | ||||
| 	_material_dirty_list.add(&p_material->dirty_list); | ||||
| } | ||||
| 
 | ||||
| RID RasterizerStorageGLES3::material_create(){ | ||||
| 
 | ||||
| 	return RID(); | ||||
| 	Material *material = memnew( Material ); | ||||
| 
 | ||||
| 	return material_owner.make_rid(material); | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::material_set_shader(RID p_shader_material, RID p_shader){ | ||||
| void RasterizerStorageGLES3::material_set_shader(RID p_material, RID p_shader){ | ||||
| 
 | ||||
| 	Material *material = material_owner.get(  p_material ); | ||||
| 	ERR_FAIL_COND(!material); | ||||
| 
 | ||||
| 	Shader *shader=shader_owner.getornull(p_shader); | ||||
| 
 | ||||
| 	if (material->shader) { | ||||
| 		//if shader, remove from previous shader material list
 | ||||
| 		material->shader->materials.remove( &material->list ); | ||||
| 	} | ||||
| 	material->shader=shader; | ||||
| 
 | ||||
| 	if (shader) { | ||||
| 		shader->materials.add(&material->list); | ||||
| 	} | ||||
| 
 | ||||
| 	_material_make_dirty(material); | ||||
| 
 | ||||
| } | ||||
| RID RasterizerStorageGLES3::material_get_shader(RID p_shader_material) const{ | ||||
| 
 | ||||
| RID RasterizerStorageGLES3::material_get_shader(RID p_material) const{ | ||||
| 
 | ||||
| 	const Material *material = material_owner.get(  p_material ); | ||||
| 	ERR_FAIL_COND_V(!material,RID()); | ||||
| 
 | ||||
| 	if (material->shader) | ||||
| 		return material->shader->self; | ||||
| 
 | ||||
| 	return RID(); | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value){ | ||||
| 
 | ||||
| 	Material *material = material_owner.get(  p_material ); | ||||
| 	ERR_FAIL_COND(!material); | ||||
| 
 | ||||
| 	if (p_value.get_type()==Variant::NIL) | ||||
| 		material->params.erase(p_param); | ||||
| 	else | ||||
| 		material->params[p_param]=p_value; | ||||
| 
 | ||||
| 	_material_make_dirty(material); | ||||
| 
 | ||||
| } | ||||
| Variant RasterizerStorageGLES3::material_get_param(RID p_material, const StringName& p_param) const{ | ||||
| 
 | ||||
| 	const Material *material = material_owner.get(  p_material ); | ||||
| 	ERR_FAIL_COND_V(!material,RID()); | ||||
| 
 | ||||
| 	if (material->params.has(p_param)) | ||||
| 		return material->params[p_param]; | ||||
| 
 | ||||
| 	return Variant(); | ||||
| } | ||||
| 
 | ||||
| _FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant& value, uint8_t *data) { | ||||
| 	switch(type) { | ||||
| 		case ShaderLanguage::TYPE_BOOL: { | ||||
| 
 | ||||
| 			bool v = value; | ||||
| 
 | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			*gui = v ? GL_TRUE : GL_FALSE; | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC2: { | ||||
| 
 | ||||
| 			int v = value; | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=v&1 ? GL_TRUE : GL_FALSE; | ||||
| 			gui[1]=v&2 ? GL_TRUE : GL_FALSE; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC3: { | ||||
| 
 | ||||
| 			int v = value; | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=v&1 ? GL_TRUE : GL_FALSE; | ||||
| 			gui[1]=v&2 ? GL_TRUE : GL_FALSE; | ||||
| 			gui[2]=v&4 ? GL_TRUE : GL_FALSE; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC4: { | ||||
| 
 | ||||
| 			int v = value; | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=v&1 ? GL_TRUE : GL_FALSE; | ||||
| 			gui[1]=v&2 ? GL_TRUE : GL_FALSE; | ||||
| 			gui[2]=v&4 ? GL_TRUE : GL_FALSE; | ||||
| 			gui[3]=v&8 ? GL_TRUE : GL_FALSE; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_INT: { | ||||
| 
 | ||||
| 			int v = value; | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 			gui[0]=v; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_IVEC2: { | ||||
| 
 | ||||
| 			DVector<int> iv = value; | ||||
| 			int s = iv.size(); | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			DVector<int>::Read r = iv.read(); | ||||
| 
 | ||||
| 			for(int i=0;i<2;i++) { | ||||
| 				if (i<s) | ||||
| 					gui[i]=r[i]; | ||||
| 				else | ||||
| 					gui[i]=0; | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_IVEC3: { | ||||
| 
 | ||||
| 			DVector<int> iv = value; | ||||
| 			int s = iv.size(); | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			DVector<int>::Read r = iv.read(); | ||||
| 
 | ||||
| 			for(int i=0;i<3;i++) { | ||||
| 				if (i<s) | ||||
| 					gui[i]=r[i]; | ||||
| 				else | ||||
| 					gui[i]=0; | ||||
| 
 | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_IVEC4: { | ||||
| 
 | ||||
| 
 | ||||
| 			DVector<int> iv = value; | ||||
| 			int s = iv.size(); | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			DVector<int>::Read r = iv.read(); | ||||
| 
 | ||||
| 			for(int i=0;i<4;i++) { | ||||
| 				if (i<s) | ||||
| 					gui[i]=r[i]; | ||||
| 				else | ||||
| 					gui[i]=0; | ||||
| 
 | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UINT: { | ||||
| 
 | ||||
| 			int v = value; | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=v; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UVEC2: { | ||||
| 
 | ||||
| 			DVector<int> iv = value; | ||||
| 			int s = iv.size(); | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 
 | ||||
| 			DVector<int>::Read r = iv.read(); | ||||
| 
 | ||||
| 			for(int i=0;i<2;i++) { | ||||
| 				if (i<s) | ||||
| 					gui[i]=r[i]; | ||||
| 				else | ||||
| 					gui[i]=0; | ||||
| 
 | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UVEC3: { | ||||
| 			DVector<int> iv = value; | ||||
| 			int s = iv.size(); | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 
 | ||||
| 			DVector<int>::Read r = iv.read(); | ||||
| 
 | ||||
| 			for(int i=0;i<3;i++) { | ||||
| 				if (i<s) | ||||
| 					gui[i]=r[i]; | ||||
| 				else | ||||
| 					gui[i]=0; | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UVEC4: { | ||||
| 			DVector<int> iv = value; | ||||
| 			int s = iv.size(); | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 
 | ||||
| 			DVector<int>::Read r = iv.read(); | ||||
| 
 | ||||
| 			for(int i=0;i<4;i++) { | ||||
| 				if (i<s) | ||||
| 					gui[i]=r[i]; | ||||
| 				else | ||||
| 					gui[i]=0; | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_FLOAT: { | ||||
| 			float v = value; | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 			gui[0]=v; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_VEC2: { | ||||
| 			Vector2 v = value; | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 			gui[0]=v.x; | ||||
| 			gui[1]=v.y; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_VEC3: { | ||||
| 			Vector3 v = value; | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 			gui[0]=v.x; | ||||
| 			gui[1]=v.y; | ||||
| 			gui[2]=v.z; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_VEC4: { | ||||
| 
 | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			if (value.get_type()==Variant::COLOR) { | ||||
| 				Color v=value; | ||||
| 
 | ||||
| 				gui[0]=v.r; | ||||
| 				gui[1]=v.g; | ||||
| 				gui[3]=v.b; | ||||
| 				gui[4]=v.a; | ||||
| 			} else if (value.get_type()==Variant::RECT2) { | ||||
| 				Rect2 v=value; | ||||
| 
 | ||||
| 				gui[0]=v.pos.x; | ||||
| 				gui[1]=v.pos.y; | ||||
| 				gui[3]=v.size.x; | ||||
| 				gui[4]=v.size.y; | ||||
| 			} else if (value.get_type()==Variant::QUAT) { | ||||
| 				Quat v=value; | ||||
| 
 | ||||
| 				gui[0]=v.x; | ||||
| 				gui[1]=v.y; | ||||
| 				gui[3]=v.z; | ||||
| 				gui[4]=v.w; | ||||
| 			} else { | ||||
| 				Plane v=value; | ||||
| 
 | ||||
| 				gui[0]=v.normal.x; | ||||
| 				gui[1]=v.normal.y; | ||||
| 				gui[3]=v.normal.x; | ||||
| 				gui[4]=v.d; | ||||
| 
 | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT2: { | ||||
| 			Matrix32 v = value; | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			gui[ 0]=v.elements[0][0]; | ||||
| 			gui[ 1]=v.elements[0][1]; | ||||
| 			gui[ 2]=v.elements[1][0]; | ||||
| 			gui[ 3]=v.elements[1][1]; | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT3: { | ||||
| 
 | ||||
| 
 | ||||
| 			Matrix3 v = value; | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			gui[ 0]=v.elements[0][0]; | ||||
| 			gui[ 1]=v.elements[1][0]; | ||||
| 			gui[ 2]=v.elements[2][0]; | ||||
| 			gui[ 3]=0; | ||||
| 			gui[ 4]=v.elements[0][1]; | ||||
| 			gui[ 5]=v.elements[1][1]; | ||||
| 			gui[ 6]=v.elements[2][1]; | ||||
| 			gui[ 7]=0; | ||||
| 			gui[ 8]=v.elements[0][2]; | ||||
| 			gui[ 9]=v.elements[1][2]; | ||||
| 			gui[10]=v.elements[2][2]; | ||||
| 			gui[11]=0; | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT4: { | ||||
| 
 | ||||
| 			Transform v = value; | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			gui[ 0]=v.basis.elements[0][0]; | ||||
| 			gui[ 1]=v.basis.elements[1][0]; | ||||
| 			gui[ 2]=v.basis.elements[2][0]; | ||||
| 			gui[ 3]=0; | ||||
| 			gui[ 4]=v.basis.elements[0][1]; | ||||
| 			gui[ 5]=v.basis.elements[1][1]; | ||||
| 			gui[ 6]=v.basis.elements[2][1]; | ||||
| 			gui[ 7]=0; | ||||
| 			gui[ 8]=v.basis.elements[0][2]; | ||||
| 			gui[ 9]=v.basis.elements[1][2]; | ||||
| 			gui[10]=v.basis.elements[2][2]; | ||||
| 			gui[11]=0; | ||||
| 			gui[12]=v.origin.x; | ||||
| 			gui[13]=v.origin.y; | ||||
| 			gui[14]=v.origin.z; | ||||
| 			gui[15]=1; | ||||
| 		} break; | ||||
| 		default: {} | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| _FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector<ShaderLanguage::ConstantNode::Value>& value, uint8_t *data) { | ||||
| 
 | ||||
| 	switch(type) { | ||||
| 		case ShaderLanguage::TYPE_BOOL: { | ||||
| 
 | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			*gui = value[0].boolean ? GL_TRUE : GL_FALSE; | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC2: { | ||||
| 
 | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; | ||||
| 			gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC3: { | ||||
| 
 | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; | ||||
| 			gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; | ||||
| 			gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC4: { | ||||
| 
 | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=value[0].boolean ? GL_TRUE : GL_FALSE; | ||||
| 			gui[1]=value[1].boolean ? GL_TRUE : GL_FALSE; | ||||
| 			gui[2]=value[2].boolean ? GL_TRUE : GL_FALSE; | ||||
| 			gui[3]=value[3].boolean ? GL_TRUE : GL_FALSE; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_INT: { | ||||
| 
 | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 			gui[0]=value[0].sint; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_IVEC2: { | ||||
| 
 | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<2;i++) { | ||||
| 				gui[i]=value[i].sint; | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_IVEC3: { | ||||
| 
 | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<3;i++) { | ||||
| 				gui[i]=value[i].sint; | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_IVEC4: { | ||||
| 
 | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<4;i++) { | ||||
| 				gui[i]=value[i].sint; | ||||
| 
 | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UINT: { | ||||
| 
 | ||||
| 
 | ||||
| 			GLuint *gui = (GLuint*)data; | ||||
| 			gui[0]=value[0].uint; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UVEC2: { | ||||
| 
 | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<2;i++) { | ||||
| 				gui[i]=value[i].uint; | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UVEC3: { | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<3;i++) { | ||||
| 				gui[i]=value[i].uint; | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_UVEC4: { | ||||
| 			GLint *gui = (GLint*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<4;i++) { | ||||
| 				gui[i]=value[i].uint; | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_FLOAT: { | ||||
| 
 | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 			gui[0]=value[0].real; | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_VEC2: { | ||||
| 
 | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<2;i++) { | ||||
| 				gui[i]=value[i].real; | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_VEC3: { | ||||
| 
 | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<3;i++) { | ||||
| 				gui[i]=value[i].real; | ||||
| 			} | ||||
| 
 | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_VEC4: { | ||||
| 
 | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<4;i++) { | ||||
| 				gui[i]=value[i].real; | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT2: { | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<2;i++) { | ||||
| 				gui[i]=value[i].real; | ||||
| 			} | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT3: { | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			gui[ 0]=value[0].real; | ||||
| 			gui[ 1]=value[1].real; | ||||
| 			gui[ 2]=value[2].real; | ||||
| 			gui[ 3]=0; | ||||
| 			gui[ 4]=value[3].real; | ||||
| 			gui[ 5]=value[4].real; | ||||
| 			gui[ 6]=value[5].real; | ||||
| 			gui[ 7]=0; | ||||
| 			gui[ 8]=value[6].real; | ||||
| 			gui[ 9]=value[7].real; | ||||
| 			gui[10]=value[8].real; | ||||
| 			gui[11]=0; | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT4: { | ||||
| 
 | ||||
| 			GLfloat *gui = (GLfloat*)data; | ||||
| 
 | ||||
| 			for(int i=0;i<16;i++) { | ||||
| 				gui[i]=value[i].real; | ||||
| 			} | ||||
| 		} break; | ||||
| 		default: {} | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| _FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) { | ||||
| 
 | ||||
| 	switch(type) { | ||||
| 
 | ||||
| 		case ShaderLanguage::TYPE_BOOL: | ||||
| 		case ShaderLanguage::TYPE_INT: | ||||
| 		case ShaderLanguage::TYPE_UINT: | ||||
| 		case ShaderLanguage::TYPE_FLOAT: { | ||||
| 			zeromem(data,4); | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC2: | ||||
| 		case ShaderLanguage::TYPE_IVEC2: | ||||
| 		case ShaderLanguage::TYPE_UVEC2: | ||||
| 		case ShaderLanguage::TYPE_VEC2: { | ||||
| 			zeromem(data,8); | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_BVEC3: | ||||
| 		case ShaderLanguage::TYPE_IVEC3: | ||||
| 		case ShaderLanguage::TYPE_UVEC3: | ||||
| 		case ShaderLanguage::TYPE_VEC3: | ||||
| 		case ShaderLanguage::TYPE_BVEC4: | ||||
| 		case ShaderLanguage::TYPE_IVEC4: | ||||
| 		case ShaderLanguage::TYPE_UVEC4: | ||||
| 		case ShaderLanguage::TYPE_VEC4: | ||||
| 		case ShaderLanguage::TYPE_MAT2:{ | ||||
| 
 | ||||
| 			zeromem(data,16); | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT3:{ | ||||
| 
 | ||||
| 			zeromem(data,48); | ||||
| 		} break; | ||||
| 		case ShaderLanguage::TYPE_MAT4:{ | ||||
| 			zeromem(data,64); | ||||
| 		} break; | ||||
| 
 | ||||
| 		default: {} | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::_update_material(Material* material) { | ||||
| 
 | ||||
| 	if (material->dirty_list.in_list()) | ||||
| 		_material_dirty_list.remove( &material->dirty_list ); | ||||
| 
 | ||||
| 	//clear ubo if it needs to be cleared
 | ||||
| 	if (material->ubo_size) { | ||||
| 
 | ||||
| 		if (!material->shader || material->shader->ubo_size!=material->ubo_size) { | ||||
| 			//by by ubo
 | ||||
| 			glDeleteBuffers(1,&material->ubo_id); | ||||
| 			material->ubo_id=0; | ||||
| 			material->ubo_size=0; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	//create ubo if it needs to be created
 | ||||
| 	if (material->ubo_size==0 && material->shader && material->shader->ubo_size) { | ||||
| 
 | ||||
| 		glGenBuffers(1, &material->ubo_id); | ||||
| 		glBindBuffer(GL_UNIFORM_BUFFER, material->ubo_id); | ||||
| 		glBufferData(GL_UNIFORM_BUFFER, material->shader->ubo_size, NULL, GL_DYNAMIC_DRAW); | ||||
| 		glBindBuffer(GL_UNIFORM_BUFFER, 0); | ||||
| 		material->ubo_size=material->shader->ubo_size; | ||||
| 	} | ||||
| 
 | ||||
| 	//fill up the UBO if it needs to be filled
 | ||||
| 	if (material->shader && material->ubo_size) { | ||||
| 		uint8_t* local_ubo = (uint8_t*)alloca(material->ubo_size); | ||||
| 
 | ||||
| 		for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=material->shader->uniforms.front();E;E=E->next()) { | ||||
| 
 | ||||
| 			if (E->get().order<0) | ||||
| 				continue; // texture, does not go here
 | ||||
| 
 | ||||
| 			//regular uniform
 | ||||
| 			uint8_t *data = &local_ubo[ material->shader->ubo_offsets[E->get().order] ]; | ||||
| 
 | ||||
| 			Map<StringName,Variant>::Element *V = material->params.find(E->key()); | ||||
| 
 | ||||
| 			if (V) { | ||||
| 				//user provided
 | ||||
| 				_fill_std140_variant_ubo_value(E->get().type,V->get(),data); | ||||
| 			} else if (E->get().default_value.size()){ | ||||
| 				//default value
 | ||||
| 				_fill_std140_ubo_value(E->get().type,E->get().default_value,data); | ||||
| 				//value=E->get().default_value;
 | ||||
| 			} else { | ||||
| 				//zero because it was not provided
 | ||||
| 				_fill_std140_ubo_empty(E->get().type,data); | ||||
| 			} | ||||
| 
 | ||||
| 
 | ||||
| 		} | ||||
| 
 | ||||
| 		glBindBuffer(GL_UNIFORM_BUFFER,material->ubo_id); | ||||
| 		glBufferSubData(GL_UNIFORM_BUFFER, 0, material->ubo_size, local_ubo); | ||||
| 		glBindBuffer(GL_UNIFORM_BUFFER, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	//set up the texture array, for easy access when it needs to be drawn
 | ||||
| 	if (material->shader && material->shader->texture_count) { | ||||
| 
 | ||||
| 		material->textures.resize(material->shader->texture_count); | ||||
| 
 | ||||
| 		for(Map<StringName,ShaderLanguage::ShaderNode::Uniform>::Element *E=material->shader->uniforms.front();E;E=E->next()) { | ||||
| 
 | ||||
| 			if (E->get().texture_order<0) | ||||
| 				continue; // not a texture, does not go here
 | ||||
| 
 | ||||
| 			RID texture; | ||||
| 
 | ||||
| 			Map<StringName,Variant>::Element *V = material->params.find(E->key()); | ||||
| 			if (V) { | ||||
| 				texture=V->get(); | ||||
| 			} | ||||
| 
 | ||||
| 			if (!texture.is_valid()) { | ||||
| 				Map<StringName,RID>::Element *W = material->shader->default_textures.find(E->key()); | ||||
| 				if (W) { | ||||
| 					texture=W->get(); | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			material->textures[ E->get().texture_order ]=texture; | ||||
| 
 | ||||
| 
 | ||||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 	} else { | ||||
| 		material->textures.clear(); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void RasterizerStorageGLES3::update_dirty_materials() { | ||||
| 
 | ||||
| 	while( _material_dirty_list.first() ) { | ||||
| 
 | ||||
| 		Material *material = _material_dirty_list.first()->self(); | ||||
| 
 | ||||
| 		_update_material(material); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* MESH API */ | ||||
| 
 | ||||
| RID RasterizerStorageGLES3::mesh_create(){ | ||||
|  | @ -1950,6 +2792,49 @@ bool RasterizerStorageGLES3::free(RID p_rid){ | |||
| 		info.texture_mem-=texture->total_data_size; | ||||
| 		texture_owner.free(p_rid); | ||||
| 		memdelete(texture); | ||||
| 
 | ||||
| 	} else if (shader_owner.owns(p_rid)) { | ||||
| 
 | ||||
| 		// delete the texture
 | ||||
| 		Shader *shader = shader_owner.get(p_rid); | ||||
| 
 | ||||
| 		if (shader->shader) | ||||
| 			shader->shader->free_custom_shader(shader->custom_code_id); | ||||
| 
 | ||||
| 		if (shader->dirty_list.in_list()) | ||||
| 			_shader_dirty_list.remove(&shader->dirty_list); | ||||
| 
 | ||||
| 		while (shader->materials.first()) { | ||||
| 
 | ||||
| 			Material *mat = shader->materials.first()->self(); | ||||
| 
 | ||||
| 			mat->shader=NULL; | ||||
| 			_material_make_dirty(mat); | ||||
| 
 | ||||
| 			shader->materials.remove( shader->materials.first() ); | ||||
| 		} | ||||
| 
 | ||||
| 		//material_shader.free_custom_shader(shader->custom_code_id);
 | ||||
| 		shader_owner.free(p_rid); | ||||
| 		memdelete(shader); | ||||
| 
 | ||||
| 	} else if (material_owner.owns(p_rid)) { | ||||
| 
 | ||||
| 		// delete the texture
 | ||||
| 		Material *material = material_owner.get(p_rid); | ||||
| 
 | ||||
| 		if (material->shader) { | ||||
| 			material->shader->materials.remove( & material->list ); | ||||
| 		} | ||||
| 
 | ||||
| 		if (material->ubo_id) { | ||||
| 			glDeleteBuffers(1,&material->ubo_id); | ||||
| 		} | ||||
| 
 | ||||
| 		material_owner.free(p_rid); | ||||
| 		memdelete(material); | ||||
| 
 | ||||
| 
 | ||||
| 	} else if (canvas_occluder_owner.owns(p_rid)) { | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,16 +2,21 @@ | |||
| #define RASTERIZERSTORAGEGLES3_H | ||||
| 
 | ||||
| #include "servers/visual/rasterizer.h" | ||||
| #include "servers/visual/shader_language.h" | ||||
| #include "shader_gles3.h" | ||||
| #include "shaders/copy.glsl.h" | ||||
| #include "shaders/canvas.glsl.h" | ||||
| #include "self_list.h" | ||||
| #include "shader_compiler_gles3.h" | ||||
| 
 | ||||
| 
 | ||||
| class RasterizerCanvasGLES3; | ||||
| 
 | ||||
| 
 | ||||
| class RasterizerStorageGLES3 : public RasterizerStorage { | ||||
| public: | ||||
| 
 | ||||
| 	RasterizerCanvasGLES3 *canvas; | ||||
| 
 | ||||
| 	enum FBOFormat { | ||||
| 		FBO_FORMAT_16_BITS, | ||||
| 		FBO_FORMAT_32_BITS, | ||||
|  | @ -47,9 +52,13 @@ public: | |||
| 		Set<String> extensions; | ||||
| 	} config; | ||||
| 
 | ||||
| 	struct Shaders { | ||||
| 	mutable struct Shaders { | ||||
| 
 | ||||
| 		CopyShaderGLES3 copy; | ||||
| 
 | ||||
| 		ShaderCompilerGLES3 compiler; | ||||
| 
 | ||||
| 		ShaderCompilerGLES3::IdentifierActions actions_canvas; | ||||
| 	} shaders; | ||||
| 
 | ||||
| 	struct Resources { | ||||
|  | @ -169,11 +178,71 @@ public: | |||
| 
 | ||||
| 	/* SHADER API */ | ||||
| 
 | ||||
| 	struct Material; | ||||
| 
 | ||||
| 	struct Shader : public RID_Data { | ||||
| 
 | ||||
| 		RID self; | ||||
| 
 | ||||
| 		VS::ShaderMode mode; | ||||
| 		ShaderGLES3 *shader; | ||||
| 		String code; | ||||
| 		SelfList<Material>::List materials; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 		Map<StringName,ShaderLanguage::ShaderNode::Uniform> uniforms; | ||||
| 		Vector<uint32_t> ubo_offsets; | ||||
| 		uint32_t ubo_size; | ||||
| 
 | ||||
| 		uint32_t texture_count; | ||||
| 
 | ||||
| 		uint32_t custom_code_id; | ||||
| 		uint32_t version; | ||||
| 
 | ||||
| 		SelfList<Shader> dirty_list; | ||||
| 
 | ||||
| 		Map<StringName,RID> default_textures; | ||||
| 
 | ||||
| 		bool valid; | ||||
| 
 | ||||
| 		String path; | ||||
| 
 | ||||
| 		struct CanvasItem { | ||||
| 
 | ||||
| 			enum BlendMode { | ||||
| 				BLEND_MODE_MIX, | ||||
| 				BLEND_MODE_ADD, | ||||
| 				BLEND_MODE_SUB, | ||||
| 				BLEND_MODE_MUL, | ||||
| 				BLEND_MODE_PMALPHA, | ||||
| 			}; | ||||
| 
 | ||||
| 			int blend_mode; | ||||
| 
 | ||||
| 			enum LightMode { | ||||
| 				LIGHT_MODE_NORMAL, | ||||
| 				LIGHT_MODE_UNSHADED, | ||||
| 				LIGHT_MODE_LIGHT_ONLY | ||||
| 			}; | ||||
| 
 | ||||
| 			int light_mode; | ||||
| 
 | ||||
| 		} canvas_item; | ||||
| 
 | ||||
| 		Shader() : dirty_list(this) { | ||||
| 
 | ||||
| 			shader=NULL; | ||||
| 			valid=false; | ||||
| 			custom_code_id=0; | ||||
| 			version=1; | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	mutable SelfList<Shader>::List _shader_dirty_list; | ||||
| 	void _shader_make_dirty(Shader* p_shader); | ||||
| 
 | ||||
| 	mutable RID_Owner<Shader> shader_owner; | ||||
| 
 | ||||
| 	virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL); | ||||
| 
 | ||||
|  | @ -187,17 +256,48 @@ public: | |||
| 	virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture); | ||||
| 	virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const; | ||||
| 
 | ||||
| 	void _update_shader(Shader* p_shader) const; | ||||
| 
 | ||||
| 	void update_dirty_shaders(); | ||||
| 
 | ||||
| 	/* COMMON MATERIAL API */ | ||||
| 
 | ||||
| 	struct Material : public RID_Data { | ||||
| 
 | ||||
| 		Shader *shader; | ||||
| 		GLuint ubo_id; | ||||
| 		uint32_t ubo_size; | ||||
| 		Map<StringName,Variant> params; | ||||
| 		SelfList<Material> list; | ||||
| 		SelfList<Material> dirty_list; | ||||
| 		Vector<RID> textures; | ||||
| 
 | ||||
| 		Material() : list(this), dirty_list(this) { | ||||
| 			shader=NULL; | ||||
| 			ubo_id=0; | ||||
| 			ubo_size=0; | ||||
| 		} | ||||
| 
 | ||||
| 	}; | ||||
| 
 | ||||
| 	mutable SelfList<Material>::List _material_dirty_list; | ||||
| 	void _material_make_dirty(Material *p_material) const; | ||||
| 
 | ||||
| 
 | ||||
| 	mutable RID_Owner<Material> material_owner; | ||||
| 
 | ||||
| 	virtual RID material_create(); | ||||
| 
 | ||||
| 	virtual void material_set_shader(RID p_shader_material, RID p_shader); | ||||
| 	virtual RID material_get_shader(RID p_shader_material) const; | ||||
| 	virtual void material_set_shader(RID p_material, RID p_shader); | ||||
| 	virtual RID material_get_shader(RID p_material) const; | ||||
| 
 | ||||
| 	virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value); | ||||
| 	virtual Variant material_get_param(RID p_material, const StringName& p_param) const; | ||||
| 
 | ||||
| 	void _update_material(Material* material); | ||||
| 
 | ||||
| 	void update_dirty_materials(); | ||||
| 
 | ||||
| 	/* MESH API */ | ||||
| 
 | ||||
| 	virtual RID mesh_create(); | ||||
|  | @ -432,6 +532,7 @@ public: | |||
| 		bool clear_request; | ||||
| 		Color clear_request_color; | ||||
| 		int canvas_draw_commands; | ||||
| 		float time[4]; | ||||
| 	} frame; | ||||
| 
 | ||||
| 	void initialize(); | ||||
|  |  | |||
							
								
								
									
										528
									
								
								drivers/gles3/shader_compiler_gles3.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										528
									
								
								drivers/gles3/shader_compiler_gles3.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -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
									
								
								drivers/gles3/shader_compiler_gles3.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								drivers/gles3/shader_compiler_gles3.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -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
 | ||||
|  | @ -214,6 +214,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 	v.ok=false; | ||||
| 	/* SETUP CONDITIONALS */ | ||||
| 	 | ||||
|  | @ -245,6 +247,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 	CharString code_string; | ||||
| 	CharString code_string2; | ||||
| 	CharString code_globals; | ||||
| 	CharString material_string; | ||||
| 
 | ||||
| 
 | ||||
| 	//print_line("code version? "+itos(conditional_version.code_version));
 | ||||
|  | @ -258,6 +261,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 		cc=&custom_code_map[conditional_version.code_version]; | ||||
| 		v.code_version=cc->version; | ||||
| 		define_line_ofs+=2; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
|  | @ -273,7 +277,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 	if (cc) { | ||||
| 		for(int i=0;i<cc->custom_defines.size();i++) { | ||||
| 
 | ||||
| 			strings.push_back(cc->custom_defines[i]); | ||||
| 			strings.push_back(cc->custom_defines[i].get_data()); | ||||
| 			DEBUG_PRINT("CD #"+itos(i)+": "+String(cc->custom_defines[i])); | ||||
| 		} | ||||
| 	} | ||||
|  | @ -305,14 +309,22 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 		code_globals=cc->vertex_globals.ascii(); | ||||
| 		strings.push_back(code_globals.get_data()); | ||||
| 	} | ||||
| 
 | ||||
| 	strings.push_back(vertex_code1.get_data()); | ||||
| 
 | ||||
| 	if (cc) { | ||||
| 		material_string=cc->uniforms.ascii(); | ||||
| 		strings.push_back(material_string.get_data()); | ||||
| 	} | ||||
| 
 | ||||
| 	strings.push_back(vertex_code2.get_data()); | ||||
| 
 | ||||
| 	if (cc) { | ||||
| 		code_string=cc->vertex.ascii(); | ||||
| 		strings.push_back(code_string.get_data()); | ||||
| 	} | ||||
| 
 | ||||
| 	strings.push_back(vertex_code2.get_data()); | ||||
| 	strings.push_back(vertex_code3.get_data()); | ||||
| #ifdef DEBUG_SHADER | ||||
| 
 | ||||
| 	DEBUG_PRINT("\nVertex Code:\n\n"+String(code_string.get_data())); | ||||
|  | @ -367,7 +379,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 		 | ||||
| 		ERR_FAIL_V(NULL); | ||||
| 	}	 | ||||
| 	 | ||||
| 
 | ||||
| 
 | ||||
| 	/* FRAGMENT SHADER */ | ||||
| 
 | ||||
| 	strings.resize(strings_base_size); | ||||
|  | @ -396,21 +409,29 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 		code_globals=cc->fragment_globals.ascii(); | ||||
| 		strings.push_back(code_globals.get_data()); | ||||
| 	} | ||||
| 
 | ||||
| 	strings.push_back(fragment_code1.get_data()); | ||||
| 
 | ||||
| 	if (cc) { | ||||
| 		material_string=cc->uniforms.ascii(); | ||||
| 		strings.push_back(material_string.get_data()); | ||||
| 	} | ||||
| 
 | ||||
| 	strings.push_back(fragment_code2.get_data()); | ||||
| 
 | ||||
| 	if (cc) { | ||||
| 		code_string=cc->fragment.ascii(); | ||||
| 		strings.push_back(code_string.get_data()); | ||||
| 	} | ||||
| 
 | ||||
| 	strings.push_back(fragment_code2.get_data()); | ||||
| 	strings.push_back(fragment_code3.get_data()); | ||||
| 
 | ||||
| 	if (cc) { | ||||
| 		code_string2=cc->light.ascii(); | ||||
| 		strings.push_back(code_string2.get_data()); | ||||
| 	} | ||||
| 
 | ||||
| 	strings.push_back(fragment_code3.get_data()); | ||||
| 	strings.push_back(fragment_code4.get_data()); | ||||
| 
 | ||||
| #ifdef DEBUG_SHADER | ||||
| 	DEBUG_PRINT("\nFragment Code:\n\n"+String(code_string.get_data())); | ||||
|  | @ -463,7 +484,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 		 | ||||
| 		ERR_FAIL_V( NULL ); | ||||
| 	}		 | ||||
| 	 | ||||
| 
 | ||||
| 	glAttachShader(v.id,v.frag_id); | ||||
| 	glAttachShader(v.id,v.vert_id); | ||||
| 
 | ||||
|  | @ -552,10 +573,11 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() { | |||
| 
 | ||||
| 	if ( cc ) { | ||||
| 
 | ||||
| 		v.custom_uniform_locations.resize(cc->custom_uniforms.size()); | ||||
| 		for(int i=0;i<cc->custom_uniforms.size();i++) { | ||||
| 		v.texture_uniform_locations.resize(cc->texture_uniforms.size()); | ||||
| 		for(int i=0;i<cc->texture_uniforms.size();i++) { | ||||
| 
 | ||||
| 			v.custom_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->custom_uniforms[i]).ascii().get_data()); | ||||
| 			v.texture_uniform_locations[i]=glGetUniformLocation(v.id,String(cc->texture_uniforms[i]).ascii().get_data()); | ||||
| 			glUniform1i(v.texture_uniform_locations[i],i+base_material_tex_index); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -597,6 +619,7 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co | |||
| 	//split vertex and shader code (thank you, retarded shader compiler programmers from you know what company).
 | ||||
| 	{ | ||||
| 		String globals_tag="\nVERTEX_SHADER_GLOBALS"; | ||||
| 		String material_tag="\nMATERIAL_UNIFORMS"; | ||||
| 		String code_tag="\nVERTEX_SHADER_CODE"; | ||||
| 		String code =  vertex_code; | ||||
| 		int cpos = code.find(globals_tag); | ||||
|  | @ -606,20 +629,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co | |||
| 			vertex_code0=code.substr(0,cpos).ascii(); | ||||
| 			code = code.substr(cpos+globals_tag.length(),code.length()); | ||||
| 
 | ||||
| 			cpos = code.find(code_tag); | ||||
| 			cpos = code.find(material_tag); | ||||
| 
 | ||||
| 			if (cpos==-1) { | ||||
| 				vertex_code1=code.ascii(); | ||||
| 			} else { | ||||
| 
 | ||||
| 				vertex_code1=code.substr(0,cpos).ascii(); | ||||
| 				vertex_code2=code.substr(cpos+code_tag.length(),code.length()).ascii(); | ||||
| 				String code2 = code.substr(cpos+material_tag.length(),code.length()); | ||||
| 
 | ||||
| 				cpos = code2.find(code_tag); | ||||
| 				if (cpos==-1) { | ||||
| 					vertex_code2=code2.ascii(); | ||||
| 				} else { | ||||
| 
 | ||||
| 					vertex_code2=code2.substr(0,cpos).ascii(); | ||||
| 					vertex_code3 = code2.substr(cpos+code_tag.length(),code2.length()).ascii(); | ||||
| 				} | ||||
| 
 | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 		String globals_tag="\nFRAGMENT_SHADER_GLOBALS"; | ||||
| 		String material_tag="\nMATERIAL_UNIFORMS"; | ||||
| 		String code_tag="\nFRAGMENT_SHADER_CODE"; | ||||
| 		String light_code_tag="\nLIGHT_SHADER_CODE"; | ||||
| 		String code =  fragment_code; | ||||
|  | @ -630,22 +664,31 @@ void ShaderGLES3::setup(const char** p_conditional_defines, int p_conditional_co | |||
| 			fragment_code0=code.substr(0,cpos).ascii(); | ||||
| 			code = code.substr(cpos+globals_tag.length(),code.length()); | ||||
| 
 | ||||
| 			cpos = code.find(code_tag); | ||||
| 			cpos = code.find(material_tag); | ||||
| 
 | ||||
| 			if (cpos==-1) { | ||||
| 				fragment_code1=code.ascii(); | ||||
| 			} else { | ||||
| 
 | ||||
| 				fragment_code1=code.substr(0,cpos).ascii(); | ||||
| 				String code2 = code.substr(cpos+code_tag.length(),code.length()); | ||||
| 				String code2 = code.substr(cpos+material_tag.length(),code.length()); | ||||
| 
 | ||||
| 				cpos = code2.find(light_code_tag); | ||||
| 				cpos = code2.find(code_tag); | ||||
| 				if (cpos==-1) { | ||||
| 					fragment_code2=code2.ascii(); | ||||
| 				} else { | ||||
| 
 | ||||
| 					fragment_code2=code2.substr(0,cpos).ascii(); | ||||
| 					fragment_code3 = code2.substr(cpos+light_code_tag.length(),code2.length()).ascii(); | ||||
| 					String code3 = code2.substr(cpos+code_tag.length(),code2.length()); | ||||
| 
 | ||||
| 					cpos = code3.find(light_code_tag); | ||||
| 					if (cpos==-1) { | ||||
| 						fragment_code3=code3.ascii(); | ||||
| 					} else { | ||||
| 
 | ||||
| 						fragment_code3=code3.substr(0,cpos).ascii(); | ||||
| 						fragment_code4 = code3.substr(cpos+light_code_tag.length(),code3.length()).ascii(); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | @ -697,7 +740,7 @@ uint32_t ShaderGLES3::create_custom_shader() { | |||
| 	return last_custom_code++; | ||||
| } | ||||
| 
 | ||||
| void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_light, const String& p_fragment_globals,const Vector<StringName>& p_uniforms,const Vector<const char*> &p_custom_defines) { | ||||
| void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_vertex, const String& p_vertex_globals, const String& p_fragment, const String& p_light, const String& p_fragment_globals, const String &p_uniforms, const Vector<StringName> &p_texture_uniforms, const Vector<CharString> &p_custom_defines) { | ||||
| 
 | ||||
| 	ERR_FAIL_COND(!custom_code_map.has(p_code_id)); | ||||
| 	CustomCode *cc=&custom_code_map[p_code_id]; | ||||
|  | @ -707,7 +750,8 @@ void ShaderGLES3::set_custom_shader_code(uint32_t p_code_id, const String& p_ver | |||
| 	cc->fragment=p_fragment; | ||||
| 	cc->fragment_globals=p_fragment_globals; | ||||
| 	cc->light=p_light; | ||||
| 	cc->custom_uniforms=p_uniforms; | ||||
| 	cc->texture_uniforms=p_texture_uniforms; | ||||
| 	cc->uniforms=p_uniforms; | ||||
| 	cc->custom_defines=p_custom_defines; | ||||
| 	cc->version++; | ||||
| } | ||||
|  | @ -734,13 +778,16 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| void ShaderGLES3::set_base_material_tex_index(int p_idx) { | ||||
| 
 | ||||
| 	base_material_tex_index=p_idx; | ||||
| } | ||||
| 
 | ||||
| ShaderGLES3::ShaderGLES3() { | ||||
| 	version=NULL; | ||||
| 	last_custom_code=1; | ||||
| 	uniforms_dirty = true; | ||||
| 
 | ||||
| 	base_material_tex_index=0; | ||||
| 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&max_image_units); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -105,9 +105,10 @@ private: | |||
| 		String fragment; | ||||
| 		String fragment_globals; | ||||
| 		String light; | ||||
| 		String uniforms; | ||||
| 		uint32_t version; | ||||
| 		Vector<StringName> custom_uniforms; | ||||
| 		Vector<const char*> custom_defines; | ||||
| 		Vector<StringName> texture_uniforms; | ||||
| 		Vector<CharString> custom_defines; | ||||
| 
 | ||||
| 	}; | ||||
| 
 | ||||
|  | @ -118,7 +119,7 @@ private: | |||
| 		GLuint vert_id; | ||||
| 		GLuint frag_id;					 | ||||
| 		GLint *uniform_location; | ||||
| 		Vector<GLint> custom_uniform_locations; | ||||
| 		Vector<GLint> texture_uniform_locations; | ||||
| 		uint32_t code_version; | ||||
| 		bool ok; | ||||
| 		Version() { code_version=0; ok=false; uniform_location=NULL; } | ||||
|  | @ -166,10 +167,14 @@ private: | |||
| 	CharString fragment_code1; | ||||
| 	CharString fragment_code2; | ||||
| 	CharString fragment_code3; | ||||
| 	CharString fragment_code4; | ||||
| 
 | ||||
| 	CharString vertex_code0; | ||||
| 	CharString vertex_code1; | ||||
| 	CharString vertex_code2; | ||||
| 	CharString vertex_code3; | ||||
| 
 | ||||
| 	int base_material_tex_index; | ||||
| 
 | ||||
| 	Version * get_current_version(); | ||||
| 	 | ||||
|  | @ -308,7 +313,7 @@ public: | |||
| 	void clear_caches(); | ||||
| 
 | ||||
| 	uint32_t create_custom_shader(); | ||||
| 	void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const Vector<StringName>& p_uniforms,const Vector<const char*> &p_custom_defines); | ||||
| 	void set_custom_shader_code(uint32_t p_id,const String& p_vertex, const String& p_vertex_globals,const String& p_fragment,const String& p_p_light,const String& p_fragment_globals,const String& p_uniforms,const Vector<StringName>& p_texture_uniforms,const Vector<CharString> &p_custom_defines); | ||||
| 	void set_custom_shader(uint32_t p_id); | ||||
| 	void free_custom_shader(uint32_t p_id); | ||||
| 
 | ||||
|  | @ -332,23 +337,25 @@ public: | |||
| 		uniforms_dirty = true; | ||||
| 	}; | ||||
| 
 | ||||
| 	_FORCE_INLINE_ void set_custom_uniform(int p_idx, const Variant& p_value) { | ||||
| 	_FORCE_INLINE_ void set_texture_uniform(int p_idx, const Variant& p_value) { | ||||
| 
 | ||||
| 		ERR_FAIL_COND(!version); | ||||
| 		ERR_FAIL_INDEX(p_idx,version->custom_uniform_locations.size()); | ||||
| 		_set_uniform_variant( version->custom_uniform_locations[p_idx], p_value ); | ||||
| 		ERR_FAIL_INDEX(p_idx,version->texture_uniform_locations.size()); | ||||
| 		_set_uniform_variant( version->texture_uniform_locations[p_idx], p_value ); | ||||
| 	} | ||||
| 	 | ||||
| 	_FORCE_INLINE_ GLint get_custom_uniform_location(int p_idx) { | ||||
| 	_FORCE_INLINE_ GLint get_texture_uniform_location(int p_idx) { | ||||
| 
 | ||||
| 		ERR_FAIL_COND_V(!version,-1); | ||||
| 		ERR_FAIL_INDEX_V(p_idx,version->custom_uniform_locations.size(),-1); | ||||
| 		return version->custom_uniform_locations[p_idx]; | ||||
| 		ERR_FAIL_INDEX_V(p_idx,version->texture_uniform_locations.size(),-1); | ||||
| 		return version->texture_uniform_locations[p_idx]; | ||||
| 	} | ||||
| 
 | ||||
| 	virtual void init()=0; | ||||
| 	void finish(); | ||||
| 
 | ||||
| 	void set_base_material_tex_index(int p_idx); | ||||
| 
 | ||||
| 	virtual ~ShaderGLES3(); | ||||
| 
 | ||||
| }; | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| [vertex] | ||||
| 
 | ||||
| 
 | ||||
| layout(location=0) in highp vec3 vertex; | ||||
| layout(location=0) in highp vec2 vertex; | ||||
| layout(location=3) in vec4 color_attrib; | ||||
| 
 | ||||
| #ifdef USE_TEXTURE_RECT | ||||
|  | @ -20,6 +20,7 @@ layout(location=4) in highp vec2 uv_attrib; | |||
| layout(std140) uniform CanvasItemData { //ubo:0 | ||||
| 
 | ||||
| 	highp mat4 projection_matrix; | ||||
| 	highp vec4 time; | ||||
| }; | ||||
| 
 | ||||
| uniform highp mat4 modelview_matrix; | ||||
|  | @ -29,10 +30,6 @@ uniform highp mat4 extra_matrix; | |||
| out mediump vec2 uv_interp; | ||||
| out mediump vec4 color_interp; | ||||
| 
 | ||||
| #if defined(USE_TIME) | ||||
| uniform float time; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_LIGHTING | ||||
| 
 | ||||
| layout(std140) uniform LightData { //ubo:1 | ||||
|  | @ -51,6 +48,7 @@ layout(std140) uniform LightData { //ubo:1 | |||
| 	highp float shadow_distance_mult; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| out vec4 light_uv_interp; | ||||
| 
 | ||||
| #if defined(NORMAL_USED) | ||||
|  | @ -66,20 +64,30 @@ out highp vec2 pos; | |||
| 
 | ||||
| VERTEX_SHADER_GLOBALS | ||||
| 
 | ||||
| #if defined(USE_MATERIAL) | ||||
| 
 | ||||
| layout(std140) uniform UniformData { //ubo:2 | ||||
| 
 | ||||
| MATERIAL_UNIFORMS | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| void main() { | ||||
| 
 | ||||
| 	color_interp = color_attrib; | ||||
| 	vec4 vertex_color = color_attrib; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef USE_TEXTURE_RECT | ||||
| 
 | ||||
| 
 | ||||
| 	uv_interp = src_rect.xy + abs(src_rect.zw) * vertex.xy; | ||||
| 	highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex.xy,vec2(1.0,1.0)-vertex.xy,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0); | ||||
| 	uv_interp = src_rect.xy + abs(src_rect.zw) * vertex; | ||||
| 	highp vec4 outvec = vec4(dst_rect.xy + dst_rect.zw * mix(vertex,vec2(1.0,1.0)-vertex,lessThan(src_rect.zw,vec2(0.0,0.0))),0.0,1.0); | ||||
| 
 | ||||
| #else | ||||
| 	uv_interp = uv_attrib; | ||||
| 	highp vec4 outvec = vec4(vertex, 1.0); | ||||
| 	highp vec4 outvec = vec4(vertex,0.0,1.0); | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
|  | @ -90,16 +98,16 @@ VERTEX_SHADER_CODE | |||
| 
 | ||||
| } | ||||
| 
 | ||||
| #if !defined(USE_WORLD_VEC) | ||||
| #if !defined(SKIP_TRANSFORM_USED) | ||||
| 	outvec = extra_matrix * outvec; | ||||
| 	outvec = modelview_matrix * outvec; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| 	color_interp = vertex_color; | ||||
| 
 | ||||
| #ifdef USE_PIXEL_SNAP | ||||
| 
 | ||||
| 	outvec.xy=floor(outvec.xy+0.5); | ||||
| 	outvec.xy=floor(outvec+0.5); | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
|  | @ -132,20 +140,24 @@ VERTEX_SHADER_CODE | |||
| 
 | ||||
| 
 | ||||
| uniform mediump sampler2D color_texture; // texunit:0 | ||||
| uniform highp vec2 color_texpixel_size; | ||||
| 
 | ||||
| in mediump vec2 uv_interp; | ||||
| in mediump vec4 color_interp; | ||||
| 
 | ||||
| 
 | ||||
| #if defined(ENABLE_TEXSCREEN) | ||||
| #if defined(SCREEN_TEXTURE_USED) | ||||
| 
 | ||||
| uniform sampler2D texscreen_tex; // texunit:-3 | ||||
| uniform sampler2D screen_texture; // texunit:-3 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(USE_TIME) | ||||
| uniform float time; | ||||
| #endif | ||||
| layout(std140) uniform CanvasItemData { | ||||
| 
 | ||||
| 	highp mat4 projection_matrix; | ||||
| 	highp vec4 time; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #ifdef USE_LIGHTING | ||||
| 
 | ||||
|  | @ -188,6 +200,17 @@ FRAGMENT_SHADER_GLOBALS | |||
| 
 | ||||
| layout(location=0) out mediump vec4 frag_color; | ||||
| 
 | ||||
| 
 | ||||
| #if defined(USE_MATERIAL) | ||||
| 
 | ||||
| layout(std140) uniform UniformData { | ||||
| 
 | ||||
| MATERIAL_UNIFORMS | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| void main() { | ||||
| 
 | ||||
| 	vec4 color = color_interp; | ||||
|  | @ -195,6 +218,9 @@ void main() { | |||
| 	vec3 normal = vec3(0.0,0.0,1.0); | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(COLOR_USED) | ||||
| //default behavior, texture by color | ||||
| 
 | ||||
| #ifdef USE_DISTANCE_FIELD | ||||
| 	const float smoothing = 1.0/32.0; | ||||
| 	float distance = texture(color_texture, uv_interp).a; | ||||
|  | @ -204,6 +230,7 @@ void main() { | |||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #if defined(ENABLE_SCREEN_UV) | ||||
| 	vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; | ||||
|  | @ -211,14 +238,15 @@ void main() { | |||
| 
 | ||||
| 
 | ||||
| { | ||||
| #if defined(USE_NORMALMAP) | ||||
| 	vec3 normal_map=vec3(0.0,0.0,1.0); | ||||
| 	float normal_depth=1.0; | ||||
| 
 | ||||
| #if defined(NORMALMAP_USED) | ||||
| 	vec3 normal_map=vec3(0.0,0.0,1.0); | ||||
| #endif | ||||
| 
 | ||||
| FRAGMENT_SHADER_CODE | ||||
| 
 | ||||
| #if defined(USE_NORMALMAP) | ||||
| #if defined(NORMALMAP_USED) | ||||
| 	normal = mix(vec3(0.0,0.0,1.0), normal_map * vec3(2.0,-2.0,1.0) - vec3( 1.0, -1.0, 0.0 ), normal_depth ); | ||||
| #endif | ||||
| 
 | ||||
|  | @ -246,7 +274,7 @@ FRAGMENT_SHADER_CODE | |||
| 
 | ||||
| 	vec2 light_uv = light_uv_interp.xy; | ||||
| 	vec4 light = texture(light_texture,light_uv) * light_color; | ||||
| #if defined(USE_OUTPUT_SHADOW_COLOR) | ||||
| #if defined(SHADOW_COLOR_USED) | ||||
| 	vec4 shadow_color=vec4(0.0,0.0,0.0,0.0); | ||||
| #endif | ||||
| 
 | ||||
|  | @ -409,7 +437,7 @@ LIGHT_SHADER_CODE | |||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| #if defined(USE_OUTPUT_SHADOW_COLOR) | ||||
| #if defined(SHADOW_COLOR_USED) | ||||
| 	color=mix(shadow_color,color,shadow_attenuation); | ||||
| #else | ||||
| 	//color*=shadow_attenuation; | ||||
|  |  | |||
|  | @ -88,6 +88,10 @@ void OS_Unix::print_error(const char* p_function,const char* p_file,int p_line,c | |||
| 			print("\E[1;35mSCRIPT ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details); | ||||
| 			print("\E[0;35m   At: %s:%i.\E[0m\n",p_file,p_line); | ||||
| 			break; | ||||
| 		case ERR_SHADER: | ||||
| 			print("\E[1;36mSHADER ERROR: %s: \E[0m\E[1m%s\n",p_function,err_details); | ||||
| 			print("\E[0;36m   At: %s:%i.\E[0m\n",p_file,p_line); | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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("          At: %s:%i\n", p_file, p_line); | ||||
| 				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 { | ||||
|  | @ -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_WARNING: basecol = FOREGROUND_RED | FOREGROUND_GREEN; break; | ||||
| 			case ERR_SCRIPT: basecol = FOREGROUND_RED | FOREGROUND_BLUE; break; | ||||
| 			case ERR_SHADER: basecol = FOREGROUND_GREEN | FOREGROUND_BLUE; break; | ||||
| 		} | ||||
| 
 | ||||
| 		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_WARNING: print("WARNING: "); break; | ||||
| 				case ERR_SCRIPT: print("SCRIPT ERROR: "); break; | ||||
| 				case ERR_SCRIPT: print("SHADER ERROR: "); break; | ||||
| 			} | ||||
| 
 | ||||
| 			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_WARNING: print("     At: "); break; | ||||
| 				case ERR_SCRIPT: print("          At: "); break; | ||||
| 				case ERR_SHADER: print("          At: "); break; | ||||
| 			} | ||||
| 
 | ||||
| 			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_WARNING: print("WARNING: %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); | ||||
|  | @ -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_WARNING: print("     At: "); break; | ||||
| 				case ERR_SCRIPT: print("          At: "); break; | ||||
| 				case ERR_SHADER: print("          At: "); break; | ||||
| 			} | ||||
| 
 | ||||
| 			SetConsoleTextAttribute(hCon, current_fg | current_bg); | ||||
|  |  | |||
|  | @ -55,7 +55,7 @@ bool CanvasItemMaterial::_set(const StringName& p_name, const Variant& p_value) | |||
| 				} | ||||
| 			} | ||||
| 			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; | ||||
| 			} | ||||
| 		} | ||||
|  | @ -78,7 +78,7 @@ bool CanvasItemMaterial::_get(const StringName& p_name,Variant &r_ret) const { | |||
| 
 | ||||
| 			StringName pr = shader->remap_param(p_name); | ||||
| 			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; | ||||
| 			} | ||||
| 		} | ||||
|  | @ -111,7 +111,7 @@ void CanvasItemMaterial::set_shader(const Ref<Shader>& p_shader) { | |||
| 	if (shader.is_valid()) | ||||
| 		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
 | ||||
| 	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){ | ||||
| 
 | ||||
| 	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{ | ||||
| 
 | ||||
| 	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() { | ||||
|  |  | |||
|  | @ -41,10 +41,9 @@ class Font; | |||
| 
 | ||||
| class StyleBox; | ||||
| 
 | ||||
| class CanvasItemMaterial : public Material{ | ||||
| class CanvasItemMaterial : public Material { | ||||
| 
 | ||||
| 	OBJ_TYPE(CanvasItemMaterial,Material); | ||||
| 	RID material; | ||||
| 	Ref<Shader> shader; | ||||
| public: | ||||
| 	/*enum ShadingMode {
 | ||||
|  | @ -70,7 +69,6 @@ public: | |||
| 	void set_shader_param(const StringName& p_param,const Variant& p_value); | ||||
| 	Variant get_shader_param(const StringName& p_param) const; | ||||
| 
 | ||||
| 	virtual RID get_rid() const; | ||||
| 	CanvasItemMaterial(); | ||||
| 	~CanvasItemMaterial(); | ||||
| }; | ||||
|  |  | |||
|  | @ -34,31 +34,12 @@ | |||
| #include "os/input.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) { | ||||
| 
 | ||||
| 
 | ||||
| 	switch(p_what) { | ||||
| 		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")); | ||||
| 			w_edit->set_texture(get_icon("color_hue")); | ||||
| 			sample->set_texture(get_icon("color_sample")); | ||||
|  | @ -68,8 +49,6 @@ void ColorPicker::_notification(int p_what) { | |||
| 
 | ||||
| 		case NOTIFICATION_ENTER_TREE: { | ||||
| 			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(); | ||||
| 			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()) | ||||
| 		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(); | ||||
| 	w_edit->get_child(0)->cast_to<Control>()->update(); | ||||
|  | @ -509,7 +486,6 @@ ColorPicker::ColorPicker() : | |||
| 	uv_edit->add_child(c); | ||||
| 	c->set_area_as_parent_rect(); | ||||
| 	c->set_stop_mouse(false); | ||||
| 	c->set_material(memnew ( CanvasItemMaterial )); | ||||
| 	Vector<Variant> args=Vector<Variant>(); | ||||
| 	args.push_back(0); | ||||
| 	args.push_back(c); | ||||
|  | @ -525,7 +501,6 @@ ColorPicker::ColorPicker() : | |||
| 	w_edit->add_child(c); | ||||
| 	c->set_area_as_parent_rect(); | ||||
| 	c->set_stop_mouse(false); | ||||
| 	c->set_material(memnew ( CanvasItemMaterial )); | ||||
| 	args.clear(); | ||||
| 	args.push_back(1); | ||||
| 	args.push_back(c); | ||||
|  | @ -593,18 +568,6 @@ ColorPicker::ColorPicker() : | |||
| 	//_update_color();
 | ||||
| 	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)); | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -57,8 +57,6 @@ private: | |||
| 	List<Color> presets; | ||||
| 	ToolButton *btn_pick; | ||||
| 	CheckButton *btn_mode; | ||||
| 	Ref<CanvasItemMaterial> uv_material; | ||||
| 	Ref<CanvasItemMaterial> w_material; | ||||
| 	HSlider *scroll[4]; | ||||
| 	SpinBox *values[4]; | ||||
| 	Label *labels[4]; | ||||
|  |  | |||
|  | @ -46,6 +46,9 @@ class Material : public Resource { | |||
| 	OBJ_SAVE_TYPE( Material ); | ||||
| 
 | ||||
| 	RID material; | ||||
| protected: | ||||
| 
 | ||||
| 	_FORCE_INLINE_  RID _get_material() const { return material; } | ||||
| public: | ||||
| 
 | ||||
| 	virtual RID get_rid() const; | ||||
|  |  | |||
|  | @ -712,6 +712,8 @@ bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) { | |||
| 
 | ||||
| void ShaderLanguage::clear() { | ||||
| 
 | ||||
| 	current_function=StringName(); | ||||
| 
 | ||||
| 	completion_type=COMPLETION_NONE; | ||||
| 	completion_block=NULL; | ||||
| 	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; | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
| 
 | ||||
| 	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) { | ||||
| 
 | ||||
| 	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); | ||||
| 
 | ||||
| 				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) { | ||||
|  | @ -3140,6 +3175,9 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy | |||
| 
 | ||||
| 	Token tk = _get_token(); | ||||
| 
 | ||||
| 	int texture_uniforms = 0; | ||||
| 	int uniforms =0; | ||||
| 
 | ||||
| 	while(tk.type!=TK_EOF) { | ||||
| 
 | ||||
| 		switch(tk.type) { | ||||
|  | @ -3160,12 +3198,12 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy | |||
| 						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)+"'"); | ||||
| 						return ERR_PARSE_ERROR; | ||||
| 					} | ||||
| 
 | ||||
| 					shader->render_modes.insert(tk.text); | ||||
| 					shader->render_modes.push_back(tk.text); | ||||
| 
 | ||||
| 					tk = _get_token(); | ||||
| 					if (tk.type==TK_COMMA) { | ||||
|  | @ -3225,6 +3263,13 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy | |||
| 
 | ||||
| 					ShaderNode::Uniform uniform; | ||||
| 					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.precission=precision; | ||||
| 
 | ||||
|  | @ -3520,9 +3565,13 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy | |||
| 					return ERR_PARSE_ERROR; | ||||
| 				} | ||||
| 
 | ||||
| 				current_function = name; | ||||
| 
 | ||||
| 				Error err = _parse_block(func_node->body,builtin_types); | ||||
| 				if (err) | ||||
| 					return err; | ||||
| 
 | ||||
| 				current_function=StringName(); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -370,6 +370,7 @@ public: | |||
| 		struct Function { | ||||
| 			StringName name; | ||||
| 			FunctionNode*function; | ||||
| 			Set<StringName> uses_function; | ||||
| 			bool callable; | ||||
| 		}; | ||||
| 
 | ||||
|  | @ -391,6 +392,7 @@ public: | |||
| 			}; | ||||
| 
 | ||||
| 			int order; | ||||
| 			int texture_order; | ||||
| 			DataType type; | ||||
| 			DataPrecision precission; | ||||
| 			Vector<ConstantNode::Value> default_value; | ||||
|  | @ -403,7 +405,7 @@ public: | |||
| 
 | ||||
| 		Map<StringName,Varying> varyings; | ||||
| 		Map<StringName,Uniform> uniforms; | ||||
| 		Set<StringName> render_modes; | ||||
| 		Vector<StringName> render_modes; | ||||
| 
 | ||||
| 		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 DataType get_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_builtin_funcs(List<String> *r_keywords); | ||||
| private: | ||||
| 
 | ||||
| 	struct KeyWord { TokenType token; const char *text;}; | ||||
|  | @ -476,6 +480,8 @@ private: | |||
| 	int char_idx; | ||||
| 	int tk_line; | ||||
| 
 | ||||
| 	StringName current_function; | ||||
| 
 | ||||
| 	struct TkPos { | ||||
| 		int char_idx; | ||||
| 		int tk_line; | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ ShaderTypes::ShaderTypes() | |||
| { | ||||
| 	singleton=this; | ||||
| 
 | ||||
| 	/*************** SPATIAL ***********************/ | ||||
| 
 | ||||
| 	shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_VERTEX"]=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_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"); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -140,6 +140,7 @@ public: | |||
| 		SHADER_SPATIAL, | ||||
| 		SHADER_CANVAS_ITEM, | ||||
| 		SHADER_LIGHT, | ||||
| 		SHADER_MAX | ||||
| 	}; | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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"); | ||||
| 		} break; | ||||
| 		case ERR_HANDLER_SHADER: { | ||||
| 
 | ||||
| 			icon = self->get_icon("Shader","EditorIcons"); | ||||
| 		} break; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Juan Linietsky
						Juan Linietsky