summaryrefslogtreecommitdiff
path: root/drivers/gles3
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2016-12-08 09:48:38 -0300
committerJuan Linietsky <reduzio@gmail.com>2016-12-08 09:48:38 -0300
commit18ebd22000478dffc91255e89b9845f74b05b606 (patch)
tree868b51e8d4645a38e369003b7331a0eaf1729949 /drivers/gles3
parent8534ced22d7b889dafb64ab0c40435c5b12b7cbc (diff)
Multi stage glow with light bleeding from HDR
Diffstat (limited to 'drivers/gles3')
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.cpp160
-rw-r--r--drivers/gles3/rasterizer_scene_gles3.h22
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp4
-rw-r--r--drivers/gles3/shaders/effect_blur.glsl67
-rw-r--r--drivers/gles3/shaders/tonemap.glsl81
5 files changed, 329 insertions, 5 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp
index 4abeef89be..ec304e7a46 100644
--- a/drivers/gles3/rasterizer_scene_gles3.cpp
+++ b/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){
diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h
index b0a875aa16..6ca4529ed9 100644
--- a/drivers/gles3/rasterizer_scene_gles3.h
+++ b/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);
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index ddb60273e4..cfa50f6100 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/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++;
diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl
index 211b60ca2e..589af64d44 100644
--- a/drivers/gles3/shaders/effect_blur.glsl
+++ b/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;
diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl
index 566d194a02..8ee51e9d0c 100644
--- a/drivers/gles3/shaders/tonemap.glsl
+++ b/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
{