From a2505542ffeea705208f72459152c5b86779e327 Mon Sep 17 00:00:00 2001
From: Juan Linietsky <reduzio@gmail.com>
Date: Sun, 20 Nov 2016 22:49:53 -0300
Subject: [PATCH] Huge amount of improvement in the material system. Materials
 should be a lot more complete and usable now.

---
 drivers/gles3/rasterizer_canvas_gles3.cpp  |   4 +
 drivers/gles3/rasterizer_scene_gles3.cpp   |   7 +-
 drivers/gles3/rasterizer_storage_gles3.cpp |  20 +-
 drivers/gles3/rasterizer_storage_gles3.h   |   1 +
 drivers/gles3/shader_compiler_gles3.cpp    |  51 +++-
 drivers/gles3/shaders/scene.glsl           | 205 +++++++++++-----
 scene/3d/light.cpp                         |   2 +-
 scene/resources/material.cpp               | 268 ++++++++++++++++++---
 scene/resources/material.h                 |  49 +++-
 servers/visual/shader_language.cpp         |  25 ++
 servers/visual/shader_language.h           |   4 +
 servers/visual/shader_types.cpp            |   7 +
 12 files changed, 533 insertions(+), 110 deletions(-)

diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 4573f94d222..10a89125616 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -934,9 +934,13 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list,int p_z,const
 					if (!t) {
 
 						switch(texture_hints[i]) {
+							case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
 							case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
 								glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex);
 							} break;
+							case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
+								glBindTexture(GL_TEXTURE_2D,storage->resources.aniso_tex);
+							} break;
 							case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
 								glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex);
 							} break;
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index e04908ea670..3ead218226d 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/drivers/gles3/rasterizer_scene_gles3.cpp
@@ -1035,9 +1035,13 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
 		if (!t) {
 			//check hints
 			switch(texture_hints[i]) {
+				case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO:
 				case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: {
 					glBindTexture(GL_TEXTURE_2D,storage->resources.black_tex);
 				} break;
+				case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: {
+					glBindTexture(GL_TEXTURE_2D,storage->resources.aniso_tex);
+				} break;
 				case ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL: {
 					glBindTexture(GL_TEXTURE_2D,storage->resources.normal_tex);
 				} break;
@@ -1046,7 +1050,6 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
 				} break;
 			}
 
-			glBindTexture(GL_TEXTURE_2D,storage->resources.white_tex);
 			continue;
 		}
 
@@ -1054,7 +1057,7 @@ bool RasterizerSceneGLES3::_setup_material(RasterizerStorageGLES3::Material* p_m
 			//if SRGB decode extension is present, simply switch the texture to whathever is needed
 			bool must_srgb=false;
 
-			if (t->srgb && texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO) {
+			if (t->srgb && (texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || texture_hints[i]==ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO)) {
 				must_srgb=true;
 			}
 
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index 8188fe3adb8..669ab960367 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -2285,6 +2285,7 @@ void RasterizerStorageGLES3::_update_material(Material* material) {
 			if (V) {
 				//user provided				
 				_fill_std140_variant_ubo_value(E->get().type,V->get(),data,material->shader->mode==VS::SHADER_SPATIAL);
+
 			} else if (E->get().default_value.size()){
 				//default value
 				_fill_std140_ubo_value(E->get().type,E->get().default_value,data);
@@ -3304,7 +3305,7 @@ RID RasterizerStorageGLES3::light_create(VS::LightType p_type){
 	light->type=p_type;
 
 	light->param[VS::LIGHT_PARAM_ENERGY]=1.0;
-	light->param[VS::LIGHT_PARAM_SPECULAR]=1.0;
+	light->param[VS::LIGHT_PARAM_SPECULAR]=0.5;
 	light->param[VS::LIGHT_PARAM_RANGE]=1.0;
 	light->param[VS::LIGHT_PARAM_SPOT_ANGLE]=45;
 	light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE]=0;
@@ -4491,7 +4492,7 @@ void RasterizerStorageGLES3::initialize() {
 
 		glGenTextures(1, &resources.black_tex);
 		unsigned char blacktexdata[8*8*3];
-		for(int i=0;i<8*8;i++) {
+		for(int i=0;i<8*8*3;i++) {
 			blacktexdata[i]=0;
 		}
 
@@ -4515,6 +4516,21 @@ void RasterizerStorageGLES3::initialize() {
 		glGenerateMipmap(GL_TEXTURE_2D);
 		glBindTexture(GL_TEXTURE_2D,0);
 
+
+		glGenTextures(1, &resources.aniso_tex);
+		unsigned char anisotexdata[8*8*3];
+		for(int i=0;i<8*8*3;i+=3) {
+			anisotexdata[i+0]=255;
+			anisotexdata[i+1]=128;
+			anisotexdata[i+2]=0;
+		}
+
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D,resources.aniso_tex);
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE,anisotexdata);
+		glGenerateMipmap(GL_TEXTURE_2D);
+		glBindTexture(GL_TEXTURE_2D,0);
+
 	}
 
 	glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,&config.max_texture_image_units);
diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h
index 5f07efeb0a9..b433bcd517b 100644
--- a/drivers/gles3/rasterizer_storage_gles3.h
+++ b/drivers/gles3/rasterizer_storage_gles3.h
@@ -74,6 +74,7 @@ public:
 		GLuint white_tex;
 		GLuint black_tex;
 		GLuint normal_tex;
+		GLuint aniso_tex;
 
 		GLuint quadie;
 		GLuint quadie_array;
diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp
index dce52ecd934..c54fc011e98 100644
--- a/drivers/gles3/shader_compiler_gles3.cpp
+++ b/drivers/gles3/shader_compiler_gles3.cpp
@@ -52,6 +52,7 @@ static int _get_datatype_size(SL::DataType p_type) {
 }
 
 
+
 static String _prestr(SL::DataPrecision p_pres) {
 
 
@@ -248,7 +249,11 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 			r_gen_code.texture_hints.resize(max_texture_uniforms);
 
 			Vector<int> uniform_sizes;
+			Vector<int> uniform_alignments;
+			Vector<StringName> uniform_defines;
 			uniform_sizes.resize(max_uniforms);
+			uniform_alignments.resize(max_uniforms);
+			uniform_defines.resize(max_uniforms);
 
 			for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
 
@@ -272,19 +277,31 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 
 						r_gen_code.defines.push_back(String("#define USE_MATERIAL\n").ascii());
 					}
-					r_gen_code.uniforms+=ucode;
+					uniform_defines[E->get().order]=ucode;
 					uniform_sizes[E->get().order]=_get_datatype_size(E->get().type);
+					uniform_alignments[E->get().order]=MIN(16,_get_datatype_size(E->get().type));
 				}
 
 				p_actions.uniforms->insert(E->key(),E->get());
 
 			}
 
+			for(int i=0;i<max_uniforms;i++) {
+				r_gen_code.uniforms+=uniform_defines[i];
+			}
 			// add up
 			for(int i=0;i<uniform_sizes.size();i++) {
 
-				if (i>0)
+				if (i>0) {
+
+					int align = uniform_sizes[i-1] % uniform_alignments[i];
+					if (align!=0) {
+						uniform_sizes[i-1]+=uniform_alignments[i]-align;
+					}
+
 					uniform_sizes[i]=uniform_sizes[i]+uniform_sizes[i-1];
+
+				}
 			}
 			//offset
 			r_gen_code.uniform_offsets.resize(uniform_sizes.size());
@@ -294,8 +311,21 @@ String ShaderCompilerGLES3::_dump_node_code(SL::Node *p_node, int p_level, Gener
 					r_gen_code.uniform_offsets[i]=uniform_sizes[i-1];
 				else
 					r_gen_code.uniform_offsets[i]=0;
+
+
+			}
+/*
+			for(Map<StringName,SL::ShaderNode::Uniform>::Element *E=pnode->uniforms.front();E;E=E->next()) {
+
+				if (SL::is_sampler_type(E->get().type)) {
+					continue;
+				}
+
+				print_line("u - "+String(E->key())+" offset: "+itos(r_gen_code.uniform_offsets[E->get().order]));
+
 			}
 
+*/
 			if (uniform_sizes.size()) {
 				r_gen_code.uniform_total_size=uniform_sizes[ uniform_sizes.size() -1 ];
 			} else {
@@ -549,13 +579,11 @@ Error ShaderCompilerGLES3::compile(VS::ShaderMode p_mode, const String& p_code,
 	r_gen_code.uses_vertex_time=false;
 
 
-
 	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;
 
 }
@@ -636,8 +664,14 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
 	actions[VS::SHADER_SPATIAL].renames["ALPHA"]="alpha";
 	actions[VS::SHADER_SPATIAL].renames["SPECULAR"]="specular";
 	actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"]="roughness";
+	actions[VS::SHADER_SPATIAL].renames["RIM"]="rim";
+	actions[VS::SHADER_SPATIAL].renames["RIM_TINT"]="rim_tint";
+	actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"]="clearcoat";
+	actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"]="clearcoat_gloss";
+	actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"]="anisotropy";
+	actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"]="anisotropy_flow";
+	actions[VS::SHADER_SPATIAL].renames["AO"]="ao";
 	actions[VS::SHADER_SPATIAL].renames["EMISSION"]="emission";
-	actions[VS::SHADER_SPATIAL].renames["SPECIAL"]="special";
 	actions[VS::SHADER_SPATIAL].renames["DISCARD"]="_discard";
 //	actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
 	actions[VS::SHADER_SPATIAL].renames["POINT_COORD"]="gl_PointCoord";
@@ -645,6 +679,13 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() {
 
 	actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"]="#define ENABLE_TANGENT_INTERP\n";
 	actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"]="@TANGENT";
+	actions[VS::SHADER_SPATIAL].usage_defines["RIM"]="#define LIGHT_USE_RIM\n";
+	actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"]="@RIM";
+	actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"]="#define LIGHT_USE_CLEARCOAT\n";
+	actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"]="@CLEARCOAT";
+	actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"]="#define LIGHT_USE_ANISOTROPY\n";
+	actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"]="@ANISOTROPY";
+	actions[VS::SHADER_SPATIAL].usage_defines["AO"]="#define ENABLE_AO\n";
 	actions[VS::SHADER_SPATIAL].usage_defines["UV"]="#define ENABLE_UV_INTERP\n";
 	actions[VS::SHADER_SPATIAL].usage_defines["UV2"]="#define ENABLE_UV2_INTERP\n";
 	actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"]="#define ENABLE_NORMALMAP\n";
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index a923c130dca..aa8b3cacdce 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -108,7 +108,7 @@ out vec2 uv2_interp;
 #endif
 
 
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
 out vec3 tangent_interp;
 out vec3 binormal_interp;
 #endif
@@ -146,7 +146,7 @@ void main() {
 	highp mat4 modelview = camera_inverse_matrix * world_transform;
 	vec3 normal = normal_attrib * normal_mult;
 
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
 	vec3 tangent = tangent_attrib.xyz;
 	tangent*=normal_mult;
 	float binormalf = tangent_attrib.a;
@@ -163,7 +163,7 @@ void main() {
 
 		vertex = vertex_in * m;
 		normal = (vec4(normal,0.0) * m).xyz;
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
 		tangent = (vec4(tangent,0.0) * m).xyz;
 #endif
 	}
@@ -176,7 +176,7 @@ void main() {
 	normal = normalize((modelview * vec4(normal,0.0)).xyz);
 #endif
 
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
 # if !defined(SKIP_TRANSFORM_USED)
 
 	tangent=normalize((modelview * vec4(tangent,0.0)).xyz);
@@ -207,7 +207,7 @@ VERTEX_SHADER_CODE
 	vertex_interp = vertex.xyz;
 	normal_interp = normal;
 
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
 	tangent_interp = tangent;
 	binormal_interp = binormal;
 #endif
@@ -276,7 +276,7 @@ in vec2 uv_interp;
 in vec2 uv2_interp;
 #endif
 
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
 in vec3 tangent_interp;
 in vec3 binormal_interp;
 #endif
@@ -455,40 +455,86 @@ float G1V(float dotNV, float k)
     return 1.0 / (dotNV * (1.0 - k) + k);
 }
 
-float specularGGX(vec3 N, vec3 V, vec3 L, float roughness, float F0)
+
+float SchlickFresnel(float u)
 {
-    float alpha = roughness * roughness;
-
-    vec3 H = normalize(V + L);
-
-    float dotNL = max(dot(N,L), 0.0 );
-    float dotNV = max(dot(N,V), 0.0 );
-    float dotNH = max(dot(N,H), 0.0 );
-    float dotLH = max(dot(L,H), 0.0 );
-
-    // D
-    float alphaSqr = alpha * alpha;
-    float pi = M_PI;
-    float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
-    float D = alphaSqr / (pi * denom * denom);
-
-    // F
-    float dotLH5 = pow(1.0 - dotLH, 5.0);
-    float F = F0 + (1.0 - F0) * (dotLH5);
-
-    // V
-    float k = alpha / 2.0f;
-    float vis = G1V(dotNL, k) * G1V(dotNV, k);
-
-    return dotNL * D * F * vis;
+    float m = 1.0-u;
+    float m2 = m*m;
+    return m2*m2*m; // pow(m,5)
 }
 
-void light_compute(vec3 normal, vec3 light_vec,vec3 eye_vec,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float roughness, inout vec3 diffuse, inout vec3 specular) {
+float GTR1(float NdotH, float a)
+{
+    if (a >= 1.0) return 1.0/M_PI;
+    float a2 = a*a;
+    float t = 1.0 + (a2-1.0)*NdotH*NdotH;
+    return (a2-1.0) / (M_PI*log(a2)*t);
+}
+
+void light_compute(vec3 N, vec3 L,vec3 V,vec3 B, vec3 T,vec3 light_color,vec3 diffuse_color, vec3 specular_color, float specular_blob_intensity, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse, inout vec3 specular) {
+
+	float dotNL = max(dot(N,L), 0.0 );
+	float dotNV = max(dot(N,V), 0.0 );
+
+#if defined(LIGHT_USE_RIM)
+	float rim_light = pow(1.0-dotNV,(1.0-roughness)*16.0);
+	diffuse += rim_light * rim * mix(vec3(1.0),diffuse_color,rim_tint) * light_color;
+#endif
+
+	diffuse += dotNL * light_color * diffuse_color;
+
+	if (roughness > 0.0) {
+
+		float alpha = roughness * roughness;
+
+		vec3 H = normalize(V + L);
+
+		float dotNH = max(dot(N,H), 0.0 );
+		float dotLH = max(dot(L,H), 0.0 );
+
+		// D
+#if defined(LIGHT_USE_ANISOTROPY)
+
+		float aspect = sqrt(1.0-anisotropy*0.9);
+		float rx = roughness/aspect;
+		float ry = roughness*aspect;
+		float ax = rx*rx;
+		float ay = ry*ry;
+		float dotXH = dot( T, H );
+		float dotYH = dot( B, H );
+		float pi = M_PI;
+		float denom = dotXH*dotXH / (ax*ax) + dotYH*dotYH / (ay*ay) + dotNH*dotNH;
+		float D = 1.0 / ( pi * ax*ay * denom*denom );
+
+#else
+		float alphaSqr = alpha * alpha;
+		float pi = M_PI;
+		float denom = dotNH * dotNH * (alphaSqr - 1.0) + 1.0;
+		float D = alphaSqr / (pi * denom * denom);
+#endif
+		// F
+		float F0 = 1.0;
+		float dotLH5 = SchlickFresnel( dotLH );
+		float F = F0 + (1.0 - F0) * (dotLH5);
+
+		// V
+		float k = alpha / 2.0f;
+		float vis = G1V(dotNL, k) * G1V(dotNV, k);
+
+		float speci = dotNL * D * F * vis;
+
+		specular += speci * light_color * specular_color * specular_blob_intensity;
+
+#if defined(LIGHT_USE_CLEARCOAT)
+		float Dr = GTR1(dotNH, mix(.1,.001,clearcoat_gloss));
+		float Fr = mix(.04, 1.0, dotLH5);
+		float Gr = G1V(dotNL, .25) * G1V(dotNV, .25);
+
+		specular += .25*clearcoat*Gr*Fr*Dr;
+#endif
+	}
+
 
-	diffuse += max(0.0,dot(normal,light_vec)) * light_color * diffuse_color;
-	//specular += specular_ggx( roughness, max(0.0,dot(normal,eye_vec)) ) * specular_color * attenuation;
-	float s = roughness > 0.0 ? specularGGX(normal,eye_vec,light_vec,roughness,1.0) : 0.0;
-	specular += s * light_color * specular_color;
 }
 
 
@@ -536,7 +582,7 @@ in highp float dp_clip;
 
 #endif
 
-void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 binormal, vec3 tangent, vec3 albedo, vec3 specular, float roughness, float rim, float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy,inout vec3 diffuse_light, inout vec3 specular_light) {
 
 	vec3 light_rel_vec = omni_lights[idx].light_pos_inv_radius.xyz-vertex;
 	float normalized_distance = length( light_rel_vec )*omni_lights[idx].light_pos_inv_radius.w;
@@ -577,11 +623,11 @@ void light_process_omni(int idx, vec3 vertex, vec3 eye_vec,vec3 normal,vec3 albe
 		light_attenuation*=mix(omni_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,clamp_rect));
 	}
 
-	light_compute(normal,normalize(light_rel_vec),eye_vec,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light);
+	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,omni_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,omni_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 
 }
 
-void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, vec3 specular, float roughness, inout vec3 diffuse_light, inout vec3 specular_light) {
+void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 binormal, vec3 tangent,vec3 albedo, vec3 specular, float roughness, float rim,float rim_tint, float clearcoat, float clearcoat_gloss,float anisotropy, inout vec3 diffuse_light, inout vec3 specular_light) {
 
 	vec3 light_rel_vec = spot_lights[idx].light_pos_inv_radius.xyz-vertex;
 	float normalized_distance = length( light_rel_vec )*spot_lights[idx].light_pos_inv_radius.w;
@@ -589,8 +635,8 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 al
 	vec3 spot_dir = spot_lights[idx].light_direction_attenuation.xyz;
 	float spot_cutoff=spot_lights[idx].light_params.y;
 	float scos = max(dot(-normalize(light_rel_vec), spot_dir),spot_cutoff);
-	float rim = (1.0 - scos) / (1.0 - spot_cutoff);
-	light_attenuation *= 1.0 - pow( rim, spot_lights[idx].light_params.x);
+	float spot_rim = (1.0 - scos) / (1.0 - spot_cutoff);
+	light_attenuation *= 1.0 - pow( spot_rim, spot_lights[idx].light_params.x);
 
 	if (spot_lights[idx].light_params.w>0.5) {
 		//there is a shadowmap
@@ -599,11 +645,11 @@ void light_process_spot(int idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 al
 		light_attenuation*=mix(spot_lights[idx].shadow_color.rgb,vec3(1.0),sample_shadow(shadow_atlas,shadow_atlas_pixel_size,splane.xy,splane.z,spot_lights[idx].light_clamp));
 	}
 
-	light_compute(normal,normalize(light_rel_vec),eye_vec,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light);
+	light_compute(normal,normalize(light_rel_vec),eye_vec,binormal,tangent,spot_lights[idx].light_color_energy.rgb*light_attenuation,albedo,specular,spot_lights[idx].light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 
 }
 
-void reflection_process(int idx, vec3 vertex, vec3 normal,float roughness,vec3 ambient,vec3 skybox,vec2 brdf, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) {
+void reflection_process(int idx, vec3 vertex, vec3 normal,vec3 binormal, vec3 tangent,float roughness,float anisotropy,vec3 ambient,vec3 skybox,vec2 brdf, inout highp vec4 reflection_accum,inout highp vec4 ambient_accum) {
 
 	vec3 ref_vec = normalize(reflect(vertex,normal));
 	vec3 local_pos = (reflections[idx].local_matrix * vec4(vertex,1.0)).xyz;
@@ -729,7 +775,19 @@ void main() {
 	highp vec3 vertex = vertex_interp;
 	vec3 albedo = vec3(0.8,0.8,0.8);
 	vec3 specular = vec3(0.2,0.2,0.2);
+	vec3 emission = vec3(0.0,0.0,0.0);
 	float roughness = 1.0;
+	float rim = 0.0;
+	float rim_tint = 0.0;
+	float clearcoat=0.0;
+	float clearcoat_gloss=0.0;
+	float anisotropy = 1.0;
+	vec2 anisotropy_flow = vec2(1.0,0.0);
+
+#if defined(ENABLE_AO)
+	float ao=1.0;
+#endif
+
 	float alpha = 1.0;
 
 #ifdef METERIAL_DOUBLESIDED
@@ -739,9 +797,12 @@ void main() {
 #endif
 
 
-#if defined(ENABLE_TANGENT_INTERP)
+#if defined(ENABLE_TANGENT_INTERP) || defined(ENABLE_NORMALMAP) || defined(LIGHT_USE_ANISOTROPY)
 	vec3 binormal = normalize(binormal_interp)*side;
 	vec3 tangent = normalize(tangent_interp)*side;
+#else
+	vec3 binormal = vec3(0.0);
+	vec3 tangent = vec3(0.0);
 #endif
 	vec3 normal = normalize(normal_interp)*side;
 
@@ -777,9 +838,26 @@ FRAGMENT_SHADER_CODE
 
 }
 
+
+
 #if defined(ENABLE_NORMALMAP)
 
-	normal = normalize( mix(normal_interp,tangent_interp * normalmap.x + binormal_interp * normalmap.y + normal_interp * normalmap.z,normaldepth) ) * side;
+	normalmap.xy=normalmap.xy*2.0-1.0;
+	normalmap.z=sqrt(1.0-dot(normalmap.xy,normalmap.xy)); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc.
+
+	normal = normalize( mix(normal_interp,tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z,normaldepth) ) * side;
+
+#endif
+
+#if defined(LIGHT_USE_ANISOTROPY)
+
+	if (anisotropy>0.01) {
+		//rotation matrix
+		mat3 rot = mat3( tangent, binormal, normal );
+		//make local to space
+		tangent = normalize(rot * vec3(anisotropy_flow.x,anisotropy_flow.y,0.0));
+		binormal = normalize(rot * vec3(-anisotropy_flow.y,anisotropy_flow.x,0.0));
+	}
 
 #endif
 
@@ -799,6 +877,10 @@ FRAGMENT_SHADER_CODE
 
 /////////////////////// LIGHTING //////////////////////////////
 
+	//apply energy conservation
+	vec3 diffuse=mix(albedo,vec3(0.0),specular);
+	specular = max(vec3(0.04),specular);
+
 	vec3 specular_light = vec3(0.0,0.0,0.0);
 	vec3 ambient_light;
 	vec3 diffuse_light = vec3(0.0,0.0,0.0);
@@ -839,8 +921,7 @@ FRAGMENT_SHADER_CODE
 
 				norm.xy/=norm.z;
 				norm.xy=norm.xy * vec2(0.5,0.25) + vec2(0.5,0.25+y_ofs);
-				vec3 radiance = textureLod(radiance_map, norm.xy, lod).xyz * ( brdf.x + brdf.y);
-				specular_light=mix(albedo,radiance,specular);
+				specular_light = textureLod(radiance_map, norm.xy, lod).xyz * ( brdf.x + brdf.y);
 
 			}
 			//no longer a cubemap
@@ -996,7 +1077,7 @@ FRAGMENT_SHADER_CODE
 
 #endif //LIGHT_DIRECTIONAL_SHADOW
 
-	light_compute(normal,-light_direction_attenuation.xyz,eye_vec,light_color_energy.rgb*light_attenuation,albedo,specular,roughness,diffuse_light,specular_light);
+	light_compute(normal,-light_direction_attenuation.xyz,eye_vec,binormal,tangent,light_color_energy.rgb*light_attenuation,diffuse,specular,light_params.z,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 
 
 #endif //#USE_LIGHT_DIRECTIONAL
@@ -1008,23 +1089,22 @@ FRAGMENT_SHADER_CODE
 	highp vec4 ambient_accum = vec4(0.0,0.0,0.0,0.0);
 
 	for(int i=0;i<reflection_count;i++) {
-		reflection_process(reflection_indices[i],vertex,normal,roughness,ambient_light,specular_light,brdf,reflection_accum,ambient_accum);
+		reflection_process(reflection_indices[i],vertex,normal,binormal,tangent,roughness,anisotropy,ambient_light,specular_light,brdf,reflection_accum,ambient_accum);
 	}
 
 	if (reflection_accum.a>0.0) {
 		specular_light=reflection_accum.rgb/reflection_accum.a;
-		specular_light*=specular;
 	}
 	if (ambient_accum.a>0.0) {
 		ambient_light=ambient_accum.rgb/ambient_accum.a;
 	}
 
 	for(int i=0;i<omni_light_count;i++) {
-		light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,albedo,specular,roughness,diffuse_light,specular_light);
+		light_process_omni(omni_light_indices[i],vertex,eye_vec,normal,binormal,tangent,diffuse,specular,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 	}
 
 	for(int i=0;i<spot_light_count;i++) {
-		light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,albedo,specular,roughness,diffuse_light,specular_light);
+		light_process_spot(spot_light_indices[i],vertex,eye_vec,normal,binormal,tangent,diffuse,specular,roughness,rim,rim_tint,clearcoat,clearcoat_gloss,anisotropy,diffuse_light,specular_light);
 	}
 
 
@@ -1048,16 +1128,28 @@ LIGHT_SHADER_CODE
 #else
 
 	specular_light*=reflection_multiplier;
+	specular_light*=specular;
+	ambient_light*=albedo; //ambient must be multiplied by albedo at the end
+
+#if defined(ENABLE_AO)
+	ambient_light*=ao;
+#endif
 
 #ifdef USE_MULTIPLE_RENDER_TARGETS
 
+#if defined(ENABLE_AO)
+
+	float ambient_scale=0.0; // AO is supplied by material
+#else
 	//approximate ambient scale for SSAO, since we will lack full ambient
+	float max_emission=max(emission.r,max(emission.g,emission.b));
 	float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b));
 	float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b));
-	float total_ambient = max_ambient+max_diffuse;
+	float total_ambient = max_ambient+max_diffuse+max_emission;
 	float ambient_scale = (total_ambient>0.0) ? max_ambient/total_ambient : 0.0;
+#endif //ENABLE_AO
 
-	diffuse_buffer=vec4(diffuse_light+ambient_light,ambient_scale);
+	diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale);
 	specular_buffer=vec4(specular_light,0.0);
 	normal_mr_buffer=vec4(normal.x,normal.y,max(specular.r,max(specular.g,specular.b)),roughness);
 
@@ -1067,11 +1159,14 @@ LIGHT_SHADER_CODE
 #ifdef SHADELESS
 	frag_color=vec4(albedo,alpha);
 #else
-	frag_color=vec4(ambient_light+diffuse_light+specular_light,alpha);
+	frag_color=vec4(emission+ambient_light+diffuse_light+specular_light,alpha);
 #endif //SHADELESS
 
+
 #endif //USE_MULTIPLE_RENDER_TARGETS
 
+
+
 #endif //RENDER_SHADOW
 
 
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index dfb95216390..49bffd3c219 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -254,7 +254,7 @@ Light::Light(VisualServer::LightType p_type) {
 	set_cull_mask(0xFFFFFFFF);
 
 	set_param(PARAM_ENERGY,1);
-	set_param(PARAM_SPECULAR,1);
+	set_param(PARAM_SPECULAR,0.5);
 	set_param(PARAM_RANGE,5);
 	set_param(PARAM_ATTENUATION,1);
 	set_param(PARAM_SPOT_ANGLE,45);
diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp
index cb55f4f0305..99b7a130f77 100644
--- a/scene/resources/material.cpp
+++ b/scene/resources/material.cpp
@@ -64,25 +64,30 @@ void FixedSpatialMaterial::init_shaders() {
 	shader_names->specular="specular";
 	shader_names->roughness="roughness";
 	shader_names->emission="emission";
+	shader_names->emission_energy="emission_energy";
 	shader_names->normal_scale="normal_scale";
-	shader_names->sheen="sheen";
-	shader_names->sheen_color="sheen_color";
+	shader_names->rim="rim";
+	shader_names->rim_tint="rim_tint";
 	shader_names->clearcoat="clearcoat";
 	shader_names->clearcoat_gloss="clearcoat_gloss";
-	shader_names->anisotropy="anisotropy";
+	shader_names->anisotropy="anisotropy_ratio";
 	shader_names->height_scale="height_scale";
 	shader_names->subsurface_scattering="subsurface_scattering";
 	shader_names->refraction="refraction";
 	shader_names->refraction_roughness="refraction_roughness";
 	shader_names->point_size="point_size";
+	shader_names->uv1_scale="uv1_scale";
+	shader_names->uv1_offset="uv1_offset";
+	shader_names->uv2_scale="uv2_scale";
+	shader_names->uv2_offset="uv2_offset";
 
 	shader_names->texture_names[TEXTURE_ALBEDO]="texture_albedo";
 	shader_names->texture_names[TEXTURE_SPECULAR]="texture_specular";
 	shader_names->texture_names[TEXTURE_EMISSION]="texture_emission";
 	shader_names->texture_names[TEXTURE_NORMAL]="texture_normal";
-	shader_names->texture_names[TEXTURE_SHEEN]="texture_sheen";
+	shader_names->texture_names[TEXTURE_RIM]="texture_rim";
 	shader_names->texture_names[TEXTURE_CLEARCOAT]="texture_clearcoat";
-	shader_names->texture_names[TEXTURE_ANISOTROPY]="texture_anisotropy";
+	shader_names->texture_names[TEXTURE_FLOWMAP]="texture_flowmap";
 	shader_names->texture_names[TEXTURE_AMBIENT_OCCLUSION]="texture_ambient_occlusion";
 	shader_names->texture_names[TEXTURE_HEIGHT]="texture_height";
 	shader_names->texture_names[TEXTURE_SUBSURFACE_SCATTERING]="texture_subsurface_scattering";
@@ -172,6 +177,46 @@ void FixedSpatialMaterial::_update_shader() {
 	code+="uniform float roughness : hint_range(0,1);\n";
 	code+="uniform float point_size : hint_range(0,128);\n";
 	code+="uniform sampler2D texture_specular : hint_white;\n";
+	code+="uniform vec2 uv1_scale;\n";
+	code+="uniform vec2 uv1_offset;\n";
+	code+="uniform vec2 uv2_scale;\n";
+	code+="uniform vec2 uv2_offset;\n";
+
+	if (features[FEATURE_EMISSION]) {
+
+		code+="uniform sampler2D texture_emission : hint_black_albedo;\n";
+		code+="uniform vec4 emission : hint_color;\n";
+		code+="uniform float emission_energy;\n";
+	}
+
+	if (features[FEATURE_NORMAL_MAPPING]) {
+		code+="uniform sampler2D texture_normal : hint_normal;\n";
+		code+="uniform float normal_scale : hint_range(-16,16);\n";
+	}
+	if (features[FEATURE_RIM]) {
+		code+="uniform float rim : hint_range(0,1);\n";
+		code+="uniform float rim_tint : hint_range(0,1);\n";
+		code+="uniform sampler2D texture_rim : hint_white;\n";
+	}
+	if (features[FEATURE_CLEARCOAT]) {
+		code+="uniform float clearcoat : hint_range(0,1);\n";
+		code+="uniform float clearcoat_gloss : hint_range(0,1);\n";
+		code+="uniform sampler2D texture_clearcoat : hint_white;\n";
+	}
+	if (features[FEATURE_ANISOTROPY]) {
+		code+="uniform float anisotropy_ratio : hint_range(0,256);\n";
+		code+="uniform sampler2D texture_flowmap : hint_aniso;\n";
+	}
+	if (features[FEATURE_AMBIENT_OCCLUSION]) {
+		code+="uniform sampler2D texture_ambient_occlusion : hint_white;\n";
+	}
+
+	if (features[FEATURE_DETAIL]) {
+		code+="uniform sampler2D texture_detail_albedo : hint_albedo;\n";
+		code+="uniform sampler2D texture_detail_normal : hint_normal;\n";
+		code+="uniform sampler2D texture_detail_mask : hint_white;\n";
+	}
+
 	code+="\n\n";
 
 	code+="void vertex() {\n";
@@ -184,6 +229,10 @@ void FixedSpatialMaterial::_update_shader() {
 
 		code+="\tPOINT_SIZE=point_size;\n";
 	}
+	code+="\tUV=UV*uv1_scale+uv1_offset;\n";
+	if (detail_blend_mode==DETAIL_UV_2) {
+		code+="\tUV2=UV2*uv2_scale+uv2_offset;\n";
+	}
 
 	code+="}\n";
 	code+="\n\n";
@@ -203,6 +252,66 @@ void FixedSpatialMaterial::_update_shader() {
 	if (features[FEATURE_TRANSPARENT]) {
 		code+="\tALPHA = albedo.a * albedo_tex.a;\n";
 	}
+
+	if (features[FEATURE_EMISSION]) {
+		code+="\tEMISSION = (emission.rgb+texture(texture_emission,UV).rgb)*emission_energy;\n";
+	}
+
+	if (features[FEATURE_NORMAL_MAPPING]) {
+		code+="\tNORMALMAP = texture(texture_normal,UV).rgb;\n";
+		code+="\tNORMALMAP_DEPTH = normal_scale;\n";
+	}
+
+	if (features[FEATURE_RIM]) {
+		code+="\tvec2 rim_tex = texture(texture_rim,UV).xw;\n";
+		code+="\tRIM = rim*rim_tex.x;";
+		code+="\tRIM_TINT = rim_tint*rim_tex.y;\n";
+	}
+
+	if (features[FEATURE_CLEARCOAT]) {
+		code+="\tvec2 clearcoat_tex = texture(texture_clearcoat,UV).xw;\n";
+		code+="\tCLEARCOAT = clearcoat*clearcoat_tex.x;";
+		code+="\tCLEARCOAT_GLOSS = clearcoat_gloss*clearcoat_tex.y;\n";
+	}
+
+	if (features[FEATURE_ANISOTROPY]) {
+		code+="\tvec4 anisotropy_tex = texture(texture_flowmap,UV);\n";
+		code+="\tANISOTROPY = anisotropy_ratio*anisotropy_tex.a;\n";
+		code+="\tANISOTROPY_FLOW = anisotropy_tex.rg*2.0-1.0;\n";
+	}
+
+	if (features[FEATURE_AMBIENT_OCCLUSION]) {
+		code+="\tAO = texture(texture_ambient_occlusion,UV).r;\n";
+	}
+
+	if (features[FEATURE_DETAIL]) {
+		String det_uv=detail_uv==DETAIL_UV_1?"UV":"UV2";
+		code+="\tvec4 detail_tex = texture(texture_detail_albedo,"+det_uv+");\n";
+		code+="\tvec4 detail_norm_tex = texture(texture_detail_normal,"+det_uv+");\n";
+		code+="\tvec4 detail_mask_tex = texture(texture_detail_mask,UV);\n";
+
+		switch(detail_blend_mode) {
+			case BLEND_MODE_MIX: {
+				code+="\tvec3 detail = mix(ALBEDO.rgb,detail_tex.rgb,detail_tex.a);\n";
+			} break;
+			case BLEND_MODE_ADD: {
+				code+="\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb+detail_tex.rgb,detail_tex.a);\n";
+			} break;
+			case BLEND_MODE_SUB: {
+				code+="\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb-detail_tex.rgb,detail_tex.a);\n";
+			} break;
+			case BLEND_MODE_MUL: {
+				code+="\tvec3 detail = mix(ALBEDO.rgb,ALBEDO.rgb*detail_tex.rgb,detail_tex.a);\n";
+			} break;
+
+		}
+
+		code+="\tvec3 detail_norm = mix(NORMALMAP,detail_norm_tex.rgb,detail_tex.a);\n";
+
+		code+="\tNORMALMAP = mix(NORMALMAP,detail_norm,detail_mask_tex.r);\n";
+		code+="\tALBEDO.rgb = mix(ALBEDO.rgb,detail,detail_mask_tex.r);\n";
+	}
+
 	code+="\tvec4 specular_tex = texture(texture_specular,UV);\n";
 	code+="\tSPECULAR = specular.rgb * specular_tex.rgb;\n";
 	code+="\tROUGHNESS = specular.a * roughness;\n";
@@ -308,6 +417,18 @@ Color FixedSpatialMaterial::get_emission() const{
 	return emission;
 }
 
+
+void FixedSpatialMaterial::set_emission_energy(float p_emission_energy){
+
+	emission_energy=p_emission_energy;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->emission_energy,p_emission_energy);
+
+}
+float FixedSpatialMaterial::get_emission_energy() const{
+
+	return emission_energy;
+}
+
 void FixedSpatialMaterial::set_normal_scale(float p_normal_scale){
 
 	normal_scale=p_normal_scale;
@@ -319,27 +440,27 @@ float FixedSpatialMaterial::get_normal_scale() const{
 	return normal_scale;
 }
 
-void FixedSpatialMaterial::set_sheen(float p_sheen){
+void FixedSpatialMaterial::set_rim(float p_rim){
 
-	sheen=p_sheen;
-	VS::get_singleton()->material_set_param(_get_material(),shader_names->sheen,p_sheen);
+	rim=p_rim;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->rim,p_rim);
 
 
 }
-float FixedSpatialMaterial::get_sheen() const{
+float FixedSpatialMaterial::get_rim() const{
 
-	return sheen;
+	return rim;
 }
 
-void FixedSpatialMaterial::set_sheen_color(const Color& p_sheen_color){
+void FixedSpatialMaterial::set_rim_tint(float p_rim_tint){
 
-	sheen_color=p_sheen_color;
-	VS::get_singleton()->material_set_param(_get_material(),shader_names->sheen_color,p_sheen_color);
+	rim_tint=p_rim_tint;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->rim_tint,p_rim_tint);
 
 }
-Color FixedSpatialMaterial::get_sheen_color() const{
+float FixedSpatialMaterial::get_rim_tint() const{
 
-	return sheen_color;
+	return rim_tint;
 }
 
 void FixedSpatialMaterial::set_clearcoat(float p_clearcoat){
@@ -565,7 +686,8 @@ void FixedSpatialMaterial::_validate_feature(const String& text, Feature feature
 
 void FixedSpatialMaterial::_validate_property(PropertyInfo& property) const {
 	_validate_feature("normal",FEATURE_NORMAL_MAPPING,property);
-	_validate_feature("sheen",FEATURE_SHEEN,property);
+	_validate_feature("emission",FEATURE_EMISSION,property);
+	_validate_feature("rim",FEATURE_RIM,property);
 	_validate_feature("clearcoat",FEATURE_CLEARCOAT,property);
 	_validate_feature("anisotropy",FEATURE_ANISOTROPY,property);
 	_validate_feature("ao",FEATURE_AMBIENT_OCCLUSION,property);
@@ -598,6 +720,53 @@ float FixedSpatialMaterial::get_point_size() const {
 	return point_size;
 }
 
+
+void FixedSpatialMaterial::set_uv1_scale(const Vector2& p_scale) {
+
+	uv1_scale=p_scale;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->uv1_scale,p_scale);
+}
+
+Vector2 FixedSpatialMaterial::get_uv1_scale() const{
+
+	return uv1_scale;
+}
+
+void FixedSpatialMaterial::set_uv1_offset(const Vector2& p_offset){
+
+	uv1_offset=p_offset;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->uv1_offset,p_offset);
+
+}
+Vector2 FixedSpatialMaterial::get_uv1_offset() const{
+
+	return uv1_offset;
+}
+
+
+void FixedSpatialMaterial::set_uv2_scale(const Vector2& p_scale) {
+
+	uv2_scale=p_scale;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->uv2_scale,p_scale);
+}
+
+Vector2 FixedSpatialMaterial::get_uv2_scale() const{
+
+	return uv2_scale;
+}
+
+void FixedSpatialMaterial::set_uv2_offset(const Vector2& p_offset){
+
+	uv2_offset=p_offset;
+	VS::get_singleton()->material_set_param(_get_material(),shader_names->uv2_offset,p_offset);
+
+}
+
+Vector2 FixedSpatialMaterial::get_uv2_offset() const{
+
+	return uv2_offset;
+}
+
 void FixedSpatialMaterial::_bind_methods() {
 
 
@@ -613,14 +782,17 @@ void FixedSpatialMaterial::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_emission","emission"),&FixedSpatialMaterial::set_emission);
 	ObjectTypeDB::bind_method(_MD("get_emission"),&FixedSpatialMaterial::get_emission);
 
+	ObjectTypeDB::bind_method(_MD("set_emission_energy","emission_energy"),&FixedSpatialMaterial::set_emission_energy);
+	ObjectTypeDB::bind_method(_MD("get_emission_energy"),&FixedSpatialMaterial::get_emission_energy);
+
 	ObjectTypeDB::bind_method(_MD("set_normal_scale","normal_scale"),&FixedSpatialMaterial::set_normal_scale);
 	ObjectTypeDB::bind_method(_MD("get_normal_scale"),&FixedSpatialMaterial::get_normal_scale);
 
-	ObjectTypeDB::bind_method(_MD("set_sheen","sheen"),&FixedSpatialMaterial::set_sheen);
-	ObjectTypeDB::bind_method(_MD("get_sheen"),&FixedSpatialMaterial::get_sheen);
+	ObjectTypeDB::bind_method(_MD("set_rim","rim"),&FixedSpatialMaterial::set_rim);
+	ObjectTypeDB::bind_method(_MD("get_rim"),&FixedSpatialMaterial::get_rim);
 
-	ObjectTypeDB::bind_method(_MD("set_sheen_color","sheen_color"),&FixedSpatialMaterial::set_sheen_color);
-	ObjectTypeDB::bind_method(_MD("get_sheen_color"),&FixedSpatialMaterial::get_sheen_color);
+	ObjectTypeDB::bind_method(_MD("set_rim_tint","rim_tint"),&FixedSpatialMaterial::set_rim_tint);
+	ObjectTypeDB::bind_method(_MD("get_rim_tint"),&FixedSpatialMaterial::get_rim_tint);
 
 	ObjectTypeDB::bind_method(_MD("set_clearcoat","clearcoat"),&FixedSpatialMaterial::set_clearcoat);
 	ObjectTypeDB::bind_method(_MD("get_clearcoat"),&FixedSpatialMaterial::get_clearcoat);
@@ -676,6 +848,18 @@ void FixedSpatialMaterial::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_detail_blend_mode","detail_blend_mode"),&FixedSpatialMaterial::set_detail_blend_mode);
 	ObjectTypeDB::bind_method(_MD("get_detail_blend_mode"),&FixedSpatialMaterial::get_detail_blend_mode);
 
+	ObjectTypeDB::bind_method(_MD("set_uv1_scale","scale"),&FixedSpatialMaterial::set_uv1_scale);
+	ObjectTypeDB::bind_method(_MD("get_uv1_scale"),&FixedSpatialMaterial::get_uv1_scale);
+
+	ObjectTypeDB::bind_method(_MD("set_uv1_offset","offset"),&FixedSpatialMaterial::set_uv1_offset);
+	ObjectTypeDB::bind_method(_MD("get_uv1_offset"),&FixedSpatialMaterial::get_uv1_offset);
+
+	ObjectTypeDB::bind_method(_MD("set_uv2_scale","scale"),&FixedSpatialMaterial::set_uv2_scale);
+	ObjectTypeDB::bind_method(_MD("get_uv2_scale"),&FixedSpatialMaterial::get_uv2_scale);
+
+	ObjectTypeDB::bind_method(_MD("set_uv2_offset","offset"),&FixedSpatialMaterial::set_uv2_offset);
+	ObjectTypeDB::bind_method(_MD("get_uv2_offset"),&FixedSpatialMaterial::get_uv2_offset);
+
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags/transparent"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_TRANSPARENT);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags/unshaded"),_SCS("set_flag"),_SCS("get_flag"),FLAG_UNSHADED);
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"flags/on_top"),_SCS("set_flag"),_SCS("get_flag"),FLAG_ONTOP);
@@ -693,27 +877,32 @@ void FixedSpatialMaterial::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"albedo/color"),_SCS("set_albedo"),_SCS("get_albedo"));
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"albedo/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_ALBEDO);
 
-	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"specular/color"),_SCS("set_specular"),_SCS("get_specular"));
+	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"specular/color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_specular"),_SCS("get_specular"));
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"specular/roughness",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_roughness"),_SCS("get_roughness"));
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"specular/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_SPECULAR);
 
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"emission/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_EMISSION);
+	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"emission/color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_emission"),_SCS("get_emission"));
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"emission/energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_emission_energy"),_SCS("get_emission_energy"));
+	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"emission/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_EMISSION);
+
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"normal/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_NORMAL_MAPPING);
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"normal/scale",PROPERTY_HINT_RANGE,"-16,16,0.01"),_SCS("set_normal_scale"),_SCS("get_normal_scale"));
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"normal/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_NORMAL);
 
-	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"sheen/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_SHEEN);
-	ADD_PROPERTY(PropertyInfo(Variant::REAL,"sheen/amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_sheen"),_SCS("get_sheen"));
-	ADD_PROPERTY(PropertyInfo(Variant::REAL,"sheen/color"),_SCS("set_sheen_color"),_SCS("get_sheen_color"));
-	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"sheen/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_SHEEN);
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"rim/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_RIM);
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"rim/amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_rim"),_SCS("get_rim"));
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"rim/tint",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_rim_tint"),_SCS("get_rim_tint"));
+	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"rim/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_RIM);
 
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"clearcoat/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_CLEARCOAT);
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"clearcoat/amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_clearcoat"),_SCS("get_clearcoat"));
-	ADD_PROPERTY(PropertyInfo(Variant::REAL,"clearcoat/gloss"),_SCS("set_clearcoat_gloss"),_SCS("get_clearcoat_gloss"));
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"clearcoat/gloss",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_clearcoat_gloss"),_SCS("get_clearcoat_gloss"));
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"clearcoat/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_CLEARCOAT);
 
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"anisotropy/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_ANISOTROPY);
-	ADD_PROPERTY(PropertyInfo(Variant::REAL,"anisotropy/amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_anisotropy"),_SCS("get_anisotropy"));
-	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"anisotropy/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_ANISOTROPY);
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"anisotropy/anisotropy",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_anisotropy"),_SCS("get_anisotropy"));
+	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"anisotropy/flowmap",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_FLOWMAP);
 
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"ao/enabled"),_SCS("set_feature"),_SCS("get_feature"),FEATURE_AMBIENT_OCCLUSION);
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"ao/texture",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_AMBIENT_OCCLUSION);
@@ -738,13 +927,19 @@ void FixedSpatialMaterial::_bind_methods() {
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail/albedo",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_DETAIL_ALBEDO);
 	ADD_PROPERTYI(PropertyInfo(Variant::OBJECT,"detail/normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"),_SCS("set_texture"),_SCS("get_texture"),TEXTURE_DETAIL_NORMAL);
 
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv1/scale"),_SCS("set_uv1_scale"),_SCS("get_uv1_scale"));
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv1/offset"),_SCS("set_uv1_offset"),_SCS("get_uv1_offset"));
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv2/scale"),_SCS("set_uv2_scale"),_SCS("get_uv2_scale"));
+	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"uv2/offset"),_SCS("set_uv2_offset"),_SCS("get_uv2_offset"));
+
+
 	BIND_CONSTANT( TEXTURE_ALBEDO );
 	BIND_CONSTANT( TEXTURE_SPECULAR );
 	BIND_CONSTANT( TEXTURE_EMISSION );
 	BIND_CONSTANT( TEXTURE_NORMAL );
-	BIND_CONSTANT( TEXTURE_SHEEN );
+	BIND_CONSTANT( TEXTURE_RIM );
 	BIND_CONSTANT( TEXTURE_CLEARCOAT );
-	BIND_CONSTANT( TEXTURE_ANISOTROPY );
+	BIND_CONSTANT( TEXTURE_FLOWMAP );
 	BIND_CONSTANT( TEXTURE_AMBIENT_OCCLUSION );
 	BIND_CONSTANT( TEXTURE_HEIGHT );
 	BIND_CONSTANT( TEXTURE_SUBSURFACE_SCATTERING );
@@ -762,7 +957,7 @@ void FixedSpatialMaterial::_bind_methods() {
 	BIND_CONSTANT( FEATURE_TRANSPARENT );
 	BIND_CONSTANT( FEATURE_EMISSION );
 	BIND_CONSTANT( FEATURE_NORMAL_MAPPING );
-	BIND_CONSTANT( FEATURE_SHEEN );
+	BIND_CONSTANT( FEATURE_RIM );
 	BIND_CONSTANT( FEATURE_CLEARCOAT );
 	BIND_CONSTANT( FEATURE_ANISOTROPY );
 	BIND_CONSTANT( FEATURE_AMBIENT_OCCLUSION );
@@ -808,10 +1003,11 @@ FixedSpatialMaterial::FixedSpatialMaterial() : element(this) {
 	set_specular(Color(0.1,0.1,0.1));
 	set_roughness(0.0);
 	set_emission(Color(0,0,0));
+	set_emission_energy(1.0);
 	set_normal_scale(1);
-	set_sheen(0);
-	set_sheen_color(Color(1,1,1,1));
-	set_clearcoat(0);
+	set_rim(1.0);
+	set_rim_tint(0.5);
+	set_clearcoat(1);
 	set_clearcoat_gloss(0.5);
 	set_anisotropy(0);
 	set_height_scale(1);
@@ -820,6 +1016,10 @@ FixedSpatialMaterial::FixedSpatialMaterial() : element(this) {
 	set_refraction_roughness(0);
 	set_line_width(1);
 	set_point_size(1);
+	set_uv1_offset(Vector2(0,0));
+	set_uv1_scale(Vector2(1,1));
+	set_uv2_offset(Vector2(0,0));
+	set_uv2_scale(Vector2(1,1));
 
 	detail_uv=DETAIL_UV_1;
 	blend_mode=BLEND_MODE_MIX;
diff --git a/scene/resources/material.h b/scene/resources/material.h
index 35f01d47561..15c5910a9c5 100644
--- a/scene/resources/material.h
+++ b/scene/resources/material.h
@@ -69,9 +69,9 @@ public:
 		TEXTURE_SPECULAR,
 		TEXTURE_EMISSION,
 		TEXTURE_NORMAL,
-		TEXTURE_SHEEN,
+		TEXTURE_RIM,
 		TEXTURE_CLEARCOAT,
-		TEXTURE_ANISOTROPY,
+		TEXTURE_FLOWMAP,
 		TEXTURE_AMBIENT_OCCLUSION,
 		TEXTURE_HEIGHT,
 		TEXTURE_SUBSURFACE_SCATTERING,
@@ -95,7 +95,7 @@ public:
 		FEATURE_TRANSPARENT,
 		FEATURE_EMISSION,
 		FEATURE_NORMAL_MAPPING,
-		FEATURE_SHEEN,
+		FEATURE_RIM,
 		FEATURE_CLEARCOAT,
 		FEATURE_ANISOTROPY,
 		FEATURE_AMBIENT_OCCLUSION,
@@ -205,9 +205,10 @@ private:
 		StringName specular;
 		StringName roughness;
 		StringName emission;
+		StringName emission_energy;
 		StringName normal_scale;
-		StringName sheen;
-		StringName sheen_color;
+		StringName rim;
+		StringName rim_tint;
 		StringName clearcoat;
 		StringName clearcoat_gloss;
 		StringName anisotropy;
@@ -216,6 +217,10 @@ private:
 		StringName refraction;
 		StringName refraction_roughness;
 		StringName point_size;
+		StringName uv1_scale;
+		StringName uv1_offset;
+		StringName uv2_scale;
+		StringName uv2_offset;
 		StringName texture_names[TEXTURE_MAX];
 
 	};
@@ -234,9 +239,10 @@ private:
 	Color specular;
 	float roughness;
 	Color emission;
+	float emission_energy;
 	float normal_scale;
-	float sheen;
-	Color sheen_color;
+	float rim;
+	float rim_tint;
 	float clearcoat;
 	float clearcoat_gloss;
 	float anisotropy;
@@ -247,6 +253,12 @@ private:
 	float line_width;
 	float point_size;
 
+	Vector2 uv1_scale;
+	Vector2 uv1_offset;
+
+	Vector2 uv2_scale;
+	Vector2 uv2_offset;
+
 	DetailUV detail_uv;
 
 	BlendMode blend_mode;
@@ -282,14 +294,17 @@ public:
 	void set_emission(const Color& p_emission);
 	Color get_emission() const;
 
+	void set_emission_energy(float p_emission_energy);
+	float get_emission_energy() const;
+
 	void set_normal_scale(float p_normal_scale);
 	float get_normal_scale() const;
 
-	void set_sheen(float p_sheen);
-	float get_sheen() const;
+	void set_rim(float p_rim);
+	float get_rim() const;
 
-	void set_sheen_color(const Color& p_sheen_color);
-	Color get_sheen_color() const;
+	void set_rim_tint(float p_rim_tint);
+	float get_rim_tint() const;
 
 	void set_clearcoat(float p_clearcoat);
 	float get_clearcoat() const;
@@ -345,6 +360,18 @@ public:
 	void set_feature(Feature p_feature,bool p_enabled);
 	bool get_feature(Feature p_feature) const;
 
+	void set_uv1_scale(const Vector2& p_scale);
+	Vector2 get_uv1_scale() const;
+
+	void set_uv1_offset(const Vector2& p_offset);
+	Vector2 get_uv1_offset() const;
+
+	void set_uv2_scale(const Vector2& p_scale);
+	Vector2 get_uv2_scale() const;
+
+	void set_uv2_offset(const Vector2& p_offset);
+	Vector2 get_uv2_offset() const;
+
 	static void init_shaders();
 	static void finish_shaders();
 	static void flush_changes();
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 357546e5950..f6220250d9d 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -183,7 +183,9 @@ const char * ShaderLanguage::token_names[TK_MAX]={
 	"HINT_WHITE_TEXTURE",
 	"HINT_BLACK_TEXTURE",
 	"HINT_NORMAL_TEXTURE",
+	"HINT_ANISO_TEXTURE",
 	"HINT_ALBEDO_TEXTURE",
+	"HINT_BLACK_ALBEDO_TEXTURE",
 	"HINT_COLOR",
 	"HINT_RANGE",
 	"CURSOR",
@@ -263,7 +265,9 @@ const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[]={
 	{TK_HINT_WHITE_TEXTURE,"hint_white"},
 	{TK_HINT_BLACK_TEXTURE,"hint_black"},
 	{TK_HINT_NORMAL_TEXTURE,"hint_normal"},
+	{TK_HINT_ANISO_TEXTURE,"hint_aniso"},
 	{TK_HINT_ALBEDO_TEXTURE,"hint_albedo"},
+	{TK_HINT_BLACK_ALBEDO_TEXTURE,"hint_black_albedo"},
 	{TK_HINT_COLOR,"hint_color"},
 	{TK_HINT_RANGE,"hint_range"},
 
@@ -3303,8 +3307,12 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
 							uniform.hint=ShaderNode::Uniform::HINT_BLACK;
 						} else if (tk.type==TK_HINT_NORMAL_TEXTURE) {
 							uniform.hint=ShaderNode::Uniform::HINT_NORMAL;
+						} else if (tk.type==TK_HINT_ANISO_TEXTURE) {
+							uniform.hint=ShaderNode::Uniform::HINT_ANISO;
 						} else if (tk.type==TK_HINT_ALBEDO_TEXTURE) {
 							uniform.hint=ShaderNode::Uniform::HINT_ALBEDO;
+						} else if (tk.type==TK_HINT_BLACK_ALBEDO_TEXTURE) {
+							uniform.hint=ShaderNode::Uniform::HINT_BLACK_ALBEDO;
 						} else if (tk.type==TK_HINT_COLOR) {
 							if (type!=TYPE_VEC4) {
 								_set_error("Color hint is for vec4 only");
@@ -3327,12 +3335,20 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
 
 							tk = _get_token();
 
+							float sign=1.0;
+
+							if (tk.type==TK_OP_SUB) {
+								sign=-1.0;
+								tk = _get_token();
+							}
+
 							if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) {
 								_set_error("Expected integer constant");
 								return ERR_PARSE_ERROR;
 							}
 
 							uniform.hint_range[0]=tk.constant;
+							uniform.hint_range[0]*=sign;
 
 							tk = _get_token();
 
@@ -3343,12 +3359,21 @@ Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataTy
 
 							tk = _get_token();
 
+							sign=1.0;
+
+							if (tk.type==TK_OP_SUB) {
+								sign=-1.0;
+								tk = _get_token();
+							}
+
+
 							if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) {
 								_set_error("Expected integer constant after ','");
 								return ERR_PARSE_ERROR;
 							}
 
 							uniform.hint_range[1]=tk.constant;
+							uniform.hint_range[1]*=sign;
 
 							tk = _get_token();
 
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index dc1279efd39..e6b515167eb 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -138,7 +138,9 @@ public:
 		TK_HINT_WHITE_TEXTURE,
 		TK_HINT_BLACK_TEXTURE,
 		TK_HINT_NORMAL_TEXTURE,
+		TK_HINT_ANISO_TEXTURE,
 		TK_HINT_ALBEDO_TEXTURE,
+		TK_HINT_BLACK_ALBEDO_TEXTURE,
 		TK_HINT_COLOR,
 		TK_HINT_RANGE,
 		TK_CURSOR,
@@ -385,9 +387,11 @@ public:
 				HINT_COLOR,
 				HINT_RANGE,
 				HINT_ALBEDO,
+				HINT_BLACK_ALBEDO,
 				HINT_NORMAL,
 				HINT_BLACK,
 				HINT_WHITE,
+				HINT_ANISO,
 				HINT_MAX
 			};
 
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
index 8a0818c299d..f799329026b 100644
--- a/servers/visual/shader_types.cpp
+++ b/servers/visual/shader_types.cpp
@@ -60,6 +60,13 @@ ShaderTypes::ShaderTypes()
 	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ALPHA"]=ShaderLanguage::TYPE_FLOAT;
 	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECULAR"]=ShaderLanguage::TYPE_VEC3;
 	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ROUGHNESS"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM_TINT"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT_GLOSS"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY"]=ShaderLanguage::TYPE_FLOAT;
+	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY_FLOW"]=ShaderLanguage::TYPE_VEC2;
+	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["AO"]=ShaderLanguage::TYPE_FLOAT;
 	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["EMISSION"]=ShaderLanguage::TYPE_VEC3;
 	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECIAL"]=ShaderLanguage::TYPE_FLOAT;
 	shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DISCARD"]=ShaderLanguage::TYPE_BOOL;