diff options
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.cpp | 235 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_scene_gles3.h | 29 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.cpp | 21 | ||||
-rw-r--r-- | drivers/gles3/rasterizer_storage_gles3.h | 15 | ||||
-rw-r--r-- | drivers/gles3/shaders/SCsub | 2 | ||||
-rw-r--r-- | drivers/gles3/shaders/exposure.glsl | 98 | ||||
-rw-r--r-- | drivers/gles3/shaders/tonemap.glsl | 97 | ||||
-rw-r--r-- | scene/resources/environment.cpp | 41 | ||||
-rw-r--r-- | scene/resources/environment.h | 9 | ||||
-rw-r--r-- | servers/visual/rasterizer.h | 3 | ||||
-rw-r--r-- | servers/visual/visual_server_raster.h | 3 | ||||
-rw-r--r-- | servers/visual_server.h | 5 |
12 files changed, 517 insertions, 41 deletions
diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index ad88bda719..4abeef89be 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -890,11 +890,24 @@ void RasterizerSceneGLES3::environment_set_ssao(RID p_env,bool p_enable, float p } +void RasterizerSceneGLES3::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) { -void RasterizerSceneGLES3::environment_set_tonemap(RID p_env, bool p_enable, float p_exposure, float p_white, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale, VS::EnvironmentToneMapper p_tone_mapper){ + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + + env->tone_mapper=p_tone_mapper; + env->tone_mapper_exposure=p_exposure; + env->tone_mapper_exposure_white=p_white; + env->auto_exposure=p_auto_exposure; + env->auto_exposure_speed=p_auto_exp_speed; + env->auto_exposure_min=p_min_luminance; + env->auto_exposure_max=p_max_luminance; + env->auto_exposure_grey=p_auto_exp_scale; } + void RasterizerSceneGLES3::environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp) { @@ -3010,6 +3023,172 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c } +void RasterizerSceneGLES3::_post_process(Environment *env){ + + //copy to front buffer + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1,1,1,1); + + //turn off everything used + + if (!env) { + //no environment, simply return and convert to SRGB + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,true); + storage->shaders.copy.bind(); + + _copy_screen(); + + storage->shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB,false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::DISABLE_ALPHA,false); //compute luminance + + return; + + } + + + //order of operation + //1) DOF Blur (first blur, then copy to buffer applying the blur) + //2) Motion Blur + //3) Bloom + //4) Tonemap + //5) Adjustments + + GLuint composite_from = storage->frame.current_rt->buffers.diffuse; + + + if ( env->auto_exposure) { + + //compute auto exposure + //first step, copy from image to luminance buffer + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN,true); + state.exposure_shader.bind(); + int ss[2]={ + storage->frame.current_rt->width, + storage->frame.current_rt->height, + }; + int ds[2]={ + exposure_shrink_size, + exposure_shrink_size, + }; + + glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::SOURCE_RENDER_SIZE),1,ss); + glUniform2iv(state.exposure_shader.get_uniform(ExposureShaderGLES3::TARGET_SIZE),1,ds); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + + + glBindFramebuffer(GL_FRAMEBUFFER,exposure_shrink[0].fbo); + glViewport(0,0,exposure_shrink_size,exposure_shrink_size); + + _copy_screen(); + + + + + + //second step, shrink to 2x2 pixels + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_BEGIN,false); + state.exposure_shader.bind(); + //shrink from second to previous to last level + + int s_size=exposure_shrink_size/3; + for(int i=1;i<exposure_shrink.size()-1;i++) { + + glBindFramebuffer(GL_FRAMEBUFFER,exposure_shrink[i].fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,exposure_shrink[i-1].color); + + _copy_screen(); + + glViewport(0,0,s_size,s_size); + + s_size/=3; + + } + //third step, shrink to 1x1 pixel taking in consideration the previous exposure + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END,true); + + uint64_t tick = OS::get_singleton()->get_ticks_usec(); + uint64_t tick_diff = storage->frame.current_rt->last_exposure_tick==0?0:tick-storage->frame.current_rt->last_exposure_tick; + storage->frame.current_rt->last_exposure_tick=tick; + + if (tick_diff==0 || tick_diff>1000000) { + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET,true); + + } + + state.exposure_shader.bind(); + + glBindFramebuffer(GL_FRAMEBUFFER,exposure_shrink[exposure_shrink.size()-1].fbo); + glViewport(0,0,1,1); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,exposure_shrink[exposure_shrink.size()-2].color); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); //read from previous + + + state.exposure_shader.set_uniform(ExposureShaderGLES3::EXPOSURE_ADJUST,env->auto_exposure_speed*(tick_diff/1000000.0)); + state.exposure_shader.set_uniform(ExposureShaderGLES3::MAX_LUMINANCE,env->auto_exposure_max); + state.exposure_shader.set_uniform(ExposureShaderGLES3::MIN_LUMINANCE,env->auto_exposure_min); + + _copy_screen(); + + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_FORCE_SET,false); + state.exposure_shader.set_conditional(ExposureShaderGLES3::EXPOSURE_END,false); + + //last step, swap with the framebuffer exposure, so the right exposure is kept int he framebuffer + SWAP(exposure_shrink[exposure_shrink.size()-1].fbo,storage->frame.current_rt->exposure.fbo); + SWAP(exposure_shrink[exposure_shrink.size()-1].color,storage->frame.current_rt->exposure.color); + + + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); + + } + + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->fbo); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,composite_from); + + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_FILMIC_TONEMAPPER,env->tone_mapper==VS::ENV_TONE_MAPPER_FILMIC); + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_ACES_TONEMAPPER,env->tone_mapper==VS::ENV_TONE_MAPPER_ACES); + 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.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 (env->auto_exposure) { + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); + state.tonemap_shader.set_uniform(TonemapShaderGLES3::AUTO_EXPOSURE_GREY,env->auto_exposure_grey); + + } + + _copy_screen(); + + //turn off everything used + state.tonemap_shader.set_conditional(TonemapShaderGLES3::USE_AUTO_EXPOSURE,false); + 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); + +} 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){ @@ -3056,8 +3235,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C render_list.clear(); - bool use_mrt=true; - + bool use_mrt=false; _fill_render_list(p_cull_result,p_cull_count,false); @@ -3074,6 +3252,7 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C GLuint current_fbo; + if (probe) { ReflectionAtlas *ref_atlas = reflection_atlas_owner.getptr(probe->atlas); @@ -3100,6 +3279,8 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } else { + use_mrt = state.used_sss || (env && (env->ssao_enabled || env->ssr_enabled)); //only enable MRT rendering if any of these is enabled + glViewport(0,0,storage->frame.current_rt->width,storage->frame.current_rt->height); if (use_mrt) { @@ -3267,9 +3448,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C return; } - _copy_to_front_buffer(env); -/* if (shadow_atlas) { + _post_process(env); + + + if (false && shadow_atlas) { //_copy_texture_to_front_buffer(shadow_atlas->depth); storage->canvas->canvas_begin(); @@ -3279,7 +3462,17 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/2,storage->frame.current_rt->height/2),Rect2(0,0,1,1)); } -*/ + + if (false && storage->frame.current_rt) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,exposure_shrink[4].color); +// glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); + storage->canvas->draw_generic_textured_rect(Rect2(0,0,storage->frame.current_rt->width/16,storage->frame.current_rt->height/16),Rect2(0,0,1,1)); + + } if (false && reflection_atlas && storage->frame.current_rt) { @@ -4199,6 +4392,8 @@ void RasterizerSceneGLES3::initialize() { state.ssao_minify_shader.init(); state.ssao_shader.init(); state.ssao_blur_shader.init(); + state.exposure_shader.init(); + state.tonemap_shader.init(); { @@ -4209,6 +4404,34 @@ void RasterizerSceneGLES3::initialize() { GLOBAL_DEF("rendering/gles3/subsurface_scattering/follow_surface",false); } + exposure_shrink_size=243; + int max_exposure_shrink_size=exposure_shrink_size; + + while(max_exposure_shrink_size>0) { + + RasterizerStorageGLES3::RenderTarget::Exposure e; + + glGenFramebuffers(1, &e.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, e.fbo); + + glGenTextures(1, &e.color); + glBindTexture(GL_TEXTURE_2D, e.color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, max_exposure_shrink_size, max_exposure_shrink_size, 0, GL_RED, GL_FLOAT, NULL); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, e.color, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + exposure_shrink.push_back(e); + max_exposure_shrink_size/=3; + + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + ERR_CONTINUE(status!=GL_FRAMEBUFFER_COMPLETE); + + + } + } void RasterizerSceneGLES3::iteration() { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 6b9295deee..b0a875aa16 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -11,6 +11,8 @@ #include "drivers/gles3/shaders/ssao_minify.glsl.h" #include "drivers/gles3/shaders/ssao.glsl.h" #include "drivers/gles3/shaders/ssao_blur.glsl.h" +#include "drivers/gles3/shaders/exposure.glsl.h" +#include "drivers/gles3/shaders/tonemap.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -48,6 +50,9 @@ public: RasterizerStorageGLES3 *storage; + Vector<RasterizerStorageGLES3::RenderTarget::Exposure> exposure_shrink; + int exposure_shrink_size; + struct State { @@ -68,6 +73,8 @@ public: SsaoMinifyShaderGLES3 ssao_minify_shader; SsaoShaderGLES3 ssao_shader; SsaoBlurShaderGLES3 ssao_blur_shader; + ExposureShaderGLES3 exposure_shader; + TonemapShaderGLES3 tonemap_shader; struct SceneDataUBO { @@ -334,6 +341,15 @@ public: Color ssao_color; bool ssao_filter; + VS::EnvironmentToneMapper tone_mapper; + float tone_mapper_exposure; + float tone_mapper_exposure_white; + bool auto_exposure; + float auto_exposure_speed; + float auto_exposure_min; + float auto_exposure_max; + float auto_exposure_grey; + Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; skybox_scale=1.0; @@ -360,6 +376,14 @@ public: ssao_light_affect=0; ssao_filter=true; + tone_mapper=VS::ENV_TONE_MAPPER_LINEAR; + tone_mapper_exposure=1.0; + tone_mapper_exposure_white=1.0; + auto_exposure=false; + auto_exposure_speed=0.5; + auto_exposure_min=0.05; + auto_exposure_max=8; + auto_exposure_grey=0.4; } }; @@ -382,7 +406,8 @@ public: 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,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper); + virtual void environment_set_tonemap(RID p_env,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); @@ -618,6 +643,8 @@ 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); + virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass); virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count); virtual bool free(RID p_rid); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index f21b7021e9..ddb60273e4 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4799,6 +4799,10 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { glDeleteTextures(1,&rt->effects.ssao.linear_depth); } + if (rt->exposure.fbo) { + glDeleteFramebuffers(1,&rt->exposure.fbo); + glDeleteTextures(1,&rt->exposure.color); + } Texture *tex = texture_owner.get(rt->texture); tex->alloc_height=0; tex->alloc_width=0; @@ -5120,6 +5124,23 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ rt->effects.ssao.depth_mipmap_fbos.push_back(fbo); } + + //////Exposure + + glGenFramebuffers(1, &rt->exposure.fbo); + glBindFramebuffer(GL_FRAMEBUFFER, rt->exposure.fbo); + + glGenTextures(1, &rt->exposure.color); + glBindTexture(GL_TEXTURE_2D, rt->exposure.color); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + } } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index c2aea391b1..7802b28158 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -922,12 +922,19 @@ public: SSAO() { blur_fbo[0]=0; blur_fbo[1]=0; linear_depth=0; } } ssao; - Effects() { - - } + Effects() {} } effects; + struct Exposure { + GLuint fbo; + GLuint color; + + Exposure() { fbo=0; } + } exposure; + + uint64_t last_exposure_tick; + int width,height; bool flags[RENDER_TARGET_FLAG_MAX]; @@ -950,6 +957,8 @@ public: flags[RENDER_TARGET_TRANSPARENT]=false; flags[RENDER_TARGET_NO_3D]=false; flags[RENDER_TARGET_NO_SAMPLING]=false; + + last_exposure_tick=0; } }; diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index dd7ec45242..272f9bb5e1 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -15,5 +15,7 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('ssao.glsl'); env.GLES3_GLSL('ssao_minify.glsl'); env.GLES3_GLSL('ssao_blur.glsl'); + env.GLES3_GLSL('exposure.glsl'); + env.GLES3_GLSL('tonemap.glsl'); diff --git a/drivers/gles3/shaders/exposure.glsl b/drivers/gles3/shaders/exposure.glsl new file mode 100644 index 0000000000..001b90a0f1 --- /dev/null +++ b/drivers/gles3/shaders/exposure.glsl @@ -0,0 +1,98 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + + +void main() { + + gl_Position = vertex_attrib; + +} + +[fragment] + + +uniform highp sampler2D source_exposure; //texunit:0 + +#ifdef EXPOSURE_BEGIN + +uniform highp ivec2 source_render_size; +uniform highp ivec2 target_size; + +#endif + +#ifdef EXPOSURE_END + +uniform highp sampler2D prev_exposure; //texunit:1 +uniform highp float exposure_adjust; +uniform highp float min_luminance; +uniform highp float max_luminance; + +#endif + +layout(location = 0) out highp float exposure; + + + +void main() { + + + +#ifdef EXPOSURE_BEGIN + + + ivec2 src_pos = ivec2(gl_FragCoord.xy)*source_render_size/target_size; + +#if 1 + //more precise and expensive, but less jittery + ivec2 next_pos = ivec2(gl_FragCoord.xy+ivec2(1))*source_render_size/target_size; + next_pos = max(next_pos,src_pos+ivec2(1)); //so it at least reads one pixel + highp vec3 source_color=vec3(0.0); + for(int i=src_pos.x;i<next_pos.x;i++) { + for(int j=src_pos.y;j<next_pos.y;j++) { + source_color += texelFetch(source_exposure,ivec2(i,j),0).rgb; + } + } + + source_color/=float( (next_pos.x-src_pos.x)*(next_pos.y-src_pos.y) ); +#else + highp vec3 source_color = texelFetch(source_exposure,src_pos,0).rgb; + +#endif + + exposure = max(source_color.r,max(source_color.g,source_color.b)); + +#else + + ivec2 coord = ivec2(gl_FragCoord.xy); + exposure = texelFetch(source_exposure,coord*3+ivec2(0,0),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(1,0),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(2,0),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(0,1),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(1,1),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(2,1),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(0,2),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(1,2),0).r; + exposure += texelFetch(source_exposure,coord*3+ivec2(2,2),0).r; + exposure *= (1.0/9.0); + +#ifdef EXPOSURE_END + +#ifdef EXPOSURE_FORCE_SET + //will stay as is +#else + highp float prev_lum = texelFetch(prev_exposure,ivec2(0,0),0).r; //1 pixel previous exposure + exposure = clamp( prev_lum + (exposure-prev_lum)*exposure_adjust,min_luminance,max_luminance); + +#endif //EXPOSURE_FORCE_SET + + +#endif //EXPOSURE_END + +#endif //EXPOSURE_BEGIN + + +} + + diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl new file mode 100644 index 0000000000..566d194a02 --- /dev/null +++ b/drivers/gles3/shaders/tonemap.glsl @@ -0,0 +1,97 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + + +void main() { + + gl_Position = vertex_attrib; + +} + +[fragment] + + +uniform highp sampler2D source; //texunit:0 + +uniform float exposure; +uniform float white; + +#ifdef USE_AUTO_EXPOSURE + +uniform highp sampler2D source_auto_exposure; //texunit:1 +uniform highp float auto_exposure_grey; + +#endif + + +layout(location = 0) out vec4 frag_color; + + +void main() { + + ivec2 coord = ivec2(gl_FragCoord.xy); + vec3 color = texelFetch(source,coord,0).rgb; + + +#ifdef USE_AUTO_EXPOSURE + + color/=texelFetch(source_auto_exposure,ivec2(0,0),0).r/auto_exposure_grey; +#endif + + color*=exposure; + + +#ifdef USE_REINDHART_TONEMAPPER + + { + color.rgb = ( color.rgb * ( 1.0 + ( color.rgb / ( white) ) ) ) / ( 1.0 + color.rgb ); + + } +#endif + +#ifdef USE_FILMIC_TONEMAPPER + + { + + float A = 0.15; + float B = 0.50; + float C = 0.10; + float D = 0.20; + float E = 0.02; + float F = 0.30; + float W = 11.2; + + vec3 coltn = ((color.rgb*(A*color.rgb+C*B)+D*E)/(color.rgb*(A*color.rgb+B)+D*F))-E/F; + float whitetn = ((white*(A*white+C*B)+D*E)/(white*(A*white+B)+D*F))-E/F; + + color.rgb=coltn/whitetn; + + } +#endif + +#ifdef USE_ACES_TONEMAPPER + + { + float a = 2.51f; + float b = 0.03f; + float c = 2.43f; + float d = 0.59f; + float e = 0.14f; + color.rgb = clamp((color.rgb*(a*color.rgb+b))/(color.rgb*(c*color.rgb+d)+e),vec3(0.0),vec3(1.0)); + } + +#endif + + //regular Linear -> SRGB conversion + vec3 a = vec3(0.055); + color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308))); + + + + + frag_color=vec4(color.rgb,1.0); +} + + diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index c945d2a95d..2b691125d0 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -136,7 +136,7 @@ float Environment::get_ambient_light_skybox_contribution() const{ void Environment::set_tonemapper(ToneMapper p_tone_mapper) { tone_mapper=p_tone_mapper; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } Environment::ToneMapper Environment::get_tonemapper() const{ @@ -147,18 +147,18 @@ Environment::ToneMapper Environment::get_tonemapper() const{ void Environment::set_tonemap_exposure(float p_exposure){ tonemap_exposure=p_exposure; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } float Environment::get_tonemap_exposure() const{ - return get_tonemap_auto_exposure(); + return tonemap_exposure; } void Environment::set_tonemap_white(float p_white){ tonemap_white=p_white; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } float Environment::get_tonemap_white() const { @@ -169,7 +169,7 @@ float Environment::get_tonemap_white() const { void Environment::set_tonemap_auto_exposure(bool p_enabled) { tonemap_auto_exposure=p_enabled; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } bool Environment::get_tonemap_auto_exposure() const { @@ -180,7 +180,7 @@ bool Environment::get_tonemap_auto_exposure() const { void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) { tonemap_auto_exposure_max=p_auto_exposure_max; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } float Environment::get_tonemap_auto_exposure_max() const { @@ -191,7 +191,7 @@ float Environment::get_tonemap_auto_exposure_max() const { void Environment::set_tonemap_auto_exposure_min(float p_auto_exposure_min) { tonemap_auto_exposure_min=p_auto_exposure_min; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } float Environment::get_tonemap_auto_exposure_min() const { @@ -202,7 +202,7 @@ float Environment::get_tonemap_auto_exposure_min() const { void Environment::set_tonemap_auto_exposure_speed(float p_auto_exposure_speed) { tonemap_auto_exposure_speed=p_auto_exposure_speed; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } float Environment::get_tonemap_auto_exposure_speed() const { @@ -210,15 +210,15 @@ float Environment::get_tonemap_auto_exposure_speed() const { return tonemap_auto_exposure_speed; } -void Environment::set_tonemap_auto_exposure_scale(float p_auto_exposure_scale) { +void Environment::set_tonemap_auto_exposure_grey(float p_auto_exposure_grey) { - tonemap_auto_exposure_scale=p_auto_exposure_scale; - VS::get_singleton()->environment_set_tonemap(environment,tonemap_auto_exposure,tonemap_exposure,tonemap_white,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_scale,VS::EnvironmentToneMapper(tone_mapper)); + tonemap_auto_exposure_grey=p_auto_exposure_grey; + VS::get_singleton()->environment_set_tonemap(environment,VS::EnvironmentToneMapper(tone_mapper),tonemap_exposure,tonemap_white,tonemap_auto_exposure,tonemap_auto_exposure_min,tonemap_auto_exposure_max,tonemap_auto_exposure_speed,tonemap_auto_exposure_grey); } -float Environment::get_tonemap_auto_exposure_scale() const { +float Environment::get_tonemap_auto_exposure_grey() const { - return tonemap_auto_exposure_scale; + return tonemap_auto_exposure_grey; } void Environment::set_adjustment_enable(bool p_enable) { @@ -597,17 +597,17 @@ void Environment::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_tonemap_auto_exposure_speed","exposure_speed"),&Environment::set_tonemap_auto_exposure_speed); ObjectTypeDB::bind_method(_MD("get_tonemap_auto_exposure_speed"),&Environment::get_tonemap_auto_exposure_speed); - ObjectTypeDB::bind_method(_MD("set_tonemap_auto_exposure_scale","exposure_scale"),&Environment::set_tonemap_auto_exposure_scale); - ObjectTypeDB::bind_method(_MD("get_tonemap_auto_exposure_scale"),&Environment::get_tonemap_auto_exposure_scale); + ObjectTypeDB::bind_method(_MD("set_tonemap_auto_exposure_grey","exposure_grey"),&Environment::set_tonemap_auto_exposure_grey); + 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,Log,Reindhart,Filmic,Aces"),_SCS("set_tonemapper"),_SCS("get_tonemapper") ); + 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::REAL,"auto_exposure/scale",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_tonemap_auto_exposure_scale"),_SCS("get_tonemap_auto_exposure_scale") ); + 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") ); ADD_PROPERTY(PropertyInfo(Variant::REAL,"auto_exposure/speed",PROPERTY_HINT_RANGE,"0.01,64,0.01"),_SCS("set_tonemap_auto_exposure_speed"),_SCS("get_tonemap_auto_exposure_speed") ); @@ -648,10 +648,9 @@ void Environment::_bind_methods() { BIND_CONSTANT(GLOW_BLEND_MODE_SOFTLIGHT); BIND_CONSTANT(GLOW_BLEND_MODE_DISABLED); BIND_CONSTANT(TONE_MAPPER_LINEAR); - BIND_CONSTANT(TONE_MAPPER_LOG); BIND_CONSTANT(TONE_MAPPER_REINHARDT); BIND_CONSTANT(TONE_MAPPER_FILMIC); - BIND_CONSTANT(TONE_MAPPER_ACES_FILMIC); + BIND_CONSTANT(TONE_MAPPER_ACES); } @@ -671,9 +670,9 @@ Environment::Environment() { tonemap_white=1.0; tonemap_auto_exposure=false; tonemap_auto_exposure_max=8; - tonemap_auto_exposure_min=0.4; + tonemap_auto_exposure_min=0.05; tonemap_auto_exposure_speed=0.5; - tonemap_auto_exposure_scale=0.4; + tonemap_auto_exposure_grey=0.4; set_tonemapper(tone_mapper); //update diff --git a/scene/resources/environment.h b/scene/resources/environment.h index c489ff97fc..3cf9f550b4 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -58,10 +58,9 @@ public: enum ToneMapper { TONE_MAPPER_LINEAR, - TONE_MAPPER_LOG, TONE_MAPPER_REINHARDT, TONE_MAPPER_FILMIC, - TONE_MAPPER_ACES_FILMIC + TONE_MAPPER_ACES }; @@ -86,7 +85,7 @@ private: float tonemap_auto_exposure_max; float tonemap_auto_exposure_min; float tonemap_auto_exposure_speed; - float tonemap_auto_exposure_scale; + float tonemap_auto_exposure_grey; bool adjustment_enabled; float adjustment_contrast; @@ -163,8 +162,8 @@ public: void set_tonemap_auto_exposure_speed(float p_auto_exposure_speed); float get_tonemap_auto_exposure_speed() const; - void set_tonemap_auto_exposure_scale(float p_auto_exposure_scale); - float get_tonemap_auto_exposure_scale() const; + void set_tonemap_auto_exposure_grey(float p_auto_exposure_grey); + float get_tonemap_auto_exposure_grey() const; void set_adjustment_enable(bool p_enable); bool is_adjustment_enabled() const; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 09d59e3175..4f357afa68 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -67,7 +67,8 @@ public: virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0; virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0; - virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper)=0; + virtual void environment_set_tonemap(RID p_env,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)=0; + virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0; struct InstanceBase : RID_Data { diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index ff1a622107..c7e49ede2c 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -882,7 +882,8 @@ public: BIND7(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode ) BIND5(environment_set_fog,RID,bool ,float ,float ,RID ) - BIND9(environment_set_tonemap,RID,bool ,float ,float ,float ,float ,float,float ,EnvironmentToneMapper ) + BIND9(environment_set_tonemap,RID,EnvironmentToneMapper, float ,float ,bool, float ,float ,float,float ) + BIND6(environment_set_adjustment,RID,bool ,float ,float ,float ,RID ) diff --git a/servers/visual_server.h b/servers/visual_server.h index 6c4a080437..0b3a9771a8 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -546,13 +546,12 @@ public: enum EnvironmentToneMapper { ENV_TONE_MAPPER_LINEAR, - ENV_TONE_MAPPER_LOG, ENV_TONE_MAPPER_REINHARDT, ENV_TONE_MAPPER_FILMIC, - ENV_TONE_MAPPER_ACES_FILMIC + ENV_TONE_MAPPER_ACES }; - virtual void environment_set_tonemap(RID p_env,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,EnvironmentToneMapper p_tone_mapper)=0; + virtual void environment_set_tonemap(RID p_env,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_grey)=0; virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0; virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0; |