Browse Source

More 3D Work
-=-=-=-=-=-

-ESM Shadow Mapping for softer and less glitchy shadows
-HDR Pipeline (convert to Linear on texture import, convert to SRGB at the end)
-Fix to xml parse bug

Juan Linietsky 11 years ago
parent
commit
703004f830
40 changed files with 1114 additions and 116 deletions
  1. 11 0
      core/color.h
  2. 39 0
      core/image.cpp
  3. 1 0
      core/image.h
  4. 2 2
      demos/3d/platformer/engine.cfg
  5. 13 10
      demos/3d/platformer/stage.xml
  6. BIN
      demos/3d/platformer/texture.tex
  7. 5 0
      drivers/gles1/rasterizer_gles1.cpp
  8. 1 1
      drivers/gles1/rasterizer_gles1.h
  9. 233 62
      drivers/gles2/rasterizer_gles2.cpp
  10. 7 1
      drivers/gles2/rasterizer_gles2.h
  11. 2 0
      drivers/gles2/shader_gles2.h
  12. 147 10
      drivers/gles2/shaders/copy.glsl
  13. 57 4
      drivers/gles2/shaders/material.glsl
  14. 9 1
      modules/gdscript/gd_compiler.cpp
  15. 13 0
      modules/gdscript/gd_functions.cpp
  16. 1 0
      modules/gdscript/gd_functions.h
  17. 2 0
      modules/gdscript/gd_script.cpp
  18. 1 0
      modules/gdscript/gd_script.h
  19. 1 1
      platform/flash/rasterizer_flash.h
  20. 7 1
      scene/3d/light.cpp
  21. 2 0
      scene/3d/light.h
  22. 13 0
      scene/main/node.cpp
  23. 1 0
      scene/main/node.h
  24. 2 0
      scene/register_scene_types.cpp
  25. 4 5
      scene/resources/environment.cpp
  26. 1 2
      scene/resources/environment.h
  27. 413 0
      scene/resources/polygon_path_finder.cpp
  28. 58 0
      scene/resources/polygon_path_finder.h
  29. 2 0
      servers/visual/rasterizer.h
  30. 6 0
      servers/visual/rasterizer_dummy.cpp
  31. 2 1
      servers/visual/rasterizer_dummy.h
  32. 4 2
      servers/visual/visual_server_raster.cpp
  33. 2 0
      servers/visual/visual_server_wrap_mt.cpp
  34. 26 2
      servers/visual/visual_server_wrap_mt.h
  35. 3 2
      servers/visual_server.h
  36. 1 1
      tools/editor/editor_node.cpp
  37. 11 0
      tools/editor/io_plugins/editor_texture_import_plugin.cpp
  38. 2 1
      tools/editor/io_plugins/editor_texture_import_plugin.h
  39. 8 6
      tools/editor/plugins/baked_light_baker.cpp
  40. 1 1
      tools/editor/plugins/baked_light_editor_plugin.cpp

+ 11 - 0
core/color.h

@@ -30,6 +30,7 @@
 #define COLOR_H
 #define COLOR_H
 
 
 #include "ustring.h"
 #include "ustring.h"
+#include "math_funcs.h"
 /**
 /**
 	@author Juan Linietsky <[email protected]>
 	@author Juan Linietsky <[email protected]>
 */
 */
@@ -97,6 +98,16 @@ struct Color {
 		return res;
 		return res;
 	}
 	}
 
 
+	_FORCE_INLINE_ Color to_linear() const {
+
+		return Color(
+			r<0.04045 ? r * (1.0 / 12.92) : Math::pow((r + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+			g<0.04045 ? g * (1.0 / 12.92) : Math::pow((g + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+			b<0.04045 ? b * (1.0 / 12.92) : Math::pow((b + 0.055) * (1.0 / (1 + 0.055)), 2.4),
+			a
+		);
+	}
+
 	static Color hex(uint32_t p_hex);
 	static Color hex(uint32_t p_hex);
 	static Color html(const String& p_color);
 	static Color html(const String& p_color);
 	static bool html_is_valid(const String& p_color);
 	static bool html_is_valid(const String& p_color);

+ 39 - 0
core/image.cpp

@@ -1664,6 +1664,45 @@ void Image::set_compress_bc_func(void (*p_compress_func)(Image *)) {
 
 
 
 
 
 
+void Image::srgb_to_linear() {
+
+	if (data.size()==0)
+		return;
+
+	static const uint8_t srgb2lin[256]={0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 22, 23, 23, 24, 24, 25, 26, 26, 27, 27, 28, 29, 29, 30, 31, 31, 32, 33, 33, 34, 35, 36, 36, 37, 38, 38, 39, 40, 41, 42, 42, 43, 44, 45, 46, 47, 47, 48, 49, 50, 51, 52, 53, 54, 55, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 85, 87, 88, 89, 90, 92, 93, 94, 95, 97, 98, 99, 101, 102, 103, 105, 106, 107, 109, 110, 112, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 144, 145, 147, 148, 150, 152, 153, 155, 157, 159, 160, 162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 188, 190, 192, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 218, 220, 222, 224, 226, 228, 230, 232, 235, 237, 239, 241, 243, 245, 248, 250, 252};
+
+
+	ERR_FAIL_COND( format!=FORMAT_RGB && format!=FORMAT_RGBA  );
+
+	if (format==FORMAT_RGBA) {
+
+		int len = data.size()/4;
+		DVector<uint8_t>::Write wp = data.write();
+		unsigned char *data_ptr=wp.ptr();
+
+		for(int i=0;i<len;i++) {
+
+			data_ptr[(i<<2)+0]=srgb2lin[ data_ptr[(i<<2)+0] ];
+			data_ptr[(i<<2)+1]=srgb2lin[ data_ptr[(i<<2)+1] ];
+			data_ptr[(i<<2)+2]=srgb2lin[ data_ptr[(i<<2)+2] ];
+		}
+
+	} else if (format==FORMAT_RGB) {
+
+		int len = data.size()/3;
+		DVector<uint8_t>::Write wp = data.write();
+		unsigned char *data_ptr=wp.ptr();
+
+		for(int i=0;i<len;i++) {
+
+			data_ptr[(i*3)+0]=srgb2lin[ data_ptr[(i*3)+0] ];
+			data_ptr[(i*3)+1]=srgb2lin[ data_ptr[(i*3)+1] ];
+			data_ptr[(i*3)+2]=srgb2lin[ data_ptr[(i*3)+2] ];
+		}
+	}
+
+}
+
 void Image::premultiply_alpha() {
 void Image::premultiply_alpha() {
 
 
 	if (data.size()==0)
 	if (data.size()==0)

+ 1 - 0
core/image.h

@@ -321,6 +321,7 @@ public:
 
 
 	void fix_alpha_edges();
 	void fix_alpha_edges();
 	void premultiply_alpha();
 	void premultiply_alpha();
+	void srgb_to_linear();
 
 
 	void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
 	void blit_rect(const Image& p_src, const Rect2& p_src_rect,const Point2& p_dest);
 	void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);
 	void brush_transfer(const Image& p_src, const Image& p_brush, const Point2& p_dest);

+ 2 - 2
demos/3d/platformer/engine.cfg

@@ -22,5 +22,5 @@ shoot=[key(Z)]
 
 
 max_shadow_buffer_size=1024
 max_shadow_buffer_size=1024
 framebuffer_shrink=1
 framebuffer_shrink=1
-shadow_filter=1
-;debug_shadow_maps=true
+shadow_filter=3
+debug_shadow_maps=false

+ 13 - 10
demos/3d/platformer/stage.xml

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="UTF-8" ?>
 <?xml version="1.0" encoding="UTF-8" ?>
 <resource_file type="PackedScene" subresource_count="7" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
 <resource_file type="PackedScene" subresource_count="7" version="1.0" version_name="Godot Engine v1.0.3917-beta1">
+	<ext_resource path="res://enemy.scn" type="PackedScene"></ext_resource>
+	<ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
 	<ext_resource path="res://sb.cube" type="CubeMap"></ext_resource>
 	<ext_resource path="res://sb.cube" type="CubeMap"></ext_resource>
 	<ext_resource path="res://tiles.res" type="MeshLibrary"></ext_resource>
 	<ext_resource path="res://tiles.res" type="MeshLibrary"></ext_resource>
 	<ext_resource path="res://coin.scn" type="PackedScene"></ext_resource>
 	<ext_resource path="res://coin.scn" type="PackedScene"></ext_resource>
-	<ext_resource path="res://player.xml" type="PackedScene"></ext_resource>
-	<ext_resource path="res://enemy.scn" type="PackedScene"></ext_resource>
 	<resource type="Environment" path="local://1">
 	<resource type="Environment" path="local://1">
 		<bool name="fxaa/enabled"> False </bool>
 		<bool name="fxaa/enabled"> False </bool>
 		<int name="background/mode"> 4 </int>
 		<int name="background/mode"> 4 </int>
@@ -50,13 +50,14 @@
 	<main_resource>
 	<main_resource>
 		<dictionary name="_bundled" shared="false">
 		<dictionary name="_bundled" shared="false">
 			<string> "names" </string>
 			<string> "names" </string>
-			<string_array  len="86">
+			<string_array  len="89">
 				<string> "world" </string>
 				<string> "world" </string>
 				<string> "Spatial" </string>
 				<string> "Spatial" </string>
 				<string> "__meta__" </string>
 				<string> "__meta__" </string>
 				<string> "GridMap" </string>
 				<string> "GridMap" </string>
 				<string> "theme/theme" </string>
 				<string> "theme/theme" </string>
 				<string> "theme/bake" </string>
 				<string> "theme/bake" </string>
+				<string> "lighting/bake" </string>
 				<string> "cell/size" </string>
 				<string> "cell/size" </string>
 				<string> "cell/octant_size" </string>
 				<string> "cell/octant_size" </string>
 				<string> "cell/center_x" </string>
 				<string> "cell/center_x" </string>
@@ -67,6 +68,8 @@
 				<string> "DirectionalLight" </string>
 				<string> "DirectionalLight" </string>
 				<string> "transform/local" </string>
 				<string> "transform/local" </string>
 				<string> "layers" </string>
 				<string> "layers" </string>
+				<string> "params/enabled" </string>
+				<string> "params/bake_mode" </string>
 				<string> "params/energy" </string>
 				<string> "params/energy" </string>
 				<string> "colors/ambient" </string>
 				<string> "colors/ambient" </string>
 				<string> "colors/diffuse" </string>
 				<string> "colors/diffuse" </string>
@@ -172,17 +175,17 @@
 							<array  len="4" shared="false">
 							<array  len="4" shared="false">
 								<dictionary  shared="false">
 								<dictionary  shared="false">
 									<string> "distance" </string>
 									<string> "distance" </string>
-									<real> 6.622579 </real>
+									<real> 4.173348 </real>
 									<string> "x_rot" </string>
 									<string> "x_rot" </string>
-									<real> 0.358295 </real>
+									<real> 0.558294 </real>
 									<string> "y_rot" </string>
 									<string> "y_rot" </string>
-									<real> 0.45 </real>
+									<real> 1.049999 </real>
 									<string> "use_orthogonal" </string>
 									<string> "use_orthogonal" </string>
 									<bool> False </bool>
 									<bool> False </bool>
 									<string> "use_environment" </string>
 									<string> "use_environment" </string>
 									<bool> False </bool>
 									<bool> False </bool>
 									<string> "pos" </string>
 									<string> "pos" </string>
-									<vector3> 9.41795, 2.98588, 13.6496 </vector3>
+									<vector3> 13.4293, 5.68289, 13.9717 </vector3>
 								</dictionary>
 								</dictionary>
 								<dictionary  shared="false">
 								<dictionary  shared="false">
 									<string> "distance" </string>
 									<string> "distance" </string>
@@ -267,14 +270,14 @@
 				</dictionary>
 				</dictionary>
 				<transform> 0.522923, 0.663002, -0.535706, -0.24539, 0.718971, 0.650281, 0.816294, -0.20859, 0.53866, 0, 0, 0 </transform>
 				<transform> 0.522923, 0.663002, -0.535706, -0.24539, 0.718971, 0.650281, 0.816294, -0.20859, 0.53866, 0, 0, 0 </transform>
 				<int> 1 </int>
 				<int> 1 </int>
+				<int> 0 </int>
 				<real> 1.5 </real>
 				<real> 1.5 </real>
 				<color> 0.159092, 0.219774, 0.52093, 1 </color>
 				<color> 0.159092, 0.219774, 0.52093, 1 </color>
 				<color> 1, 1, 1, 1 </color>
 				<color> 1, 1, 1, 1 </color>
 				<real> 0 </real>
 				<real> 0 </real>
 				<real> 0.08 </real>
 				<real> 0.08 </real>
 				<real> 0.5 </real>
 				<real> 0.5 </real>
-				<resource name=""></resource>				<int> 0 </int>
-				<int> 2 </int>
+				<resource name=""></resource>				<int> 2 </int>
 				<real> 40 </real>
 				<real> 40 </real>
 				<real> 0.410558 </real>
 				<real> 0.410558 </real>
 				<resource  resource_type="Environment" path="local://1">  </resource>
 				<resource  resource_type="Environment" path="local://1">  </resource>
@@ -336,7 +339,7 @@
 				<transform> 0.0160676, 0, -0.999871, 0, 1, 0, 0.999871, 0, 0.0160676, 8.50167, 4.15811, 15.9334 </transform>
 				<transform> 0.0160676, 0, -0.999871, 0, 1, 0, 0.999871, 0, 0.0160676, 8.50167, 4.15811, 15.9334 </transform>
 			</array>
 			</array>
 			<string> "nodes" </string>
 			<string> "nodes" </string>
-			<int_array  len="541"> 				-1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 3, 3, -1, 10, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 5, 10, 5, 11, 6, 12, 7, 2, 8, 0, 0, 0, 13, 13, -1, 16, 14, 9, 15, 10, 16, 11, 17, 12, 18, 13, 19, 13, 20, 5, 21, 14, 22, 15, 23, 16, 24, 17, 25, 18, 26, 19, 27, 20, 28, 21, 29, 3, 0, 0, 0, 31, 30, -1, 1, 30, 22, 0, 0, 0, 33, 32, -1, 1, 2, 23, 0, 4, 0, 35, 34, 24, 1, 14, 25, 0, 4, 0, 35, 36, 24, 1, 14, 26, 0, 4, 0, 35, 37, 24, 1, 14, 27, 0, 4, 0, 35, 38, 24, 1, 14, 28, 0, 4, 0, 35, 39, 24, 1, 14, 29, 0, 4, 0, 35, 40, 24, 1, 14, 30, 0, 4, 0, 35, 41, 24, 1, 14, 31, 0, 4, 0, 35, 42, 24, 1, 14, 32, 0, 4, 0, 35, 43, 24, 1, 14, 33, 0, 4, 0, 35, 44, 24, 1, 14, 34, 0, 4, 0, 35, 45, 24, 1, 14, 35, 0, 4, 0, 35, 46, 24, 1, 14, 36, 0, 4, 0, 35, 47, 24, 1, 14, 37, 0, 4, 0, 35, 48, 24, 1, 14, 38, 0, 4, 0, 35, 49, 24, 1, 14, 39, 0, 4, 0, 35, 50, 24, 1, 14, 40, 0, 4, 0, 35, 51, 24, 1, 14, 41, 0, 4, 0, 35, 52, 24, 1, 14, 42, 0, 4, 0, 35, 53, 24, 1, 14, 43, 0, 4, 0, 35, 54, 24, 1, 14, 44, 0, 4, 0, 35, 55, 24, 1, 14, 45, 0, 4, 0, 35, 56, 24, 1, 14, 46, 0, 4, 0, 35, 57, 24, 1, 14, 47, 0, 4, 0, 35, 58, 24, 1, 14, 48, 0, 4, 0, 35, 59, 24, 1, 14, 49, 0, 4, 0, 35, 60, 24, 1, 14, 50, 0, 4, 0, 35, 61, 24, 1, 14, 51, 0, 4, 0, 35, 62, 24, 1, 14, 52, 0, 4, 0, 35, 63, 24, 1, 14, 53, 0, 4, 0, 35, 64, 24, 1, 14, 54, 0, 4, 0, 35, 65, 24, 1, 14, 55, 0, 4, 0, 35, 66, 24, 1, 14, 56, 0, 4, 0, 35, 67, 24, 1, 14, 57, 0, 4, 0, 35, 68, 24, 1, 14, 58, 0, 4, 0, 35, 69, 24, 1, 14, 59, 0, 4, 0, 35, 70, 24, 1, 14, 60, 0, 4, 0, 35, 71, 24, 1, 14, 61, 0, 4, 0, 35, 72, 24, 1, 14, 62, 0, 4, 0, 35, 73, 24, 1, 14, 63, 0, 4, 0, 35, 74, 24, 1, 14, 64, 0, 4, 0, 35, 75, 24, 1, 14, 65, 0, 4, 0, 35, 76, 24, 1, 14, 66, 0, 4, 0, 35, 77, 24, 1, 14, 67, 0, 4, 0, 35, 78, 24, 1, 14, 68, 0, 0, 0, 33, 79, -1, 0, 0, 49, 0, 81, 80, 69, 1, 14, 70, 0, 49, 0, 81, 82, 69, 1, 14, 71, 0, 49, 0, 81, 83, 69, 1, 14, 72, 0, 49, 0, 81, 84, 69, 1, 14, 73, 0, 0, 0, 81, 85, 74, 1, 14, 75, 0 </int_array>
+			<int_array  len="547"> 				-1, -1, 1, 0, -1, 1, 2, 0, 0, 0, 0, 3, 3, -1, 11, 4, 1, 5, 2, 6, 2, 7, 3, 8, 4, 9, 5, 10, 5, 11, 5, 12, 6, 13, 7, 2, 8, 0, 0, 0, 14, 14, -1, 18, 15, 9, 16, 10, 17, 5, 18, 11, 19, 12, 20, 13, 21, 14, 22, 14, 23, 5, 24, 15, 25, 16, 26, 17, 27, 18, 28, 11, 29, 19, 30, 20, 31, 21, 32, 3, 0, 0, 0, 34, 33, -1, 1, 33, 22, 0, 0, 0, 36, 35, -1, 1, 2, 23, 0, 4, 0, 38, 37, 24, 1, 15, 25, 0, 4, 0, 38, 39, 24, 1, 15, 26, 0, 4, 0, 38, 40, 24, 1, 15, 27, 0, 4, 0, 38, 41, 24, 1, 15, 28, 0, 4, 0, 38, 42, 24, 1, 15, 29, 0, 4, 0, 38, 43, 24, 1, 15, 30, 0, 4, 0, 38, 44, 24, 1, 15, 31, 0, 4, 0, 38, 45, 24, 1, 15, 32, 0, 4, 0, 38, 46, 24, 1, 15, 33, 0, 4, 0, 38, 47, 24, 1, 15, 34, 0, 4, 0, 38, 48, 24, 1, 15, 35, 0, 4, 0, 38, 49, 24, 1, 15, 36, 0, 4, 0, 38, 50, 24, 1, 15, 37, 0, 4, 0, 38, 51, 24, 1, 15, 38, 0, 4, 0, 38, 52, 24, 1, 15, 39, 0, 4, 0, 38, 53, 24, 1, 15, 40, 0, 4, 0, 38, 54, 24, 1, 15, 41, 0, 4, 0, 38, 55, 24, 1, 15, 42, 0, 4, 0, 38, 56, 24, 1, 15, 43, 0, 4, 0, 38, 57, 24, 1, 15, 44, 0, 4, 0, 38, 58, 24, 1, 15, 45, 0, 4, 0, 38, 59, 24, 1, 15, 46, 0, 4, 0, 38, 60, 24, 1, 15, 47, 0, 4, 0, 38, 61, 24, 1, 15, 48, 0, 4, 0, 38, 62, 24, 1, 15, 49, 0, 4, 0, 38, 63, 24, 1, 15, 50, 0, 4, 0, 38, 64, 24, 1, 15, 51, 0, 4, 0, 38, 65, 24, 1, 15, 52, 0, 4, 0, 38, 66, 24, 1, 15, 53, 0, 4, 0, 38, 67, 24, 1, 15, 54, 0, 4, 0, 38, 68, 24, 1, 15, 55, 0, 4, 0, 38, 69, 24, 1, 15, 56, 0, 4, 0, 38, 70, 24, 1, 15, 57, 0, 4, 0, 38, 71, 24, 1, 15, 58, 0, 4, 0, 38, 72, 24, 1, 15, 59, 0, 4, 0, 38, 73, 24, 1, 15, 60, 0, 4, 0, 38, 74, 24, 1, 15, 61, 0, 4, 0, 38, 75, 24, 1, 15, 62, 0, 4, 0, 38, 76, 24, 1, 15, 63, 0, 4, 0, 38, 77, 24, 1, 15, 64, 0, 4, 0, 38, 78, 24, 1, 15, 65, 0, 4, 0, 38, 79, 24, 1, 15, 66, 0, 4, 0, 38, 80, 24, 1, 15, 67, 0, 4, 0, 38, 81, 24, 1, 15, 68, 0, 0, 0, 36, 82, -1, 0, 0, 49, 0, 84, 83, 69, 1, 15, 70, 0, 49, 0, 84, 85, 69, 1, 15, 71, 0, 49, 0, 84, 86, 69, 1, 15, 72, 0, 49, 0, 84, 87, 69, 1, 15, 73, 0, 0, 0, 84, 88, 74, 1, 15, 75, 0 </int_array>
 			<string> "conns" </string>
 			<string> "conns" </string>
 			<int_array  len="0"> 				 </int_array>
 			<int_array  len="0"> 				 </int_array>
 		</dictionary>
 		</dictionary>

BIN
demos/3d/platformer/texture.tex


+ 5 - 0
drivers/gles1/rasterizer_gles1.cpp

@@ -2847,6 +2847,11 @@ int RasterizerGLES1::light_instance_get_shadow_passes(RID p_light_instance) cons
 	return 0;
 	return 0;
 }
 }
 
 
+bool RasterizerGLES1::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const {
+
+	return false;
+}
+
 void RasterizerGLES1::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
 void RasterizerGLES1::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
 
 
 	LightInstance *lighti = light_instance_owner.get( p_light_instance );
 	LightInstance *lighti = light_instance_owner.get( p_light_instance );

+ 1 - 1
drivers/gles1/rasterizer_gles1.h

@@ -482,7 +482,6 @@ class RasterizerGLES1 : public Rasterizer {
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
-			fx_param[VS::ENV_FX_PARAM_GAMMA]=1.0;
 
 
 		}
 		}
 
 
@@ -1100,6 +1099,7 @@ public:
 	virtual bool light_instance_assign_shadow(RID p_light_instance);
 	virtual bool light_instance_assign_shadow(RID p_light_instance);
 	virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const;
 	virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const;
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const;
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const;
+	virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const;
 	virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
 	virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; }
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; }
 
 

+ 233 - 62
drivers/gles2/rasterizer_gles2.cpp

@@ -43,6 +43,11 @@
 #define   _GL_HALF_FLOAT_OES      0x8D61
 #define   _GL_HALF_FLOAT_OES      0x8D61
 #endif
 #endif
 
 
+#define _GL_RGBA16F_EXT                                  0x881A
+#define _GL_RGB16F_EXT                                   0x881B
+#define _GL_RG16F_EXT                                    0x822F
+#define _GL_R16F_EXT                                     0x822D
+#define _GL_R32F_EXT 0x822E
 
 
 #define _DEPTH_COMPONENT24_OES                 0x81A6
 #define _DEPTH_COMPONENT24_OES                 0x81A6
 
 
@@ -3317,6 +3322,11 @@ int RasterizerGLES2::light_instance_get_shadow_passes(RID p_light_instance) cons
 		return 1;
 		return 1;
 }
 }
 
 
+bool RasterizerGLES2::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const {
+
+	return shadow_filter>=SHADOW_FILTER_ESM;
+}
+
 void RasterizerGLES2::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
 void RasterizerGLES2::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
 
 
 	LightInstance *lighti = light_instance_owner.get( p_light_instance );
 	LightInstance *lighti = light_instance_owner.get( p_light_instance );
@@ -3590,9 +3600,10 @@ void RasterizerGLES2::begin_frame() {
 	glFrontFace(GL_CW);
 	glFrontFace(GL_CW);
 
 
 	//fragment_lighting=Globals::get_singleton()->get("rasterizer/use_fragment_lighting");
 	//fragment_lighting=Globals::get_singleton()->get("rasterizer/use_fragment_lighting");
+#ifdef TOOLS_ENABLED
 	canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false));
 	canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false));
 	shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter")));
 	shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter")));
-
+#endif
 
 
 	window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height );
 	window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height );
 
 
@@ -4302,6 +4313,13 @@ void RasterizerGLES2::add_particles( const RID& p_particle_instance, const Insta
 
 
 }
 }
 
 
+Color RasterizerGLES2::_convert_color(const Color& p_color) {
+
+	if (current_env && current_env->fx_enabled[VS::ENV_FX_SRGB])
+		return p_color.to_linear();
+	else
+		return p_color;
+}
 
 
 void RasterizerGLES2::_set_cull(bool p_front,bool p_reverse_cull) {
 void RasterizerGLES2::_set_cull(bool p_front,bool p_reverse_cull) {
 
 
@@ -4383,9 +4401,9 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
 
 
 	//all goes to false by default
 	//all goes to false by default
 	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PASS,shadow!=NULL);
 	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PASS,shadow!=NULL);
-	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,shadow_filter!=SHADOW_FILTER_NONE);
-	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter>SHADOW_FILTER_PCF5);
-	//material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,true);
+	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,shadow_filter==SHADOW_FILTER_PCF5 || shadow_filter==SHADOW_FILTER_PCF13);
+	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF13);
+	material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM);
 
 
 	if (p_opaque_pass && p_material->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS] && p_material->shader_cache && p_material->shader_cache->has_alpha) {
 	if (p_opaque_pass && p_material->hints[VS::MATERIAL_HINT_OPAQUE_PRE_PASS] && p_material->shader_cache && p_material->shader_cache->has_alpha) {
 
 
@@ -4484,6 +4502,9 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
 					glBindTexture(GL_TEXTURE_2D,white_tex); //no texture
 					glBindTexture(GL_TEXTURE_2D,white_tex); //no texture
 				texcoord++;
 				texcoord++;
 
 
+			} else if (E->get().value.get_type()==Variant::COLOR){
+				Color c = E->get().value;
+				material_shader.set_custom_uniform(E->get().index,_convert_color(c));
 			} else {
 			} else {
 				material_shader.set_custom_uniform(E->get().index,E->get().value);
 				material_shader.set_custom_uniform(E->get().index,E->get().value);
 			}
 			}
@@ -4534,6 +4555,8 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material
 
 
 		Color col_begin = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR];
 		Color col_begin = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR];
 		Color col_end = current_env->fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR];
 		Color col_end = current_env->fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR];
+		col_begin=_convert_color(col_begin);
+		col_end=_convert_color(col_end);
 		float from = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN];
 		float from = current_env->fx_param[VS::ENV_FX_PARAM_FOG_BEGIN];
 		float zf = camera_z_far;
 		float zf = camera_z_far;
 		float curve = current_env->fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION];
 		float curve = current_env->fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION];
@@ -4588,11 +4611,14 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) {
 	LightInstance *li=light_instances[p_light];
 	LightInstance *li=light_instances[p_light];
 	Light *l=li->base;
 	Light *l=li->base;
 
 
+	Color col_ambient=_convert_color(l->colors[VS::LIGHT_COLOR_AMBIENT]);
+	Color col_diffuse=_convert_color(l->colors[VS::LIGHT_COLOR_DIFFUSE]);
+	Color col_specular=_convert_color(l->colors[VS::LIGHT_COLOR_SPECULAR]);
 
 
 	for(int j=0;j<3;j++) {
 	for(int j=0;j<3;j++) {
-		light_data[VL_LIGHT_AMBIENT][j]=l->colors[VS::LIGHT_COLOR_AMBIENT][j];
-		light_data[VL_LIGHT_DIFFUSE][j]=l->colors[VS::LIGHT_COLOR_DIFFUSE][j];
-		light_data[VL_LIGHT_SPECULAR][j]=l->colors[VS::LIGHT_COLOR_SPECULAR][j];
+		light_data[VL_LIGHT_AMBIENT][j]=col_ambient[j];
+		light_data[VL_LIGHT_DIFFUSE][j]=col_diffuse[j];
+		light_data[VL_LIGHT_SPECULAR][j]=col_specular[j];
 	}
 	}
 
 
 	if (l->type!=VS::LIGHT_OMNI) {
 	if (l->type!=VS::LIGHT_OMNI) {
@@ -4626,6 +4652,8 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) {
 		material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]);
 		material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]);
 		material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size);
 		material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size);
 		material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,7);
 		material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,7);
+		if (shadow_filter==SHADOW_FILTER_ESM)
+			material_shader.set_uniform(MaterialShaderGLES2::ESM_MULTIPLIER,float(li->base->vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER]));
 
 
 		if (li->base->type==VS::LIGHT_DIRECTIONAL) {
 		if (li->base->type==VS::LIGHT_DIRECTIONAL) {
 
 
@@ -6064,7 +6092,7 @@ void RasterizerGLES2::_draw_tex_bg() {
 	}
 	}
 
 
 	float nrg =float(current_env->bg_param[VS::ENV_BG_PARAM_ENERGY]);
 	float nrg =float(current_env->bg_param[VS::ENV_BG_PARAM_ENERGY]);
-	if (current_env->fx_enabled[VS::ENV_FX_HDR])
+	if (current_env->fx_enabled[VS::ENV_FX_HDR] && !use_fp16_fb)
 		nrg*=0.25; //go down a quarter for hdr
 		nrg*=0.25; //go down a quarter for hdr
 	copy_shader.set_uniform(CopyShaderGLES2::ENERGY,nrg);
 	copy_shader.set_uniform(CopyShaderGLES2::ENERGY,nrg);
 	copy_shader.set_uniform(CopyShaderGLES2::CUSTOM_ALPHA,float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]));
 	copy_shader.set_uniform(CopyShaderGLES2::CUSTOM_ALPHA,float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]));
@@ -6178,7 +6206,7 @@ void RasterizerGLES2::end_scene() {
 		glViewport( 0,0,viewport.width / framebuffer.scale, viewport.height / framebuffer.scale );
 		glViewport( 0,0,viewport.width / framebuffer.scale, viewport.height / framebuffer.scale );
 		glScissor(  0,0,viewport.width / framebuffer.scale, viewport.height / framebuffer.scale );
 		glScissor(  0,0,viewport.width / framebuffer.scale, viewport.height / framebuffer.scale );
 
 
-		material_shader.set_conditional(MaterialShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]);
+		material_shader.set_conditional(MaterialShaderGLES2::USE_8BIT_HDR,!use_fp16_fb && current_env && current_env->fx_enabled[VS::ENV_FX_HDR]);
 
 
 	} else {
 	} else {
 		if (current_rt) {
 		if (current_rt) {
@@ -6218,6 +6246,7 @@ void RasterizerGLES2::end_scene() {
 					bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR];
 					bgcolor = current_env->bg_param[VS::ENV_BG_PARAM_COLOR];
 				else
 				else
 					bgcolor = Globals::get_singleton()->get("render/default_clear_color");
 					bgcolor = Globals::get_singleton()->get("render/default_clear_color");
+				bgcolor = _convert_color(bgcolor);
 				float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0;
 				float a = use_fb ? float(current_env->bg_param[VS::ENV_BG_PARAM_GLOW]) : 1.0;
 				glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a);
 				glClearColor(bgcolor.r,bgcolor.g,bgcolor.b,a);
 				_glClearDepth(1.0);
 				_glClearDepth(1.0);
@@ -6237,7 +6266,8 @@ void RasterizerGLES2::end_scene() {
 		}
 		}
 	} else {
 	} else {
 
 
-		glClearColor(0.3,0.3,0.3,1.0);
+		Color c = _convert_color(Color(0.3,0.3,0.3));
+		glClearColor(c.r,c.g,c.b,0.0);
 		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 		glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 	}
 	}
 
 
@@ -6340,7 +6370,7 @@ void RasterizerGLES2::end_scene() {
 
 
 		//time to copy!!!
 		//time to copy!!!
 		copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,current_env && current_env->fx_enabled[VS::ENV_FX_BCS]);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,current_env && current_env->fx_enabled[VS::ENV_FX_BCS]);
-		copy_shader.set_conditional(CopyShaderGLES2::USE_GAMMA,current_env && current_env->fx_enabled[VS::ENV_FX_GAMMA]);
+		copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,current_env && current_env->fx_enabled[VS::ENV_FX_GLOW]);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,current_env && current_env->fx_enabled[VS::ENV_FX_HDR]);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,true);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,true);
@@ -6378,9 +6408,7 @@ void RasterizerGLES2::end_scene() {
 			bcs.z=current_env->fx_param[VS::ENV_FX_PARAM_BCS_SATURATION];
 			bcs.z=current_env->fx_param[VS::ENV_FX_PARAM_BCS_SATURATION];
 			copy_shader.set_uniform(CopyShaderGLES2::BCS,bcs);
 			copy_shader.set_uniform(CopyShaderGLES2::BCS,bcs);
 		}
 		}
-		if (current_env && current_env->fx_enabled[VS::ENV_FX_GAMMA]) {
-			copy_shader.set_uniform(CopyShaderGLES2::GAMMA,float(current_env->fx_param[VS::ENV_FX_PARAM_GAMMA]));
-		}
+
 		glActiveTexture(GL_TEXTURE0);
 		glActiveTexture(GL_TEXTURE0);
 		glBindTexture(GL_TEXTURE_2D, framebuffer.color );
 		glBindTexture(GL_TEXTURE_2D, framebuffer.color );
 		glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
 		glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
@@ -6388,7 +6416,7 @@ void RasterizerGLES2::end_scene() {
 		_copy_screen_quad();
 		_copy_screen_quad();
 
 
 		copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_BCS,false);
-		copy_shader.set_conditional(CopyShaderGLES2::USE_GAMMA,false);
+		copy_shader.set_conditional(CopyShaderGLES2::USE_SRGB,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_HDR,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_NO_ALPHA,false);
@@ -6396,7 +6424,7 @@ void RasterizerGLES2::end_scene() {
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SCREEN,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false);
 		copy_shader.set_conditional(CopyShaderGLES2::USE_GLOW_SOFTLIGHT,false);
 
 
-		material_shader.set_conditional(MaterialShaderGLES2::USE_HDR,false);
+		material_shader.set_conditional(MaterialShaderGLES2::USE_8BIT_HDR,false);
 
 
 
 
 		if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR] && GLOBAL_DEF("rasterizer/debug_hdr",false)) {
 		if (current_env && current_env->fx_enabled[VS::ENV_FX_HDR] && GLOBAL_DEF("rasterizer/debug_hdr",false)) {
@@ -6443,6 +6471,7 @@ void RasterizerGLES2::end_shadow_map() {
 
 
 	float dp_direction=0.0;
 	float dp_direction=0.0;
 	bool flip_facing=false;
 	bool flip_facing=false;
+	Rect2 vp_rect;
 
 
 	switch(shadow->base->type) {
 	switch(shadow->base->type) {
 
 
@@ -6455,24 +6484,30 @@ void RasterizerGLES2::end_shadow_map() {
 
 
 				if (shadow_pass==0) {
 				if (shadow_pass==0) {
 
 
-					glViewport(0, sb->size*0.5, sb->size*0.5, sb->size*0.5);
-					glScissor(0, sb->size*0.5, sb->size*0.5, sb->size*0.5);
+					vp_rect=Rect2(0, sb->size/2, sb->size/2, sb->size/2);
+					glViewport(0, sb->size/2, sb->size/2, sb->size/2);
+					glScissor(0, sb->size/2, sb->size/2, sb->size/2);
 				} else if (shadow_pass==1) {
 				} else if (shadow_pass==1) {
 
 
-					glViewport(0, 0, sb->size*0.5, sb->size*0.5);
-					glScissor(0, 0, sb->size*0.5, sb->size*0.5);
+					vp_rect=Rect2(0, 0, sb->size/2, sb->size/2);
+					glViewport(0, 0, sb->size/2, sb->size/2);
+					glScissor(0, 0, sb->size/2, sb->size/2);
 
 
 				} else if (shadow_pass==2) {
 				} else if (shadow_pass==2) {
 
 
-					glViewport(sb->size*0.5, sb->size*0.5, sb->size*0.5, sb->size*0.5);
-					glScissor(sb->size*0.5, sb->size*0.5, sb->size*0.5, sb->size*0.5);
+					vp_rect=Rect2(sb->size/2, sb->size/2, sb->size/2, sb->size/2);
+					glViewport(sb->size/2, sb->size/2, sb->size/2, sb->size/2);
+					glScissor(sb->size/2, sb->size/2, sb->size/2, sb->size/2);
 				} else if (shadow_pass==3) {
 				} else if (shadow_pass==3) {
 
 
-					glViewport(sb->size*0.5, 0, sb->size*0.5, sb->size*0.5);
-					glScissor(sb->size*0.5, 0, sb->size*0.5, sb->size*0.5);
+					vp_rect=Rect2(sb->size/2, 0, sb->size/2, sb->size/2);
+					glViewport(sb->size/2, 0, sb->size/2, sb->size/2);
+					glScissor(sb->size/2, 0, sb->size/2, sb->size/2);
 
 
 				}
 				}
 
 
+
+
 				glEnable(GL_SCISSOR_TEST);
 				glEnable(GL_SCISSOR_TEST);
 
 
 			} else if (shadow->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
 			} else if (shadow->base->directional_shadow_mode==VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) {
@@ -6481,14 +6516,16 @@ void RasterizerGLES2::end_shadow_map() {
 
 
 					cm = shadow->custom_projection[0];
 					cm = shadow->custom_projection[0];
 					light_transform=shadow->custom_transform[0];
 					light_transform=shadow->custom_transform[0];
-					glViewport(0, sb->size*0.5, sb->size, sb->size*0.5);
-					glScissor(0, sb->size*0.5, sb->size, sb->size*0.5);
+					vp_rect=Rect2(0, sb->size/2, sb->size, sb->size/2);
+					glViewport(0, sb->size/2, sb->size, sb->size/2);
+					glScissor(0, sb->size/2, sb->size, sb->size/2);
 				} else {
 				} else {
 
 
 					cm = shadow->custom_projection[1];
 					cm = shadow->custom_projection[1];
 					light_transform=shadow->custom_transform[1];
 					light_transform=shadow->custom_transform[1];
-					glViewport(0, 0, sb->size, sb->size*0.5);
-					glScissor(0, 0, sb->size, sb->size*0.5);
+					vp_rect=Rect2(0, 0, sb->size, sb->size/2);
+					glViewport(0, 0, sb->size, sb->size/2);
+					glScissor(0, 0, sb->size, sb->size/2);
 
 
 				}
 				}
 
 
@@ -6497,6 +6534,7 @@ void RasterizerGLES2::end_shadow_map() {
 			} else {
 			} else {
 				cm = shadow->custom_projection[0];
 				cm = shadow->custom_projection[0];
 				light_transform=shadow->custom_transform[0];
 				light_transform=shadow->custom_transform[0];
+				vp_rect=Rect2(0, 0, sb->size, sb->size);
 				glViewport(0, 0, sb->size, sb->size);
 				glViewport(0, 0, sb->size, sb->size);
 			}
 			}
 
 
@@ -6527,11 +6565,13 @@ void RasterizerGLES2::end_shadow_map() {
 			shadow->dp.y=dp_direction;
 			shadow->dp.y=dp_direction;
 
 
 			if (shadow_pass==0) {
 			if (shadow_pass==0) {
-				glViewport(0, sb->size*0.5, sb->size, sb->size*0.5);
-				glScissor(0, sb->size*0.5, sb->size, sb->size*0.5);
+				vp_rect=Rect2(0, sb->size/2, sb->size, sb->size/2);
+				glViewport(0, sb->size/2, sb->size, sb->size/2);
+				glScissor(0, sb->size/2, sb->size, sb->size/2);
 			} else {
 			} else {
-				glViewport(0, 0, sb->size, sb->size*0.5);
-				glScissor(0, 0, sb->size, sb->size*0.5);
+				vp_rect=Rect2(0, 0, sb->size, sb->size/2);
+				glViewport(0, 0, sb->size, sb->size/2);
+				glScissor(0, 0, sb->size, sb->size/2);
 			}
 			}
 			glEnable(GL_SCISSOR_TEST);
 			glEnable(GL_SCISSOR_TEST);
 			shadow->projection=cm;
 			shadow->projection=cm;
@@ -6565,6 +6605,7 @@ void RasterizerGLES2::end_shadow_map() {
 			z_far=cm.get_z_far();
 			z_far=cm.get_z_far();
 
 
 			glViewport(0, 0, sb->size, sb->size);
 			glViewport(0, 0, sb->size, sb->size);
+			vp_rect=Rect2(0, 0, sb->size, sb->size);
 			_glClearDepth(1.0f);
 			_glClearDepth(1.0f);
 			glClearColor(1,1,1,1);
 			glClearColor(1,1,1,1);
 			if (use_rgba_shadowmaps)
 			if (use_rgba_shadowmaps)
@@ -6583,16 +6624,124 @@ void RasterizerGLES2::end_shadow_map() {
 
 
 	material_shader.set_conditional(MaterialShaderGLES2::USE_DUAL_PARABOLOID,false);
 	material_shader.set_conditional(MaterialShaderGLES2::USE_DUAL_PARABOLOID,false);
 
 
-	glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
-	//glDisable(GL_POLYGON_OFFSET_FILL);
-
 
 
 	//if (!use_rgba_shadowmaps)
 	//if (!use_rgba_shadowmaps)
-	glColorMask(1, 1, 1, 1);
+
+	if (shadow_filter==SHADOW_FILTER_ESM) {
+
+		copy_shader.set_conditional(CopyShaderGLES2::USE_RGBA_DEPTH,use_rgba_shadowmaps);
+		copy_shader.set_conditional(CopyShaderGLES2::USE_HIGHP_SOURCE,!use_rgba_shadowmaps);
+
+		Vector2 psize(1.0/sb->size,1.0/sb->size);
+		float pscale = 1.0;
+		int passes=shadow->base->vars[VS::LIGHT_PARAM_SHADOW_BLUR_PASSES];
+		glDisable(GL_BLEND);
+		glDisable(GL_CULL_FACE);
+#ifdef GLEW_ENABLED
+		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
+#endif
+
+		for(int i=0;i<VS::ARRAY_MAX;i++) {
+			glDisableVertexAttribArray(i);
+		}
+		glBindBuffer(GL_ARRAY_BUFFER,0);
+		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+		glDisable(GL_SCISSOR_TEST);
+
+		if (!use_rgba_shadowmaps) {
+			glEnable(GL_DEPTH_TEST);
+			glDepthFunc(GL_ALWAYS);
+			glDepthMask(true);
+		} else {
+			glDisable(GL_DEPTH_TEST);
+		}
+
+		for(int i=0;i<passes;i++) {
+
+
+			Vector2 src_sb_uv[4]={
+				(vp_rect.pos+Vector2(0,vp_rect.size.y))/sb->size,
+				(vp_rect.pos+vp_rect.size)/sb->size,
+				(vp_rect.pos+Vector2(vp_rect.size.x,0))/sb->size,
+				(vp_rect.pos)/sb->size
+			};
+/*
+			Vector2 src_uv[4]={
+				Vector2( 0, 1),
+				Vector2( 1, 1),
+				Vector2( 1, 0),
+				Vector2( 0, 0)
+			};
+*/
+			static const Vector2 dst_pos[4]={
+				Vector2(-1, 1),
+				Vector2( 1, 1),
+				Vector2( 1,-1),
+				Vector2(-1,-1)
+			};
+
+			glBindFramebuffer(GL_FRAMEBUFFER, blur_shadow_buffer.fbo);
+			glActiveTexture(GL_TEXTURE0);
+			glBindTexture(GL_TEXTURE_2D, sb->depth);
+#ifdef GLEW_ENABLED
+			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+#endif
+
+			copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_V_PASS,true);
+			copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false);
+
+			copy_shader.bind();
+			copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize);
+			copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale);
+			copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1);
+			//copy_shader.set_uniform(CopyShaderGLES2::SOURCE,0);
+			glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
+
+
+			_draw_gui_primitive(4,dst_pos,NULL,src_sb_uv);
+
+
+			Vector2 src_bb_uv[4]={
+				(vp_rect.pos+Vector2(0,vp_rect.size.y))/blur_shadow_buffer.size,
+				(vp_rect.pos+vp_rect.size)/blur_shadow_buffer.size,
+				(vp_rect.pos+Vector2(vp_rect.size.x,0))/blur_shadow_buffer.size,
+				(vp_rect.pos)/blur_shadow_buffer.size,
+			};
+
+			glBindFramebuffer(GL_FRAMEBUFFER, sb->fbo);
+			glActiveTexture(GL_TEXTURE0);
+			glBindTexture(GL_TEXTURE_2D, blur_shadow_buffer.depth);
+#ifdef GLEW_ENABLED
+
+			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+#endif
+
+			copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_V_PASS,false);
+			copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,true);
+			copy_shader.bind();
+			copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SIZE,psize);
+			copy_shader.set_uniform(CopyShaderGLES2::PIXEL_SCALE,pscale);
+			copy_shader.set_uniform(CopyShaderGLES2::BLUR_MAGNITUDE,1);
+			glUniform1i(copy_shader.get_uniform_location(CopyShaderGLES2::SOURCE),0);
+
+			_draw_gui_primitive(4,dst_pos,NULL,src_bb_uv);
+
+
+		}
+
+		glDepthFunc(GL_LEQUAL);
+		copy_shader.set_conditional(CopyShaderGLES2::USE_RGBA_DEPTH,false);
+		copy_shader.set_conditional(CopyShaderGLES2::USE_HIGHP_SOURCE,false);
+		copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_V_PASS,false);
+		copy_shader.set_conditional(CopyShaderGLES2::SHADOW_BLUR_H_PASS,false);
+
+	}
 
 
 	DEBUG_TEST_ERROR("Drawing Shadow");
 	DEBUG_TEST_ERROR("Drawing Shadow");
 	shadow=NULL;
 	shadow=NULL;
-
+	glBindFramebuffer(GL_FRAMEBUFFER, current_rt?current_rt->fbo:base_framebuffer);
+	glColorMask(1, 1, 1, 1);
+	//glDisable(GL_POLYGON_OFFSET_FILL);
 
 
 }
 }
 
 
@@ -6635,23 +6784,14 @@ void RasterizerGLES2::_debug_draw_shadows_type(Vector<ShadowBuffer>& p_shadows,P
 //	Size2 debug_size(512,512);
 //	Size2 debug_size(512,512);
 
 
 
 
-	for (int i=0;i<p_shadows.size();i++) {
+	int useblur=shadow_filter==SHADOW_FILTER_ESM?1:0;
+	for (int i=0;i<p_shadows.size()+useblur;i++) {
 
 
-		ShadowBuffer *sb=&p_shadows[i];
+		ShadowBuffer *sb=i==p_shadows.size()?&blur_shadow_buffer:&p_shadows[i];
 
 
-		if (!sb->owner)
+		if (!sb->owner && i!=p_shadows.size())
 			continue;
 			continue;
 
 
-
-		if (sb->owner->base->type==VS::LIGHT_DIRECTIONAL) {
-
-			//if (sb->owner->shadow_pass!=scene_pass-1)
-			//	continue;
-		} else {
-
-			//if (sb->owner->shadow_pass!=frame)
-			//	continue;
-		}
 		_debug_draw_shadow(sb->depth, Rect2( ofs, debug_size ));
 		_debug_draw_shadow(sb->depth, Rect2( ofs, debug_size ));
 		ofs.x+=debug_size.x;
 		ofs.x+=debug_size.x;
 		if ( (ofs.x+debug_size.x) > viewport.width ) {
 		if ( (ofs.x+debug_size.x) > viewport.width ) {
@@ -7560,6 +7700,11 @@ bool RasterizerGLES2::ShadowBuffer::init(int p_size,bool p_use_depth) {
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0,
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, size, size, 0,
 			     GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
 			     GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
 
 
+#ifdef GLEW_ENABLED
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+#endif
+
 		// Attach the depth texture to FBO depth attachment point
 		// Attach the depth texture to FBO depth attachment point
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
 				       GL_TEXTURE_2D, depth, 0);
 				       GL_TEXTURE_2D, depth, 0);
@@ -7778,9 +7923,17 @@ void RasterizerGLES2::_update_framebuffer() {
 
 
 #endif
 #endif
 	//color
 	//color
+
+	GLuint format_rgba = use_fp16_fb?_GL_RGBA16F_EXT:GL_RGBA;
+	GLuint format_rgb = use_fp16_fb?_GL_RGB16F_EXT:GL_RGB;
+	GLuint format_type = use_fp16_fb?_GL_HALF_FLOAT_OES:GL_UNSIGNED_BYTE;
+	GLuint format_luminance = use_fp16_fb?_GL_R32F_EXT:GL_RGBA;
+	GLuint format_luminance_type = use_fp16_fb?GL_FLOAT:GL_UNSIGNED_BYTE;
+	GLuint format_luminance_components = use_fp16_fb?GL_RED:GL_RGBA;
+
 	glGenTextures(1, &framebuffer.color);
 	glGenTextures(1, &framebuffer.color);
 	glBindTexture(GL_TEXTURE_2D, framebuffer.color);
 	glBindTexture(GL_TEXTURE_2D, framebuffer.color);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  framebuffer.width, framebuffer.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+	glTexImage2D(GL_TEXTURE_2D, 0, format_rgba,  framebuffer.width, framebuffer.height, 0, GL_RGBA, format_type, NULL);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 //	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 //	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -7814,7 +7967,7 @@ void RasterizerGLES2::_update_framebuffer() {
 	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.sample_fbo);
 	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.sample_fbo);
 	glGenTextures(1, &framebuffer.sample_color);
 	glGenTextures(1, &framebuffer.sample_color);
 	glBindTexture(GL_TEXTURE_2D, framebuffer.sample_color);
 	glBindTexture(GL_TEXTURE_2D, framebuffer.sample_color);
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  framebuffer.width, framebuffer.height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+	glTexImage2D(GL_TEXTURE_2D, 0, format_rgba,  framebuffer.width, framebuffer.height, 0, GL_RGBA, format_type, NULL);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 //	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 //	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -7873,8 +8026,8 @@ void RasterizerGLES2::_update_framebuffer() {
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0,
-				     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+			glTexImage2D(GL_TEXTURE_2D, 0, format_rgba, size, size, 0,
+				     GL_RGBA, format_type, NULL);
 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 					       GL_TEXTURE_2D, framebuffer.blur[i].color, 0);
 					       GL_TEXTURE_2D, framebuffer.blur[i].color, 0);
 
 
@@ -7922,8 +8075,8 @@ void RasterizerGLES2::_update_framebuffer() {
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lb.size, lb.size, 0,
-				     GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+			glTexImage2D(GL_TEXTURE_2D, 0, format_luminance, lb.size, lb.size, 0,
+				     format_luminance_components, format_luminance_type, NULL);
 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
 					       GL_TEXTURE_2D, lb.color, 0);
 					       GL_TEXTURE_2D, lb.color, 0);
 
 
@@ -8052,6 +8205,7 @@ void RasterizerGLES2::init() {
 //	framebuffer.blur[1].fbo=false;
 //	framebuffer.blur[1].fbo=false;
 	framebuffer.active=false;
 	framebuffer.active=false;
 
 
+
 	//do a single initial clear
 	//do a single initial clear
 	glClearColor(0,0,0,1);
 	glClearColor(0,0,0,1);
 	//glClearDepth(1.0);
 	//glClearDepth(1.0);
@@ -8086,8 +8240,9 @@ void RasterizerGLES2::init() {
 	use_attribute_instancing=true;
 	use_attribute_instancing=true;
 #ifdef OSX_ENABLED
 #ifdef OSX_ENABLED
 	use_rgba_shadowmaps=true;
 	use_rgba_shadowmaps=true;
+	use_fp16_fb=false;
 #else
 #else
-	use_rgba_shadowmaps=false;
+
 #endif
 #endif
 	use_half_float=true;
 	use_half_float=true;
 
 
@@ -8098,6 +8253,9 @@ void RasterizerGLES2::init() {
 	}
 	}
 	read_depth_supported=extensions.has("GL_OES_depth_texture");
 	read_depth_supported=extensions.has("GL_OES_depth_texture");
 	use_rgba_shadowmaps=!read_depth_supported;
 	use_rgba_shadowmaps=!read_depth_supported;
+	if (shadow_filter>=SHADOW_FILTER_ESM && !extensions.has("GL_EXT_frag_depth")) {
+		use_rgba_shadowmaps=true; //no other way, go back to rgba
+	}
 	pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc");
 	pvr_supported=extensions.has("GL_IMG_texture_compression_pvrtc");
 	etc_supported=extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
 	etc_supported=extensions.has("GL_OES_compressed_ETC1_RGB8_texture");
 	use_depth24 = extensions.has("GL_OES_depth24");
 	use_depth24 = extensions.has("GL_OES_depth24");
@@ -8131,6 +8289,10 @@ void RasterizerGLES2::init() {
 		use_attribute_instancing=false;
 		use_attribute_instancing=false;
 	}
 	}
 
 
+	if (use_fp16_fb) {
+		use_fp16_fb=extensions.has("GL_OES_texture_half_float") && extensions.has("GL_EXT_color_buffer_half_float");
+	}
+
 
 
 	//etc_supported=false;
 	//etc_supported=false;
 	use_hw_skeleton_xform=false;
 	use_hw_skeleton_xform=false;
@@ -8150,15 +8312,19 @@ void RasterizerGLES2::init() {
 
 
 		//don't use a shadowbuffer too big in GLES, this should be the maximum
 		//don't use a shadowbuffer too big in GLES, this should be the maximum
 		int max_shadow_size = GLOBAL_DEF("rasterizer/max_shadow_buffer_size",1024);//nearest_power_of_2(MIN(vm.width,vm.height))/2;
 		int max_shadow_size = GLOBAL_DEF("rasterizer/max_shadow_buffer_size",1024);//nearest_power_of_2(MIN(vm.width,vm.height))/2;
-		while(max_shadow_size>=16) {
+		int smsize=max_shadow_size;
+		while(smsize>=16) {
 
 
 			ShadowBuffer sb;
 			ShadowBuffer sb;
-			bool s = sb.init(max_shadow_size,!use_rgba_shadowmaps);
+			bool s = sb.init(smsize,!use_rgba_shadowmaps);
 			if (s)
 			if (s)
 				near_shadow_buffers.push_back(sb);
 				near_shadow_buffers.push_back(sb);
-			max_shadow_size/=2;
+			smsize/=2;
 		}
 		}
 
 
+		blur_shadow_buffer.init(max_shadow_size,!use_rgba_shadowmaps);
+
+
 		//material_shader
 		//material_shader
 		material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
 		material_shader.set_conditional(MaterialShaderGLES2::USE_DEPTH_SHADOWS,!use_rgba_shadowmaps);
 
 
@@ -8168,6 +8334,9 @@ void RasterizerGLES2::init() {
 	shadow_material = material_create(); //empty with nothing
 	shadow_material = material_create(); //empty with nothing
 	shadow_mat_ptr = material_owner.get(shadow_material);
 	shadow_mat_ptr = material_owner.get(shadow_material);
 	overdraw_material = create_overdraw_debug_material();
 	overdraw_material = create_overdraw_debug_material();
+	copy_shader.set_conditional(CopyShaderGLES2::USE_8BIT_HDR,!use_fp16_fb);
+
+	canvas_shader.set_conditional(CanvasShaderGLES2::USE_PIXEL_SNAP,GLOBAL_DEF("rasterizer/use_pixel_snap",false));
 
 
 	npo2_textures_available=true;
 	npo2_textures_available=true;
 	//fragment_lighting=false;
 	//fragment_lighting=false;
@@ -8423,6 +8592,8 @@ void RasterizerGLES2::reload_vram() {
 		near_shadow_buffers[i].init(near_shadow_buffers[i].size,!use_rgba_shadowmaps);
 		near_shadow_buffers[i].init(near_shadow_buffers[i].size,!use_rgba_shadowmaps);
 	}
 	}
 
 
+	blur_shadow_buffer.init(near_shadow_buffers[0].size,!use_rgba_shadowmaps);
+
 
 
 
 
 	canvas_shader.clear_caches();
 	canvas_shader.clear_caches();
@@ -8473,8 +8644,8 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo
 	fragment_lighting=GLOBAL_DEF("rasterizer/use_fragment_lighting",true);
 	fragment_lighting=GLOBAL_DEF("rasterizer/use_fragment_lighting",true);
 	read_depth_supported=true; //todo check for extension
 	read_depth_supported=true; //todo check for extension
 	shadow_filter=ShadowFilterTechnique((int)(GLOBAL_DEF("rasterizer/shadow_filter",SHADOW_FILTER_PCF5)));
 	shadow_filter=ShadowFilterTechnique((int)(GLOBAL_DEF("rasterizer/shadow_filter",SHADOW_FILTER_PCF5)));
-	Globals::get_singleton()->set_custom_property_info("rasterizer/shadow_filter",PropertyInfo(Variant::INT,"rasterizer/shadow_filter",PROPERTY_HINT_ENUM,"None,PCF5,PCF13,ESM,VSM"));
-
+	Globals::get_singleton()->set_custom_property_info("rasterizer/shadow_filter",PropertyInfo(Variant::INT,"rasterizer/shadow_filter",PROPERTY_HINT_ENUM,"None,PCF5,PCF13,ESM"));
+	use_fp16_fb=bool(GLOBAL_DEF("rasterizer/fp16_framebuffer",true));
 	use_shadow_mapping=true;
 	use_shadow_mapping=true;
 	use_fast_texture_filter=!bool(GLOBAL_DEF("rasterizer/trilinear_mipmap_filter",true));
 	use_fast_texture_filter=!bool(GLOBAL_DEF("rasterizer/trilinear_mipmap_filter",true));
 	skel_default.resize(1024*4);
 	skel_default.resize(1024*4);

+ 7 - 1
drivers/gles2/rasterizer_gles2.h

@@ -80,6 +80,7 @@ class RasterizerGLES2 : public Rasterizer {
 	bool read_depth_supported;
 	bool read_depth_supported;
 	bool use_framebuffers;
 	bool use_framebuffers;
 	bool use_shadow_mapping;
 	bool use_shadow_mapping;
+	bool use_fp16_fb;
 	ShadowFilterTechnique shadow_filter;
 	ShadowFilterTechnique shadow_filter;
 
 
 	bool use_shadow_esm;
 	bool use_shadow_esm;
@@ -585,6 +586,8 @@ class RasterizerGLES2 : public Rasterizer {
 			vars[VS::LIGHT_PARAM_SHADOW_DARKENING]=0.0;
 			vars[VS::LIGHT_PARAM_SHADOW_DARKENING]=0.0;
 			vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.2;
 			vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.2;
 			vars[VS::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE]=1.4;
 			vars[VS::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE]=1.4;
+			vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER]=60.0;
+			vars[VS::LIGHT_PARAM_SHADOW_BLUR_PASSES]=1;
 			colors[VS::LIGHT_COLOR_AMBIENT]=Color(0,0,0);
 			colors[VS::LIGHT_COLOR_AMBIENT]=Color(0,0,0);
 			colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1);
 			colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1);
 			colors[VS::LIGHT_COLOR_SPECULAR]=Color(1,1,1);
 			colors[VS::LIGHT_COLOR_SPECULAR]=Color(1,1,1);
@@ -645,7 +648,6 @@ class RasterizerGLES2 : public Rasterizer {
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
-			fx_param[VS::ENV_FX_PARAM_GAMMA]=1.0;
 
 
 		}
 		}
 
 
@@ -998,6 +1000,8 @@ class RasterizerGLES2 : public Rasterizer {
 	};
 	};
 
 
 	Vector<ShadowBuffer> near_shadow_buffers;
 	Vector<ShadowBuffer> near_shadow_buffers;
+	ShadowBuffer blur_shadow_buffer;
+
 	Vector<ShadowBuffer> far_shadow_buffers;
 	Vector<ShadowBuffer> far_shadow_buffers;
 
 
 	LightInstance *shadow;
 	LightInstance *shadow;
@@ -1100,6 +1104,7 @@ class RasterizerGLES2 : public Rasterizer {
 	bool cull_front;
 	bool cull_front;
 	bool lights_use_shadow;
 	bool lights_use_shadow;
 	_FORCE_INLINE_ void _set_cull(bool p_front,bool p_reverse_cull=false);
 	_FORCE_INLINE_ void _set_cull(bool p_front,bool p_reverse_cull=false);
+	_FORCE_INLINE_ Color _convert_color(const Color& p_color);
 
 
 	void _process_glow_bloom();
 	void _process_glow_bloom();
 	void _process_hdr();
 	void _process_hdr();
@@ -1376,6 +1381,7 @@ public:
 
 
 	virtual ShadowType light_instance_get_shadow_type(RID p_light_instance,bool p_far=false) const;
 	virtual ShadowType light_instance_get_shadow_type(RID p_light_instance,bool p_far=false) const;
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const;
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const;
+	virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const;
 	virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
 	virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const;
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const;
 
 

+ 2 - 0
drivers/gles2/shader_gles2.h

@@ -308,6 +308,8 @@ public:
 		uniforms_dirty = true;
 		uniforms_dirty = true;
 	};
 	};
 
 
+	uint32_t get_version() const { return new_conditional_version.version; }
+
 	void set_uniform_camera(int p_idx, const CameraMatrix& p_mat) {
 	void set_uniform_camera(int p_idx, const CameraMatrix& p_mat) {
 
 
 		uniform_cameras[p_idx] = p_mat;
 		uniform_cameras[p_idx] = p_mat;

+ 147 - 10
drivers/gles2/shaders/copy.glsl

@@ -54,8 +54,12 @@ varying vec3 cube_interp;
 uniform samplerCube source_cube;
 uniform samplerCube source_cube;
 #else
 #else
 varying vec2 uv_interp;
 varying vec2 uv_interp;
+#ifdef HIGHP_SOURCE
+uniform highp sampler2D source;
+#else
 uniform sampler2D source;
 uniform sampler2D source;
 #endif
 #endif
+#endif
 varying vec2 uv2_interp;
 varying vec2 uv2_interp;
 
 
 #ifdef USE_GLOW
 #ifdef USE_GLOW
@@ -83,12 +87,6 @@ uniform vec3 bcs;
 
 
 #endif
 #endif
 
 
-#ifdef USE_GAMMA
-
-uniform float gamma;
-
-#endif
-
 #ifdef USE_GLOW_COPY
 #ifdef USE_GLOW_COPY
 
 
 uniform float bloom;
 uniform float bloom;
@@ -96,7 +94,7 @@ uniform float bloom_treshold;
 
 
 #endif
 #endif
 
 
-#if defined(BLUR_V_PASS) || defined(BLUR_H_PASS) || defined(USE_HDR_REDUCE)
+#if defined(SHADOW_BLUR_V_PASS) || defined(SHADOW_BLUR_H_PASS) || defined(BLUR_V_PASS) || defined(BLUR_H_PASS) || defined(USE_HDR_REDUCE)
 
 
 uniform vec2 pixel_size;
 uniform vec2 pixel_size;
 uniform float pixel_scale;
 uniform float pixel_scale;
@@ -133,6 +131,17 @@ uniform float custom_alpha;
 void main() {
 void main() {
 
 
 	//vec4 color = color_interp;
 	//vec4 color = color_interp;
+#ifdef USE_HIGHP_SOURCE
+
+#ifdef USE_CUBEMAP
+	highp vec4 color = textureCube( source_cube,  normalize(cube_interp) );
+
+#else
+	highp vec4 color = texture2D( source,  uv_interp );
+#endif
+
+#else
+
 #ifdef USE_CUBEMAP
 #ifdef USE_CUBEMAP
 	vec4 color = textureCube( source_cube,  normalize(cube_interp) );
 	vec4 color = textureCube( source_cube,  normalize(cube_interp) );
 
 
@@ -141,6 +150,8 @@ void main() {
 #endif
 #endif
 
 
 
 
+#endif
+
 #ifdef USE_FXAA
 #ifdef USE_FXAA
 
 
 #define FXAA_REDUCE_MIN   (1.0/ 128.0)
 #define FXAA_REDUCE_MIN   (1.0/ 128.0)
@@ -226,17 +237,103 @@ void main() {
 
 
 #endif
 #endif
 
 
+#ifdef SHADOW_BLUR_V_PASS
+
+#ifdef USE_RGBA_DEPTH
+
+#define VEC42DEPTH(m_vec4) dot(m_vec4,vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1))
+
+	highp float depth = VEC42DEPTH(color)*0.383;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale))*0.006;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale))*0.061;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale))*0.242;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale))*0.242;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale))*0.061;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale))*0.006;
+	highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
+	comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
+	color=comp;
+
+#else
+
+	highp float depth = color.r*0.383;
+	depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-3.0)*pixel_scale).r*0.006;
+	depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-2.0)*pixel_scale).r*0.061;
+	depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*-1.0)*pixel_scale).r*0.242;
+	depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*1.0)*pixel_scale).r*0.242;
+	depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*2.0)*pixel_scale).r*0.061;
+	depth+=texture2D(source,uv_interp+vec2(0.0,pixel_size.y*3.0)*pixel_scale).r*0.006;
+
+#ifdef USE_GLES_OVER_GL
+	gl_FragDepth = depth;
+
+#else
+	gl_FragDepthEXT = depth;
+#endif
+
+	return;
+#endif
+
+#endif
+
+#ifdef SHADOW_BLUR_H_PASS
+
+
+#ifdef USE_RGBA_DEPTH
+
+#define VEC42DEPTH(m_vec4) dot(m_vec4,vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1))
+
+	highp float depth = VEC42DEPTH(color)*0.383;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale))*0.006;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale))*0.061;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale))*0.242;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale))*0.242;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale))*0.061;
+	depth+=VEC42DEPTH(texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale))*0.006;
+	highp vec4 comp = fract(depth * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
+	comp -= comp.xxyz * vec4(0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
+	color=comp;
+#else
+
+
+	highp float depth = color.r*0.383;
+	depth+=texture2D(source,uv_interp+vec2(pixel_size.x*-3.0,0.0)*pixel_scale).r*0.006;
+	depth+=texture2D(source,uv_interp+vec2(pixel_size.x*-2.0,0.0)*pixel_scale).r*0.061;
+	depth+=texture2D(source,uv_interp+vec2(pixel_size.x*-1.0,0.0)*pixel_scale).r*0.242;
+	depth+=texture2D(source,uv_interp+vec2(pixel_size.x*1.0,0.0)*pixel_scale).r*0.242;
+	depth+=texture2D(source,uv_interp+vec2(pixel_size.x*2.0,0.0)*pixel_scale).r*0.061;
+	depth+=texture2D(source,uv_interp+vec2(pixel_size.x*3.0,0.0)*pixel_scale).r*0.006;
+
+#ifdef USE_GLES_OVER_GL
+	gl_FragDepth = depth;
+#else
+	gl_FragDepthEXT = depth;
+#endif
+
+	return;
+
+#endif
+
+#endif
+
 #ifdef USE_HDR
 #ifdef USE_HDR
 
 
+
+#ifdef USE_8BIT_HDR
 	highp vec4 _mult = vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1);
 	highp vec4 _mult = vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0,1);
 	highp float hdr_lum = dot(texture2D( hdr_source, vec2(0.0) ), _mult  );
 	highp float hdr_lum = dot(texture2D( hdr_source, vec2(0.0) ), _mult  );
 	color.rgb*=LUM_RANGE;
 	color.rgb*=LUM_RANGE;
 	hdr_lum*=LUM_RANGE; //restore to full range
 	hdr_lum*=LUM_RANGE; //restore to full range
+#else
+	highp float hdr_lum = texture2D( hdr_source, vec2(0.0) ).r;
+#endif
+
 	highp float tone_scale = tonemap_exposure / hdr_lum; //only linear supported
 	highp float tone_scale = tonemap_exposure / hdr_lum; //only linear supported
 	color.rgb*=tone_scale;
 	color.rgb*=tone_scale;
 
 
 #endif
 #endif
 
 
+
 #ifdef USE_GLOW_COPY
 #ifdef USE_GLOW_COPY
 
 
 	highp vec3 glowcol = color.rgb*color.a+step(bloom_treshold,dot(vec3(0.3333,0.3333,0.3333),color.rgb))*bloom*color.rgb;
 	highp vec3 glowcol = color.rgb*color.a+step(bloom_treshold,dot(vec3(0.3333,0.3333,0.3333),color.rgb))*bloom*color.rgb;
@@ -281,10 +378,15 @@ void main() {
 
 
 #endif
 #endif
 
 
-#ifdef USE_GAMMA
-
-	color.rgb = pow(color.rgb,gamma);
+#ifdef USE_SRGB
 
 
+	{ //i have my doubts about how fast this is
+		color.rgb = min(color.rgb,vec3(1.0)); //clamp just in case
+		vec3 S1 = sqrt(color.rgb);
+		vec3 S2 = sqrt(S1);
+		vec3 S3 = sqrt(S2);
+		color.rgb = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.225411470 * color.rgb;
+	}
 #endif
 #endif
 
 
 
 
@@ -292,13 +394,20 @@ void main() {
 
 
 	//highp float lum = dot(color.rgb,highp vec3(1.0/3.0,1.0/3.0,1.0/3.0));
 	//highp float lum = dot(color.rgb,highp vec3(1.0/3.0,1.0/3.0,1.0/3.0));
 	highp float lum = max(color.r,max(color.g,color.b));
 	highp float lum = max(color.r,max(color.g,color.b));
+#ifdef USE_8BIT_HDR
 	highp vec4 comp = fract(lum * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
 	highp vec4 comp = fract(lum * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
 	comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
 	comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
 	color=comp;
 	color=comp;
+#else
+	color.rgb=vec3(lum);
+#endif
+
+
 #endif
 #endif
 
 
 #ifdef USE_HDR_REDUCE
 #ifdef USE_HDR_REDUCE
 
 
+#ifdef USE_8BIT_HDR
 	highp vec4 _multcv = vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0, 1.0);
 	highp vec4 _multcv = vec4(1.0 / (256.0 * 256.0 * 256.0),1.0 / (256.0 * 256.0),1.0 / 256.0, 1.0);
 	highp float lum_accum = dot(color,_multcv  );
 	highp float lum_accum = dot(color,_multcv  );
 	lum_accum += dot(texture2D( source,  uv_interp+vec2(-pixel_size.x,-pixel_size.y) ),_multcv  );
 	lum_accum += dot(texture2D( source,  uv_interp+vec2(-pixel_size.x,-pixel_size.y) ),_multcv  );
@@ -310,16 +419,42 @@ void main() {
 	lum_accum += dot(texture2D( source,  uv_interp+vec2(0.0,pixel_size.y) ),_multcv  );
 	lum_accum += dot(texture2D( source,  uv_interp+vec2(0.0,pixel_size.y) ),_multcv  );
 	lum_accum += dot(texture2D( source,  uv_interp+vec2(pixel_size.x,pixel_size.y) ),_multcv  );
 	lum_accum += dot(texture2D( source,  uv_interp+vec2(pixel_size.x,pixel_size.y) ),_multcv  );
 	lum_accum/=9.0;
 	lum_accum/=9.0;
+#else
+
+	highp float lum_accum = color.r;
+	lum_accum += texture2D( source,  uv_interp+vec2(-pixel_size.x,-pixel_size.y) ).r;
+	lum_accum += texture2D( source,  uv_interp+vec2(0.0,-pixel_size.y) ).r;
+	lum_accum += texture2D( source,  uv_interp+vec2(pixel_size.x,-pixel_size.y) ).r;
+	lum_accum += texture2D( source,  uv_interp+vec2(-pixel_size.x,0.0) ).r;
+	lum_accum += texture2D( source,  uv_interp+vec2(pixel_size.x,0.0) ).r;
+	lum_accum += texture2D( source,  uv_interp+vec2(-pixel_size.x,pixel_size.y) ).r;
+	lum_accum += texture2D( source,  uv_interp+vec2(0.0,pixel_size.y) ).r;
+	lum_accum += texture2D( source,  uv_interp+vec2(pixel_size.x,pixel_size.y) ).r;
+	lum_accum/=9.0;
+
+#endif
 
 
 #ifdef USE_HDR_STORE
 #ifdef USE_HDR_STORE
 
 
+#ifdef USE_8BIT_HDR
 	highp float vd_lum = dot(texture2D( source_vd_lum, vec2(0.0) ), _multcv  );
 	highp float vd_lum = dot(texture2D( source_vd_lum, vec2(0.0) ), _multcv  );
 	lum_accum = clamp( vd_lum + (lum_accum-vd_lum)*hdr_time_delta*hdr_exp_adj_speed,min_luminance*(1.0/LUM_RANGE),max_luminance*(1.0/LUM_RANGE));
 	lum_accum = clamp( vd_lum + (lum_accum-vd_lum)*hdr_time_delta*hdr_exp_adj_speed,min_luminance*(1.0/LUM_RANGE),max_luminance*(1.0/LUM_RANGE));
+#else
+	highp float vd_lum=texture2D( source_vd_lum, vec2(0.0) );
+	lum_accum = clamp( vd_lum + (lum_accum-vd_lum)*hdr_time_delta*hdr_exp_adj_speed,min_luminance,max_luminance);
+#endif
+
 #endif
 #endif
 
 
+#ifdef USE_8BIT_HDR
 	highp vec4 comp = fract(lum_accum * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
 	highp vec4 comp = fract(lum_accum * vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0));
 	comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
 	comp -= comp.xxyz * vec4(0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0);
 	color=comp;
 	color=comp;
+#else
+	color.rgb=vec3(lum_accum);
+#endif
+
+
 #endif
 #endif
 
 
 #ifdef USE_RGBE
 #ifdef USE_RGBE
@@ -338,6 +473,8 @@ void main() {
 #ifdef USE_CUSTOM_ALPHA
 #ifdef USE_CUSTOM_ALPHA
 	color.a=custom_alpha;
 	color.a=custom_alpha;
 #endif
 #endif
+
+
         gl_FragColor = color;
         gl_FragColor = color;
 }
 }
 
 

+ 57 - 4
drivers/gles2/shaders/material.glsl

@@ -342,7 +342,7 @@ VERTEX_SHADER_CODE
 
 
 #ifdef USE_FOG
 #ifdef USE_FOG
 
 
-	fog_interp.a = pow( clamp( (-vertex_interp.z-fog_params.x)/(fog_params.y-fog_params.x), 0.0, 1.0 ), fog_params.z );
+	fog_interp.a = pow( clamp( (length(vertex_interp)-fog_params.x)/(fog_params.y-fog_params.x), 0.0, 1.0 ), fog_params.z );
 	fog_interp.rgb = mix( fog_color_begin, fog_color_end, fog_interp.a );
 	fog_interp.rgb = mix( fog_color_begin, fog_color_end, fog_interp.a );
 #endif
 #endif
 
 
@@ -666,9 +666,14 @@ float SAMPLE_SHADOW_TEX( highp vec2 coord, highp float refdepth) {
 
 
 #ifdef USE_SHADOW_ESM
 #ifdef USE_SHADOW_ESM
 
 
+uniform float esm_multiplier;
 
 
 float SAMPLE_SHADOW_TEX(vec2 p_uv,float p_depth) {
 float SAMPLE_SHADOW_TEX(vec2 p_uv,float p_depth) {
 
 
+#if defined (USE_DEPTH_SHADOWS)
+	//these only are used if interpolation exists
+	highp float occluder = SHADOW_DEPTH(shadow_texture, p_uv);
+#else
 	vec2 unnormalized = p_uv/shadow_texel_size;
 	vec2 unnormalized = p_uv/shadow_texel_size;
 	vec2 fractional = fract(unnormalized);
 	vec2 fractional = fract(unnormalized);
 	unnormalized = floor(unnormalized);
 	unnormalized = floor(unnormalized);
@@ -681,7 +686,8 @@ float SAMPLE_SHADOW_TEX(vec2 p_uv,float p_depth) {
 
 
 	highp float occluder = (exponent.w + (exponent.x - exponent.w) * fractional.y);
 	highp float occluder = (exponent.w + (exponent.x - exponent.w) * fractional.y);
 	occluder = occluder + ((exponent.z + (exponent.y - exponent.z) * fractional.y) - occluder)*fractional.x;
 	occluder = occluder + ((exponent.z + (exponent.y - exponent.z) * fractional.y) - occluder)*fractional.x;
-	return clamp(exp(28.0 * ( occluder - p_depth )),0.0,1.0);
+#endif
+	return clamp(exp(esm_multiplier* ( occluder - p_depth )),0.0,1.0);
 
 
 }
 }
 
 
@@ -818,7 +824,7 @@ FRAGMENT_SHADER_CODE
 		vec3 col_up=texture2D(ambient_octree_tex,octant_uv).rgb;
 		vec3 col_up=texture2D(ambient_octree_tex,octant_uv).rgb;
 		octant_uv.y+=ambient_octree_pix_size.y*2.0;
 		octant_uv.y+=ambient_octree_pix_size.y*2.0;
 		vec3 col_down=texture2D(ambient_octree_tex,octant_uv).rgb;
 		vec3 col_down=texture2D(ambient_octree_tex,octant_uv).rgb;
-		ambientmap_color=mix(col_down,col_up,1.0-sub.z);
+		ambientmap_color=mix(col_up,col_down,sub.z);
 
 
 		ambientmap_color*=diffuse.rgb;
 		ambientmap_color*=diffuse.rgb;
 
 
@@ -866,6 +872,15 @@ FRAGMENT_SHADER_CODE
 	vec2 pssm_coord;
 	vec2 pssm_coord;
 	float pssm_z;
 	float pssm_z;
 
 
+#if defined(LIGHT_USE_PSSM) && defined(USE_SHADOW_ESM)
+#define USE_PSSM_BLEND
+	float pssm_blend;
+	vec2 pssm_coord_2;
+	float pssm_z_2;
+	vec3 light_pssm_split_inv = 1.0/light_pssm_split;
+	float w_inv = 1.0/gl_FragCoord.w;
+#endif
+
 #ifdef LIGHT_USE_PSSM4
 #ifdef LIGHT_USE_PSSM4
 
 
 
 
@@ -874,10 +889,21 @@ FRAGMENT_SHADER_CODE
 		if (gl_FragCoord.w > light_pssm_split.x) {
 		if (gl_FragCoord.w > light_pssm_split.x) {
 			pssm_coord=shadow_coord.xy;
 			pssm_coord=shadow_coord.xy;
 			pssm_z=shadow_coord.z;
 			pssm_z=shadow_coord.z;
+#if defined(USE_PSSM_BLEND)
+			pssm_coord_2=shadow_coord2.xy;
+			pssm_z_2=shadow_coord2.z;
+			pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+#endif
 
 
 		} else {
 		} else {
 			pssm_coord=shadow_coord2.xy;
 			pssm_coord=shadow_coord2.xy;
 			pssm_z=shadow_coord2.z;
 			pssm_z=shadow_coord2.z;
+#if defined(USE_PSSM_BLEND)
+			pssm_coord_2=shadow_coord3.xy;
+			pssm_z_2=shadow_coord3.z;
+			pssm_blend=smoothstep(light_pssm_split_inv.x,light_pssm_split_inv.y,w_inv);
+#endif
+
 		}
 		}
 	} else {
 	} else {
 
 
@@ -885,9 +911,21 @@ FRAGMENT_SHADER_CODE
 		if (gl_FragCoord.w > light_pssm_split.z) {
 		if (gl_FragCoord.w > light_pssm_split.z) {
 			pssm_coord=shadow_coord3.xy;
 			pssm_coord=shadow_coord3.xy;
 			pssm_z=shadow_coord3.z;
 			pssm_z=shadow_coord3.z;
+#if defined(USE_PSSM_BLEND)
+			pssm_coord_2=shadow_coord4.xy;
+			pssm_z_2=shadow_coord4.z;
+			pssm_blend=smoothstep(light_pssm_split_inv.y,light_pssm_split_inv.z,w_inv);
+#endif
+
 		} else {
 		} else {
 			pssm_coord=shadow_coord4.xy;
 			pssm_coord=shadow_coord4.xy;
 			pssm_z=shadow_coord4.z;
 			pssm_z=shadow_coord4.z;
+#if defined(USE_PSSM_BLEND)
+			pssm_coord_2=shadow_coord4.xy;
+			pssm_z_2=shadow_coord4.z;
+			pssm_blend=0.0;
+#endif
+
 		}
 		}
 	}
 	}
 
 
@@ -896,16 +934,31 @@ FRAGMENT_SHADER_CODE
 	if (gl_FragCoord.w > light_pssm_split.x) {
 	if (gl_FragCoord.w > light_pssm_split.x) {
 		pssm_coord=shadow_coord.xy;
 		pssm_coord=shadow_coord.xy;
 		pssm_z=shadow_coord.z;
 		pssm_z=shadow_coord.z;
+#if defined(USE_PSSM_BLEND)
+		pssm_coord_2=shadow_coord2.xy;
+		pssm_z_2=shadow_coord2.z;
+		pssm_blend=smoothstep(0.0,light_pssm_split_inv.x,w_inv);
+#endif
 
 
 	} else {
 	} else {
 		pssm_coord=shadow_coord2.xy;
 		pssm_coord=shadow_coord2.xy;
 		pssm_z=shadow_coord2.z;
 		pssm_z=shadow_coord2.z;
+#if defined(USE_PSSM_BLEND)
+		pssm_coord_2=shadow_coord2.xy;
+		pssm_z_2=shadow_coord2.z;
+		pssm_blend=0.0;
+#endif
+
 	}
 	}
 
 
 #endif
 #endif
 
 
 	//one one sample
 	//one one sample
 	shadow_attenuation=SAMPLE_SHADOW_TEX(pssm_coord,pssm_z);
 	shadow_attenuation=SAMPLE_SHADOW_TEX(pssm_coord,pssm_z);
+#if defined(USE_PSSM_BLEND)
+	shadow_attenuation=mix(shadow_attenuation,SAMPLE_SHADOW_TEX(pssm_coord_2,pssm_z_2),pssm_blend);
+#endif
+
 
 
 #endif
 #endif
 
 
@@ -1054,7 +1107,7 @@ FRAGMENT_SHADER_CODE
 	diffuse.a=glow;
 	diffuse.a=glow;
 #endif
 #endif
 
 
-#ifdef USE_HDR
+#ifdef USE_8BIT_HDR
 	diffuse.rgb*=0.25;
 	diffuse.rgb*=0.25;
 #endif
 #endif
 
 

+ 9 - 1
modules/gdscript/gd_compiler.cpp

@@ -1330,12 +1330,17 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
 				}
 				}
 				path=base.get_base_dir().plus_file(path);
 				path=base.get_base_dir().plus_file(path);
 			}
 			}
-
 			script = ResourceLoader::load(path);
 			script = ResourceLoader::load(path);
 			if (script.is_null()) {
 			if (script.is_null()) {
 				_set_error("Could not load base class: "+path,p_class);
 				_set_error("Could not load base class: "+path,p_class);
 				return ERR_FILE_NOT_FOUND;
 				return ERR_FILE_NOT_FOUND;
 			}
 			}
+			if (!script->valid) {
+
+				_set_error("Script not fully loaded (cyclic preload?): "+path,p_class);
+				return ERR_BUSY;
+			}
+			//print_line("EXTENDS PATH: "+path+" script is "+itos(script.is_valid())+" indices is "+itos(script->member_indices.size())+" valid? "+itos(script->valid));
 
 
 			if (p_class->extends_class.size()) {
 			if (p_class->extends_class.size()) {
 
 
@@ -1438,6 +1443,9 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars
 	}
 	}
 
 
 
 
+	print_line("Script: "+p_script->get_path()+" indices: "+itos(p_script->member_indices.size()));
+
+
 	for(int i=0;i<p_class->variables.size();i++) {
 	for(int i=0;i<p_class->variables.size();i++) {
 
 
 		StringName name = p_class->variables[i].identifier;
 		StringName name = p_class->variables[i].identifier;

+ 13 - 0
modules/gdscript/gd_functions.cpp

@@ -93,6 +93,7 @@ const char *GDFunctions::get_func_name(Function p_func) {
 		"load",
 		"load",
 		"inst2dict",
 		"inst2dict",
 		"dict2inst",
 		"dict2inst",
+		"hash",
 		"print_stack",
 		"print_stack",
 	};
 	};
 
 
@@ -863,6 +864,12 @@ void GDFunctions::call(Function p_func,const Variant **p_args,int p_arg_count,Va
 
 
 			r_ret = gdscr->_new(NULL,0,r_error);
 			r_ret = gdscr->_new(NULL,0,r_error);
 
 
+		} break;
+		case HASH: {
+
+			VALIDATE_ARG_COUNT(1);
+			r_ret=p_args[0]->hash();
+
 		} break;
 		} break;
 
 
 		case PRINT_STACK: {
 		case PRINT_STACK: {
@@ -1238,6 +1245,12 @@ MethodInfo GDFunctions::get_info(Function p_func) {
 			mi.return_val.type=Variant::OBJECT;
 			mi.return_val.type=Variant::OBJECT;
 			return mi;
 			return mi;
 		} break;
 		} break;
+		case HASH: {
+
+			MethodInfo mi("hash",PropertyInfo(Variant::NIL,"var:var"));
+			mi.return_val.type=Variant::INT;
+			return mi;
+		} break;
 
 
 		case PRINT_STACK: {
 		case PRINT_STACK: {
 			MethodInfo mi("print_stack");
 			MethodInfo mi("print_stack");

+ 1 - 0
modules/gdscript/gd_functions.h

@@ -89,6 +89,7 @@ public:
 		RESOURCE_LOAD,
 		RESOURCE_LOAD,
 		INST2DICT,
 		INST2DICT,
 		DICT2INST,
 		DICT2INST,
+		HASH,
 		PRINT_STACK,
 		PRINT_STACK,
 		FUNC_MAX
 		FUNC_MAX
 
 

+ 2 - 0
modules/gdscript/gd_script.cpp

@@ -1451,6 +1451,7 @@ Error GDScript::reload() {
 
 
 
 
 
 
+
 	valid=false;
 	valid=false;
 	GDParser parser;
 	GDParser parser;
 	Error err = parser.parse(source,basedir);
 	Error err = parser.parse(source,basedir);
@@ -1721,6 +1722,7 @@ GDScript::GDScript() {
 	_base=NULL;
 	_base=NULL;
 	_owner=NULL;
 	_owner=NULL;
 	tool=false;
 	tool=false;
+
 }
 }
 
 
 
 

+ 1 - 0
modules/gdscript/gd_script.h

@@ -183,6 +183,7 @@ class GDScript : public Script {
 	bool valid;
 	bool valid;
 
 
 
 
+
 friend class GDInstance;
 friend class GDInstance;
 friend class GDFunction;
 friend class GDFunction;
 friend class GDCompiler;
 friend class GDCompiler;

+ 1 - 1
platform/flash/rasterizer_flash.h

@@ -441,7 +441,7 @@ class RasterizerFlash : public Rasterizer {
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
-			fx_param[VS::ENV_FX_PARAM_GAMMA]=1.0;
+			fx_param[VS::ENV_FX_PARAM_SRGB_CONVERT]=1.0;
 
 
 		}
 		}
 
 

+ 7 - 1
scene/3d/light.cpp

@@ -40,7 +40,9 @@ static const char* _light_param_names[VS::LIGHT_PARAM_MAX]={
 	"params/attenuation",
 	"params/attenuation",
 	"shadow/darkening",
 	"shadow/darkening",
 	"shadow/z_offset",
 	"shadow/z_offset",
-	"shadow/z_slope_scale"
+	"shadow/z_slope_scale",
+	"shadow/esm_multiplier",
+	"shadow/blur_passes"
 };
 };
 
 
 void Light::set_parameter(Parameter p_param, float p_value) {
 void Light::set_parameter(Parameter p_param, float p_value) {
@@ -479,6 +481,8 @@ void Light::_bind_methods() {
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkening", PROPERTY_HINT_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_DARKENING );
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkening", PROPERTY_HINT_RANGE, "0,64,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_DARKENING );
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_offset", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_OFFSET);
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_offset", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_OFFSET);
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_slope_scale", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_SLOPE_SCALE);
 	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_slope_scale", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_SLOPE_SCALE);
+	ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/esm_multiplier", PROPERTY_HINT_RANGE, "1.0,512.0,0.1"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_ESM_MULTIPLIER);
+	ADD_PROPERTYI( PropertyInfo( Variant::INT, "shadow/blur_passes", PROPERTY_HINT_RANGE, "0,4,1"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_BLUR_PASSES);
 	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "projector",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_projector"), _SCS("get_projector"));
 	ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "projector",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_projector"), _SCS("get_projector"));
 	ADD_PROPERTY( PropertyInfo( Variant::INT, "operator",PROPERTY_HINT_ENUM,"Add,Sub"), _SCS("set_operator"), _SCS("get_operator"));
 	ADD_PROPERTY( PropertyInfo( Variant::INT, "operator",PROPERTY_HINT_ENUM,"Add,Sub"), _SCS("set_operator"), _SCS("get_operator"));
 
 
@@ -511,6 +515,8 @@ Light::Light(VisualServer::LightType p_type) {
 	set_parameter(PARAM_SHADOW_DARKENING,0.0);
 	set_parameter(PARAM_SHADOW_DARKENING,0.0);
 	set_parameter(PARAM_SHADOW_Z_OFFSET,0.05);
 	set_parameter(PARAM_SHADOW_Z_OFFSET,0.05);
 	set_parameter(PARAM_SHADOW_Z_SLOPE_SCALE,0);
 	set_parameter(PARAM_SHADOW_Z_SLOPE_SCALE,0);
+	set_parameter(PARAM_SHADOW_ESM_MULTIPLIER,60);
+	set_parameter(PARAM_SHADOW_BLUR_PASSES,1);
 
 
 	set_color( COLOR_AMBIENT, Color(0,0,0));
 	set_color( COLOR_AMBIENT, Color(0,0,0));
 	set_color( COLOR_DIFFUSE, Color(1,1,1));
 	set_color( COLOR_DIFFUSE, Color(1,1,1));

+ 2 - 0
scene/3d/light.h

@@ -53,6 +53,8 @@ public:
 		PARAM_SHADOW_DARKENING=VisualServer::LIGHT_PARAM_SHADOW_DARKENING,
 		PARAM_SHADOW_DARKENING=VisualServer::LIGHT_PARAM_SHADOW_DARKENING,
 		PARAM_SHADOW_Z_OFFSET=VisualServer::LIGHT_PARAM_SHADOW_Z_OFFSET,
 		PARAM_SHADOW_Z_OFFSET=VisualServer::LIGHT_PARAM_SHADOW_Z_OFFSET,
 		PARAM_SHADOW_Z_SLOPE_SCALE=VisualServer::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
 		PARAM_SHADOW_Z_SLOPE_SCALE=VisualServer::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
+		PARAM_SHADOW_ESM_MULTIPLIER=VisualServer::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER,
+		PARAM_SHADOW_BLUR_PASSES=VisualServer::LIGHT_PARAM_SHADOW_BLUR_PASSES,
 		PARAM_MAX=VisualServer::LIGHT_PARAM_MAX
 		PARAM_MAX=VisualServer::LIGHT_PARAM_MAX
 	};
 	};
 	
 	

+ 13 - 0
scene/main/node.cpp

@@ -1078,6 +1078,18 @@ void Node::remove_from_group(const StringName& p_identifier) {
 
 
 }
 }
 
 
+Array Node::_get_groups() const {
+
+	Array groups;
+	List<GroupInfo> gi;
+	get_groups(&gi);
+	for (List<GroupInfo>::Element *E=gi.front();E;E=E->next()) {
+		groups.push_back(E->get().name);
+	}
+
+	return groups;
+}
+
 void Node::get_groups(List<GroupInfo> *p_groups) const {
 void Node::get_groups(List<GroupInfo> *p_groups) const {
 
 
 	const StringName *K=NULL;
 	const StringName *K=NULL;
@@ -1712,6 +1724,7 @@ void Node::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("remove_from_group","group"),&Node::remove_from_group);
 	ObjectTypeDB::bind_method(_MD("remove_from_group","group"),&Node::remove_from_group);
 	ObjectTypeDB::bind_method(_MD("is_in_group","group"),&Node::is_in_group);
 	ObjectTypeDB::bind_method(_MD("is_in_group","group"),&Node::is_in_group);
 	ObjectTypeDB::bind_method(_MD("move_child","child_node:Node","to_pos"),&Node::move_child);
 	ObjectTypeDB::bind_method(_MD("move_child","child_node:Node","to_pos"),&Node::move_child);
+	ObjectTypeDB::bind_method(_MD("get_groups"),&Node::_get_groups);
 	ObjectTypeDB::bind_method(_MD("raise"),&Node::raise);
 	ObjectTypeDB::bind_method(_MD("raise"),&Node::raise);
 	ObjectTypeDB::bind_method(_MD("set_owner","owner:Node"),&Node::set_owner);
 	ObjectTypeDB::bind_method(_MD("set_owner","owner:Node"),&Node::set_owner);
 	ObjectTypeDB::bind_method(_MD("get_owner:Node"),&Node::get_owner);
 	ObjectTypeDB::bind_method(_MD("get_owner:Node"),&Node::get_owner);

+ 1 - 0
scene/main/node.h

@@ -125,6 +125,7 @@ private:
 
 
 	void _duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_reown_map) const;
 	void _duplicate_and_reown(Node* p_new_parent, const Map<Node*,Node*>& p_reown_map) const;
 	Array _get_children() const;
 	Array _get_children() const;
+	Array _get_groups() const;
 
 
 friend class SceneMainLoop;
 friend class SceneMainLoop;
 
 

+ 2 - 0
scene/register_scene_types.cpp

@@ -140,6 +140,7 @@
 #include "scene/resources/mesh_library.h"
 #include "scene/resources/mesh_library.h"
 
 
 #include "scene/resources/image_path_finder.h"
 #include "scene/resources/image_path_finder.h"
+#include "scene/resources/polygon_path_finder.h"
 
 
 #include "scene/resources/sample.h"
 #include "scene/resources/sample.h"
 #include "scene/audio/sample_player.h"
 #include "scene/audio/sample_player.h"
@@ -536,6 +537,7 @@ void register_scene_types() {
 	ObjectTypeDB::register_type<StyleBoxImageMask>();
 	ObjectTypeDB::register_type<StyleBoxImageMask>();
 	ObjectTypeDB::register_type<Theme>();
 	ObjectTypeDB::register_type<Theme>();
 	ObjectTypeDB::register_type<ImagePathFinder>();
 	ObjectTypeDB::register_type<ImagePathFinder>();
+	ObjectTypeDB::register_type<PolygonPathFinder>();
 	ObjectTypeDB::register_type<BitMap>();
 	ObjectTypeDB::register_type<BitMap>();
 
 
 	OS::get_singleton()->yield(); //may take time to init
 	OS::get_singleton()->yield(); //may take time to init

+ 4 - 5
scene/resources/environment.cpp

@@ -140,8 +140,8 @@ void Environment::_bind_methods() {
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/brightness",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_BRIGHTNESS);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/brightness",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_BRIGHTNESS);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/contrast",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_CONTRAST);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/contrast",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_CONTRAST);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/saturation",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_SATURATION);
 	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"bcs/saturation",PROPERTY_HINT_RANGE,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_BCS_SATURATION);
-	ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"gamma/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_GAMMA);
-	ADD_PROPERTYI( PropertyInfo(Variant::REAL,"gamma/gamma",PROPERTY_HINT_EXP_EASING,"0.01,8,0.01"),_SCS("fx_set_param"),_SCS("fx_get_param"), FX_PARAM_GAMMA);
+	ADD_PROPERTYI( PropertyInfo(Variant::BOOL,"srgb/enabled"),_SCS("set_enable_fx"),_SCS("is_fx_enabled"), FX_SRGB);
+
 
 
 
 
 
 
@@ -194,7 +194,7 @@ void Environment::_bind_methods() {
 	BIND_CONSTANT( FX_HDR );
 	BIND_CONSTANT( FX_HDR );
 	BIND_CONSTANT( FX_FOG );
 	BIND_CONSTANT( FX_FOG );
 	BIND_CONSTANT( FX_BCS);
 	BIND_CONSTANT( FX_BCS);
-	BIND_CONSTANT( FX_GAMMA );
+	BIND_CONSTANT( FX_SRGB );
 	BIND_CONSTANT( FX_MAX );
 	BIND_CONSTANT( FX_MAX );
 
 
 
 
@@ -226,7 +226,6 @@ void Environment::_bind_methods() {
 	BIND_CONSTANT( FX_PARAM_BCS_BRIGHTNESS );
 	BIND_CONSTANT( FX_PARAM_BCS_BRIGHTNESS );
 	BIND_CONSTANT( FX_PARAM_BCS_CONTRAST );
 	BIND_CONSTANT( FX_PARAM_BCS_CONTRAST );
 	BIND_CONSTANT( FX_PARAM_BCS_SATURATION );
 	BIND_CONSTANT( FX_PARAM_BCS_SATURATION );
-	BIND_CONSTANT( FX_PARAM_GAMMA );
 	BIND_CONSTANT( FX_PARAM_MAX );
 	BIND_CONSTANT( FX_PARAM_MAX );
 
 
 }
 }
@@ -269,7 +268,7 @@ Environment::Environment() {
 	fx_set_param(FX_PARAM_BCS_BRIGHTNESS,1.0);
 	fx_set_param(FX_PARAM_BCS_BRIGHTNESS,1.0);
 	fx_set_param(FX_PARAM_BCS_CONTRAST,1.0);
 	fx_set_param(FX_PARAM_BCS_CONTRAST,1.0);
 	fx_set_param(FX_PARAM_BCS_SATURATION,1.0);
 	fx_set_param(FX_PARAM_BCS_SATURATION,1.0);
-	fx_set_param(FX_PARAM_GAMMA,1.0);
+
 }
 }
 Environment::~Environment() {
 Environment::~Environment() {
 
 

+ 1 - 2
scene/resources/environment.h

@@ -67,7 +67,7 @@ public:
 		FX_HDR=VS::ENV_FX_HDR,
 		FX_HDR=VS::ENV_FX_HDR,
 		FX_FOG=VS::ENV_FX_FOG,
 		FX_FOG=VS::ENV_FX_FOG,
 		FX_BCS=VS::ENV_FX_BCS,
 		FX_BCS=VS::ENV_FX_BCS,
-		FX_GAMMA=VS::ENV_FX_GAMMA,
+		FX_SRGB=VS::ENV_FX_SRGB,
 		FX_MAX=VS::ENV_FX_MAX,
 		FX_MAX=VS::ENV_FX_MAX,
 	};
 	};
 
 
@@ -102,7 +102,6 @@ public:
 		FX_PARAM_BCS_BRIGHTNESS=VS::ENV_FX_PARAM_BCS_BRIGHTNESS,
 		FX_PARAM_BCS_BRIGHTNESS=VS::ENV_FX_PARAM_BCS_BRIGHTNESS,
 		FX_PARAM_BCS_CONTRAST=VS::ENV_FX_PARAM_BCS_CONTRAST,
 		FX_PARAM_BCS_CONTRAST=VS::ENV_FX_PARAM_BCS_CONTRAST,
 		FX_PARAM_BCS_SATURATION=VS::ENV_FX_PARAM_BCS_SATURATION,
 		FX_PARAM_BCS_SATURATION=VS::ENV_FX_PARAM_BCS_SATURATION,
-		FX_PARAM_GAMMA=VS::ENV_FX_PARAM_GAMMA,
 		FX_PARAM_MAX=VS::ENV_FX_PARAM_MAX
 		FX_PARAM_MAX=VS::ENV_FX_PARAM_MAX
 	};
 	};
 private:
 private:

+ 413 - 0
scene/resources/polygon_path_finder.cpp

@@ -0,0 +1,413 @@
+#include "polygon_path_finder.h"
+#include "geometry.h"
+
+
+bool PolygonPathFinder::_is_point_inside(const Vector2& p_point) {
+
+	int crosses=0;
+
+
+	for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
+
+
+		const Edge& e=E->get();
+
+		Vector2 a = points[e.points[0]].pos;
+		Vector2 b = points[e.points[1]].pos;
+
+
+		if (Geometry::segment_intersects_segment_2d(a,b,p_point,outside_point,NULL)) {
+			crosses++;
+		}
+	}
+
+	return crosses&1;
+}
+
+void PolygonPathFinder::setup(const Vector<Vector2>& p_points, const Vector<int>& p_connections) {
+
+
+	ERR_FAIL_COND(p_connections.size()&1);
+
+	points.clear();
+	edges.clear();
+
+	//insert points
+
+	int point_count=p_points.size();
+	points.resize(point_count+2);
+
+	for(int i=0;i<p_points.size();i++) {
+
+		points[i].pos=p_points[i];
+
+		outside_point.x = i==0?p_points[0].x:(MAX( p_points[i].x, outside_point.x ));
+		outside_point.y = i==0?p_points[0].y:(MAX( p_points[i].y, outside_point.y ));
+	}
+
+	outside_point.x+=20.451+Math::randf()*10.2039;
+	outside_point.y+=21.193+Math::randf()*12.5412;
+
+	//insert edges (which are also connetions)
+
+	for(int i=0;i<p_connections.size();i+=2) {
+
+		Edge e(p_connections[i],p_connections[i+1]);
+		ERR_FAIL_INDEX(e.points[0],point_count);
+		ERR_FAIL_INDEX(e.points[1],point_count);
+		points[p_connections[i]].connections.insert(p_connections[i+1]);
+		points[p_connections[i+1]].connections.insert(p_connections[i]);
+		edges.insert(e);
+	}
+
+
+	//fill the remaining connections based on visibility
+
+	for(int i=0;i<point_count;i++) {
+
+		for(int j=i+1;j<point_count;j++) {
+
+			if (edges.has(Edge(i,j)))
+				continue; //if in edge ignore
+
+			Vector2 from=points[i].pos;
+			Vector2 to=points[j].pos;
+
+			if (!_is_point_inside(from*0.5+to*0.5)) //connection between points in inside space
+				continue;
+
+			bool valid=true;
+
+			for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
+
+				const Edge& e=E->get();
+				if (e.points[0]==i || e.points[1]==i || e.points[0]==j || e.points[1]==j )
+					continue;
+
+
+				Vector2 a = points[e.points[0]].pos;
+				Vector2 b = points[e.points[1]].pos;
+
+
+				if (Geometry::segment_intersects_segment_2d(a,b,from,to,NULL)) {
+					valid=false;
+					break;
+				}
+
+			}
+
+			if (valid) {
+				points[i].connections.insert(j);
+				points[j].connections.insert(i);
+			}
+		}
+	}
+}
+
+
+Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector2& p_to) {
+
+	Vector<Vector2> path;
+	if (!_is_point_inside(p_from))
+		return path;
+	if (!_is_point_inside(p_to))
+		return path;
+
+	//test direct connection
+	{
+
+		bool can_see_eachother=true;
+
+		for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
+
+			const Edge& e=E->get();
+			Vector2 a = points[e.points[0]].pos;
+			Vector2 b = points[e.points[1]].pos;
+
+
+			if (Geometry::segment_intersects_segment_2d(a,b,p_from,p_to,NULL)) {
+				can_see_eachother=false;
+				break;
+			}
+
+		}
+
+		if (can_see_eachother) {
+
+			path.push_back(p_from);
+			path.push_back(p_to);
+			return path;
+		}
+	}
+
+	//add to graph
+
+	int aidx = points.size()-2;
+	int bidx = points.size()-1;
+	points[aidx].pos=p_from;
+	points[bidx].pos=p_to;
+	points[aidx].distance=0;
+	points[bidx].distance=0;
+	points[aidx].distance=0;
+	points[bidx].distance=0;
+
+
+	for(int i=0;i<points.size()-2;i++) {
+
+
+		bool valid_a=true;
+		bool valid_b=true;
+		points[i].prev=-1;
+		points[i].distance=0;
+
+		for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
+
+			const Edge& e=E->get();
+
+			if (e.points[0]==i || e.points[1]==i)
+				continue;
+
+			Vector2 a = points[e.points[0]].pos;
+			Vector2 b = points[e.points[1]].pos;
+
+			if (valid_a) {
+
+				if (Geometry::segment_intersects_segment_2d(a,b,p_from,points[i].pos,NULL)) {
+					valid_a=false;
+				}
+			}
+
+			if (valid_b) {
+
+				if (Geometry::segment_intersects_segment_2d(a,b,p_to,points[i].pos,NULL)) {
+					valid_b=false;
+				}
+			}
+
+			if (!valid_a && !valid_b)
+				continue;
+
+		}
+
+		if (valid_a) {
+			points[i].connections.insert(aidx);
+			points[aidx].connections.insert(i);
+		}
+
+		if (valid_b) {
+			points[i].connections.insert(bidx);
+			points[bidx].connections.insert(i);
+		}
+
+	}
+	//solve graph
+
+	Set<int> open_list;
+
+	points[aidx].distance=0;
+	points[aidx].prev=aidx;
+	for(Set<int>::Element *E=points[aidx].connections.front();E;E=E->next()) {
+
+		open_list.insert(E->get());
+		points[E->get()].distance=p_from.distance_to(points[E->get()].pos);
+		points[E->get()].prev=aidx;
+
+	}
+
+
+	bool found_route=false;
+
+	while(true) {
+
+		if (open_list.size()==0) {
+			break;
+		}
+		//check open list
+
+		int least_cost_point=-1;
+		float least_cost=1e30;
+
+		//this could be faster (cache previous results)
+		for (Set<int>::Element *E=open_list.front();E;E=E->next()) {
+
+			const Point& p =points[E->get()];
+			float cost = p.distance;
+			cost+=p.pos.distance_to(p_to);
+			if (cost<least_cost) {
+
+				least_cost_point=E->get();
+				least_cost=cost;
+			}
+		}
+
+
+		Point &np = points[least_cost_point];
+		//open the neighbours for search
+
+		for(Set<int>::Element *E=np.connections.front();E;E=E->next()) {
+
+			Point& p =points[E->get()];
+			float distance = np.pos.distance_to(p.pos) + np.distance;
+
+			if (p.prev!=-1) {
+				//oh this was visited already, can we win the cost?
+
+				if (p.distance>distance) {
+
+					p.prev=least_cost_point; //reasign previous
+					p.distance=distance;
+				}
+			} else {
+				//add to open neighbours
+
+				p.prev=least_cost_point;
+				p.distance=distance;
+				open_list.insert(E->get());
+
+				if (E->get()==bidx) {
+					//oh my reached end! stop algorithm
+					found_route=true;
+					break;
+
+				}
+
+			}
+		}
+
+		if (found_route)
+			break;
+
+		open_list.erase(least_cost_point);
+	}
+
+	if (found_route) {
+		int at = bidx;
+		path.push_back(points[at].pos);
+		do {
+			at=points[at].prev;
+			path.push_back(points[at].pos);
+		} while (at!=aidx);
+
+		path.invert();;
+	}
+
+	for(int i=0;i<points.size()-2;i++) {
+
+		points[i].connections.erase(aidx);
+		points[i].connections.erase(bidx);
+		points[i].prev=-1;
+		points[i].distance=0;
+	}
+
+	points[aidx].connections.clear();
+	points[aidx].prev=-1;
+	points[aidx].distance=0;
+	points[bidx].connections.clear();
+	points[bidx].prev=-1;
+	points[bidx].distance=0;
+
+	return path;
+}
+
+void PolygonPathFinder::_set_data(const Dictionary& p_data) {
+
+
+	ERR_FAIL_COND(!p_data.has("points"));
+	ERR_FAIL_COND(!p_data.has("connections"));
+	ERR_FAIL_COND(!p_data.has("segments"));
+
+	DVector<Vector2> p=p_data["points"];
+	Array c=p_data["connections"];
+
+	ERR_FAIL_COND(c.size()!=p.size());
+	if (c.size())
+		return;
+
+	int pc = p.size();
+	points.resize(pc+2);
+
+	DVector<Vector2>::Read pr=p.read();
+	for(int i=0;i<pc;i++) {
+		points[i].pos=pr[i];
+		DVector<int> con=c[i];
+		DVector<int>::Read cr=con.read();
+		int cc=con.size();
+		for(int j=0;j<cc;j++) {
+
+			points[i].connections.insert(cr[j]);
+		}
+
+	}
+
+	DVector<int> segs=p_data["segments"];
+	int sc=segs.size();
+	ERR_FAIL_COND(sc&1);
+	DVector<int>::Read sr = segs.read();
+	for(int i=0;i<sc;i+=2) {
+
+		Edge e(sr[i],sr[i+1]);
+		edges.insert(e);
+	}
+
+}
+
+Dictionary PolygonPathFinder::_get_data() const{
+
+	Dictionary d;
+	DVector<Vector2> p;
+	DVector<int> ind;
+	Array connections;
+	p.resize(points.size()-2);
+	connections.resize(points.size()-2);
+	ind.resize(edges.size()*2);
+	{
+		DVector<Vector2>::Write wp=p.write();
+		for(int i=0;i<points.size()-2;i++) {
+			wp[i]=points[i].pos;
+			DVector<int> c;
+			c.resize(points[i].connections.size());
+			{
+				DVector<int>::Write cw=c.write();
+				int idx=0;
+				for (Set<int>::Element *E=points[i].connections.front();E;E=E->next()) {
+					cw[idx++]=E->get();
+				}
+			}
+			connections[i]=c;
+		}
+	}
+	{
+
+		DVector<int>::Write iw=ind.write();
+		int idx=0;
+		for (Set<Edge>::Element *E=edges.front();E;E=E->next()) {
+			iw[idx++]=E->get().points[0];
+			iw[idx++]=E->get().points[1];
+		}
+
+	}
+
+	d["points"]=p;
+	d["connections"]=connections;
+	d["segments"]=ind;
+
+	return d;
+
+}
+
+void PolygonPathFinder::_bind_methods() {
+
+	ObjectTypeDB::bind_method(_MD("setup","points","connections"),&PolygonPathFinder::setup);
+	ObjectTypeDB::bind_method(_MD("find_path","from","to"),&PolygonPathFinder::find_path);
+	ObjectTypeDB::bind_method(_MD("_set_data"),&PolygonPathFinder::_set_data);
+	ObjectTypeDB::bind_method(_MD("_get_data"),&PolygonPathFinder::_get_data);
+
+	ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY,"data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR),_SCS("_set_data"),_SCS("_get_data"));
+
+}
+
+PolygonPathFinder::PolygonPathFinder()
+{
+}
+
+

+ 58 - 0
scene/resources/polygon_path_finder.h

@@ -0,0 +1,58 @@
+#ifndef POLYGON_PATH_FINDER_H
+#define POLYGON_PATH_FINDER_H
+
+#include "resource.h"
+
+class PolygonPathFinder : public Resource {
+
+	OBJ_TYPE(PolygonPathFinder,Resource);
+
+	struct Point {
+		Vector2 pos;
+		Set<int> connections;
+		float distance;
+		int prev;
+	};
+
+	struct Edge {
+
+		int points[2];
+
+		_FORCE_INLINE_ bool operator<(const Edge& p_edge) const {
+
+			if (points[0]==p_edge.points[0])
+				return points[1]<p_edge.points[1];
+			else
+				return points[0]<p_edge.points[0];
+		}
+
+		Edge(int a=0, int b=0) {
+
+			if (a>b) {
+				SWAP(a,b);
+			}
+		}
+	};
+
+	Vector2 outside_point;
+
+	Vector<Point> points;
+	Set<Edge> edges;
+
+	bool _is_point_inside(const Vector2& p_point);
+
+	void _set_data(const Dictionary& p_data);
+	Dictionary _get_data() const;
+protected:
+
+	static void _bind_methods();
+public:
+
+
+	void setup(const Vector<Vector2>& p_points, const Vector<int>& p_connections);
+	Vector<Vector2> find_path(const Vector2& p_from, const Vector2& p_to);
+
+	PolygonPathFinder();
+};
+
+#endif // POLYGON_PATH_FINDER_H

+ 2 - 0
servers/visual/rasterizer.h

@@ -167,6 +167,7 @@ public:
 	};
 	};
 
 
 
 
+
 	/* TEXTURE API */
 	/* TEXTURE API */
 
 
 	virtual RID texture_create()=0;
 	virtual RID texture_create()=0;
@@ -455,6 +456,7 @@ public:
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const=0;
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const=0;
 	virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0)=0;
 	virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0)=0;
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const=0;
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const=0;
+	virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const=0;
 
 
 	/* SHADOWS */
 	/* SHADOWS */
 
 

+ 6 - 0
servers/visual/rasterizer_dummy.cpp

@@ -1371,6 +1371,12 @@ int RasterizerDummy::light_instance_get_shadow_passes(RID p_light_instance) cons
 	return 0;
 	return 0;
 }
 }
 
 
+bool RasterizerDummy::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const {
+
+	return false;
+}
+
+
 void RasterizerDummy::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
 void RasterizerDummy::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
 
 
 	LightInstance *lighti = light_instance_owner.get( p_light_instance );
 	LightInstance *lighti = light_instance_owner.get( p_light_instance );

+ 2 - 1
servers/visual/rasterizer_dummy.h

@@ -345,7 +345,7 @@ class RasterizerDummy : public Rasterizer {
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
 			fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
-			fx_param[VS::ENV_FX_PARAM_GAMMA]=1.0;
+
 
 
 		}
 		}
 
 
@@ -628,6 +628,7 @@ public:
 	virtual bool light_instance_assign_shadow(RID p_light_instance);
 	virtual bool light_instance_assign_shadow(RID p_light_instance);
 	virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const;
 	virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const;
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const;
 	virtual int light_instance_get_shadow_passes(RID p_light_instance) const;
+	virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const;
 	virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
 	virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; }
 	virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; }
 
 

+ 4 - 2
servers/visual/visual_server_raster.cpp

@@ -3970,6 +3970,8 @@ void VisualServerRaster::_light_instance_update_pssm_shadow(Instance *p_light,Sc
 	//float cull_max=p_cull_range.max;
 	//float cull_max=p_cull_range.max;
 
 
 	
 	
+	bool overlap = 	rasterizer->light_instance_get_pssm_shadow_overlap(p_light->light_info->instance);
+
 	float cull_min=p_camera->znear;
 	float cull_min=p_camera->znear;
 	float cull_max=p_camera->zfar;
 	float cull_max=p_camera->zfar;
 	float max_dist = rasterizer->light_directional_get_shadow_param(p_light->base_rid,VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE);
 	float max_dist = rasterizer->light_directional_get_shadow_param(p_light->base_rid,VS::LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE);
@@ -3999,7 +4001,7 @@ void VisualServerRaster::_light_instance_update_pssm_shadow(Instance *p_light,Sc
 				camera_matrix.set_orthogonal(
 				camera_matrix.set_orthogonal(
 					p_camera->size,
 					p_camera->size,
 					viewport_rect.width / (float)viewport_rect.height,
 					viewport_rect.width / (float)viewport_rect.height,
-					distances[i],
+					distances[(i==0 || !overlap )?i:i-1],
 					distances[i+1],
 					distances[i+1],
 					p_camera->vaspect
 					p_camera->vaspect
 
 
@@ -4011,7 +4013,7 @@ void VisualServerRaster::_light_instance_update_pssm_shadow(Instance *p_light,Sc
 				camera_matrix.set_perspective(
 				camera_matrix.set_perspective(
 					p_camera->fov,
 					p_camera->fov,
 					viewport_rect.width / (float)viewport_rect.height,
 					viewport_rect.width / (float)viewport_rect.height,
-					distances[i],
+					distances[(i==0 || !overlap )?i:i-1],
 					distances[i+1],
 					distances[i+1],
 					p_camera->vaspect
 					p_camera->vaspect
 
 

+ 2 - 0
servers/visual/visual_server_wrap_mt.cpp

@@ -165,6 +165,7 @@ void VisualServerWrapMT::finish() {
 
 
 
 
 		texture_free_cached_ids();
 		texture_free_cached_ids();
+		mesh_free_cached_ids();
 
 
 		thread=NULL;
 		thread=NULL;
 	} else {
 	} else {
@@ -187,6 +188,7 @@ VisualServerWrapMT::VisualServerWrapMT(VisualServer* p_contained,bool p_create_t
 	draw_thread_up=false;
 	draw_thread_up=false;
 	alloc_mutex=Mutex::create();
 	alloc_mutex=Mutex::create();
 	texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",20);
 	texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",20);
+	mesh_pool_max_size=GLOBAL_DEF("render/thread_meshes_prealloc",20);
 	if (!p_create_thread) {
 	if (!p_create_thread) {
 		server_thread=Thread::get_caller_ID();
 		server_thread=Thread::get_caller_ID();
 	} else {
 	} else {

+ 26 - 2
servers/visual/visual_server_wrap_mt.h

@@ -66,6 +66,16 @@ class VisualServerWrapMT : public VisualServer {
 	int texture_pool_max_size;
 	int texture_pool_max_size;
 	List<RID> texture_id_pool;
 	List<RID> texture_id_pool;
 
 
+	int mesh_pool_max_size;
+	List<RID> mesh_id_pool;
+
+//#define DEBUG_SYNC
+
+#ifdef DEBUG_SYNC
+#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__));
+#else
+#define SYNC_DEBUG
+#endif
 
 
 public:
 public:
 
 
@@ -74,6 +84,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type();\
 			return visual_server->m_type();\
@@ -115,6 +126,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type();\
 			return visual_server->m_type();\
@@ -168,6 +180,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1);\
 			return visual_server->m_type(p1);\
@@ -179,6 +192,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1);\
 			return visual_server->m_type(p1);\
@@ -231,6 +245,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2);\
 			return visual_server->m_type(p1, p2);\
@@ -242,6 +257,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2);\
 			return visual_server->m_type(p1, p2);\
@@ -294,6 +310,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3);\
 			return visual_server->m_type(p1, p2, p3);\
@@ -357,6 +374,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3, p4);\
 			return visual_server->m_type(p1, p2, p3, p4);\
@@ -368,6 +386,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3, p4);\
 			return visual_server->m_type(p1, p2, p3, p4);\
@@ -420,6 +439,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3, p4, p5);\
 			return visual_server->m_type(p1, p2, p3, p4, p5);\
@@ -431,6 +451,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3, p4, p5);\
 			return visual_server->m_type(p1, p2, p3, p4, p5);\
@@ -483,6 +504,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3, p4, p5, p6);\
 			return visual_server->m_type(p1, p2, p3, p4, p5, p6);\
@@ -546,6 +568,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\
 			return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\
@@ -557,6 +580,7 @@ public:
 		if (Thread::get_caller_ID()!=server_thread) {\
 		if (Thread::get_caller_ID()!=server_thread) {\
 			m_r ret;\
 			m_r ret;\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\
 			command_queue.push_and_ret( visual_server, &VisualServer::m_type,p1, p2, p3, p4, p5, p6, p7,&ret);\
+			SYNC_DEBUG\
 			return ret;\
 			return ret;\
 		} else {\
 		} else {\
 			return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\
 			return visual_server->m_type(p1, p2, p3, p4, p5, p6, p7);\
@@ -691,7 +715,7 @@ public:
 	FUNC1RC(float,fixed_material_get_point_size,RID);
 	FUNC1RC(float,fixed_material_get_point_size,RID);
 
 
 	/* SURFACE API */
 	/* SURFACE API */
-	FUNC0R(RID,mesh_create);
+	FUNCRID(mesh);
 
 
 	FUNC2(mesh_set_morph_target_count,RID,int);
 	FUNC2(mesh_set_morph_target_count,RID,int);
 	FUNC1RC(int,mesh_get_morph_target_count,RID);
 	FUNC1RC(int,mesh_get_morph_target_count,RID);
@@ -1122,7 +1146,7 @@ public:
 	/* RENDER INFO */
 	/* RENDER INFO */
 
 
 	FUNC1R(int,get_render_info,RenderInfo );
 	FUNC1R(int,get_render_info,RenderInfo );
-	FUNC1RC(bool,has_feature,Features );
+	virtual bool has_feature(Features p_feature) const { return visual_server->has_feature(p_feature); }
 
 
 	FUNC2(set_boot_image,const Image& , const Color& );
 	FUNC2(set_boot_image,const Image& , const Color& );
 	FUNC1(set_default_clear_color,const Color& );
 	FUNC1(set_default_clear_color,const Color& );

+ 3 - 2
servers/visual_server.h

@@ -481,6 +481,8 @@ public:
 		LIGHT_PARAM_SHADOW_DARKENING,
 		LIGHT_PARAM_SHADOW_DARKENING,
 		LIGHT_PARAM_SHADOW_Z_OFFSET,
 		LIGHT_PARAM_SHADOW_Z_OFFSET,
 		LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
 		LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
+		LIGHT_PARAM_SHADOW_ESM_MULTIPLIER,
+		LIGHT_PARAM_SHADOW_BLUR_PASSES,
 		LIGHT_PARAM_MAX
 		LIGHT_PARAM_MAX
 	};
 	};
 
 
@@ -728,7 +730,7 @@ public:
 		ENV_FX_HDR,
 		ENV_FX_HDR,
 		ENV_FX_FOG,
 		ENV_FX_FOG,
 		ENV_FX_BCS,
 		ENV_FX_BCS,
-		ENV_FX_GAMMA,
+		ENV_FX_SRGB,
 		ENV_FX_MAX
 		ENV_FX_MAX
 	};
 	};
 
 
@@ -768,7 +770,6 @@ public:
 		ENV_FX_PARAM_BCS_BRIGHTNESS,
 		ENV_FX_PARAM_BCS_BRIGHTNESS,
 		ENV_FX_PARAM_BCS_CONTRAST,
 		ENV_FX_PARAM_BCS_CONTRAST,
 		ENV_FX_PARAM_BCS_SATURATION,
 		ENV_FX_PARAM_BCS_SATURATION,
-		ENV_FX_PARAM_GAMMA,
 		ENV_FX_PARAM_MAX
 		ENV_FX_PARAM_MAX
 	};
 	};
 
 

+ 1 - 1
tools/editor/editor_node.cpp

@@ -4067,7 +4067,7 @@ EditorNode::EditorNode() {
 
 
 
 
 	import_menu->get_popup()->add_separator();
 	import_menu->get_popup()->add_separator();
-	import_menu->get_popup()->add_item("Import Settings",SETTINGS_IMPORT);
+	import_menu->get_popup()->add_item("Re-Import..",SETTINGS_IMPORT);
 
 
 	editor_plugin_screen=NULL;
 	editor_plugin_screen=NULL;
 	editor_plugin_over=NULL;
 	editor_plugin_over=NULL;

+ 11 - 0
tools/editor/io_plugins/editor_texture_import_plugin.cpp

@@ -45,6 +45,7 @@ static const char *flag_names[]={
 	"Repeat",
 	"Repeat",
 	"Filter (Magnifying)",
 	"Filter (Magnifying)",
 	"Premultiply Alpha",
 	"Premultiply Alpha",
+	"Convert SRGB->Linear",
 	NULL
 	NULL
 };
 };
 
 
@@ -57,6 +58,7 @@ static const char *flag_short_names[]={
 	"Repeat",
 	"Repeat",
 	"Filter",
 	"Filter",
 	"PMAlpha",
 	"PMAlpha",
+	"ToLinear",
 	NULL
 	NULL
 };
 };
 
 
@@ -927,6 +929,10 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
 			image.premultiply_alpha();
 			image.premultiply_alpha();
 		}
 		}
 
 
+		if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+
+			image.srgb_to_linear();
+		}
 
 
 		if (shrink>1) {
 		if (shrink>1) {
 
 
@@ -985,6 +991,11 @@ Error EditorTextureImportPlugin::import2(const String& p_path, const Ref<Resourc
 			image.premultiply_alpha();
 			image.premultiply_alpha();
 		}
 		}
 
 
+		if ((image.get_format()==Image::FORMAT_RGB || image.get_format()==Image::FORMAT_RGBA) && flags&IMAGE_FLAG_CONVERT_TO_LINEAR) {
+
+			image.srgb_to_linear();
+		}
+
 		int orig_w=image.get_width();
 		int orig_w=image.get_width();
 		int orig_h=image.get_height();
 		int orig_h=image.get_height();
 
 

+ 2 - 1
tools/editor/io_plugins/editor_texture_import_plugin.h

@@ -92,7 +92,8 @@ public:
 		IMAGE_FLAG_NO_MIPMAPS=16, //normal for 2D games
 		IMAGE_FLAG_NO_MIPMAPS=16, //normal for 2D games
 		IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
 		IMAGE_FLAG_REPEAT=32, //usually disabled in 2D
 		IMAGE_FLAG_FILTER=64, //almost always enabled
 		IMAGE_FLAG_FILTER=64, //almost always enabled
-		IMAGE_FLAG_PREMULT_ALPHA=128//almost always enabled
+		IMAGE_FLAG_PREMULT_ALPHA=128,//almost always enabled
+		IMAGE_FLAG_CONVERT_TO_LINEAR=256 //convert image to linear
 	};
 	};
 
 
 	virtual String get_name() const;
 	virtual String get_name() const;

+ 8 - 6
tools/editor/plugins/baked_light_baker.cpp

@@ -912,12 +912,6 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
 		Color diffuse_at_point(0.8,0.8,0.8);
 		Color diffuse_at_point(0.8,0.8,0.8);
 		Color specular_at_point(0.0,0.0,0.0);
 		Color specular_at_point(0.0,0.0,0.0);
 
 
-		if (triangle->material) {
-
-			//triangle->get_uv(r_point);
-			diffuse_at_point=triangle->material->diffuse.get_color(uv);
-			specular_at_point=triangle->material->specular.get_color(uv);
-		}
 
 
 		float dist = p_begin.distance_to(r_point);
 		float dist = p_begin.distance_to(r_point);
 
 
@@ -963,6 +957,14 @@ float BakedLightBaker::_throw_ray(int p_light_index,const Vector3& p_begin, cons
 
 
 
 
 
 
+			if (triangle->material) {
+
+				//triangle->get_uv(r_point);
+
+				diffuse_at_point=triangle->material->diffuse.get_color(uv);
+				specular_at_point=triangle->material->specular.get_color(uv);
+			}
+
 
 
 			diffuse_at_point.r=res_light.r*diffuse_at_point.r;
 			diffuse_at_point.r=res_light.r*diffuse_at_point.r;
 			diffuse_at_point.g=res_light.g*diffuse_at_point.g;
 			diffuse_at_point.g=res_light.g*diffuse_at_point.g;

+ 1 - 1
tools/editor/plugins/baked_light_editor_plugin.cpp

@@ -111,7 +111,7 @@ void BakedLightEditor::_notification(int p_option) {
 				ERR_FAIL_COND(node->get_baked_light().is_null());
 				ERR_FAIL_COND(node->get_baked_light().is_null());
 
 
 				baker->update_octree_image(octree_texture);
 				baker->update_octree_image(octree_texture);
-#if 0
+#if 1
 //debug
 //debug
 				Image img(baker->baked_octree_texture_w,baker->baked_octree_texture_h,0,Image::FORMAT_RGBA,octree_texture);
 				Image img(baker->baked_octree_texture_w,baker->baked_octree_texture_h,0,Image::FORMAT_RGBA,octree_texture);
 				Ref<ImageTexture> it = memnew( ImageTexture );
 				Ref<ImageTexture> it = memnew( ImageTexture );