Sfoglia il codice sorgente

DOF blur, near and far fields..

Juan Linietsky 8 anni fa
parent
commit
22a90e8f2a

+ 1 - 1
core/math/camera_matrix.cpp

@@ -54,7 +54,7 @@ void CameraMatrix::set_zero() {
 }
 
 
-Plane CameraMatrix::xform4(const Plane& p_vec4) {
+Plane CameraMatrix::xform4(const Plane& p_vec4) const {
 
 	Plane ret;
 

+ 1 - 1
core/math/camera_matrix.h

@@ -80,7 +80,7 @@ struct CameraMatrix {
 
 	CameraMatrix operator*(const CameraMatrix& p_matrix) const;
 
-	Plane xform4(const Plane& p_vec4);
+	Plane xform4(const Plane& p_vec4) const;
 	_FORCE_INLINE_ Vector3 xform(const Vector3& p_vec3) const;
 
 	operator String() const;

+ 193 - 3
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -850,7 +850,36 @@ void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color&
 
 }
 
-void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale) {
+
+
+void RasterizerSceneGLES3::environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_amount,VS::EnvironmentDOFBlurQuality p_quality){
+
+	Environment *env=environment_owner.getornull(p_env);
+	ERR_FAIL_COND(!env);
+
+	env->dof_blur_far_enabled=p_enable;
+	env->dof_blur_far_distance=p_distance;
+	env->dof_blur_far_transition=p_transition;
+	env->dof_blur_far_amount=p_amount;
+	env->dof_blur_far_quality=p_quality;
+
+
+}
+
+void RasterizerSceneGLES3::environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_amount,VS::EnvironmentDOFBlurQuality p_quality){
+
+	Environment *env=environment_owner.getornull(p_env);
+	ERR_FAIL_COND(!env);
+
+	env->dof_blur_near_enabled=p_enable;
+	env->dof_blur_near_distance=p_distance;
+	env->dof_blur_near_transition=p_transition;
+	env->dof_blur_near_amount=p_amount;
+	env->dof_blur_near_quality=p_quality;
+
+
+}
+void RasterizerSceneGLES3::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_treshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, bool p_bicubic_upscale) {
 
 	Environment *env=environment_owner.getornull(p_env);
 	ERR_FAIL_COND(!env);
@@ -863,6 +892,7 @@ void RasterizerSceneGLES3::environment_set_glow(RID p_env,bool p_enable,int p_le
 	env->glow_blend_mode=p_blend_mode;
 	env->glow_hdr_bleed_treshold=p_hdr_bleed_treshold;
 	env->glow_hdr_bleed_scale=p_hdr_bleed_scale;
+	env->glow_bicubic_upscale=p_bicubic_upscale;
 
 }
 void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture){
@@ -3035,7 +3065,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c
 
 }
 
-void RasterizerSceneGLES3::_post_process(Environment *env){
+void RasterizerSceneGLES3::_post_process(Environment *env,const CameraMatrix &p_cam_projection){
 
 	//copy to front buffer
 
@@ -3077,6 +3107,157 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 	GLuint composite_from = storage->frame.current_rt->buffers.diffuse;
 
 
+	if (env->dof_blur_far_enabled) {
+
+		//blur diffuse into effect mipmaps using separatable convolution
+		//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
+
+		int vp_h = storage->frame.current_rt->height;
+		int vp_w = storage->frame.current_rt->width;
+
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR,true);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,env->dof_blur_far_quality==VS::ENV_DOF_BLUR_QUALITY_LOW);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,env->dof_blur_far_quality==VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,env->dof_blur_far_quality==VS::ENV_DOF_BLUR_QUALITY_HIGH);
+
+		state.effect_blur_shader.bind();
+		int qsteps[3]={4,10,20};
+
+		float radius = (env->dof_blur_far_amount*env->dof_blur_far_amount) / qsteps[env->dof_blur_far_quality];
+
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN,env->dof_blur_far_distance);
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END,env->dof_blur_far_distance+env->dof_blur_far_transition);
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(1,0));
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS,radius);
+		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::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
+
+		glActiveTexture(GL_TEXTURE1);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
+
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D,composite_from);
+		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);
+
+		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); //copy to front first
+
+		_copy_screen();
+
+
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color);
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(0,1));
+		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
+		_copy_screen();
+
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,false);
+
+
+		composite_from=storage->frame.current_rt->effects.mip_maps[0].color;
+
+	}
+
+	if (env->dof_blur_near_enabled) {
+
+		//blur diffuse into effect mipmaps using separatable convolution
+		//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
+
+		int vp_h = storage->frame.current_rt->height;
+		int vp_w = storage->frame.current_rt->width;
+
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR,true);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP,true);
+
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,env->dof_blur_near_quality==VS::ENV_DOF_BLUR_QUALITY_LOW);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,env->dof_blur_near_quality==VS::ENV_DOF_BLUR_QUALITY_MEDIUM);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,env->dof_blur_near_quality==VS::ENV_DOF_BLUR_QUALITY_HIGH);
+
+		state.effect_blur_shader.bind();
+		int qsteps[3]={4,10,20};
+
+		float radius = (env->dof_blur_near_amount*env->dof_blur_near_amount) / qsteps[env->dof_blur_near_quality];
+
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN,env->dof_blur_near_distance);
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END,env->dof_blur_near_distance-env->dof_blur_near_transition);
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(1,0));
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS,radius);
+		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::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
+
+		glActiveTexture(GL_TEXTURE1);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth);
+
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D,composite_from);
+		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);
+
+		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); //copy to front first
+
+		_copy_screen();
+		//manually do the blend if this is the first operation resolving from the diffuse buffer
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE,composite_from == storage->frame.current_rt->buffers.diffuse);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP,false);
+		state.effect_blur_shader.bind();
+
+
+
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_BEGIN,env->dof_blur_near_distance);
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_END,env->dof_blur_near_distance-env->dof_blur_near_transition);
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_DIR,Vector2(0,1));
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::DOF_RADIUS,radius);
+		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::CAMERA_Z_NEAR,p_cam_projection.get_z_near());
+		state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far());
+
+
+		glActiveTexture(GL_TEXTURE0);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->color);
+
+		glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level
+
+		if (composite_from != storage->frame.current_rt->buffers.diffuse) {
+
+			glEnable(GL_BLEND);
+			glBlendEquation(GL_FUNC_ADD);
+			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+		} else {
+			glActiveTexture(GL_TEXTURE2);
+			glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse);
+
+		}
+
+		_copy_screen();
+
+		if (composite_from != storage->frame.current_rt->buffers.diffuse) {
+
+			glDisable(GL_BLEND);
+		}
+
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_FIRST_TAP,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_NEAR_BLUR_MERGE,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM,false);
+		state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH,false);
+
+
+		composite_from=storage->frame.current_rt->effects.mip_maps[0].color;
+
+	}
+
 	if ( env->auto_exposure) {
 
 		//compute auto exposure
@@ -3266,6 +3447,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINDHART_TONEMAPPER,env->tone_mapper==VS::ENV_TONE_MAPPER_REINHARDT);
 
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE,env->auto_exposure);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC,env->glow_bicubic_upscale);
 
 
 
@@ -3315,6 +3497,12 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 	if (max_glow_level>=0) {
 
 		state.tonemap_shader.set_uniform(TonemapShaderGLES3::GLOW_INTENSITY,env->glow_intensity);
+		int ss[2]={
+			storage->frame.current_rt->width,
+			storage->frame.current_rt->height,
+		};
+		glUniform2iv(state.tonemap_shader.get_uniform(TonemapShaderGLES3::GLOW_TEXTURE_SIZE),1,ss);
+
 	}
 
 	if (env->auto_exposure)	{
@@ -3344,6 +3532,8 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE,false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN,false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT,false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_FILTER_BICUBIC,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){
@@ -3605,7 +3795,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C
 	}
 
 
-	_post_process(env);
+	_post_process(env,p_cam_projection);
 
 
 	if (false && shadow_atlas) {

+ 29 - 2
drivers/gles3/rasterizer_scene_gles3.h

@@ -349,6 +349,7 @@ public:
 		VS::EnvironmentGlowBlendMode glow_blend_mode;
 		float glow_hdr_bleed_treshold;
 		float glow_hdr_bleed_scale;
+		bool glow_bicubic_upscale;
 
 		VS::EnvironmentToneMapper tone_mapper;
 		float tone_mapper_exposure;
@@ -359,6 +360,17 @@ public:
 		float auto_exposure_max;
 		float auto_exposure_grey;
 
+		bool dof_blur_far_enabled;
+		float dof_blur_far_distance;
+		float dof_blur_far_transition;
+		float dof_blur_far_amount;
+		VS::EnvironmentDOFBlurQuality dof_blur_far_quality;
+
+		bool dof_blur_near_enabled;
+		float dof_blur_near_distance;
+		float dof_blur_near_transition;
+		float dof_blur_near_amount;
+		VS::EnvironmentDOFBlurQuality dof_blur_near_quality;
 
 		Environment() {
 			bg_mode=VS::ENV_BG_CLEAR_COLOR;
@@ -403,7 +415,19 @@ public:
 			glow_blend_mode=VS::GLOW_BLEND_MODE_SOFTLIGHT;
 			glow_hdr_bleed_treshold=1.0;
 			glow_hdr_bleed_scale=2.0;
+			glow_bicubic_upscale=false;
+
+			dof_blur_far_enabled=false;
+			dof_blur_far_distance=10;
+			dof_blur_far_transition=5;
+			dof_blur_far_amount=0.1;
+			dof_blur_far_quality=VS::ENV_DOF_BLUR_QUALITY_MEDIUM;
 
+			dof_blur_near_enabled=false;
+			dof_blur_near_distance=2;
+			dof_blur_near_transition=1;
+			dof_blur_near_amount=0.1;
+			dof_blur_near_quality=VS::ENV_DOF_BLUR_QUALITY_MEDIUM;
 
 		}
 	};
@@ -420,12 +444,15 @@ public:
 	virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer);
 	virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0);
 
-	virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale);
+	virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality);
+	virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality);
+	virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale);
 	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_ssao(RID p_env,bool p_enable, float p_radius, float p_radius2, float p_intensity2, float p_intensity, float p_bias, float p_light_affect,const Color &p_color,bool p_blur);
 
+
 	virtual void environment_set_tonemap(RID p_env,VS::EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale);
 
 	virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp);
@@ -663,7 +690,7 @@ public:
 	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);
-	void _post_process(Environment *env);
+	void _post_process(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_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count);

+ 157 - 20
drivers/gles3/shaders/effect_blur.glsl

@@ -41,6 +41,40 @@ uniform float glow_strength;
 
 #endif
 
+#if defined(DOF_FAR_BLUR) || defined (DOF_NEAR_BLUR)
+
+#ifdef DOF_QUALITY_LOW
+const int dof_kernel_size=5;
+const int dof_kernel_from=2;
+const float dof_kernel[5] = float[] (0.153388,0.221461,0.250301,0.221461,0.153388);
+#endif
+
+#ifdef DOF_QUALITY_MEDIUM
+const int dof_kernel_size=11;
+const int dof_kernel_from=5;
+const float dof_kernel[11] = float[] (0.055037,0.072806,0.090506,0.105726,0.116061,0.119726,0.116061,0.105726,0.090506,0.072806,0.055037);
+
+#endif
+
+#ifdef DOF_QUALITY_HIGH
+const int dof_kernel_size=21;
+const int dof_kernel_from=10;
+const float dof_kernel[21] = float[] (0.028174,0.032676,0.037311,0.041944,0.046421,0.050582,0.054261,0.057307,0.059587,0.060998,0.061476,0.060998,0.059587,0.057307,0.054261,0.050582,0.046421,0.041944,0.037311,0.032676,0.028174);
+#endif
+
+uniform sampler2D dof_source_depth; //texunit:1
+uniform float dof_begin;
+uniform float dof_end;
+uniform vec2 dof_dir;
+uniform float dof_radius;
+
+#ifdef DOF_NEAR_BLUR_MERGE
+
+uniform sampler2D source_dof_original; //texunit:2
+#endif
+
+#endif
+
 
 #ifdef GLOW_FIRST_PASS
 
@@ -60,16 +94,23 @@ uniform float glow_hdr_scale;
 
 #endif
 
+uniform float camera_z_far;
+uniform float camera_z_near;
+
 void main() {
 
 
 
 #ifdef GAUSSIAN_HORIZONTAL
-	vec4 color =textureLod( source_color,  uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.38774;
-	color+=textureLod( source_color,  uv_interp+vec2( 1.0, 0.0)*pixel_size,lod )*0.24477;
-	color+=textureLod( source_color,  uv_interp+vec2( 2.0, 0.0)*pixel_size,lod )*0.06136;
-	color+=textureLod( source_color,  uv_interp+vec2(-1.0, 0.0)*pixel_size,lod )*0.24477;
-	color+=textureLod( source_color,  uv_interp+vec2(-2.0, 0.0)*pixel_size,lod )*0.06136;
+	vec2 pix_size = pixel_size;
+	pix_size*=0.5; //reading from larger buffer, so use more samples
+	vec4 color =textureLod( source_color,  uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.214607;
+	color+=textureLod( source_color,  uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.189879;
+	color+=textureLod( source_color,  uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.157305;
+	color+=textureLod( source_color,  uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.071303;
+	color+=textureLod( source_color,  uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.189879;
+	color+=textureLod( source_color,  uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.157305;
+	color+=textureLod( source_color,  uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.071303;
 	frag_color = color;
 #endif
 
@@ -82,32 +123,126 @@ void main() {
 	frag_color = color;
 #endif
 
-
+//glow uses larger sigma for a more rounded blur effect
 
 #ifdef GLOW_GAUSSIAN_HORIZONTAL
-	vec4 color =textureLod( source_color,  uv_interp+vec2( 0.0, 0.0)*pixel_size,lod )*0.174938;
-	color+=textureLod( source_color,  uv_interp+vec2( 1.0, 0.0)*pixel_size,lod )*0.165569;
-	color+=textureLod( source_color,  uv_interp+vec2( 2.0, 0.0)*pixel_size,lod )*0.140367;
-	color+=textureLod( source_color,  uv_interp+vec2( 3.0, 0.0)*pixel_size,lod )*0.106595;
-	color+=textureLod( source_color,  uv_interp+vec2(-1.0, 0.0)*pixel_size,lod )*0.165569;
-	color+=textureLod( source_color,  uv_interp+vec2(-2.0, 0.0)*pixel_size,lod )*0.140367;
-	color+=textureLod( source_color,  uv_interp+vec2(-3.0, 0.0)*pixel_size,lod )*0.165569;
+	vec2 pix_size = pixel_size;
+	pix_size*=0.5; //reading from larger buffer, so use more samples
+	vec4 color =textureLod( source_color,  uv_interp+vec2( 0.0, 0.0)*pix_size,lod )*0.174938;
+	color+=textureLod( source_color,  uv_interp+vec2( 1.0, 0.0)*pix_size,lod )*0.165569;
+	color+=textureLod( source_color,  uv_interp+vec2( 2.0, 0.0)*pix_size,lod )*0.140367;
+	color+=textureLod( source_color,  uv_interp+vec2( 3.0, 0.0)*pix_size,lod )*0.106595;
+	color+=textureLod( source_color,  uv_interp+vec2(-1.0, 0.0)*pix_size,lod )*0.165569;
+	color+=textureLod( source_color,  uv_interp+vec2(-2.0, 0.0)*pix_size,lod )*0.140367;
+	color+=textureLod( source_color,  uv_interp+vec2(-3.0, 0.0)*pix_size,lod )*0.106595;
 	color*=glow_strength;
 	frag_color = color;
 #endif
 
 #ifdef GLOW_GAUSSIAN_VERTICAL
-	vec4 color =textureLod( source_color,  uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.174938;
-	color+=textureLod( source_color,  uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.165569;
-	color+=textureLod( source_color,  uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.140367;
-	color+=textureLod( source_color,  uv_interp+vec2(0.0, 3.0)*pixel_size,lod )*0.106595;
-	color+=textureLod( source_color,  uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.165569;
-	color+=textureLod( source_color,  uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.140367;
-	color+=textureLod( source_color,  uv_interp+vec2(0.0,-3.0)*pixel_size,lod )*0.165569;
+	vec4 color =textureLod( source_color,  uv_interp+vec2(0.0, 0.0)*pixel_size,lod )*0.288713;
+	color+=textureLod( source_color,  uv_interp+vec2(0.0, 1.0)*pixel_size,lod )*0.233062;
+	color+=textureLod( source_color,  uv_interp+vec2(0.0, 2.0)*pixel_size,lod )*0.122581;
+	color+=textureLod( source_color,  uv_interp+vec2(0.0,-1.0)*pixel_size,lod )*0.233062;
+	color+=textureLod( source_color,  uv_interp+vec2(0.0,-2.0)*pixel_size,lod )*0.122581;
 	color*=glow_strength;
 	frag_color = color;
 #endif
 
+#ifdef DOF_FAR_BLUR
+
+	vec4 color_accum = vec4(0.0);
+
+	float depth = textureLod( dof_source_depth, uv_interp, 0.0).r;
+	depth = depth * 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));
+
+	float amount = smoothstep(dof_begin,dof_end,depth);
+	float k_accum=0.0;
+
+	for(int i=0;i<dof_kernel_size;i++) {
+
+		int int_ofs = i-dof_kernel_from;
+		vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * amount * dof_radius;
+
+		float tap_k = dof_kernel[i];
+
+		float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r;
+		tap_depth = tap_depth * 2.0 - 1.0;
+		tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
+
+		float tap_amount = mix(smoothstep(dof_begin,dof_end,tap_depth),1.0,int_ofs==0);
+		tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect
+
+		vec4 tap_color = textureLod( source_color, tap_uv, 0.0) * tap_k;
+
+		k_accum+=tap_k*tap_amount;
+		color_accum+=tap_color*tap_amount;
+
+
+	}
+
+	if (k_accum>0.0) {
+		color_accum/=k_accum;
+	}
+
+	frag_color = color_accum;///k_accum;
+
+#endif
+
+#ifdef DOF_NEAR_BLUR
+
+	vec4 color_accum = vec4(0.0);
+
+	float max_accum=0;
+
+	for(int i=0;i<dof_kernel_size;i++) {
+
+		int int_ofs = i-dof_kernel_from;
+		vec2 tap_uv = uv_interp + dof_dir * float(int_ofs) * dof_radius;
+		float ofs_influence = max(0.0,1.0-float(abs(int_ofs))/float(dof_kernel_from));
+
+		float tap_k = dof_kernel[i];
+
+		vec4 tap_color = textureLod( source_color, tap_uv, 0.0);
+
+		float tap_depth = texture( dof_source_depth, tap_uv, 0.0).r;
+		tap_depth = tap_depth * 2.0 - 1.0;
+		tap_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - tap_depth * (camera_z_far - camera_z_near));
+		float tap_amount = 1.0-smoothstep(dof_end,dof_begin,tap_depth);
+		tap_amount*=tap_amount*tap_amount; //prevent undesired glow effect
+
+#ifdef DOF_NEAR_FIRST_TAP
+
+		tap_color.a= 1.0-smoothstep(dof_end,dof_begin,tap_depth);
+
+#endif
+
+		max_accum=max(max_accum,tap_amount*ofs_influence);
+
+		color_accum+=tap_color*tap_k;
+
+	}
+
+	color_accum.a=max(color_accum.a,sqrt(max_accum));
+
+
+#ifdef DOF_NEAR_BLUR_MERGE
+
+	vec4 original = textureLod( source_dof_original, uv_interp, 0.0);
+	color_accum = mix(original,color_accum,color_accum.a);
+
+#endif
+
+#ifndef DOF_NEAR_FIRST_TAP
+	//color_accum=vec4(vec3(color_accum.a),1.0);
+#endif
+	frag_color = color_accum;
+
+#endif
+
+
+
 #ifdef GLOW_FIRST_PASS
 
 #ifdef GLOW_USE_AUTO_EXPOSURE
@@ -137,5 +272,7 @@ void main() {
 	frag_color = vec4( mix(color.rgb,color.rgb*mix(ssao_color.rgb,vec3(1.0),ssao),color.a), 1.0 );
 
 #endif
+
+
 }
 

+ 92 - 7
drivers/gles3/shaders/tonemap.glsl

@@ -41,6 +41,90 @@ uniform highp float glow_intensity;
 
 layout(location = 0) out vec4 frag_color;
 
+#ifdef USE_GLOW_FILTER_BICUBIC
+
+// w0, w1, w2, and w3 are the four cubic B-spline basis functions
+float w0(float a)
+{
+    return (1.0/6.0)*(a*(a*(-a + 3.0) - 3.0) + 1.0);
+}
+
+float w1(float a)
+{
+    return (1.0/6.0)*(a*a*(3.0*a - 6.0) + 4.0);
+}
+
+float w2(float a)
+{
+    return (1.0/6.0)*(a*(a*(-3.0*a + 3.0) + 3.0) + 1.0);
+}
+
+float w3(float a)
+{
+    return (1.0/6.0)*(a*a*a);
+}
+
+// g0 and g1 are the two amplitude functions
+float g0(float a)
+{
+    return w0(a) + w1(a);
+}
+
+float g1(float a)
+{
+    return w2(a) + w3(a);
+}
+
+// h0 and h1 are the two offset functions
+float h0(float a)
+{
+    return -1.0 + w1(a) / (w0(a) + w1(a));
+}
+
+float h1(float a)
+{
+    return 1.0 + w3(a) / (w2(a) + w3(a));
+}
+
+uniform ivec2 glow_texture_size;
+
+vec4 texture2D_bicubic(sampler2D tex, vec2 uv,int p_lod)
+{
+	float lod=float(p_lod);
+	vec2 tex_size = vec2(glow_texture_size >> p_lod);
+	vec2 pixel_size =1.0/tex_size;
+	uv = uv*tex_size + 0.5;
+	vec2 iuv = floor( uv );
+	vec2 fuv = fract( uv );
+
+	float g0x = g0(fuv.x);
+	float g1x = g1(fuv.x);
+	float h0x = h0(fuv.x);
+	float h1x = h1(fuv.x);
+	float h0y = h0(fuv.y);
+	float h1y = h1(fuv.y);
+
+	vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - 0.5) * pixel_size;
+	vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - 0.5) * pixel_size;
+	vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - 0.5) * pixel_size;
+	vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - 0.5) * pixel_size;
+
+	return g0(fuv.y) * (g0x * textureLod(tex, p0,lod)  +
+			    g1x * textureLod(tex, p1,lod)) +
+			g1(fuv.y) * (g0x * textureLod(tex, p2,lod)  +
+				     g1x * textureLod(tex, p3,lod));
+}
+
+
+
+#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) texture2D_bicubic(m_tex,m_uv,m_lod)
+
+#else
+
+#define GLOW_TEXTURE_SAMPLE(m_tex,m_uv,m_lod) textureLod(m_tex,m_uv,float(m_lod))
+
+#endif
+
 
 void main() {
 
@@ -60,31 +144,32 @@ void main() {
 	vec3 glow = vec3(0.0);
 
 #ifdef USE_GLOW_LEVEL1
-	glow+=textureLod(source_glow,uv_interp,1.0).rgb;
+
+	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,1).rgb;
 #endif
 
 #ifdef USE_GLOW_LEVEL2
-	glow+=textureLod(source_glow,uv_interp,2.0).rgb;
+	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,2).rgb;
 #endif
 
 #ifdef USE_GLOW_LEVEL3
-	glow+=textureLod(source_glow,uv_interp,3.0).rgb;
+	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,3).rgb;
 #endif
 
 #ifdef USE_GLOW_LEVEL4
-	glow+=textureLod(source_glow,uv_interp,4.0).rgb;
+	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,4).rgb;
 #endif
 
 #ifdef USE_GLOW_LEVEL5
-	glow+=textureLod(source_glow,uv_interp,5.0).rgb;
+	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,5).rgb;
 #endif
 
 #ifdef USE_GLOW_LEVEL6
-	glow+=textureLod(source_glow,uv_interp,6.0).rgb;
+	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,6).rgb;
 #endif
 
 #ifdef USE_GLOW_LEVEL7
-	glow+=textureLod(source_glow,uv_interp,7.0).rgb;
+	glow+=GLOW_TEXTURE_SAMPLE(source_glow,uv_interp,7).rgb;
 #endif
 
 

+ 190 - 8
scene/resources/environment.cpp

@@ -477,7 +477,7 @@ bool Environment::is_ssao_blur_enabled() const {
 void Environment::set_glow_enabled(bool p_enabled) {
 
 	glow_enabled=p_enabled;
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 }
 
 bool Environment::is_glow_enabled() const{
@@ -494,7 +494,7 @@ void Environment::set_glow_level(int p_level,bool p_enabled){
 	else
 		glow_levels&=~(1<<p_level);
 
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 
 }
 bool Environment::is_glow_level_enabled(int p_level) const{
@@ -508,7 +508,7 @@ void Environment::set_glow_intensity(float p_intensity){
 
 	glow_intensity=p_intensity;
 
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 
 }
 float Environment::get_glow_intensity() const{
@@ -519,7 +519,7 @@ float Environment::get_glow_intensity() const{
 void Environment::set_glow_strength(float p_strength){
 
 	glow_strength=p_strength;
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 
 }
 float Environment::get_glow_strength() const{
@@ -531,7 +531,7 @@ void Environment::set_glow_bloom(float p_treshold){
 
 	glow_bloom=p_treshold;
 
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 
 }
 float Environment::get_glow_bloom() const{
@@ -543,7 +543,7 @@ void Environment::set_glow_blend_mode(GlowBlendMode p_mode){
 
 	glow_blend_mode=p_mode;
 
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 
 }
 Environment::GlowBlendMode Environment::get_glow_blend_mode() const{
@@ -555,7 +555,7 @@ void Environment::set_glow_hdr_bleed_treshold(float p_treshold){
 
 	glow_hdr_bleed_treshold=p_treshold;
 
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 
 }
 float Environment::get_glow_hdr_bleed_treshold() const{
@@ -567,7 +567,7 @@ void Environment::set_glow_hdr_bleed_scale(float p_scale){
 
 	glow_hdr_bleed_scale=p_scale;
 
-	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold);
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
 
 }
 float Environment::get_glow_hdr_bleed_scale() const{
@@ -575,7 +575,128 @@ float Environment::get_glow_hdr_bleed_scale() const{
 	return glow_hdr_bleed_scale;
 }
 
+void Environment::set_glow_bicubic_upscale(bool p_enable) {
 
+	glow_bicubic_upscale=p_enable;
+	VS::get_singleton()->environment_set_glow(environment,glow_enabled,glow_levels,glow_intensity,glow_strength,glow_bloom,VS::EnvironmentGlowBlendMode(glow_blend_mode),glow_hdr_bleed_treshold,glow_hdr_bleed_treshold,glow_bicubic_upscale);
+
+}
+
+bool Environment::is_glow_bicubic_upscale_enabled() const {
+
+	return glow_bicubic_upscale;
+}
+
+
+void Environment::set_dof_blur_far_enabled(bool p_enable) {
+
+	dof_blur_far_enabled=p_enable;
+	VS::get_singleton()->environment_set_dof_blur_far(environment,dof_blur_far_enabled,dof_blur_far_distance,dof_blur_far_transition,dof_blur_far_amount,VS::EnvironmentDOFBlurQuality(dof_blur_far_quality));
+}
+
+bool Environment::is_dof_blur_far_enabled() const{
+
+	return dof_blur_far_enabled;
+}
+
+void Environment::set_dof_blur_far_distance(float p_distance){
+
+	dof_blur_far_distance=p_distance;
+	VS::get_singleton()->environment_set_dof_blur_far(environment,dof_blur_far_enabled,dof_blur_far_distance,dof_blur_far_transition,dof_blur_far_amount,VS::EnvironmentDOFBlurQuality(dof_blur_far_quality));
+
+}
+float Environment::get_dof_blur_far_distance() const{
+
+	return dof_blur_far_distance;
+}
+
+void Environment::set_dof_blur_far_transition(float p_distance){
+
+	dof_blur_far_transition=p_distance;
+	VS::get_singleton()->environment_set_dof_blur_far(environment,dof_blur_far_enabled,dof_blur_far_distance,dof_blur_far_transition,dof_blur_far_amount,VS::EnvironmentDOFBlurQuality(dof_blur_far_quality));
+}
+float Environment::get_dof_blur_far_transition() const{
+
+	return dof_blur_far_transition;
+}
+
+void Environment::set_dof_blur_far_amount(float p_amount){
+
+	dof_blur_far_amount=p_amount;
+	VS::get_singleton()->environment_set_dof_blur_far(environment,dof_blur_far_enabled,dof_blur_far_distance,dof_blur_far_transition,dof_blur_far_amount,VS::EnvironmentDOFBlurQuality(dof_blur_far_quality));
+
+}
+float Environment::get_dof_blur_far_amount() const{
+
+	return dof_blur_far_amount;
+}
+
+void Environment::set_dof_blur_far_quality(DOFBlurQuality p_quality) {
+
+	dof_blur_far_quality=p_quality;
+	VS::get_singleton()->environment_set_dof_blur_far(environment,dof_blur_far_enabled,dof_blur_far_distance,dof_blur_far_transition,dof_blur_far_amount,VS::EnvironmentDOFBlurQuality(dof_blur_far_quality));
+}
+
+Environment::DOFBlurQuality Environment::get_dof_blur_far_quality() const {
+
+	return dof_blur_far_quality;
+}
+
+
+void Environment::set_dof_blur_near_enabled(bool p_enable) {
+
+	dof_blur_near_enabled=p_enable;
+	VS::get_singleton()->environment_set_dof_blur_near(environment,dof_blur_near_enabled,dof_blur_near_distance,dof_blur_near_transition,dof_blur_near_amount,VS::EnvironmentDOFBlurQuality(dof_blur_near_quality));
+}
+
+bool Environment::is_dof_blur_near_enabled() const{
+
+	return dof_blur_near_enabled;
+}
+
+void Environment::set_dof_blur_near_distance(float p_distance){
+
+	dof_blur_near_distance=p_distance;
+	VS::get_singleton()->environment_set_dof_blur_near(environment,dof_blur_near_enabled,dof_blur_near_distance,dof_blur_near_transition,dof_blur_near_amount,VS::EnvironmentDOFBlurQuality(dof_blur_near_quality));
+}
+
+float Environment::get_dof_blur_near_distance() const{
+
+	return dof_blur_near_distance;
+}
+
+void Environment::set_dof_blur_near_transition(float p_distance){
+
+	dof_blur_near_transition=p_distance;
+	VS::get_singleton()->environment_set_dof_blur_near(environment,dof_blur_near_enabled,dof_blur_near_distance,dof_blur_near_transition,dof_blur_near_amount,VS::EnvironmentDOFBlurQuality(dof_blur_near_quality));
+}
+
+float Environment::get_dof_blur_near_transition() const{
+
+	return dof_blur_near_transition;
+}
+
+void Environment::set_dof_blur_near_amount(float p_amount){
+
+	dof_blur_near_amount=p_amount;
+	VS::get_singleton()->environment_set_dof_blur_near(environment,dof_blur_near_enabled,dof_blur_near_distance,dof_blur_near_transition,dof_blur_near_amount,VS::EnvironmentDOFBlurQuality(dof_blur_near_quality));
+}
+
+float Environment::get_dof_blur_near_amount() const{
+
+	return dof_blur_near_amount;
+}
+
+void Environment::set_dof_blur_near_quality(DOFBlurQuality p_quality) {
+
+	dof_blur_near_quality=p_quality;
+	VS::get_singleton()->environment_set_dof_blur_near(environment,dof_blur_near_enabled,dof_blur_near_distance,dof_blur_near_transition,dof_blur_near_amount,VS::EnvironmentDOFBlurQuality(dof_blur_near_quality));
+}
+
+Environment::DOFBlurQuality Environment::get_dof_blur_near_quality() const {
+
+	return dof_blur_near_quality;
+}
 
 
 void Environment::_bind_methods() {
@@ -679,6 +800,48 @@ void Environment::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::COLOR,"ambient_occlusion/color",PROPERTY_HINT_COLOR_NO_ALPHA),_SCS("set_ssao_color"),_SCS("get_ssao_color") );
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ambient_occlusion/blur"),_SCS("set_ssao_blur"),_SCS("is_ssao_blur_enabled") );
 
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_far_enabled","enabled"),&Environment::set_dof_blur_far_enabled);
+	ObjectTypeDB::bind_method(_MD("is_dof_blur_far_enabled"),&Environment::is_dof_blur_far_enabled);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_far_distance","intensity"),&Environment::set_dof_blur_far_distance);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_far_distance"),&Environment::get_dof_blur_far_distance);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_far_transition","intensity"),&Environment::set_dof_blur_far_transition);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_far_transition"),&Environment::get_dof_blur_far_transition);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_far_amount","intensity"),&Environment::set_dof_blur_far_amount);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_far_amount"),&Environment::get_dof_blur_far_amount);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_far_quality","intensity"),&Environment::set_dof_blur_far_quality);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_far_quality"),&Environment::get_dof_blur_far_quality);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_near_enabled","enabled"),&Environment::set_dof_blur_near_enabled);
+	ObjectTypeDB::bind_method(_MD("is_dof_blur_near_enabled"),&Environment::is_dof_blur_near_enabled);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_near_distance","intensity"),&Environment::set_dof_blur_near_distance);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_near_distance"),&Environment::get_dof_blur_near_distance);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_near_transition","intensity"),&Environment::set_dof_blur_near_transition);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_near_transition"),&Environment::get_dof_blur_near_transition);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_near_amount","intensity"),&Environment::set_dof_blur_near_amount);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_near_amount"),&Environment::get_dof_blur_near_amount);
+
+	ObjectTypeDB::bind_method(_MD("set_dof_blur_near_quality","level"),&Environment::set_dof_blur_near_quality);
+	ObjectTypeDB::bind_method(_MD("get_dof_blur_near_quality"),&Environment::get_dof_blur_near_quality);
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"dof_blur_far/enabled"),_SCS("set_dof_blur_far_enabled"),_SCS("is_dof_blur_far_enabled") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far/distance",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_far_distance"),_SCS("get_dof_blur_far_distance") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far/transition",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_far_transition"),_SCS("get_dof_blur_far_transition") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_far/amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dof_blur_far_amount"),_SCS("get_dof_blur_far_amount") );
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"dof_blur_far/quality",PROPERTY_HINT_ENUM,"Low,Medium,High"),_SCS("set_dof_blur_far_quality"),_SCS("get_dof_blur_far_quality") );
+
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"dof_blur_near/enabled"),_SCS("set_dof_blur_near_enabled"),_SCS("is_dof_blur_near_enabled") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near/distance",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_near_distance"),_SCS("get_dof_blur_near_distance") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near/transition",PROPERTY_HINT_EXP_RANGE,"0.01,8192,0.01"),_SCS("set_dof_blur_near_transition"),_SCS("get_dof_blur_near_transition") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"dof_blur_near/amount",PROPERTY_HINT_RANGE,"0,1,0.01"),_SCS("set_dof_blur_near_amount"),_SCS("get_dof_blur_near_amount") );
+	ADD_PROPERTY(PropertyInfo(Variant::INT,"dof_blur_near/quality",PROPERTY_HINT_ENUM,"Low,Medium,High"),_SCS("set_dof_blur_near_quality"),_SCS("get_dof_blur_near_quality") );
+
 
 	ObjectTypeDB::bind_method(_MD("set_glow_enabled","enabled"),&Environment::set_glow_enabled);
 	ObjectTypeDB::bind_method(_MD("is_glow_enabled"),&Environment::is_glow_enabled);
@@ -704,6 +867,8 @@ void Environment::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_glow_hdr_bleed_scale","scale"),&Environment::set_glow_hdr_bleed_scale);
 	ObjectTypeDB::bind_method(_MD("get_glow_hdr_bleed_scale"),&Environment::get_glow_hdr_bleed_scale);
 
+	ObjectTypeDB::bind_method(_MD("set_glow_bicubic_upscale","enabled"),&Environment::set_glow_bicubic_upscale);
+	ObjectTypeDB::bind_method(_MD("is_glow_bicubic_upscale_enabled"),&Environment::is_glow_bicubic_upscale_enabled);
 
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"glow/enabled"),_SCS("set_glow_enabled"),_SCS("is_glow_enabled") );
 	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow/levels/1"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),0 );
@@ -720,6 +885,7 @@ void Environment::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"glow/blend_mode",PROPERTY_HINT_ENUM,"Additive,Screen,Softlight,Replace"),_SCS("set_glow_blend_mode"),_SCS("get_glow_blend_mode") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow/hdr_treshold",PROPERTY_HINT_RANGE,"0.0,4.0,0.01"),_SCS("set_glow_hdr_bleed_treshold"),_SCS("get_glow_hdr_bleed_treshold") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow/hdr_scale",PROPERTY_HINT_RANGE,"0.0,4.0,0.01"),_SCS("set_glow_hdr_bleed_scale"),_SCS("get_glow_hdr_bleed_scale") );
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"glow/bicubic_upscale"),_SCS("set_glow_bicubic_upscale"),_SCS("is_glow_bicubic_upscale_enabled") );
 
 
 	ObjectTypeDB::bind_method(_MD("set_tonemapper","mode"),&Environment::set_tonemapper);
@@ -795,6 +961,9 @@ void Environment::_bind_methods() {
 	BIND_CONSTANT(TONE_MAPPER_REINHARDT);
 	BIND_CONSTANT(TONE_MAPPER_FILMIC);
 	BIND_CONSTANT(TONE_MAPPER_ACES);
+	BIND_CONSTANT(DOF_BLUR_QUALITY_LOW);
+	BIND_CONSTANT(DOF_BLUR_QUALITY_MEDIUM);
+	BIND_CONSTANT(DOF_BLUR_QUALITY_HIGH);
 
 
 }
@@ -854,6 +1023,19 @@ Environment::Environment() {
 	glow_blend_mode=GLOW_BLEND_MODE_SOFTLIGHT;
 	glow_hdr_bleed_treshold=1.0;
 	glow_hdr_bleed_scale=2.0;
+	glow_bicubic_upscale=false;
+
+	dof_blur_far_enabled=false;
+	dof_blur_far_distance=10;
+	dof_blur_far_transition=5;
+	dof_blur_far_amount=0.1;
+	dof_blur_far_quality=DOF_BLUR_QUALITY_MEDIUM;
+
+	dof_blur_near_enabled=false;
+	dof_blur_near_distance=2;
+	dof_blur_near_transition=1;
+	dof_blur_near_amount=0.1;
+	dof_blur_near_quality=DOF_BLUR_QUALITY_MEDIUM;
 
 }
 

+ 51 - 2
scene/resources/environment.h

@@ -65,6 +65,11 @@ public:
 		GLOW_BLEND_MODE_REPLACE,
 	};
 
+	enum DOFBlurQuality {
+		DOF_BLUR_QUALITY_LOW,
+		DOF_BLUR_QUALITY_MEDIUM,
+		DOF_BLUR_QUALITY_HIGH,
+	};
 
 private:
 	RID environment;
@@ -120,7 +125,19 @@ private:
 	GlowBlendMode glow_blend_mode;
 	float glow_hdr_bleed_treshold;
 	float glow_hdr_bleed_scale;
+	bool glow_bicubic_upscale;
+
+	bool dof_blur_far_enabled;
+	float dof_blur_far_distance;
+	float dof_blur_far_transition;
+	float dof_blur_far_amount;
+	DOFBlurQuality dof_blur_far_quality;
 
+	bool dof_blur_near_enabled;
+	float dof_blur_near_distance;
+	float dof_blur_near_transition;
+	float dof_blur_near_amount;
+	DOFBlurQuality dof_blur_near_quality;
 
 protected:
 
@@ -199,7 +216,7 @@ public:
 	void set_ssr_accel(float p_accel);
 	float get_ssr_accel() const;
 
-	void set_ssr_fade(float p_fade);
+	void set_ssr_fade(float p_transition);
 	float get_ssr_fade() const;
 
 	void set_ssr_depth_tolerance(float p_depth_tolerance);
@@ -263,6 +280,38 @@ public:
 	void set_glow_hdr_bleed_scale(float p_scale);
 	float get_glow_hdr_bleed_scale() const;
 
+	void set_glow_bicubic_upscale(bool p_enable);
+	bool is_glow_bicubic_upscale_enabled() const;
+
+	void set_dof_blur_far_enabled(bool p_enable);
+	bool is_dof_blur_far_enabled() const;
+
+	void set_dof_blur_far_distance(float p_distance);
+	float get_dof_blur_far_distance() const;
+
+	void set_dof_blur_far_transition(float p_distance);
+	float get_dof_blur_far_transition() const;
+
+	void set_dof_blur_far_amount(float p_amount);
+	float get_dof_blur_far_amount() const;
+
+	void set_dof_blur_far_quality(DOFBlurQuality p_quality);
+	DOFBlurQuality get_dof_blur_far_quality() const;
+
+	void set_dof_blur_near_enabled(bool p_enable);
+	bool is_dof_blur_near_enabled() const;
+
+	void set_dof_blur_near_distance(float p_distance);
+	float get_dof_blur_near_distance() const;
+
+	void set_dof_blur_near_transition(float p_distance);
+	float get_dof_blur_near_transition() const;
+
+	void set_dof_blur_near_amount(float p_amount);
+	float get_dof_blur_near_amount() const;
+
+	void set_dof_blur_near_quality(DOFBlurQuality p_quality);
+	DOFBlurQuality get_dof_blur_near_quality() const;
 
 
 	virtual RID get_rid() const;
@@ -277,6 +326,6 @@ public:
 VARIANT_ENUM_CAST(Environment::BGMode)
 VARIANT_ENUM_CAST(Environment::ToneMapper)
 VARIANT_ENUM_CAST(Environment::GlowBlendMode)
-
+VARIANT_ENUM_CAST(Environment::DOFBlurQuality)
 
 #endif // ENVIRONMENT_H

+ 3 - 1
servers/visual/rasterizer.h

@@ -61,7 +61,9 @@ public:
 	virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer)=0;
 	virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0)=0;
 
-	virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale)=0;
+	virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0;
+	virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0;
+	virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=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;

+ 4 - 1
servers/visual/visual_server_raster.h

@@ -879,7 +879,10 @@ public:
 	BIND10(environment_set_ssao,RID ,bool , float , float , float,float,float , float ,const Color &,bool )
 
 
-	BIND9(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode,float,float )
+
+	BIND6(environment_set_dof_blur_near,RID,bool ,float,float,float,EnvironmentDOFBlurQuality)
+	BIND6(environment_set_dof_blur_far,RID,bool ,float,float,float,EnvironmentDOFBlurQuality)
+	BIND10(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode,float,float,bool )
 	BIND5(environment_set_fog,RID,bool ,float ,float ,RID )
 
 	BIND9(environment_set_tonemap,RID,EnvironmentToneMapper, float ,float ,bool, float ,float ,float,float  )

+ 10 - 1
servers/visual_server.h

@@ -536,13 +536,22 @@ public:
 	//set default SSR options
 	//set default SSSSS options
 
+	enum EnvironmentDOFBlurQuality {
+		ENV_DOF_BLUR_QUALITY_LOW,
+		ENV_DOF_BLUR_QUALITY_MEDIUM,
+		ENV_DOF_BLUR_QUALITY_HIGH,
+	};
+
+	virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0;
+	virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0;
+
 	enum EnvironmentGlowBlendMode {
 		GLOW_BLEND_MODE_ADDITIVE,
 		GLOW_BLEND_MODE_SCREEN,
 		GLOW_BLEND_MODE_SOFTLIGHT,
 		GLOW_BLEND_MODE_REPLACE,
 	};
-	virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale)=0;
+	virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=0;
 	virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0;