Browse Source

Multi stage glow with light bleeding from HDR

Juan Linietsky 8 years ago
parent
commit
18ebd22000

+ 158 - 2
drivers/gles3/rasterizer_scene_gles3.cpp

@@ -850,7 +850,19 @@ void RasterizerSceneGLES3::environment_set_ambient_light(RID p_env, const Color&
 
 }
 
-void RasterizerSceneGLES3::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){
+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) {
+
+	Environment *env=environment_owner.getornull(p_env);
+	ERR_FAIL_COND(!env);
+
+	env->glow_enabled=p_enable;
+	env->glow_levels=p_level_flags;
+	env->glow_intensity=p_intensity;
+	env->glow_strength=p_strength;
+	env->glow_bloom=p_bloom_treshold;
+	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;
 
 }
 void RasterizerSceneGLES3::environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture){
@@ -3155,6 +3167,95 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 	}
 
 
+	int max_glow_level=-1;
+	int glow_mask=0;
+
+
+	if (env->glow_enabled) {
+
+
+		for(int i=0;i<VS::MAX_GLOW_LEVELS;i++) {
+			if (env->glow_levels&(1<<i)) {
+
+				if (i>=storage->frame.current_rt->effects.mip_maps[1].sizes.size()) {
+					max_glow_level=storage->frame.current_rt->effects.mip_maps[1].sizes.size()-1;
+					glow_mask|=1<<max_glow_level;
+
+				} else {
+					max_glow_level=i;
+					glow_mask|=(1<<i);
+				}
+
+			}
+		}
+
+
+		//blur diffuse into effect mipmaps using separatable convolution
+		//storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true);
+
+		for(int i=0;i<(max_glow_level+1);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
+			if (i==0) {
+				state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS,true);
+				state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE,env->auto_exposure);
+			}
+
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_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));
+			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH,env->glow_strength);
+
+			glActiveTexture(GL_TEXTURE0);
+			if (i==0) {
+				glBindTexture(GL_TEXTURE_2D,composite_from);
+
+				state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::EXPOSURE,env->tone_mapper_exposure);
+				if (env->auto_exposure) {
+					state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::AUTO_EXPOSURE_GREY,env->auto_exposure_grey);
+				}
+
+				glActiveTexture(GL_TEXTURE1);
+				glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color);
+
+				state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_BLOOM,env->glow_bloom);
+				state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_TRESHOLD,env->glow_hdr_bleed_treshold);
+				state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_HDR_SCALE,env->glow_hdr_bleed_scale);
+
+			} 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::GLOW_GAUSSIAN_HORIZONTAL,false);
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_FIRST_PASS,false);
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_USE_AUTO_EXPOSURE,false);
+
+			//vertical pass
+			state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GLOW_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));
+			state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::GLOW_STRENGTH,env->glow_strength);
+			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::GLOW_GAUSSIAN_VERTICAL,false);
+		}
+
+		glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height);
+
+	}
+
+
+
+
 	glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo);
 
 	glActiveTexture(GL_TEXTURE0);
@@ -3166,11 +3267,55 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE,env->auto_exposure);
 
+
+
+	if (max_glow_level>=0) {
+
+
+		for(int i=0;i<(max_glow_level+1);i++) {
+
+			if (glow_mask&(1<<i)) {
+				if (i==0) {
+					state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL1,true);
+				}
+				if (i==1) {
+					state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2,true);
+				}
+				if (i==2) {
+					state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3,true);
+				}
+				if (i==3) {
+					state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL4,true);
+				}
+				if (i==4) {
+					state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL5,true);
+				}
+				if (i==5) {
+					state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL6,true);
+				}
+				if (i==6) {
+					state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL7,true);
+				}
+			}
+		}
+
+		state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SCREEN,env->glow_blend_mode==VS::GLOW_BLEND_MODE_SCREEN);
+		state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_SOFTLIGHT,env->glow_blend_mode==VS::GLOW_BLEND_MODE_SOFTLIGHT);
+		state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_REPLACE,env->glow_blend_mode==VS::GLOW_BLEND_MODE_REPLACE);
+		glActiveTexture(GL_TEXTURE2);
+		glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color);
+
+	}
+
 	state.tonemap_shader.bind();
 
 	state.tonemap_shader.set_uniform(TonemapShaderGLES3::EXPOSURE,env->tone_mapper_exposure);
 	state.tonemap_shader.set_uniform(TonemapShaderGLES3::WHITE,env->tone_mapper_exposure_white);
 
+	if (max_glow_level>=0) {
+
+		state.tonemap_shader.set_uniform(TonemapShaderGLES3::GLOW_INTENSITY,env->glow_intensity);
+	}
 
 	if (env->auto_exposure)	{
 
@@ -3180,6 +3325,8 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 
 	}
 
+
+
 	_copy_screen();
 
 	//turn off everything used
@@ -3187,7 +3334,16 @@ void RasterizerSceneGLES3::_post_process(Environment *env){
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER,false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER,false);
 	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_REINDHART_TONEMAPPER,false);
-
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL1,false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL2,false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL3,false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL4,false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL5,false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL6,false);
+	state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_GLOW_LEVEL7,false);
+	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);
 }
 
 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){

+ 21 - 1
drivers/gles3/rasterizer_scene_gles3.h

@@ -341,6 +341,15 @@ public:
 		Color ssao_color;
 		bool ssao_filter;
 
+		bool glow_enabled;
+		int glow_levels;
+		float glow_intensity;
+		float glow_strength;
+		float glow_bloom;
+		VS::EnvironmentGlowBlendMode glow_blend_mode;
+		float glow_hdr_bleed_treshold;
+		float glow_hdr_bleed_scale;
+
 		VS::EnvironmentToneMapper tone_mapper;
 		float tone_mapper_exposure;
 		float tone_mapper_exposure_white;
@@ -350,6 +359,7 @@ public:
 		float auto_exposure_max;
 		float auto_exposure_grey;
 
+
 		Environment() {
 			bg_mode=VS::ENV_BG_CLEAR_COLOR;
 			skybox_scale=1.0;
@@ -385,6 +395,16 @@ public:
 			auto_exposure_max=8;
 			auto_exposure_grey=0.4;
 
+			glow_enabled=false;
+			glow_levels=(1<<2)|(1<<4);
+			glow_intensity=0.8;
+			glow_strength=1.0;
+			glow_bloom=0.0;
+			glow_blend_mode=VS::GLOW_BLEND_MODE_SOFTLIGHT;
+			glow_hdr_bleed_treshold=1.0;
+			glow_hdr_bleed_scale=2.0;
+
+
 		}
 	};
 
@@ -400,7 +420,7 @@ 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_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_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_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);

+ 2 - 2
drivers/gles3/rasterizer_storage_gles3.cpp

@@ -5020,8 +5020,8 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){
 				w>>=1;
 				h>>=1;
 
-				if (w<32 || h<32)
-					break; //going less than 32 is pointless
+				if (w<2 || h<2)
+					break;
 
 				level++;
 

+ 67 - 0
drivers/gles3/shaders/effect_blur.glsl

@@ -35,6 +35,31 @@ uniform vec4 ssao_color;
 
 #endif
 
+#if defined (GLOW_GAUSSIAN_HORIZONTAL) || defined(GLOW_GAUSSIAN_VERTICAL)
+
+uniform float glow_strength;
+
+#endif
+
+
+#ifdef GLOW_FIRST_PASS
+
+uniform float exposure;
+uniform float white;
+
+#ifdef GLOW_USE_AUTO_EXPOSURE
+
+uniform highp sampler2D source_auto_exposure; //texunit:1
+uniform highp float auto_exposure_grey;
+
+#endif
+
+uniform float glow_bloom;
+uniform float glow_hdr_treshold;
+uniform float glow_hdr_scale;
+
+#endif
+
 void main() {
 
 
@@ -57,6 +82,48 @@ void main() {
 	frag_color = color;
 #endif
 
+
+
+#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;
+	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;
+	color*=glow_strength;
+	frag_color = color;
+#endif
+
+#ifdef GLOW_FIRST_PASS
+
+#ifdef GLOW_USE_AUTO_EXPOSURE
+
+	frag_color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey;
+#endif
+	frag_color*=exposure;
+
+	float luminance = max(frag_color.r,max(frag_color.g,frag_color.b));
+	float feedback = max( smoothstep(glow_hdr_treshold,glow_hdr_treshold+glow_hdr_scale,luminance), glow_bloom );
+
+	frag_color *= feedback;
+
+#endif
+
+
 #ifdef SIMPLE_COPY
 	vec4 color =textureLod( source_color,  uv_interp,0.0);
 	frag_color = color;

+ 81 - 0
drivers/gles3/shaders/tonemap.glsl

@@ -2,17 +2,24 @@
 
 
 layout(location=0) in highp vec4 vertex_attrib;
+layout(location=4) in vec2 uv_in;
+
+out vec2 uv_interp;
+
 
 
 void main() {
 
 	gl_Position = vertex_attrib;
+	uv_interp = uv_in;
 
 }
 
 [fragment]
 
 
+in vec2 uv_interp;
+
 uniform highp sampler2D source; //texunit:0
 
 uniform float exposure;
@@ -25,6 +32,12 @@ uniform highp float auto_exposure_grey;
 
 #endif
 
+#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
+
+uniform highp sampler2D source_glow; //texunit:2
+uniform highp float glow_intensity;
+
+#endif
 
 layout(location = 0) out vec4 frag_color;
 
@@ -43,6 +56,74 @@ void main() {
 	color*=exposure;
 
 
+#if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7)
+	vec3 glow = vec3(0.0);
+
+#ifdef USE_GLOW_LEVEL1
+	glow+=textureLod(source_glow,uv_interp,1.0).rgb;
+#endif
+
+#ifdef USE_GLOW_LEVEL2
+	glow+=textureLod(source_glow,uv_interp,2.0).rgb;
+#endif
+
+#ifdef USE_GLOW_LEVEL3
+	glow+=textureLod(source_glow,uv_interp,3.0).rgb;
+#endif
+
+#ifdef USE_GLOW_LEVEL4
+	glow+=textureLod(source_glow,uv_interp,4.0).rgb;
+#endif
+
+#ifdef USE_GLOW_LEVEL5
+	glow+=textureLod(source_glow,uv_interp,5.0).rgb;
+#endif
+
+#ifdef USE_GLOW_LEVEL6
+	glow+=textureLod(source_glow,uv_interp,6.0).rgb;
+#endif
+
+#ifdef USE_GLOW_LEVEL7
+	glow+=textureLod(source_glow,uv_interp,7.0).rgb;
+#endif
+
+
+	glow *= glow_intensity;
+
+
+
+#ifdef USE_GLOW_REPLACE
+
+	color.rgb = glow;
+
+#endif
+
+#ifdef USE_GLOW_SCREEN
+
+	color.rgb = clamp((color.rgb + glow) - (color.rgb * glow), 0.0, 1.0);
+
+#endif
+
+#ifdef USE_GLOW_SOFTLIGHT
+
+	{
+
+		glow = (glow * 0.5) + 0.5;
+		color.r =  (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r)));
+		color.g =  (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g)));
+		color.b =  (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b)));
+	}
+
+#endif
+
+#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE)
+	color.rgb+=glow;
+#endif
+
+
+#endif
+
+
 #ifdef USE_REINDHART_TONEMAPPER
 
 	{

+ 159 - 6
scene/resources/environment.cpp

@@ -474,6 +474,110 @@ bool Environment::is_ssao_blur_enabled() const {
 	return ssao_blur;
 }
 
+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);
+}
+
+bool Environment::is_glow_enabled() const{
+
+	return glow_enabled;
+}
+
+void Environment::set_glow_level(int p_level,bool p_enabled){
+
+	ERR_FAIL_INDEX(p_level,VS::MAX_GLOW_LEVELS);
+
+	if (p_enabled)
+		glow_levels|=(1<<p_level);
+	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);
+
+}
+bool Environment::is_glow_level_enabled(int p_level) const{
+
+	ERR_FAIL_INDEX_V(p_level,VS::MAX_GLOW_LEVELS,false);
+
+	return glow_levels&(1<<p_level);
+}
+
+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);
+
+}
+float Environment::get_glow_intensity() const{
+
+	return glow_intensity;
+}
+
+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);
+
+}
+float Environment::get_glow_strength() const{
+
+	return glow_strength;
+}
+
+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);
+
+}
+float Environment::get_glow_bloom() const{
+
+	return glow_bloom;
+}
+
+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);
+
+}
+Environment::GlowBlendMode Environment::get_glow_blend_mode() const{
+
+	return glow_blend_mode;
+}
+
+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);
+
+}
+float Environment::get_glow_hdr_bleed_treshold() const{
+
+	return glow_hdr_bleed_treshold;
+}
+
+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);
+
+}
+float Environment::get_glow_hdr_bleed_scale() const{
+
+	return glow_hdr_bleed_scale;
+}
+
+
+
+
 void Environment::_bind_methods() {
 
 	ObjectTypeDB::bind_method(_MD("set_background","mode"),&Environment::set_background);
@@ -530,7 +634,7 @@ void Environment::_bind_methods() {
 	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::BOOL,"ss_reflections/enabled"),_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") );
@@ -565,7 +669,7 @@ void Environment::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("set_ssao_blur","enabled"),&Environment::set_ssao_blur);
 	ObjectTypeDB::bind_method(_MD("is_ssao_blur_enabled"),&Environment::is_ssao_blur_enabled);
 
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ambient_occlusion/enable"),_SCS("set_ssao_enabled"),_SCS("is_ssao_enabled") );
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ambient_occlusion/enabled"),_SCS("set_ssao_enabled"),_SCS("is_ssao_enabled") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/radius",PROPERTY_HINT_RANGE,"0.1,16,0.1"),_SCS("set_ssao_radius"),_SCS("get_ssao_radius") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/intensity",PROPERTY_HINT_RANGE,"0.0,9,0.1"),_SCS("set_ssao_intensity"),_SCS("get_ssao_intensity") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/radius2",PROPERTY_HINT_RANGE,"0.0,16,0.1"),_SCS("set_ssao_radius2"),_SCS("get_ssao_radius2") );
@@ -576,6 +680,48 @@ void Environment::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ambient_occlusion/blur"),_SCS("set_ssao_blur"),_SCS("is_ssao_blur_enabled") );
 
 
+	ObjectTypeDB::bind_method(_MD("set_glow_enabled","enabled"),&Environment::set_glow_enabled);
+	ObjectTypeDB::bind_method(_MD("is_glow_enabled"),&Environment::is_glow_enabled);
+
+	ObjectTypeDB::bind_method(_MD("set_glow_level","idx","enabled"),&Environment::set_glow_level);
+	ObjectTypeDB::bind_method(_MD("is_glow_level_enabled","idx"),&Environment::is_glow_level_enabled);
+
+	ObjectTypeDB::bind_method(_MD("set_glow_intensity","intensity"),&Environment::set_glow_intensity);
+	ObjectTypeDB::bind_method(_MD("get_glow_intensity"),&Environment::get_glow_intensity);
+
+	ObjectTypeDB::bind_method(_MD("set_glow_strength","strength"),&Environment::set_glow_strength);
+	ObjectTypeDB::bind_method(_MD("get_glow_strength"),&Environment::get_glow_strength);
+
+	ObjectTypeDB::bind_method(_MD("set_glow_bloom","amount"),&Environment::set_glow_bloom);
+	ObjectTypeDB::bind_method(_MD("get_glow_bloom"),&Environment::get_glow_bloom);
+
+	ObjectTypeDB::bind_method(_MD("set_glow_blend_mode","mode"),&Environment::set_glow_blend_mode);
+	ObjectTypeDB::bind_method(_MD("get_glow_blend_mode"),&Environment::get_glow_blend_mode);
+
+	ObjectTypeDB::bind_method(_MD("set_glow_hdr_bleed_treshold","treshold"),&Environment::set_glow_hdr_bleed_treshold);
+	ObjectTypeDB::bind_method(_MD("get_glow_hdr_bleed_treshold"),&Environment::get_glow_hdr_bleed_treshold);
+
+	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);
+
+
+	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 );
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow/levels/2"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),1 );
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow/levels/3"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),2 );
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow/levels/4"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),3 );
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow/levels/5"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),4 );
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow/levels/6"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),5 );
+	ADD_PROPERTYI(PropertyInfo(Variant::BOOL,"glow/levels/7"),_SCS("set_glow_level"),_SCS("is_glow_level_enabled"),6 );
+
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow/intensity",PROPERTY_HINT_RANGE,"0.0,8.0,0.01"),_SCS("set_glow_intensity"),_SCS("get_glow_intensity") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow/strength",PROPERTY_HINT_RANGE,"0.0,2.0,0.01"),_SCS("set_glow_strength"),_SCS("get_glow_strength") );
+	ADD_PROPERTY(PropertyInfo(Variant::REAL,"glow/bloom",PROPERTY_HINT_RANGE,"0.0,1.0,0.01"),_SCS("set_glow_bloom"),_SCS("get_glow_bloom") );
+	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") );
+
+
 	ObjectTypeDB::bind_method(_MD("set_tonemapper","mode"),&Environment::set_tonemapper);
 	ObjectTypeDB::bind_method(_MD("get_tonemapper"),&Environment::get_tonemapper);
 
@@ -601,12 +747,10 @@ void Environment::_bind_methods() {
 	ObjectTypeDB::bind_method(_MD("get_tonemap_auto_exposure_grey"),&Environment::get_tonemap_auto_exposure_grey);
 
 
-
-
 	ADD_PROPERTY(PropertyInfo(Variant::INT,"tonemap/mode",PROPERTY_HINT_ENUM,"Linear,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/white",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_white"),_SCS("get_tonemap_white") );
-	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"auto_exposure/enable"),_SCS("set_tonemap_auto_exposure"),_SCS("get_tonemap_auto_exposure") );
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL,"auto_exposure/enabled"),_SCS("set_tonemap_auto_exposure"),_SCS("get_tonemap_auto_exposure") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_exposure/scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_tonemap_auto_exposure_grey"),_SCS("get_tonemap_auto_exposure_grey") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_exposure/min_luma",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_auto_exposure_min"),_SCS("get_tonemap_auto_exposure_min") );
 	ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_exposure/max_luma",PROPERTY_HINT_RANGE,"0,16,0.01"),_SCS("set_tonemap_auto_exposure_max"),_SCS("get_tonemap_auto_exposure_max") );
@@ -646,7 +790,7 @@ void Environment::_bind_methods() {
 	BIND_CONSTANT(GLOW_BLEND_MODE_ADDITIVE);
 	BIND_CONSTANT(GLOW_BLEND_MODE_SCREEN);
 	BIND_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT);
-	BIND_CONSTANT(GLOW_BLEND_MODE_DISABLED);
+	BIND_CONSTANT(GLOW_BLEND_MODE_REPLACE);
 	BIND_CONSTANT(TONE_MAPPER_LINEAR);
 	BIND_CONSTANT(TONE_MAPPER_REINHARDT);
 	BIND_CONSTANT(TONE_MAPPER_FILMIC);
@@ -702,6 +846,15 @@ Environment::Environment() {
 	ssao_direct_light_affect=false;
 	ssao_blur=true;
 
+	glow_enabled=false;
+	glow_levels=(1<<2)|(1<<4);
+	glow_intensity=0.8;
+	glow_strength=1.0;
+	glow_bloom=0.0;
+	glow_blend_mode=GLOW_BLEND_MODE_SOFTLIGHT;
+	glow_hdr_bleed_treshold=1.0;
+	glow_hdr_bleed_scale=2.0;
+
 }
 
 Environment::~Environment() {

+ 42 - 7
scene/resources/environment.h

@@ -49,12 +49,7 @@ public:
 		BG_MAX
 	};
 
-	enum GlowBlendMode {
-		GLOW_BLEND_MODE_ADDITIVE,
-		GLOW_BLEND_MODE_SCREEN,
-		GLOW_BLEND_MODE_SOFTLIGHT,
-		GLOW_BLEND_MODE_DISABLED,
-	};
+
 
 	enum ToneMapper {
 		TONE_MAPPER_LINEAR,
@@ -63,6 +58,12 @@ public:
 		TONE_MAPPER_ACES
 	};
 
+	enum GlowBlendMode {
+		GLOW_BLEND_MODE_ADDITIVE,
+		GLOW_BLEND_MODE_SCREEN,
+		GLOW_BLEND_MODE_SOFTLIGHT,
+		GLOW_BLEND_MODE_REPLACE,
+	};
 
 
 private:
@@ -111,6 +112,15 @@ private:
 	Color ssao_color;
 	bool ssao_blur;
 
+	bool glow_enabled;
+	int glow_levels;
+	float glow_intensity;
+	float glow_strength;
+	float glow_bloom;
+	GlowBlendMode glow_blend_mode;
+	float glow_hdr_bleed_treshold;
+	float glow_hdr_bleed_scale;
+
 
 protected:
 
@@ -229,6 +239,31 @@ public:
 	bool is_ssao_blur_enabled() const;
 
 
+	void set_glow_enabled(bool p_enabled);
+	bool is_glow_enabled() const;
+
+	void set_glow_level(int p_level,bool p_enabled);
+	bool is_glow_level_enabled(int p_level) const;
+
+	void set_glow_intensity(float p_intensity);
+	float get_glow_intensity() const;
+
+	void set_glow_strength(float p_strength);
+	float get_glow_strength() const;
+
+	void set_glow_bloom(float p_treshold);
+	float get_glow_bloom() const;
+
+	void set_glow_blend_mode(GlowBlendMode p_mode);
+	GlowBlendMode get_glow_blend_mode() const;
+
+	void set_glow_hdr_bleed_treshold(float p_treshold);
+	float get_glow_hdr_bleed_treshold() const;
+
+	void set_glow_hdr_bleed_scale(float p_scale);
+	float get_glow_hdr_bleed_scale() const;
+
+
 
 	virtual RID get_rid() const;
 
@@ -240,8 +275,8 @@ public:
 
 
 VARIANT_ENUM_CAST(Environment::BGMode)
-VARIANT_ENUM_CAST(Environment::GlowBlendMode)
 VARIANT_ENUM_CAST(Environment::ToneMapper)
+VARIANT_ENUM_CAST(Environment::GlowBlendMode)
 
 
 #endif // ENVIRONMENT_H

+ 1 - 1
servers/visual/rasterizer.h

@@ -61,7 +61,7 @@ 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_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_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_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;

+ 1 - 1
servers/visual/visual_server_raster.h

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

+ 4 - 2
servers/visual_server.h

@@ -79,6 +79,8 @@ public:
 		ARRAY_WEIGHTS_SIZE=4,
 		CANVAS_ITEM_Z_MIN=-4096,
 		CANVAS_ITEM_Z_MAX=4096,
+		MAX_GLOW_LEVELS=7,
+
 
 
 
@@ -538,9 +540,9 @@ public:
 		GLOW_BLEND_MODE_ADDITIVE,
 		GLOW_BLEND_MODE_SCREEN,
 		GLOW_BLEND_MODE_SOFTLIGHT,
-		GLOW_BLEND_MODE_DISABLED,
+		GLOW_BLEND_MODE_REPLACE,
 	};
-	virtual void environment_set_glow(RID p_env,bool p_enable,int p_radius,float p_intensity,float p_strength,float p_bloom_treshold,EnvironmentGlowBlendMode p_blend_mode)=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)=0;
 	virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0;