Browse Source

Screen space reflection effect

Juan Linietsky 8 years ago
parent
commit
a47c78aed1

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

@@ -71,6 +71,11 @@ uniform sampler2D source;
 #endif
 #endif
 varying vec2 uv2_interp;
 varying vec2 uv2_interp;
 
 
+
+#ifdef USE_DEPTH
+uniform highp sampler2D source_depth; //texunit:1
+#endif
+
 #ifdef USE_GLOW
 #ifdef USE_GLOW
 
 
 uniform sampler2D glow_source;
 uniform sampler2D glow_source;
@@ -547,5 +552,10 @@ void main() {
 
 
 
 
         gl_FragColor = color;
         gl_FragColor = color;
+
+#ifdef USE_DEPTH
+	gl_FragDepth = texture(source_depth,uv_interp).r;
+#endif
+
 }
 }
 
 

+ 1 - 1
drivers/gles3/rasterizer_canvas_gles3.cpp

@@ -1349,7 +1349,7 @@ void RasterizerCanvasGLES3::reset_canvas() {
 
 
 
 
 	if (storage->frame.current_rt) {
 	if (storage->frame.current_rt) {
-		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->front.fbo);
+		glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo);
 		glColorMask(1,1,1,1); //don't touch alpha
 		glColorMask(1,1,1,1); //don't touch alpha
 	}
 	}
 
 

+ 3 - 3
drivers/gles3/rasterizer_gles3.cpp

@@ -178,7 +178,7 @@ void RasterizerGLES3::set_current_render_target(RID p_render_target){
 
 
 	if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
 	if (!p_render_target.is_valid() && storage->frame.current_rt && storage->frame.clear_request) {
 		//handle pending clear request, if the framebuffer was not cleared
 		//handle pending clear request, if the framebuffer was not cleared
-		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
+		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
 		print_line("unbind clear of: "+storage->frame.clear_request_color);
 		print_line("unbind clear of: "+storage->frame.clear_request_color);
 		glClearColor(
 		glClearColor(
 			storage->frame.clear_request_color.r,
 			storage->frame.clear_request_color.r,
@@ -213,7 +213,7 @@ void RasterizerGLES3::restore_render_target() {
 
 
 	ERR_FAIL_COND(storage->frame.current_rt==NULL);
 	ERR_FAIL_COND(storage->frame.current_rt==NULL);
 	RasterizerStorageGLES3::RenderTarget * rt = storage->frame.current_rt;
 	RasterizerStorageGLES3::RenderTarget * rt = storage->frame.current_rt;
-	glBindFramebuffer(GL_FRAMEBUFFER,rt->front.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER,rt->fbo);
 	glViewport(0,0,rt->width,rt->height);
 	glViewport(0,0,rt->width,rt->height);
 
 
 }
 }
@@ -238,7 +238,7 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target,const Rec
 	glDisable(GL_BLEND);
 	glDisable(GL_BLEND);
 	glBindFramebuffer(GL_FRAMEBUFFER,storage->config.system_fbo);
 	glBindFramebuffer(GL_FRAMEBUFFER,storage->config.system_fbo);
 	glActiveTexture(GL_TEXTURE0);
 	glActiveTexture(GL_TEXTURE0);
-	glBindTexture(GL_TEXTURE_2D,rt->front.color);
+	glBindTexture(GL_TEXTURE_2D,rt->color);
 	canvas->draw_generic_textured_rect(p_screen_rect,Rect2(0,0,1,-1));
 	canvas->draw_generic_textured_rect(p_screen_rect,Rect2(0,0,1,-1));
 	glBindTexture(GL_TEXTURE_2D,0);
 	glBindTexture(GL_TEXTURE_2D,0);
 	canvas->canvas_end();
 	canvas->canvas_end();

+ 164 - 8
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -857,6 +857,21 @@ void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_b
 
 
 }
 }
 
 
+void RasterizerSceneGLES3::environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness) {
+
+	Environment *env=environment_owner.getornull(p_env);
+	ERR_FAIL_COND(!env);
+
+	env->ssr_enabled=p_enable;
+	env->ssr_max_steps=p_max_steps;
+	env->ssr_accel=p_accel;
+	env->ssr_fade=p_fade;
+	env->ssr_depth_tolerance=p_depth_tolerance;
+	env->ssr_smooth=p_smooth;
+	env->ssr_roughness=p_roughness;
+
+}
+
 void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){
 void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){
 
 
 }
 }
@@ -2538,7 +2553,7 @@ void RasterizerSceneGLES3::_copy_screen() {
 void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
 void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
 
 
 	//copy to front buffer
 	//copy to front buffer
-	glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
 
 
 	glDepthMask(GL_FALSE);
 	glDepthMask(GL_FALSE);
 	glDisable(GL_DEPTH_TEST);
 	glDisable(GL_DEPTH_TEST);
@@ -2575,7 +2590,7 @@ void RasterizerSceneGLES3::_copy_to_front_buffer(Environment *env) {
 void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
 void RasterizerSceneGLES3::_copy_texture_to_front_buffer(GLuint p_texture) {
 
 
 	//copy to front buffer
 	//copy to front buffer
-	glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->front.fbo);
+	glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
 
 
 	glDepthMask(GL_FALSE);
 	glDepthMask(GL_FALSE);
 	glDisable(GL_DEPTH_TEST);
 	glDisable(GL_DEPTH_TEST);
@@ -2660,6 +2675,127 @@ void RasterizerSceneGLES3::_fill_render_list(InstanceBase** p_cull_result,int p_
 }
 }
 
 
 
 
+void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_cam_projection) {
+
+
+	glDepthMask(GL_FALSE);
+	glDisable(GL_DEPTH_TEST);
+	glDisable(GL_CULL_FACE);
+	glDisable(GL_BLEND);
+
+	if (env->ssr_enabled) {
+		//blur diffuse into effect mipmaps using separatable convolution
+		//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
+		for(int i=0;i<storage->frame.current_rt->effects.mip_maps[1].sizes.size();i++) {
+
+
+			int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width;
+			int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height;
+			glViewport(0,0,vp_w,vp_h);
+			//horizontal pass
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL,true);
+			state.effect_blur_shader.bind();
+			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE,Vector2(1.0/vp_w,1.0/vp_h));
+			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(i));
+			glActiveTexture(GL_TEXTURE0);
+			if (i==0) {
+				glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse);
+			} else {
+				glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger
+			}
+			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo);
+			_copy_screen();
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL,false);
+
+			//vertical pass
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL,true);
+			state.effect_blur_shader.bind();
+			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE,Vector2(1.0/vp_w,1.0/vp_h));
+			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(i));
+			glActiveTexture(GL_TEXTURE0);
+			glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color);
+			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[i+1].fbo); //next level, since mipmaps[0] starts one level bigger
+			_copy_screen();
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL,false);
+		}
+
+
+		//perform SSR
+
+		state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::SMOOTH_ACCEL,env->ssr_accel>0 && env->ssr_smooth);
+		state.ssr_shader.set_conditional(ScreenSpaceReflectionShaderGLES3::REFLECT_ROUGHNESS,env->ssr_accel>0 && env->ssr_roughness);
+
+		state.ssr_shader.bind();
+
+		int ssr_w = storage->frame.current_rt->effects.mip_maps[1].sizes[0].width;
+		int ssr_h = storage->frame.current_rt->effects.mip_maps[1].sizes[0].height;
+
+
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PIXEL_SIZE,Vector2(1.0/(ssr_w*0.5),1.0/(ssr_h*0.5)));
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::PROJECTION,p_cam_projection);
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::INVERSE_PROJECTION,p_cam_projection.inverse());
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::VIEWPORT_SIZE,Size2(ssr_w,ssr_h));
+		//state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FRAME_INDEX,int(render_pass));
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::FILTER_MIPMAP_LEVELS,float(storage->frame.current_rt->effects.mip_maps[0].sizes.size()));
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::NUM_STEPS,env->ssr_max_steps);
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::ACCELERATION,env->ssr_accel);
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DEPTH_TOLERANCE,env->ssr_depth_tolerance);
+		state.ssr_shader.set_uniform(ScreenSpaceReflectionShaderGLES3::DISTANCE_FADE,env->ssr_fade);
+
+
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse);
+		glActiveTexture(GL_TEXTURE1);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_sr);
+		glActiveTexture(GL_TEXTURE2);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+		glActiveTexture(GL_TEXTURE3);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color);
+
+		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[1].sizes[0].fbo);
+		glViewport(0,0,ssr_w,ssr_h);
+
+		_copy_screen();
+		glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height);
+
+	}
+
+
+	state.resolve_shader.set_conditional(ResolveShaderGLES3::USE_SSR,env->ssr_enabled);
+	state.resolve_shader.bind();
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse);
+	glActiveTexture(GL_TEXTURE1);
+	glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.specular);
+	if (env->ssr_enabled) {
+		glActiveTexture(GL_TEXTURE2);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[1].color);
+	}
+
+
+	glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo);
+	//glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
+	_copy_screen();
+
+	state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY,true);
+	state.effect_blur_shader.bind();
+	state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD,float(0));
+
+	glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo);
+	glActiveTexture(GL_TEXTURE0);
+	glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color);
+
+	_copy_screen();
+
+	state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SIMPLE_COPY,false);
+
+
+}
+
+
 void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass){
 void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass){
 
 
 	//first of all, make a new render pass
 	//first of all, make a new render pass
@@ -2700,7 +2836,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 	render_list.clear();
 	render_list.clear();
 
 
 
 
-	bool use_mrt=false;
+	bool use_mrt=true;
 
 
 
 
 	_fill_render_list(p_cull_result,p_cull_count,false);
 	_fill_render_list(p_cull_result,p_cull_count,false);
@@ -2712,10 +2848,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 	glEnable(GL_DEPTH_TEST);
 	glEnable(GL_DEPTH_TEST);
 	glDisable(GL_SCISSOR_TEST);
 	glDisable(GL_SCISSOR_TEST);
 
 
-
+	//rendering to a probe cubemap side
 	ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
 	ReflectionProbeInstance *probe = reflection_probe_instance_owner.getornull(p_reflection_probe);
 	GLuint current_fbo;
 	GLuint current_fbo;
 
 
+
 	if (probe) {
 	if (probe) {
 
 
 		ReflectionAtlas *ref_atlas = reflection_atlas_owner.getptr(probe->atlas);
 		ReflectionAtlas *ref_atlas = reflection_atlas_owner.getptr(probe->atlas);
@@ -2739,6 +2876,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 
 
 		glViewport(0,0,reflection_cubemaps[cubemap_index].size,reflection_cubemaps[cubemap_index].size);
 		glViewport(0,0,reflection_cubemaps[cubemap_index].size,reflection_cubemaps[cubemap_index].size);
 		glBindFramebuffer(GL_FRAMEBUFFER,current_fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER,current_fbo);
+
 	} else {
 	} else {
 
 
 		glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height);
 		glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height);
@@ -2750,6 +2888,13 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo);
 			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.fbo);
 			state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,true);
 			state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,true);
 
 
+
+			Vector<GLenum> draw_buffers;
+			draw_buffers.push_back(GL_COLOR_ATTACHMENT0);
+			draw_buffers.push_back(GL_COLOR_ATTACHMENT1);
+			draw_buffers.push_back(GL_COLOR_ATTACHMENT2);
+			glDrawBuffers(draw_buffers.size(),draw_buffers.ptr());
+
 			Color black(0,0,0,0);
 			Color black(0,0,0,0);
 			glClearBufferfv(GL_COLOR,1,black.components); // specular
 			glClearBufferfv(GL_COLOR,1,black.components); // specular
 			glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough
 			glClearBufferfv(GL_COLOR,2,black.components); // normal metal rough
@@ -2760,6 +2905,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo);
 			glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo);
 			state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false);
 			state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false);
 
 
+
 		}
 		}
 	}
 	}
 
 
@@ -2841,6 +2987,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 
 
 	state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false);
 	state.scene_shader.set_conditional(SceneShaderGLES3::USE_MULTIPLE_RENDER_TARGETS,false);
 
 
+	if (use_mrt) {
+		GLenum gldb = GL_COLOR_ATTACHMENT0;
+		glDrawBuffers(1,&gldb);
+	}
+
 	if (env && env->bg_mode==VS::ENV_BG_SKYBOX) {
 	if (env && env->bg_mode==VS::ENV_BG_SKYBOX) {
 
 
 		if (use_mrt) {
 		if (use_mrt) {
@@ -2859,16 +3010,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 
 
 //	state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false);
 //	state.scene_shader.set_conditional( SceneShaderGLES3::USE_FOG,false);
 
 
+
+	if (use_mrt) {
+		_render_mrts(env,p_cam_projection);
+	}
+
 	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 	glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 	glEnable(GL_BLEND);
 	glEnable(GL_BLEND);
 	glDepthMask(GL_TRUE);
 	glDepthMask(GL_TRUE);
 	glEnable(GL_DEPTH_TEST);
 	glEnable(GL_DEPTH_TEST);
 	glDisable(GL_SCISSOR_TEST);
 	glDisable(GL_SCISSOR_TEST);
 
 
-	if (use_mrt) {
-		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->buffers.alpha_fbo);
-	}
-
 	render_list.sort_by_depth(true);
 	render_list.sort_by_depth(true);
 
 
 	if (state.directional_light_count==0) {
 	if (state.directional_light_count==0) {
@@ -3812,6 +3964,10 @@ void RasterizerSceneGLES3::initialize() {
 	glEnable(GL_PROGRAM_POINT_SIZE);
 	glEnable(GL_PROGRAM_POINT_SIZE);
 
 
 #endif
 #endif
+
+	state.resolve_shader.init();
+	state.ssr_shader.init();
+	state.effect_blur_shader.init();
 }
 }
 
 
 void RasterizerSceneGLES3::iteration() {
 void RasterizerSceneGLES3::iteration() {

+ 27 - 0
drivers/gles3/rasterizer_scene_gles3.h

@@ -4,6 +4,9 @@
 #include "rasterizer_storage_gles3.h"
 #include "rasterizer_storage_gles3.h"
 #include "drivers/gles3/shaders/scene.glsl.h"
 #include "drivers/gles3/shaders/scene.glsl.h"
 #include "drivers/gles3/shaders/cube_to_dp.glsl.h"
 #include "drivers/gles3/shaders/cube_to_dp.glsl.h"
+#include "drivers/gles3/shaders/resolve.glsl.h"
+#include "drivers/gles3/shaders/screen_space_reflection.glsl.h"
+#include "drivers/gles3/shaders/effect_blur.glsl.h"
 
 
 class RasterizerSceneGLES3 : public RasterizerScene {
 class RasterizerSceneGLES3 : public RasterizerScene {
 public:
 public:
@@ -45,6 +48,9 @@ public:
 
 
 		SceneShaderGLES3 scene_shader;
 		SceneShaderGLES3 scene_shader;
 		CubeToDpShaderGLES3 cube_to_dp_shader;
 		CubeToDpShaderGLES3 cube_to_dp_shader;
+		ResolveShaderGLES3 resolve_shader;
+		ScreenSpaceReflectionShaderGLES3 ssr_shader;
+		EffectBlurShaderGLES3 effect_blur_shader;
 
 
 
 
 		struct SceneDataUBO {
 		struct SceneDataUBO {
@@ -289,6 +295,15 @@ public:
 
 
 		int canvas_max_layer;
 		int canvas_max_layer;
 
 
+		bool ssr_enabled;
+		int ssr_max_steps;
+		float ssr_accel;
+		float ssr_fade;
+		float ssr_depth_tolerance;
+		bool ssr_smooth;
+		bool ssr_roughness;
+
+
 
 
 		Environment() {
 		Environment() {
 			bg_mode=VS::ENV_BG_CLEAR_COLOR;
 			bg_mode=VS::ENV_BG_CLEAR_COLOR;
@@ -298,6 +313,15 @@ public:
 			ambient_energy=1.0;
 			ambient_energy=1.0;
 			ambient_skybox_contribution=0.0;
 			ambient_skybox_contribution=0.0;
 			canvas_max_layer=0;
 			canvas_max_layer=0;
+
+			ssr_enabled=false;
+			ssr_max_steps=64;
+			ssr_accel=0.04;
+			ssr_fade=2.0;
+			ssr_depth_tolerance=0.2;
+			ssr_smooth=true;
+			ssr_roughness=true;
+
 		}
 		}
 	};
 	};
 
 
@@ -316,6 +340,8 @@ public:
 	virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode);
 	virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode);
 	virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture);
 	virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture);
 
 
+	virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness);
+
 	virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper);
 	virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper);
 	virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp);
 	virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp);
 
 
@@ -551,6 +577,7 @@ public:
 
 
 	void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow);
 	void _fill_render_list(InstanceBase** p_cull_result,int p_cull_count,bool p_shadow);
 
 
+	void _render_mrts(Environment *env, const CameraMatrix &p_cam_projection);
 	virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass);
 	virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass);
 	virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count);
 	virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count);
 	virtual bool free(RID p_rid);
 	virtual bool free(RID p_rid);

+ 115 - 54
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -4760,16 +4760,10 @@ void RasterizerStorageGLES3::instance_remove_dependency(RID p_base,RasterizerSce
 
 
 void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
 void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
 
 
-	if (rt->front.fbo) {
-		glDeleteFramebuffers(1,&rt->front.fbo);
-		glDeleteTextures(1,&rt->front.color);
-		rt->front.fbo=0;
-	}
-
-	if (rt->back.fbo) {
-		glDeleteFramebuffers(1,&rt->back.fbo);
-		glDeleteTextures(1,&rt->back.color);
-		rt->back.fbo=0;
+	if (rt->fbo) {
+		glDeleteFramebuffers(1,&rt->fbo);
+		glDeleteTextures(1,&rt->color);
+		rt->fbo=0;
 	}
 	}
 
 
 	if (rt->buffers.fbo) {
 	if (rt->buffers.fbo) {
@@ -4783,7 +4777,7 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
 	}
 	}
 
 
 	if (rt->depth) {
 	if (rt->depth) {
-		glDeleteRenderbuffers(1,&rt->depth);
+		glDeleteTextures(1,&rt->depth);
 		rt->depth=0;
 		rt->depth=0;
 	}
 	}
 
 
@@ -4793,6 +4787,22 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) {
 	tex->width=0;
 	tex->width=0;
 	tex->height=0;
 	tex->height=0;
 
 
+	for(int i=0;i<2;i++) {
+		for(int j=0;j<rt->effects.mip_maps[i].sizes.size();j++) {
+			glDeleteFramebuffers(1,&rt->effects.mip_maps[i].sizes[j].fbo);
+		}
+
+		glDeleteTextures(1,&rt->effects.mip_maps[i].color);
+		rt->effects.mip_maps[i].sizes.clear();
+		rt->effects.mip_maps[i].levels=0;
+	}
+/*
+	if (rt->effects.screen_space_depth) {
+		glDeleteTextures(1,&rt->effects.screen_space_depth);
+		rt->effects.screen_space_depth=0;
+
+	}
+*/
 }
 }
 
 
 void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
@@ -4833,21 +4843,24 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 
 
 		glActiveTexture(GL_TEXTURE0);
 		glActiveTexture(GL_TEXTURE0);
 
 
-		glGenFramebuffers(1, &rt->front.fbo);
-		glBindFramebuffer(GL_FRAMEBUFFER, rt->front.fbo);
-
-
-		glGenRenderbuffers(1, &rt->depth);
-		glBindRenderbuffer(GL_RENDERBUFFER, rt->depth );
+		glGenFramebuffers(1, &rt->fbo);
+		glBindFramebuffer(GL_FRAMEBUFFER, rt->fbo);
 
 
 
 
-		glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8, rt->width, rt->height);
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
-		glBindRenderbuffer(GL_RENDERBUFFER, 0 );
+		glGenTextures(1, &rt->depth);
+		glBindTexture(GL_TEXTURE_2D, rt->depth);
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, rt->width, rt->height, 0,
+			     GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
 
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+				       GL_TEXTURE_2D, rt->depth, 0);
 
 
-		glGenTextures(1, &rt->front.color);
-		glBindTexture(GL_TEXTURE_2D, rt->front.color);
+		glGenTextures(1, &rt->color);
+		glBindTexture(GL_TEXTURE_2D, rt->color);
 
 
 		glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format,  rt->width, rt->height, 0, color_format, color_type, NULL);
 		glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format,  rt->width, rt->height, 0, color_format, color_type, NULL);
 
 
@@ -4855,7 +4868,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 		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);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->front.color, 0);
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0);
 
 
 		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 		glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
@@ -4867,7 +4880,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 		tex->gl_format_cache=color_format;
 		tex->gl_format_cache=color_format;
 		tex->gl_type_cache=color_type;
 		tex->gl_type_cache=color_type;
 		tex->gl_internal_format_cache=color_internal_format;
 		tex->gl_internal_format_cache=color_internal_format;
-		tex->tex_id=rt->front.color;
+		tex->tex_id=rt->color;
 		tex->width=rt->width;
 		tex->width=rt->width;
 		tex->alloc_width=rt->width;
 		tex->alloc_width=rt->width;
 		tex->height=rt->height;
 		tex->height=rt->height;
@@ -4881,32 +4894,6 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 
 
 	/* BACK FBO */
 	/* BACK FBO */
 
 
-	if (!rt->flags[RENDER_TARGET_NO_SAMPLING]) {
-
-		glGenFramebuffers(1, &rt->back.fbo);
-		glBindFramebuffer(GL_FRAMEBUFFER, rt->back.fbo);
-		glBindRenderbuffer(GL_RENDERBUFFER, rt->depth );
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
-
-		glGenTextures(1, &rt->back.color);
-		glBindTexture(GL_TEXTURE_2D, rt->back.color);
-		glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format,  rt->width, rt->height, 0, color_format, color_type, NULL);
-
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->back.color, 0);
-
-		GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-		glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
-
-		if (status != GL_FRAMEBUFFER_COMPLETE) {
-			_render_target_clear(rt);
-			ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
-		}
-	}
-
 	if (config.render_arch==RENDER_ARCH_DESKTOP && !rt->flags[RENDER_TARGET_NO_3D]) {
 	if (config.render_arch==RENDER_ARCH_DESKTOP && !rt->flags[RENDER_TARGET_NO_3D]) {
 
 
 
 
@@ -4915,11 +4902,12 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 		glGenFramebuffers(1, &rt->buffers.fbo);
 		glGenFramebuffers(1, &rt->buffers.fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.fbo);
 
 
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+				       GL_TEXTURE_2D, rt->depth, 0);
 
 
 		glGenTextures(1, &rt->buffers.diffuse);
 		glGenTextures(1, &rt->buffers.diffuse);
 		glBindTexture(GL_TEXTURE_2D, rt->buffers.diffuse);
 		glBindTexture(GL_TEXTURE_2D, rt->buffers.diffuse);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F,  rt->width, rt->height, 0, GL_RGBA, GL_HALF_FLOAT, 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);
 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 		glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -4958,7 +4946,9 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 		glGenFramebuffers(1, &rt->buffers.alpha_fbo);
 		glGenFramebuffers(1, &rt->buffers.alpha_fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo);
 		glBindFramebuffer(GL_FRAMEBUFFER, rt->buffers.alpha_fbo);
 
 
-		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+				       GL_TEXTURE_2D, rt->depth, 0);
+
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0);
 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->buffers.diffuse, 0);
 
 
 		status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
 		status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@@ -4969,9 +4959,80 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 			ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
 			ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
 		}
 		}
 
 
-	}
+		for(int i=0;i<2;i++) {
+
+			ERR_FAIL_COND( rt->effects.mip_maps[i].sizes.size() );
+			int w=rt->width;
+			int h=rt->height;
+
+
+			if (i>0) {
+				w>>=1;
+				h>>=1;
+			}
+
+
+			glGenTextures(1, &rt->effects.mip_maps[i].color);
+			glBindTexture(GL_TEXTURE_2D, rt->effects.mip_maps[i].color);
 
 
+			int level=0;
+
+			while(true) {
+
+				RenderTarget::Effects::MipMaps::Size mm;
+
+				glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA16F,  w, h, 0, GL_RGBA, GL_HALF_FLOAT, NULL);
+				mm.width=w;
+				mm.height=h;
+				rt->effects.mip_maps[i].sizes.push_back(mm);
+
+				w>>=1;
+				h>>=1;
+
+				if (w<32 || h<32)
+					break; //going less than 32 is pointless
+
+				level++;
+
+			}
 
 
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
+
+
+			for(int j=0;j<rt->effects.mip_maps[i].sizes.size();j++) {
+
+				RenderTarget::Effects::MipMaps::Size &mm=rt->effects.mip_maps[i].sizes[j];
+
+				glGenFramebuffers(1, &mm.fbo);
+				glBindFramebuffer(GL_FRAMEBUFFER, mm.fbo);
+				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,rt->effects.mip_maps[i].color ,j);
+
+				status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+				if (status != GL_FRAMEBUFFER_COMPLETE) {
+					_render_target_clear(rt);
+					ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE );
+				}
+
+
+				float zero[4]={1,0,1,0};
+				glClearBufferfv(GL_COLOR,0,zero);
+
+
+			}
+
+			glBindFramebuffer(GL_FRAMEBUFFER, config.system_fbo);
+			rt->effects.mip_maps[i].levels=level;
+
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+			//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+		}
+
+	}
 }
 }
 
 
 
 

+ 30 - 7
drivers/gles3/rasterizer_storage_gles3.h

@@ -877,11 +877,8 @@ public:
 
 
 	struct RenderTarget : public RID_Data {
 	struct RenderTarget : public RID_Data {
 
 
-		struct Color {
-			GLuint fbo;
-			GLuint color;
-		} front,back;
-
+		GLuint fbo;
+		GLuint color;
 		GLuint depth;
 		GLuint depth;
 
 
 		struct Buffers {
 		struct Buffers {
@@ -890,8 +887,35 @@ public:
 			GLuint specular;
 			GLuint specular;
 			GLuint diffuse;
 			GLuint diffuse;
 			GLuint normal_sr;
 			GLuint normal_sr;
+			GLuint temporal;
 		} buffers;
 		} buffers;
 
 
+		struct Effects {
+
+			struct MipMaps {
+
+				struct Size {
+					GLuint fbo;
+					int width;
+					int height;
+				};
+
+				Vector<Size> sizes;
+				GLuint color;
+				int levels;
+
+				MipMaps() { color=0; levels=0;}
+			};
+
+			MipMaps mip_maps[2]; //first mipmap chain starts from full-screen
+			//GLuint depth2; //depth for the second mipmap chain, in case of desiring upsampling
+
+			Effects() {
+
+			}
+
+		} effects;
+
 		int width,height;
 		int width,height;
 
 
 		bool flags[RENDER_TARGET_FLAG_MAX];
 		bool flags[RENDER_TARGET_FLAG_MAX];
@@ -905,8 +929,7 @@ public:
 			width=0;
 			width=0;
 			height=0;
 			height=0;
 			depth=0;
 			depth=0;
-			front.fbo=0;
-			back.fbo=0;
+			fbo=0;
 			buffers.fbo=0;
 			buffers.fbo=0;
 			buffers.alpha_fbo=0;
 			buffers.alpha_fbo=0;
 			used_in_frame=false;
 			used_in_frame=false;

+ 2 - 2
drivers/gles3/shader_gles3.cpp

@@ -393,8 +393,8 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
 
 
 	strings.resize(strings_base_size);
 	strings.resize(strings_base_size);
 	//fragment precision is medium
 	//fragment precision is medium
-	strings.push_back("precision mediump float;\n");
-	strings.push_back("precision mediump int;\n");
+	strings.push_back("precision highp float;\n");
+	strings.push_back("precision highp int;\n");
 
 
 #if 0
 #if 0
 	if (cc) {
 	if (cc) {

+ 3 - 0
drivers/gles3/shaders/SCsub

@@ -2,10 +2,13 @@ Import('env')
 
 
 if env['BUILDERS'].has_key('GLES3_GLSL'):
 if env['BUILDERS'].has_key('GLES3_GLSL'):
 	env.GLES3_GLSL('copy.glsl');
 	env.GLES3_GLSL('copy.glsl');
+	env.GLES3_GLSL('resolve.glsl');
 	env.GLES3_GLSL('canvas.glsl');
 	env.GLES3_GLSL('canvas.glsl');
 	env.GLES3_GLSL('canvas_shadow.glsl');
 	env.GLES3_GLSL('canvas_shadow.glsl');
 	env.GLES3_GLSL('scene.glsl');
 	env.GLES3_GLSL('scene.glsl');
 	env.GLES3_GLSL('cubemap_filter.glsl');
 	env.GLES3_GLSL('cubemap_filter.glsl');
 	env.GLES3_GLSL('cube_to_dp.glsl');
 	env.GLES3_GLSL('cube_to_dp.glsl');
 	env.GLES3_GLSL('blend_shape.glsl');
 	env.GLES3_GLSL('blend_shape.glsl');
+	env.GLES3_GLSL('screen_space_reflection.glsl');
+	env.GLES3_GLSL('effect_blur.glsl');
 
 

+ 19 - 0
drivers/gles3/shaders/copy.glsl

@@ -50,6 +50,7 @@ float sRGB_gamma_correct(float c){
 
 
 
 
 uniform float stuff;
 uniform float stuff;
+uniform vec2 pixel_size;
 
 
 in vec2 uv2_interp;
 in vec2 uv2_interp;
 
 
@@ -81,6 +82,24 @@ void main() {
 	color.a=1.0;
 	color.a=1.0;
 #endif
 #endif
 
 
+
+#ifdef GAUSSIAN_HORIZONTAL
+	color*=0.38774;
+	color+=texture( source,  uv_interp+vec2( 1.0, 0.0)*pixel_size )*0.24477;
+	color+=texture( source,  uv_interp+vec2( 2.0, 0.0)*pixel_size )*0.06136;
+	color+=texture( source,  uv_interp+vec2(-1.0, 0.0)*pixel_size )*0.24477;
+	color+=texture( source,  uv_interp+vec2(-2.0, 0.0)*pixel_size )*0.06136;
+#endif
+
+#ifdef GAUSSIAN_VERTICAL
+	color*=0.38774;
+	color+=texture( source,  uv_interp+vec2( 0.0, 1.0)*pixel_size )*0.24477;
+	color+=texture( source,  uv_interp+vec2( 0.0, 2.0)*pixel_size )*0.06136;
+	color+=texture( source,  uv_interp+vec2( 0.0,-1.0)*pixel_size )*0.24477;
+	color+=texture( source,  uv_interp+vec2( 0.0,-2.0)*pixel_size )*0.06136;
+#endif
+
+
 	frag_color = color;
 	frag_color = color;
 }
 }
 
 

+ 45 - 0
drivers/gles3/shaders/resolve.glsl

@@ -0,0 +1,45 @@
+[vertex]
+
+
+layout(location=0) in highp vec4 vertex_attrib;
+layout(location=4) in vec2 uv_in;
+
+out vec2 uv_interp;
+
+
+void main() {
+
+	uv_interp = uv_in;
+	gl_Position = vertex_attrib;
+}
+
+[fragment]
+
+
+in vec2 uv_interp;
+uniform sampler2D source_diffuse; //texunit:0
+uniform sampler2D source_specular; //texunit:1
+
+
+uniform sampler2D source_ssr_ssao; //texunit:2
+
+uniform float stuff;
+
+in vec2 uv2_interp;
+
+layout(location = 0) out vec4 frag_color;
+
+void main() {
+
+	vec4 diffuse = texture( source_diffuse,  uv_interp );
+	vec4 specular = texture( source_specular,  uv_interp );
+
+#ifdef USE_SSR
+
+	vec4 ssr = textureLod(source_ssr_ssao,uv_interp,0.0);
+	specular.rgb = mix(specular.rgb,ssr.rgb*specular.a,ssr.a);
+#endif
+
+	frag_color = vec4(diffuse.rgb,1.0)+vec4(specular.rgb,1.0);
+}
+

File diff suppressed because it is too large
+ 156 - 0
drivers/gles3/shaders/resolve.glsl.h


+ 4 - 2
drivers/gles3/shaders/scene.glsl

@@ -1189,8 +1189,10 @@ LIGHT_SHADER_CODE
 #endif //ENABLE_AO
 #endif //ENABLE_AO
 
 
 	diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale);
 	diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale);
-	specular_buffer=vec4(specular_light,0.0);
-	normal_mr_buffer=vec4(normal.x,normal.y,max(specular.r,max(specular.g,specular.b)),roughness);
+	specular_buffer=vec4(specular_light,max(specular.r,max(specular.g,specular.b)));
+
+
+	normal_mr_buffer=vec4(normalize(normal)*0.5+0.5,roughness);
 
 
 #else
 #else
 
 

File diff suppressed because it is too large
+ 173 - 0
drivers/gles3/shaders/screen_space.glsl.h


+ 350 - 0
drivers/gles3/shaders/screen_space_reflection.glsl

@@ -0,0 +1,350 @@
+[vertex]
+
+
+layout(location=0) in highp vec4 vertex_attrib;
+layout(location=4) in vec2 uv_in;
+
+out vec2 uv_interp;
+out vec2 pos_interp;
+
+void main() {
+
+	uv_interp = uv_in;
+	gl_Position = vertex_attrib;
+	pos_interp.xy=gl_Position.xy;
+}
+
+[fragment]
+
+
+in vec2 uv_interp;
+in vec2 pos_interp;
+
+uniform sampler2D source_diffuse; //texunit:0
+uniform sampler2D source_normal_roughness; //texunit:1
+uniform sampler2D source_depth; //texunit:2
+uniform sampler2D source_diffuse_mipmaps; //texunit:3
+
+uniform float camera_z_near;
+uniform float camera_z_far;
+
+uniform vec2 viewport_size;
+uniform vec2 pixel_size;
+
+uniform float filter_mipmap_levels;
+
+uniform mat4 inverse_projection;
+uniform mat4 projection;
+
+uniform int num_steps;
+uniform float depth_tolerance;
+uniform float distance_fade;
+uniform float acceleration;
+
+layout(location = 0) out vec4 frag_color;
+
+
+vec2 view_to_screen(vec3 view_pos,out float w) {
+    vec4 projected = projection * vec4(view_pos, 1.0);
+    projected.xyz /= projected.w;
+    projected.xy = projected.xy * 0.5 + 0.5;
+    w=projected.w;
+    return projected.xy;
+}
+
+
+
+#define M_PI 3.14159265359
+
+
+void main() {
+
+
+	////
+
+	vec4 diffuse = texture( source_diffuse,  uv_interp );
+	vec4 normal_roughness = texture( source_normal_roughness, uv_interp);
+
+	vec3 normal;
+
+	normal = normal_roughness.xyz*2.0-1.0;
+
+	float roughness = normal_roughness.w;
+
+	float depth_tex = texture(source_depth,uv_interp).r;
+
+	vec4 world_pos = inverse_projection * vec4( uv_interp*2.0-1.0, depth_tex*2.0-1.0, 1.0 );
+	vec3 vertex = world_pos.xyz/world_pos.w;
+
+	vec3 view_dir = normalize(vertex);
+	vec3 ray_dir = normalize(reflect(view_dir, normal));
+
+	if (dot(ray_dir,normal)<0.001) {
+		frag_color=vec4(0.0);
+		return;
+	}
+	//ray_dir = normalize(view_dir - normal * dot(normal,view_dir) * 2.0);
+
+	//ray_dir = normalize(vec3(1,1,-1));
+
+
+	////////////////
+
+
+	//make ray length and clip it against the near plane (don't want to trace beyond visible)
+	float ray_len = (vertex.z + ray_dir.z * camera_z_far) > -camera_z_near ? (-camera_z_near - vertex.z) / ray_dir.z : camera_z_far;
+	vec3 ray_end = vertex + ray_dir*ray_len;
+
+	float w_begin;
+	vec2 vp_line_begin = view_to_screen(vertex,w_begin);
+	float w_end;
+	vec2 vp_line_end = view_to_screen( ray_end, w_end);
+	vec2 vp_line_dir = vp_line_end-vp_line_begin;
+
+	//we need to interpolate w along the ray, to generate perspective correct reflections
+
+	w_begin = 1.0/w_begin;
+	w_end = 1.0/w_end;
+
+
+	float z_begin = vertex.z*w_begin;
+	float z_end = ray_end.z*w_end;
+
+	vec2 line_begin = vp_line_begin/pixel_size;
+	vec2 line_dir = vp_line_dir/pixel_size;
+	float z_dir = z_end - z_begin;
+	float w_dir = w_end - w_begin;
+
+
+	// clip the line to the viewport edges
+
+	float scale_max_x = min(1, 0.99 * (1.0 - vp_line_begin.x) / max(1e-5, vp_line_dir.x));
+	float scale_max_y = min(1, 0.99 * (1.0 - vp_line_begin.y) / max(1e-5, vp_line_dir.y));
+	float scale_min_x = min(1, 0.99 * vp_line_begin.x / max(1e-5, -vp_line_dir.x));
+	float scale_min_y = min(1, 0.99 * vp_line_begin.y / max(1e-5, -vp_line_dir.y));
+	float line_clip = min(scale_max_x, scale_max_y) * min(scale_min_x, scale_min_y);
+	line_dir *= line_clip;
+	z_dir *= line_clip;
+	w_dir *=line_clip;
+
+	//clip z and w advance to line advance
+	vec2 line_advance = normalize(line_dir); //down to pixel
+	float step_size = length(line_advance)/length(line_dir);
+	float z_advance = z_dir*step_size; // adapt z advance to line advance
+	float w_advance = w_dir*step_size; // adapt w advance to line advance
+
+	//make line advance faster if direction is closer to pixel edges (this avoids sampling the same pixel twice)
+	float advance_angle_adj = 1.0/max(abs(line_advance.x),abs(line_advance.y));
+	line_advance*=advance_angle_adj; // adapt z advance to line advance
+	z_advance*=advance_angle_adj;
+	w_advance*=advance_angle_adj;
+
+	vec2 pos = line_begin;
+	float z = z_begin;
+	float w = w_begin;
+	float z_from=z/w;
+	float z_to=z_from;
+	float depth;
+	vec2 prev_pos=pos;
+
+	bool found=false;
+
+	//if acceleration > 0, distance between pixels gets larger each step. This allows covering a larger area
+	float accel=1.0+acceleration;
+	float steps_taken=0;
+
+	for(float i=0;i<num_steps;i++) {
+
+		pos+=line_advance;
+		z+=z_advance;
+		w+=w_advance;
+
+		//convert to linear depth
+		depth = texture(source_depth, pos*pixel_size).r * 2.0 - 1.0;
+		depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
+		depth=-depth;
+
+		z_from = z_to;
+		z_to = z/w;
+
+		if (depth>z_to) {
+			//if depth was surpassed
+			if (depth<=max(z_to,z_from)+depth_tolerance) {
+				//check the depth tolerance
+				found=true;
+			}
+			break;
+		}
+
+		steps_taken+=1.0;
+		prev_pos=pos;
+		z_advance*=accel;
+		w_advance*=accel;
+		line_advance*=accel;
+	}
+
+
+
+
+	if (found) {
+
+		float margin_blend=1.0;
+
+
+		vec2 margin = vec2((viewport_size.x+viewport_size.y)*0.5*0.05); //make a uniform margin
+		if (any(bvec4(lessThan(pos,-margin),greaterThan(pos,viewport_size+margin)))) {
+			//clip outside screen + margin
+			frag_color=vec4(0.0);
+			return;
+		}
+
+		{
+			//blend fading out towards external margin
+			vec2 margin_grad = mix(pos-viewport_size,-pos,lessThan(pos,vec2(0.0)));
+			margin_blend = 1.0-smoothstep(0.0,margin.x,max(margin_grad.x,margin_grad.y));
+			//margin_blend=1.0;
+
+		}
+
+		vec2 final_pos;
+		float grad;
+
+#ifdef SMOOTH_ACCEL
+		//if the distance between point and prev point is >1, then take some samples in the middle for smoothing out the image
+		vec2 blend_dir = pos - prev_pos;
+		float steps = min(8.0,length(blend_dir));
+		if (steps>2.0) {
+			vec2 blend_step = blend_dir/steps;
+			float blend_z = (z_to-z_from)/steps;
+			vec2 new_pos;
+			float subgrad=0.0;
+			for(float i=0.0;i<steps;i++) {
+
+				new_pos = (prev_pos+blend_step*i);
+				float z = z_from+blend_z*i;
+
+				depth = texture(source_depth, new_pos*pixel_size).r * 2.0 - 1.0;
+				depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - depth * (camera_z_far - camera_z_near));
+				depth=-depth;
+
+				subgrad=i/steps;
+				if (depth>z)
+					break;
+			}
+
+			final_pos = new_pos;
+			grad=(steps_taken+subgrad)/num_steps;
+
+		} else {
+#endif
+			grad=steps_taken/num_steps;
+			final_pos=pos;
+#ifdef SMOOTH_ACCEL
+		}
+
+#endif
+
+
+
+#ifdef REFLECT_ROUGHNESS
+
+
+		vec4 final_color;
+		//if roughness is enabled, do screen space cone tracing
+		if (roughness > 0.001) {
+			///////////////////////////////////////////////////////////////////////////////////////
+			//use a blurred version (in consecutive mipmaps) of the screen to simulate roughness
+
+			float gloss = 1.0-roughness;
+			float cone_angle = roughness * M_PI * 0.5;
+			vec2 cone_dir = final_pos - line_begin;
+			float cone_len = length(cone_dir);
+			cone_dir = normalize(cone_dir); //will be used normalized from now on
+			float max_mipmap = filter_mipmap_levels -1;
+			float gloss_mult=gloss;
+
+			float rem_alpha=1.0;
+			final_color = vec4(0.0);
+
+			for(int i=0;i<7;i++) {
+
+				float op_len = 2.0 * tan(cone_angle) * cone_len; //oposite side of iso triangle
+				float radius;
+				{
+					//fit to sphere inside cone (sphere ends at end of cone), something like this:
+					// ___
+					// \O/
+					//  V
+					//
+					// as it avoids bleeding from beyond the reflection as much as possible. As a plus
+					// it also makes the rough reflection more elongated.
+					float a = op_len;
+					float h = cone_len;
+					float a2 = a * a;
+					float fh2 = 4.0f * h * h;
+					radius = (a * (sqrt(a2 + fh2) - a)) / (4.0f * h);
+				}
+
+				//find the place where screen must be sampled
+				vec2 sample_pos = ( line_begin + cone_dir * (cone_len - radius) ) * pixel_size;
+				//radius is in pixels, so it's natural that log2(radius) maps to the right mipmap for the amount of pixels
+				float mipmap = clamp( log2( radius ), 0.0, max_mipmap );
+
+				//mipmap = max(mipmap-1.0,0.0);
+				//do sampling
+
+				vec4 sample_color;
+				{
+					sample_color = textureLod(source_diffuse_mipmaps,sample_pos,max(1.0,mipmap));
+					if (mipmap<1.0) { //we use another image as base to avoid copying all the screen unnecesarily
+						vec4 base_sample_color = textureLod(source_diffuse,sample_pos,0.0);
+						sample_color = mix(base_sample_color,sample_color,mipmap);
+					}
+				}
+
+				//multiply by gloss
+				sample_color.rgb*=gloss_mult;
+				sample_color.a=gloss_mult;
+
+				rem_alpha -= sample_color.a;
+				if(rem_alpha < 0.0) {
+					sample_color.rgb *= (1.0 - abs(rem_alpha));
+				}
+
+				final_color+=sample_color;
+
+				if (final_color.a>=0.95) {
+					// This code of accumulating gloss and aborting on near one
+					// makes sense when you think of cone tracing.
+					// Think of it as if roughness was 0, then we could abort on the first
+					// iteration. For lesser roughness values, we need more iterations, but
+					// each needs to have less influence given the sphere is smaller
+					break;
+				}
+
+				cone_len-=radius*2.0; //go to next (smaller) circle.
+
+				gloss_mult*=gloss;
+
+
+			}
+		} else {
+			final_color = textureLod(source_diffuse,final_pos*pixel_size,0.0);
+		}
+
+		frag_color = vec4(final_color.rgb,pow(clamp(1.0-grad,0.0,1.0),distance_fade)*margin_blend);
+
+#else
+		frag_color = vec4(textureLod(source_diffuse,final_pos*pixel_size,0.0).rgb,pow(clamp(1.0-grad,0.0,1.0),distance_fade)*margin_blend);
+#endif
+
+
+
+	} else {
+		frag_color = vec4(0.0,0.0,0.0,0.0);
+	}
+
+
+
+}
+

+ 120 - 0
scene/resources/environment.cpp

@@ -300,6 +300,84 @@ void Environment::_validate_property(PropertyInfo& property) const {
 
 
 }
 }
 
 
+void Environment::set_ssr_enabled(bool p_enable) {
+
+	ssr_enabled=p_enable;
+	VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
+}
+
+bool Environment::is_ssr_enabled() const{
+
+	return ssr_enabled;
+}
+
+void Environment::set_ssr_max_steps(int p_steps){
+
+	ssr_max_steps=p_steps;
+	VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
+
+}
+int Environment::get_ssr_max_steps() const {
+
+	return ssr_max_steps;
+}
+
+void Environment::set_ssr_accel(float p_accel) {
+
+	ssr_accel=p_accel;
+	VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
+
+}
+float Environment::get_ssr_accel() const {
+
+	return ssr_accel;
+}
+
+void Environment::set_ssr_fade(float p_fade) {
+
+	ssr_fade=p_fade;
+	VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
+
+}
+float Environment::get_ssr_fade() const {
+
+	return ssr_fade;
+}
+
+void Environment::set_ssr_depth_tolerance(float p_depth_tolerance) {
+
+	ssr_depth_tolerance=p_depth_tolerance;
+	VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
+
+}
+float Environment::get_ssr_depth_tolerance() const {
+
+	return ssr_depth_tolerance;
+}
+
+void Environment::set_ssr_smooth(bool p_enable) {
+
+	ssr_smooth=p_enable;
+	VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
+
+}
+bool Environment::is_ssr_smooth() const {
+
+	return ssr_smooth;
+}
+
+void Environment::set_ssr_rough(bool p_enable) {
+
+	ssr_roughness=p_enable;
+	VS::get_singleton()->environment_set_ssr(environment,ssr_enabled,ssr_max_steps,ssr_accel,ssr_fade,ssr_depth_tolerance,ssr_smooth,ssr_roughness);
+
+}
+bool Environment::is_ssr_rough() const {
+
+	return ssr_roughness;
+}
+
+
 void Environment::_bind_methods() {
 void Environment::_bind_methods() {
 
 
 	ObjectTypeDB::bind_method(_MD("set_background","mode"),&Environment::set_background);
 	ObjectTypeDB::bind_method(_MD("set_background","mode"),&Environment::set_background);
@@ -334,6 +412,37 @@ void Environment::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light/energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_ambient_light_energy"),_SCS("get_ambient_light_energy") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light/energy",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_ambient_light_energy"),_SCS("get_ambient_light_energy") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light/skybox_contribution",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_ambient_light_skybox_contribution"),_SCS("get_ambient_light_skybox_contribution") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_light/skybox_contribution",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_ambient_light_skybox_contribution"),_SCS("get_ambient_light_skybox_contribution") );
 
 
+
+	ObjectTypeDB::bind_method(_MD("set_ssr_enabled","enabled"),&Environment::set_ssr_enabled);
+	ObjectTypeDB::bind_method(_MD("is_ssr_enabled"),&Environment::is_ssr_enabled);
+
+	ObjectTypeDB::bind_method(_MD("set_ssr_max_steps","max_steps"),&Environment::set_ssr_max_steps);
+	ObjectTypeDB::bind_method(_MD("get_ssr_max_steps"),&Environment::get_ssr_max_steps);
+
+	ObjectTypeDB::bind_method(_MD("set_ssr_accel","accel"),&Environment::set_ssr_accel);
+	ObjectTypeDB::bind_method(_MD("get_ssr_accel"),&Environment::get_ssr_accel);
+
+	ObjectTypeDB::bind_method(_MD("set_ssr_fade","fade"),&Environment::set_ssr_fade);
+	ObjectTypeDB::bind_method(_MD("get_ssr_fade"),&Environment::get_ssr_fade);
+
+	ObjectTypeDB::bind_method(_MD("set_ssr_depth_tolerance","depth_tolerance"),&Environment::set_ssr_depth_tolerance);
+	ObjectTypeDB::bind_method(_MD("get_ssr_depth_tolerance"),&Environment::get_ssr_depth_tolerance);
+
+	ObjectTypeDB::bind_method(_MD("set_ssr_smooth","smooth"),&Environment::set_ssr_smooth);
+	ObjectTypeDB::bind_method(_MD("is_ssr_smooth"),&Environment::is_ssr_smooth);
+
+	ObjectTypeDB::bind_method(_MD("set_ssr_rough","rough"),&Environment::set_ssr_rough);
+	ObjectTypeDB::bind_method(_MD("is_ssr_rough"),&Environment::is_ssr_rough);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/enable"),_SCS("set_ssr_enabled"),_SCS("is_ssr_enabled") );
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"ss_reflections/max_steps",PROPERTY_HINT_RANGE,"1,512,1"),_SCS("set_ssr_max_steps"),_SCS("get_ssr_max_steps") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections/accel",PROPERTY_HINT_RANGE,"0,4,0.01"),_SCS("set_ssr_accel"),_SCS("get_ssr_accel") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections/fade",PROPERTY_HINT_EXP_EASING),_SCS("set_ssr_fade"),_SCS("get_ssr_fade") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ss_reflections/depth_tolerance",PROPERTY_HINT_RANGE,"0.1,128,0.1"),_SCS("set_ssr_depth_tolerance"),_SCS("get_ssr_depth_tolerance") );
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/accel_smooth"),_SCS("set_ssr_smooth"),_SCS("is_ssr_smooth") );
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/roughness"),_SCS("set_ssr_rough"),_SCS("is_ssr_rough") );
+
+
 	ObjectTypeDB::bind_method(_MD("set_tonemapper","mode"),&Environment::set_tonemapper);
 	ObjectTypeDB::bind_method(_MD("set_tonemapper","mode"),&Environment::set_tonemapper);
 	ObjectTypeDB::bind_method(_MD("get_tonemapper"),&Environment::get_tonemapper);
 	ObjectTypeDB::bind_method(_MD("get_tonemapper"),&Environment::get_tonemapper);
 
 
@@ -358,6 +467,9 @@ void Environment::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_tonemap_auto_exposure_scale","exposure_scale"),&Environment::set_tonemap_auto_exposure_scale);
 	ObjectTypeDB::bind_method(_MD("set_tonemap_auto_exposure_scale","exposure_scale"),&Environment::set_tonemap_auto_exposure_scale);
 	ObjectTypeDB::bind_method(_MD("get_tonemap_auto_exposure_scale"),&Environment::get_tonemap_auto_exposure_scale);
 	ObjectTypeDB::bind_method(_MD("get_tonemap_auto_exposure_scale"),&Environment::get_tonemap_auto_exposure_scale);
 
 
+
+
+
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"tonemap/mode",PROPERTY_HINT_ENUM,"Linear,Log,Reindhart,Filmic,Aces"),_SCS("set_tonemapper"),_SCS("get_tonemapper") );
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"tonemap/mode",PROPERTY_HINT_ENUM,"Linear,Log,Reindhart,Filmic,Aces"),_SCS("set_tonemapper"),_SCS("get_tonemapper") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap/exposure",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_exposure"),_SCS("get_tonemap_exposure") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap/exposure",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_exposure"),_SCS("get_tonemap_exposure") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap/white",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_white"),_SCS("get_tonemap_white") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"tonemap/white",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_white"),_SCS("get_tonemap_white") );
@@ -441,6 +553,14 @@ Environment::Environment() {
 
 
 	environment = VS::get_singleton()->environment_create();
 	environment = VS::get_singleton()->environment_create();
 
 
+	ssr_enabled=false;
+	ssr_max_steps=64;
+	ssr_accel=0.04;
+	ssr_fade=2.0;
+	ssr_depth_tolerance=0.2;
+	ssr_smooth=true;
+	ssr_roughness=true;
+
 }
 }
 
 
 Environment::~Environment() {
 Environment::~Environment() {

+ 29 - 0
scene/resources/environment.h

@@ -94,6 +94,14 @@ private:
 	float adjustment_brightness;
 	float adjustment_brightness;
 	Ref<Texture> adjustment_color_correction;
 	Ref<Texture> adjustment_color_correction;
 
 
+	bool ssr_enabled;
+	int ssr_max_steps;
+	float ssr_accel;
+	float ssr_fade;
+	float ssr_depth_tolerance;
+	bool ssr_smooth;
+	bool ssr_roughness;
+
 protected:
 protected:
 
 
 	static void _bind_methods();
 	static void _bind_methods();
@@ -162,6 +170,27 @@ public:
 	void set_adjustment_color_correction(const Ref<Texture>& p_ramp);
 	void set_adjustment_color_correction(const Ref<Texture>& p_ramp);
 	Ref<Texture> get_adjustment_color_correction() const;
 	Ref<Texture> get_adjustment_color_correction() const;
 
 
+	void set_ssr_enabled(bool p_enable);
+	bool is_ssr_enabled() const;
+
+	void set_ssr_max_steps(int p_steps);
+	int get_ssr_max_steps() const;
+
+	void set_ssr_accel(float p_accel);
+	float get_ssr_accel() const;
+
+	void set_ssr_fade(float p_fade);
+	float get_ssr_fade() const;
+
+	void set_ssr_depth_tolerance(float p_depth_tolerance);
+	float get_ssr_depth_tolerance() const;
+
+	void set_ssr_smooth(bool p_enable);
+	bool is_ssr_smooth() const;
+
+	void set_ssr_rough(bool p_enable);
+	bool is_ssr_rough() const;
+
 
 
 	virtual RID get_rid() const;
 	virtual RID get_rid() const;
 
 

+ 2 - 0
servers/visual/rasterizer.h

@@ -64,6 +64,8 @@ public:
 	virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode)=0;
 	virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode)=0;
 	virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0;
 	virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0;
 
 
+	virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0;
+
 	virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper)=0;
 	virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper)=0;
 	virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
 	virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
 
 

+ 1 - 0
servers/visual/visual_server_raster.h

@@ -875,6 +875,7 @@ public:
 	BIND2(environment_set_bg_energy,RID,float )
 	BIND2(environment_set_bg_energy,RID,float )
 	BIND2(environment_set_canvas_max_layer,RID,int )
 	BIND2(environment_set_canvas_max_layer,RID,int )
 	BIND4(environment_set_ambient_light,RID,const Color& ,float,float )
 	BIND4(environment_set_ambient_light,RID,const Color& ,float,float )
+	BIND8(environment_set_ssr,RID,bool,int,float,float,float,bool,bool )
 
 
 	BIND7(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode )
 	BIND7(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode )
 	BIND5(environment_set_fog,RID,bool ,float ,float ,RID )
 	BIND5(environment_set_fog,RID,bool ,float ,float ,RID )

+ 1 - 1
servers/visual_server.h

@@ -555,7 +555,7 @@ public:
 	virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,EnvironmentToneMapper p_tone_mapper)=0;
 	virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,EnvironmentToneMapper p_tone_mapper)=0;
 	virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
 	virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
 
 
-
+	virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0;
 	/* SCENARIO API */
 	/* SCENARIO API */
 
 
 
 

+ 9 - 3
tools/collada/collada.cpp

@@ -463,7 +463,7 @@ Transform Collada::_read_transform(XMLParser& parser) {
 	if (parser.is_empty())
 	if (parser.is_empty())
 		return Transform();
 		return Transform();
 
 
-	Vector<float> array;
+	Vector<String> array;
 	while(parser.read()==OK) {
 	while(parser.read()==OK) {
 		// TODO: check for comments inside the element
 		// TODO: check for comments inside the element
 		// and ignore them.
 		// and ignore them.
@@ -471,7 +471,7 @@ Transform Collada::_read_transform(XMLParser& parser) {
 		if (parser.get_node_type() == XMLParser::NODE_TEXT) {
 		if (parser.get_node_type() == XMLParser::NODE_TEXT) {
 			// parse float data
 			// parse float data
 			String str = parser.get_node_data();
 			String str = parser.get_node_data();
-			array=str.split_floats(" ",false);
+			array=str.split_spaces();
 		}
 		}
 		else
 		else
 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
 		if (parser.get_node_type() == XMLParser::NODE_ELEMENT_END)
@@ -479,7 +479,13 @@ Transform Collada::_read_transform(XMLParser& parser) {
 	}
 	}
 
 
 	ERR_FAIL_COND_V(array.size()!=16,Transform());
 	ERR_FAIL_COND_V(array.size()!=16,Transform());
-	return _read_transform_from_array(array);
+	Vector<float> farr;
+	farr.resize(16);
+	for(int i=0;i<16;i++) {
+		farr[i]=array[i].to_double();
+	}
+
+	return _read_transform_from_array(farr);
 }
 }
 
 
 String Collada::_read_empty_draw_type(XMLParser& parser) {
 String Collada::_read_empty_draw_type(XMLParser& parser) {

Some files were not shown because too many files changed in this diff