From cacf9ebb7fd8df8845daca9da2fe55456cc179aa Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Wed, 9 Nov 2016 23:55:06 -0300 Subject: all light types and shadows are working, pending a lot of clean-up --- core/math/camera_matrix.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'core/math/camera_matrix.h') diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index d192b1fef..bf8cf3592 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -30,6 +30,7 @@ #define CAMERA_MATRIX_H #include "transform.h" +#include "math_2d.h" /** @author Juan Linietsky */ @@ -53,6 +54,7 @@ struct CameraMatrix { void set_identity(); void set_zero(); void set_light_bias(); + void set_light_atlas_rect(const Rect2& p_rect); void set_perspective(float p_fovy_degrees, float p_aspect, float p_z_near, float p_z_far,bool p_flip_fov=false); void set_orthogonal(float p_left, float p_right, float p_bottom, float p_top, float p_znear, float p_zfar); void set_orthogonal(float p_size, float p_aspect, float p_znear, float p_zfar,bool p_flip_fov=false); -- cgit v1.2.3-70-g09d2 From a299c3ebf1ceb3ce108526b3e134e82e5bf4413b Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sun, 4 Dec 2016 12:45:30 -0300 Subject: Support for SSAO --- core/math/camera_matrix.cpp | 9 ++ core/math/camera_matrix.h | 1 + drivers/gles3/rasterizer_scene_gles3.cpp | 185 ++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 28 ++++ drivers/gles3/rasterizer_storage_gles3.cpp | 76 +++++++++ drivers/gles3/rasterizer_storage_gles3.h | 11 ++ drivers/gles3/shaders/SCsub | 3 + drivers/gles3/shaders/effect_blur.glsl | 17 ++ drivers/gles3/shaders/scene.glsl | 4 +- drivers/gles3/shaders/ssao.glsl | 247 +++++++++++++++++++++++++++++ drivers/gles3/shaders/ssao_blur.glsl | 113 +++++++++++++ drivers/gles3/shaders/ssao_minify.glsl | 55 +++++++ scene/resources/environment.cpp | 142 +++++++++++++++++ scene/resources/environment.h | 39 +++++ servers/visual/rasterizer.h | 1 + servers/visual/visual_server_raster.h | 2 + servers/visual_server.h | 1 + 17 files changed, 927 insertions(+), 7 deletions(-) create mode 100644 drivers/gles3/shaders/ssao.glsl create mode 100644 drivers/gles3/shaders/ssao_blur.glsl create mode 100644 drivers/gles3/shaders/ssao_minify.glsl (limited to 'core/math/camera_matrix.h') diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index 3e3cd1af4..fc35908fa 100644 --- a/core/math/camera_matrix.cpp +++ b/core/math/camera_matrix.cpp @@ -534,6 +534,15 @@ float CameraMatrix::get_aspect() const { return w/h; } +int CameraMatrix::get_pixels_per_meter(int p_for_pixel_width) const { + + + Vector3 result = xform(Vector3(1,0,-1)); + + return int((result.x * 0.5 + 0.5) * p_for_pixel_width); + +} + float CameraMatrix::get_fov() const { const float * matrix = (const float*)this->matrix; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index bf8cf3592..7fcff6376 100644 --- a/core/math/camera_matrix.h +++ b/core/math/camera_matrix.h @@ -87,6 +87,7 @@ struct CameraMatrix { void scale_translate_to_fit(const AABB& p_aabb); void make_scale(const Vector3 &p_scale); + int get_pixels_per_meter(int p_for_pixel_width) const; operator Transform() const; CameraMatrix(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index c4c7d4409..2488f51e9 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -872,6 +872,25 @@ void RasterizerSceneGLES3::environment_set_ssr(RID p_env,bool p_enable, int p_ma } + +void RasterizerSceneGLES3::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) { + + Environment *env=environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->ssao_enabled=p_enable; + env->ssao_radius=p_radius; + env->ssao_intensity=p_intensity; + env->ssao_radius2=p_radius2; + env->ssao_intensity2=p_intensity2; + env->ssao_bias=p_bias; + env->ssao_light_affect=p_light_affect; + env->ssao_color=p_color; + env->ssao_filter=p_blur; + +} + + 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){ } @@ -1460,7 +1479,7 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans } } - if (p_instance->billboard) { + if (p_instance->billboard && storage->frame.current_rt) { Vector3 scale = xf.basis.get_scale(); @@ -1473,7 +1492,7 @@ void RasterizerSceneGLES3::_setup_transform(InstanceBase *p_instance,const Trans xf.basis.scale(scale); } - if (p_instance->billboard_y) { + if (p_instance->billboard_y && storage->frame.current_rt) { Vector3 scale = xf.basis.get_scale(); Vector3 look_at = p_view_transform.get_origin(); @@ -2020,6 +2039,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri state.ubo_data.bg_color[3]=bg_color.a; state.env_radiance_data.ambient_contribution=env->ambient_skybox_contribution; + state.ubo_data.ambient_occlusion_affect_light=env->ssao_light_affect; } else { state.ubo_data.bg_energy=1.0; state.ubo_data.ambient_energy=1.0; @@ -2036,6 +2056,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env,const CameraMatri state.ubo_data.bg_color[3]=linear_ambient_color.a; state.env_radiance_data.ambient_contribution=0; + state.ubo_data.ambient_occlusion_affect_light=0; } @@ -2549,7 +2570,7 @@ void RasterizerSceneGLES3::_setup_reflections(RID *p_reflection_probe_cull_resul void RasterizerSceneGLES3::_copy_screen() { - glBindVertexArray(storage->resources.quadie_array); + glBindVertexArray( storage->resources.quadie_array); glDrawArrays(GL_TRIANGLE_FAN,0,4); glBindVertexArray(0); @@ -2689,6 +2710,141 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glDisable(GL_CULL_FACE); glDisable(GL_BLEND); + bool diffuse_copied=false; + + if (env->ssao_enabled) { + //ssao + + //copy from depth, convert to linear + GLint ss[2]; + ss[0]=storage->frame.current_rt->width; + ss[1]=storage->frame.current_rt->height; + + for(int i=0;iframe.current_rt->effects.ssao.depth_mipmap_fbos.size();i++) { + + state.ssao_minify_shader.set_conditional(SsaoMinifyShaderGLES3::MINIFY_START,i==0); + state.ssao_minify_shader.bind(); + state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + state.ssao_minify_shader.set_uniform(SsaoMinifyShaderGLES3::SOURCE_MIPMAP,MAX(0,i-1)); + glUniform2iv(state.ssao_minify_shader.get_uniform(SsaoMinifyShaderGLES3::FROM_SIZE),1,ss); + ss[0]>>=1; + ss[1]>>=1; + + glActiveTexture(GL_TEXTURE0); + if (i==0) { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + } else { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth); + } + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.depth_mipmap_fbos[i]); //copy to front first + glViewport(0,0,ss[0],ss[1]); + + _copy_screen(); + + } + ss[0]=storage->frame.current_rt->width; + ss[1]=storage->frame.current_rt->height; + + glViewport(0,0,ss[0],ss[1]); + + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_GREATER); + // do SSAO! + state.ssao_shader.set_conditional(SsaoShaderGLES3::ENABLE_RADIUS2,env->ssao_radius2>0.001); + state.ssao_shader.bind(); + state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.ssao_shader.set_uniform(SsaoShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + glUniform2iv(state.ssao_shader.get_uniform(SsaoShaderGLES3::SCREEN_SIZE),1,ss); + float radius = env->ssao_radius; + state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS,radius); + float intensity = env->ssao_intensity; + state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R6,intensity / pow(radius, 6.0f)); + + if (env->ssao_radius2>0.001) { + + float radius2 = env->ssao_radius2; + state.ssao_shader.set_uniform(SsaoShaderGLES3::RADIUS2,radius2); + float intensity2 = env->ssao_intensity2; + state.ssao_shader.set_uniform(SsaoShaderGLES3::INTENSITY_DIV_R62,intensity2 / pow(radius2, 6.0f)); + + } + + float proj_info[4]={ + -2.0f / (ss[0]*p_cam_projection.matrix[0][0]), + -2.0f / (ss[1]*p_cam_projection.matrix[1][1]), + ( 1.0f - p_cam_projection.matrix[0][2]) / p_cam_projection.matrix[0][0], + ( 1.0f + p_cam_projection.matrix[1][2]) / p_cam_projection.matrix[1][1] + }; + + glUniform4fv(state.ssao_shader.get_uniform(SsaoShaderGLES3::PROJ_INFO),1,proj_info); + float pixels_per_meter = float(p_cam_projection.get_pixels_per_meter(ss[0])); + + state.ssao_shader.set_uniform(SsaoShaderGLES3::PROJ_SCALE,pixels_per_meter); + state.ssao_shader.set_uniform(SsaoShaderGLES3::BIAS,env->ssao_bias); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.linear_depth); + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.normal_rough); + + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[0]); //copy to front first + Color white(1,1,1,1); + glClearBufferfv(GL_COLOR,0,white.components); // specular + + _copy_screen(); + + //do the batm, i mean blur + + state.ssao_blur_shader.bind(); + + if (env->ssao_filter) { + for(int i=0;i<2;i++) { + + state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_FAR,p_cam_projection.get_z_far()); + state.ssao_blur_shader.set_uniform(SsaoBlurShaderGLES3::CAMERA_Z_NEAR,p_cam_projection.get_z_near()); + GLint axis[2]={i,1-i}; + glUniform2iv(state.ssao_blur_shader.get_uniform(SsaoBlurShaderGLES3::AXIS),1,axis); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[i]); + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->depth); + glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.ssao.blur_fbo[1-i]); + if (i==0) { + glClearBufferfv(GL_COLOR,0,white.components); // specular + } + _copy_screen(); + + } + } + + glDisable(GL_DEPTH_TEST); + glDepthFunc(GL_LEQUAL); + + // just copy diffuse while applying SSAO + + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::SSAO_MERGE,true); + state.effect_blur_shader.bind(); + state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::SSAO_COLOR,env->ssao_color); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); //previous level, since mipmaps[0] starts one level bigger + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.ssao.blur_red[0]); //previous level, since mipmaps[0] starts one level bigger + 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::SSAO_MERGE,false); + + + + + diffuse_copied=true; + } + + if (state.used_sss) {//sss enabled //copy diffuse while performing sss @@ -2704,7 +2860,13 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c state.sss_shader.set_uniform(SubsurfScatteringShaderGLES3::DIR,Vector2(1,0)); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + if (diffuse_copied) { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->effects.mip_maps[0].color); + } else { + glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.diffuse); + diffuse_copied=true; + } + glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->buffers.motion_sss); glActiveTexture(GL_TEXTURE2); @@ -2721,7 +2883,10 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glBindFramebuffer(GL_FRAMEBUFFER,storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); // copy to base level _copy_screen(); - } else { + } + + + if (!diffuse_copied) { // just copy diffuse storage->shaders.copy.bind(); glActiveTexture(GL_TEXTURE0); @@ -2826,7 +2991,7 @@ void RasterizerSceneGLES3::_render_mrts(Environment *env,const CameraMatrix &p_c glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_ONE,GL_ONE); //use additive to accumulate one over the other - _copy_screen(); + //_copy_screen(); glDisable(GL_BLEND); //end additive @@ -2878,6 +3043,11 @@ void RasterizerSceneGLES3::render_scene(const Transform& p_cam_transform,const C } else { state.ubo_data.reflection_multiplier=1.0; } + + state.ubo_data.subsurface_scatter_width=subsurface_scatter_size; + + + _setup_environment(env,p_cam_projection,p_cam_transform); _setup_lights(p_light_cull_result,p_light_cull_count,p_cam_transform.affine_inverse(),p_cam_projection,p_shadow_atlas); @@ -4026,6 +4196,9 @@ void RasterizerSceneGLES3::initialize() { state.ssr_shader.init(); state.effect_blur_shader.init(); state.sss_shader.init(); + state.ssao_minify_shader.init(); + state.ssao_shader.init(); + state.ssao_blur_shader.init(); { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 21711292a..6b9295dee 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -8,6 +8,9 @@ #include "drivers/gles3/shaders/screen_space_reflection.glsl.h" #include "drivers/gles3/shaders/effect_blur.glsl.h" #include "drivers/gles3/shaders/subsurf_scattering.glsl.h" +#include "drivers/gles3/shaders/ssao_minify.glsl.h" +#include "drivers/gles3/shaders/ssao.glsl.h" +#include "drivers/gles3/shaders/ssao_blur.glsl.h" class RasterizerSceneGLES3 : public RasterizerScene { public: @@ -62,6 +65,9 @@ public: ScreenSpaceReflectionShaderGLES3 ssr_shader; EffectBlurShaderGLES3 effect_blur_shader; SubsurfScatteringShaderGLES3 sss_shader; + SsaoMinifyShaderGLES3 ssao_minify_shader; + SsaoShaderGLES3 ssao_shader; + SsaoBlurShaderGLES3 ssao_blur_shader; struct SceneDataUBO { @@ -81,6 +87,8 @@ public: float shadow_atlas_pixel_size[2]; float shadow_directional_pixel_size[2]; float reflection_multiplier; + float subsurface_scatter_width; + float ambient_occlusion_affect_light; } ubo_data; @@ -316,6 +324,15 @@ public: bool ssr_roughness; + bool ssao_enabled; + float ssao_intensity; + float ssao_radius; + float ssao_intensity2; + float ssao_radius2; + float ssao_bias; + float ssao_light_affect; + Color ssao_color; + bool ssao_filter; Environment() { bg_mode=VS::ENV_BG_CLEAR_COLOR; @@ -334,6 +351,16 @@ public: ssr_smooth=true; ssr_roughness=true; + ssao_enabled=false; + ssao_intensity=1.0; + ssao_radius=1.0; + ssao_intensity2=1.0; + ssao_radius2=0.0; + ssao_bias=0.01; + ssao_light_affect=0; + ssao_filter=true; + + } }; @@ -353,6 +380,7 @@ public: 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,bool p_enable,float p_exposure,float p_white,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale,VS::EnvironmentToneMapper p_tone_mapper); virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 7b9a3f2af..f21b7021e 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4785,6 +4785,20 @@ void RasterizerStorageGLES3::_render_target_clear(RenderTarget *rt) { rt->depth=0; } + if (rt->effects.ssao.blur_fbo[0]) { + glDeleteFramebuffers(1,&rt->effects.ssao.blur_fbo[0]); + glDeleteTextures(1,&rt->effects.ssao.blur_red[0]); + glDeleteFramebuffers(1,&rt->effects.ssao.blur_fbo[1]); + glDeleteTextures(1,&rt->effects.ssao.blur_red[1]); + for(int i=0;ieffects.ssao.depth_mipmap_fbos.size();i++) { + glDeleteFramebuffers(1,&rt->effects.ssao.depth_mipmap_fbos[i]); + } + + rt->effects.ssao.depth_mipmap_fbos.clear(); + + glDeleteTextures(1,&rt->effects.ssao.linear_depth); + } + Texture *tex = texture_owner.get(rt->texture); tex->alloc_height=0; tex->alloc_width=0; @@ -5043,6 +5057,67 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt){ //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); + + + } + ///////////////// ssao + + //AO strength textures + for(int i=0;i<2;i++) { + + glGenFramebuffers(1, &rt->effects.ssao.blur_fbo[i]); + glBindFramebuffer(GL_FRAMEBUFFER, rt->effects.ssao.blur_fbo[i]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_TEXTURE_2D, rt->depth, 0); + + glGenTextures(1, &rt->effects.ssao.blur_red[i]); + glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.blur_red[i]); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, rt->width, rt->height, 0, GL_RED, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.blur_red[i], 0); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + _render_target_clear(rt); + ERR_FAIL_COND( status != GL_FRAMEBUFFER_COMPLETE ); + } + + } + //5 mip levels for depth texture, but base is read separately + + glGenTextures(1, &rt->effects.ssao.linear_depth); + glBindTexture(GL_TEXTURE_2D, rt->effects.ssao.linear_depth); + + int ssao_w=rt->width/2; + int ssao_h=rt->height/2; + + + for(int i=0;i<4;i++) { //5, but 4 mips, base is read directly to save bw + + glTexImage2D(GL_TEXTURE_2D, i, GL_R16UI, ssao_w, ssao_h, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, NULL); + ssao_w>>=1; + ssao_h>>=1; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3); + + for(int i=0;i<4;i++) { //5, but 4 mips, base is read directly to save bw + + GLuint fbo; + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->effects.ssao.linear_depth, i); + rt->effects.ssao.depth_mipmap_fbos.push_back(fbo); } } @@ -5653,6 +5728,7 @@ void RasterizerStorageGLES3::initialize() { glBindBuffer(GL_ARRAY_BUFFER,0); //unbind } + //generic quadie for copying without touching skybox { //transform feedback buffers diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index e6b89eb66..c2aea391b 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -911,6 +911,17 @@ public: MipMaps mip_maps[2]; //first mipmap chain starts from full-screen //GLuint depth2; //depth for the second mipmap chain, in case of desiring upsampling + struct SSAO { + GLuint blur_fbo[2]; // blur fbo + GLuint blur_red[2]; // 8 bits red buffer + + GLuint linear_depth; + + Vector depth_mipmap_fbos; //fbos for depth mipmapsla ver + + SSAO() { blur_fbo[0]=0; blur_fbo[1]=0; linear_depth=0; } + } ssao; + Effects() { } diff --git a/drivers/gles3/shaders/SCsub b/drivers/gles3/shaders/SCsub index b5797e78b..dd7ec4524 100644 --- a/drivers/gles3/shaders/SCsub +++ b/drivers/gles3/shaders/SCsub @@ -12,5 +12,8 @@ if env['BUILDERS'].has_key('GLES3_GLSL'): env.GLES3_GLSL('screen_space_reflection.glsl'); env.GLES3_GLSL('effect_blur.glsl'); env.GLES3_GLSL('subsurf_scattering.glsl'); + env.GLES3_GLSL('ssao.glsl'); + env.GLES3_GLSL('ssao_minify.glsl'); + env.GLES3_GLSL('ssao_blur.glsl'); diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index fc6de7f65..211b60ca2 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -19,12 +19,22 @@ void main() { in vec2 uv_interp; uniform sampler2D source_color; //texunit:0 +#ifdef SSAO_MERGE +uniform sampler2D source_ssao; //texunit:1 +#endif + uniform float lod; uniform vec2 pixel_size; layout(location = 0) out vec4 frag_color; +#ifdef SSAO_MERGE + +uniform vec4 ssao_color; + +#endif + void main() { @@ -52,6 +62,13 @@ void main() { frag_color = color; #endif +#ifdef SSAO_MERGE + + vec4 color =textureLod( source_color, uv_interp,0.0); + float ssao =textureLod( source_ssao, uv_interp,0.0).r; + frag_color = vec4( mix(color.rgb,color.rgb*mix(ssao_color.rgb,vec3(1.0),ssao),color.a), 1.0 ); + +#endif } diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 230544c1c..61e9e37d2 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -76,6 +76,7 @@ layout(std140) uniform SceneData { //ubo:0 float reflection_multiplier; float subsurface_scatter_width; + float ambient_occlusion_affect_light; }; @@ -387,6 +388,7 @@ layout(std140) uniform SceneData { float reflection_multiplier; float subsurface_scatter_width; + float ambient_occlusion_affect_light; }; @@ -1223,7 +1225,7 @@ LIGHT_SHADER_CODE float max_ambient=max(ambient_light.r,max(ambient_light.g,ambient_light.b)); float max_diffuse=max(diffuse_light.r,max(diffuse_light.g,diffuse_light.b)); float total_ambient = max_ambient+max_diffuse+max_emission; - float ambient_scale = (total_ambient>0.0) ? max_ambient/total_ambient : 0.0; + float ambient_scale = (total_ambient>0.0) ? (max_ambient+ambient_occlusion_affect_light*max_diffuse)/total_ambient : 0.0; #endif //ENABLE_AO diffuse_buffer=vec4(emission+diffuse_light+ambient_light,ambient_scale); diff --git a/drivers/gles3/shaders/ssao.glsl b/drivers/gles3/shaders/ssao.glsl new file mode 100644 index 000000000..75f49ef37 --- /dev/null +++ b/drivers/gles3/shaders/ssao.glsl @@ -0,0 +1,247 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + +void main() { + + gl_Position = vertex_attrib; + gl_Position.z=1.0; +} + +[fragment] + + +#define NUM_SAMPLES (11) + +// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower +// miplevel to maintain reasonable spatial locality in the cache +// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. +// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively +#define LOG_MAX_OFFSET (3) + +// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp +#define MAX_MIP_LEVEL (4) + +// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent +// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 +#define NUM_SPIRAL_TURNS (7) + + +uniform sampler2D source_depth; //texunit:0 +uniform usampler2D source_depth_mipmaps; //texunit:1 +uniform sampler2D source_normal; //texunit:2 + +uniform ivec2 screen_size; +uniform float camera_z_far; +uniform float camera_z_near; + +uniform float intensity_div_r6; +uniform float radius; + +#ifdef ENABLE_RADIUS2 +uniform float intensity_div_r62; +uniform float radius2; +#endif + +uniform float bias; +uniform float proj_scale; + +layout(location = 0) out float visibility; + +uniform vec4 proj_info; + +vec3 reconstructCSPosition(vec2 S, float z) { + return vec3((S.xy * proj_info.xy + proj_info.zw) * z, z); +} + +vec3 getPosition(ivec2 ssP) { + vec3 P; + P.z = texelFetch(source_depth, ssP, 0).r; + + P.z = P.z * 2.0 - 1.0; + P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); + P.z = -P.z; + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + return P; +} + +/** Reconstructs screen-space unit normal from screen-space position */ +vec3 reconstructCSFaceNormal(vec3 C) { + return normalize(cross(dFdy(C), dFdx(C))); +} + + + +/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ +vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR){ + // Radius relative to ssR + float alpha = float(sampleNumber + 0.5) * (1.0 / NUM_SAMPLES); + float angle = alpha * (NUM_SPIRAL_TURNS * 6.28) + spinAngle; + + ssR = alpha; + return vec2(cos(angle), sin(angle)); +} + + +/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ +vec3 getOffsetPosition(ivec2 ssC, vec2 unitOffset, float ssR) { + // Derivation: + // mipLevel = floor(log(ssR / MAX_OFFSET)); + int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); + + ivec2 ssP = ivec2(ssR * unitOffset) + ssC; + + vec3 P; + + // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. + // Manually clamp to the texture size because texelFetch bypasses the texture unit + ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (screen_size >> mipLevel) - ivec2(1)); + + + if (mipLevel < 1) { + //read from depth buffer + P.z = texelFetch(source_depth, mipP, 0).r; + P.z = P.z * 2.0 - 1.0; + P.z = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - P.z * (camera_z_far - camera_z_near)); + P.z = -P.z; + + } else { + //read from mipmaps + uint d = texelFetch(source_depth_mipmaps, mipP, mipLevel-1).r; + P.z = -(float(d)/65535.0)*camera_z_far; + } + + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + + return P; +} + + + +/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds + to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius + + Note that units of H() in the HPG12 paper are meters, not + unitless. The whole falloff/sampling function is therefore + unitless. In this implementation, we factor out (9 / radius). + + Four versions of the falloff function are implemented below +*/ +float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius,in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { + // Offset on the unit disk, spun for this pixel + float ssR; + vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); + ssR *= ssDiskRadius; + + // The occluding point in camera space + vec3 Q = getOffsetPosition(ssC, unitOffset, ssR); + + vec3 v = Q - C; + + float vv = dot(v, v); + float vn = dot(v, n_C); + + const float epsilon = 0.01; + float radius2 = p_radius*p_radius; + + // A: From the HPG12 paper + // Note large epsilon to avoid overdarkening within cracks + //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; + + // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] + float f=max(radius2 - vv, 0.0); + return f * f * f * max((vn - bias) / (epsilon + vv), 0.0); + + // C: Medium contrast (which looks better at high radii), no division. Note that the + // contribution still falls off with radius^2, but we've adjusted the rate in a way that is + // more computationally efficient and happens to be aesthetically pleasing. + // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); + + // D: Low contrast, no division operation + // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); +} + + + +void main() { + + + // Pixel being shaded + ivec2 ssC = ivec2(gl_FragCoord.xy); + + // World space point being shaded + vec3 C = getPosition(ssC); + +/* if (C.z <= -camera_z_far*0.999) { + // We're on the skybox + visibility=1.0; + return; + }*/ + + //visibility=-C.z/camera_z_far; + //return; + + //vec3 n_C = texelFetch(source_normal,ssC,0).rgb * 2.0 - 1.0; + + vec3 n_C = reconstructCSFaceNormal(C); + n_C = -n_C; + + + // Hash function used in the HPG12 AlchemyAO paper + float randomPatternRotationAngle = (3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10; + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + float ssDiskRadius = -proj_scale * radius / C.z; + + float sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius, radius,i, randomPatternRotationAngle); + } + + float A = max(0.0, 1.0 - sum * intensity_div_r6 * (5.0 / NUM_SAMPLES)); + +#ifdef ENABLE_RADIUS2 + + //go again for radius2 + randomPatternRotationAngle = (5 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 11; + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + ssDiskRadius = -proj_scale * radius2 / C.z; + + sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius,radius2, i, randomPatternRotationAngle); + } + + A= min(A,max(0.0, 1.0 - sum * intensity_div_r62 * (5.0 / NUM_SAMPLES))); +#endif + // Bilateral box-filter over a quad for free, respecting depth edges + // (the difference that this makes is subtle) + if (abs(dFdx(C.z)) < 0.02) { + A -= dFdx(A) * ((ssC.x & 1) - 0.5); + } + if (abs(dFdy(C.z)) < 0.02) { + A -= dFdy(A) * ((ssC.y & 1) - 0.5); + } + + visibility = A; + +} + + + diff --git a/drivers/gles3/shaders/ssao_blur.glsl b/drivers/gles3/shaders/ssao_blur.glsl new file mode 100644 index 000000000..31f3841a2 --- /dev/null +++ b/drivers/gles3/shaders/ssao_blur.glsl @@ -0,0 +1,113 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + + +void main() { + + gl_Position = vertex_attrib; + gl_Position.z=1.0; +} + +[fragment] + + +uniform sampler2D source_ssao; //texunit:0 +uniform sampler2D source_depth; //texunit:1 + + +layout(location = 0) out float visibility; + + +////////////////////////////////////////////////////////////////////////////////////////////// +// Tunable Parameters: + +/** Increase to make depth edges crisper. Decrease to reduce flicker. */ +#define EDGE_SHARPNESS (1.0) + +/** Step in 2-pixel intervals since we already blurred against neighbors in the + first AO pass. This constant can be increased while R decreases to improve + performance at the expense of some dithering artifacts. + + Morgan found that a scale of 3 left a 1-pixel checkerboard grid that was + unobjectionable after shading was applied but eliminated most temporal incoherence + from using small numbers of sample taps. + */ +#define SCALE (3) + +/** Filter radius in pixels. This will be multiplied by SCALE. */ +#define R (4) + + +////////////////////////////////////////////////////////////////////////////////////////////// + + +// Gaussian coefficients +const float gaussian[R + 1] = +// float[](0.356642, 0.239400, 0.072410, 0.009869); +// float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 + float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 +// float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 + +/** (1, 0) or (0, 1)*/ +uniform ivec2 axis; + +uniform float camera_z_far; +uniform float camera_z_near; + +void main() { + + ivec2 ssC = ivec2(gl_FragCoord.xy); + + float depth = texelFetch(source_depth, ssC, 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 depth_divide = 1.0 / camera_z_far; + + depth*=depth_divide; + + //if (depth > camera_z_far*0.999) { + // discard;//skybox + //} + + float sum = texelFetch(source_ssao, ssC, 0).r; + + // Base weight for depth falloff. Increase this for more blurriness, + // decrease it for better edge discrimination + float BASE = gaussian[0]; + float totalWeight = BASE; + sum *= totalWeight; + + + for (int r = -R; r <= R; ++r) { + // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, + // so the IF statement has no runtime cost + if (r != 0) { + + ivec2 ppos = ssC + axis * (r * SCALE); + float value = texelFetch(source_ssao, ppos, 0).r; + float temp_depth = texelFetch(source_depth, ssC, 0).r; + + temp_depth = temp_depth * 2.0 - 1.0; + temp_depth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - temp_depth * (camera_z_far - camera_z_near)); + temp_depth *= depth_divide; + + // spatial domain: offset gaussian tap + float weight = 0.3 + gaussian[abs(r)]; + + // range domain (the "bilateral" weight). As depth difference increases, decrease weight. + weight *= max(0.0, 1.0 + - (EDGE_SHARPNESS * 2000.0) * abs(temp_depth - depth) + ); + + sum += value * weight; + totalWeight += weight; + } + } + + const float epsilon = 0.0001; + visibility = sum / (totalWeight + epsilon); +} diff --git a/drivers/gles3/shaders/ssao_minify.glsl b/drivers/gles3/shaders/ssao_minify.glsl new file mode 100644 index 000000000..df9045c28 --- /dev/null +++ b/drivers/gles3/shaders/ssao_minify.glsl @@ -0,0 +1,55 @@ +[vertex] + + +layout(location=0) in highp vec4 vertex_attrib; + +void main() { + + gl_Position = vertex_attrib; +} + +[fragment] + + +#ifdef MINIFY_START + +#define SDEPTH_TYPE highp sampler2D +uniform float camera_z_far; +uniform float camera_z_near; + +#else + +#define SDEPTH_TYPE mediump usampler2D + +#endif + +uniform SDEPTH_TYPE source_depth; //texunit:0 + +uniform ivec2 from_size; +uniform int source_mipmap; + +layout(location = 0) out mediump uint depth; + +void main() { + + + ivec2 ssP = ivec2(gl_FragCoord.xy); + + // Rotated grid subsampling to avoid XY directional bias or Z precision bias while downsampling. + // On DX9, the bit-and can be implemented with floating-point modulo + +#ifdef MINIFY_START + float fdepth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; + fdepth = fdepth * 2.0 - 1.0; + fdepth = 2.0 * camera_z_near * camera_z_far / (camera_z_far + camera_z_near - fdepth * (camera_z_far - camera_z_near)); + fdepth /= camera_z_far; + depth = uint(clamp(fdepth*65535,0.0,65535.0)); + +#else + depth = texelFetch(source_depth, clamp(ssP * 2 + ivec2(ssP.y & 1, ssP.x & 1), ivec2(0), from_size - ivec2(1)), source_mipmap).r; +#endif + + +} + + diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 578a8ae50..c945d2a95 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -377,6 +377,102 @@ bool Environment::is_ssr_rough() const { return ssr_roughness; } +void Environment::set_ssao_enabled(bool p_enable) { + + ssao_enabled=p_enable; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); + +} + +bool Environment::is_ssao_enabled() const{ + + return ssao_enabled; +} + +void Environment::set_ssao_radius(float p_radius){ + + ssao_radius=p_radius; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} +float Environment::get_ssao_radius() const{ + + return ssao_radius; +} + + +void Environment::set_ssao_intensity(float p_intensity){ + + ssao_intensity=p_intensity; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} + +float Environment::get_ssao_intensity() const{ + + return ssao_intensity; +} + +void Environment::set_ssao_radius2(float p_radius){ + + ssao_radius2=p_radius; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} +float Environment::get_ssao_radius2() const{ + + return ssao_radius2; +} + + +void Environment::set_ssao_intensity2(float p_intensity){ + + ssao_intensity2=p_intensity; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} +float Environment::get_ssao_intensity2() const{ + + return ssao_intensity2; +} + +void Environment::set_ssao_bias(float p_bias){ + + ssao_bias=p_bias; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} +float Environment::get_ssao_bias() const{ + + return ssao_bias; +} + +void Environment::set_ssao_direct_light_affect(float p_direct_light_affect){ + + ssao_direct_light_affect=p_direct_light_affect; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} +float Environment::get_ssao_direct_light_affect() const{ + + return ssao_direct_light_affect; +} + + +void Environment::set_ssao_color(const Color& p_color) { + + ssao_color=p_color; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} + +Color Environment::get_ssao_color() const { + + return ssao_color; +} + +void Environment::set_ssao_blur(bool p_enable) { + + ssao_blur=p_enable; + VS::get_singleton()->environment_set_ssao(environment,ssao_enabled,ssao_radius,ssao_intensity,ssao_radius2,ssao_intensity2,ssao_bias,ssao_direct_light_affect,ssao_color,ssao_blur); +} +bool Environment::is_ssao_blur_enabled() const { + + return ssao_blur; +} void Environment::_bind_methods() { @@ -442,6 +538,43 @@ void Environment::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/accel_smooth"),_SCS("set_ssr_smooth"),_SCS("is_ssr_smooth") ); ADD_PROPERTY(PropertyInfo(Variant::BOOL,"ss_reflections/roughness"),_SCS("set_ssr_rough"),_SCS("is_ssr_rough") ); + ObjectTypeDB::bind_method(_MD("set_ssao_enabled","enabled"),&Environment::set_ssao_enabled); + ObjectTypeDB::bind_method(_MD("is_ssao_enabled"),&Environment::is_ssao_enabled); + + ObjectTypeDB::bind_method(_MD("set_ssao_radius","radius"),&Environment::set_ssao_radius); + ObjectTypeDB::bind_method(_MD("get_ssao_radius"),&Environment::get_ssao_radius); + + ObjectTypeDB::bind_method(_MD("set_ssao_intensity","intensity"),&Environment::set_ssao_intensity); + ObjectTypeDB::bind_method(_MD("get_ssao_intensity"),&Environment::get_ssao_intensity); + + ObjectTypeDB::bind_method(_MD("set_ssao_radius2","radius"),&Environment::set_ssao_radius2); + ObjectTypeDB::bind_method(_MD("get_ssao_radius2"),&Environment::get_ssao_radius2); + + ObjectTypeDB::bind_method(_MD("set_ssao_intensity2","intensity"),&Environment::set_ssao_intensity2); + ObjectTypeDB::bind_method(_MD("get_ssao_intensity2"),&Environment::get_ssao_intensity2); + + ObjectTypeDB::bind_method(_MD("set_ssao_bias","bias"),&Environment::set_ssao_bias); + ObjectTypeDB::bind_method(_MD("get_ssao_bias"),&Environment::get_ssao_bias); + + ObjectTypeDB::bind_method(_MD("set_ssao_direct_light_affect","amount"),&Environment::set_ssao_direct_light_affect); + ObjectTypeDB::bind_method(_MD("get_ssao_direct_light_affect"),&Environment::get_ssao_direct_light_affect); + + ObjectTypeDB::bind_method(_MD("set_ssao_color","color"),&Environment::set_ssao_color); + ObjectTypeDB::bind_method(_MD("get_ssao_color"),&Environment::get_ssao_color); + + 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::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") ); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/intensity2",PROPERTY_HINT_RANGE,"0.0,9,0.1"),_SCS("set_ssao_intensity2"),_SCS("get_ssao_intensity2") ); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/bias",PROPERTY_HINT_RANGE,"0.001,8,0.001"),_SCS("set_ssao_bias"),_SCS("get_ssao_bias") ); + ADD_PROPERTY(PropertyInfo(Variant::REAL,"ambient_occlusion/light_affect",PROPERTY_HINT_RANGE,"0.00,1,0.01"),_SCS("set_ssao_direct_light_affect"),_SCS("get_ssao_direct_light_affect") ); + 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_tonemapper","mode"),&Environment::set_tonemapper); ObjectTypeDB::bind_method(_MD("get_tonemapper"),&Environment::get_tonemapper); @@ -561,6 +694,15 @@ Environment::Environment() { ssr_smooth=true; ssr_roughness=true; + ssao_enabled=false; + ssao_radius=1; + ssao_intensity=1; + ssao_radius2=0; + ssao_intensity2=1; + ssao_bias=0.01; + ssao_direct_light_affect=false; + ssao_blur=true; + } Environment::~Environment() { diff --git a/scene/resources/environment.h b/scene/resources/environment.h index f4610ada4..c489ff97f 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -102,6 +102,17 @@ private: bool ssr_smooth; bool ssr_roughness; + bool ssao_enabled; + float ssao_radius; + float ssao_intensity; + float ssao_radius2; + float ssao_intensity2; + float ssao_bias; + float ssao_direct_light_affect; + Color ssao_color; + bool ssao_blur; + + protected: static void _bind_methods(); @@ -191,6 +202,34 @@ public: void set_ssr_rough(bool p_enable); bool is_ssr_rough() const; + void set_ssao_enabled(bool p_enable); + bool is_ssao_enabled() const; + + void set_ssao_radius(float p_radius); + float get_ssao_radius() const; + + void set_ssao_intensity(float p_intensity); + float get_ssao_intensity() const; + + void set_ssao_radius2(float p_radius); + float get_ssao_radius2() const; + + void set_ssao_intensity2(float p_intensity); + float get_ssao_intensity2() const; + + void set_ssao_bias(float p_bias); + float get_ssao_bias() const; + + void set_ssao_direct_light_affect(float p_direct_light_affect); + float get_ssao_direct_light_affect() const; + + void set_ssao_color(const Color& p_color); + Color get_ssao_color() const; + + void set_ssao_blur(bool p_enable); + bool is_ssao_blur_enabled() const; + + virtual RID get_rid() const; diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 0d3670646..09d59e317 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -65,6 +65,7 @@ public: virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0; virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0; + virtual void environment_set_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_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0; diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index e7594278f..ff1a62210 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -876,6 +876,8 @@ public: BIND2(environment_set_canvas_max_layer,RID,int ) BIND4(environment_set_ambient_light,RID,const Color& ,float,float ) BIND8(environment_set_ssr,RID,bool,int,float,float,float,bool,bool ) + 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 ) BIND5(environment_set_fog,RID,bool ,float ,float ,RID ) diff --git a/servers/visual_server.h b/servers/visual_server.h index 9b1a9d81a..6c4a08043 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -556,6 +556,7 @@ public: 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; + 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; /* SCENARIO API */ -- cgit v1.2.3-70-g09d2 From 22a90e8f2acce60f92958788a52b3f0bdb1a0cdf Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 10 Dec 2016 01:13:20 -0300 Subject: DOF blur, near and far fields.. --- core/math/camera_matrix.cpp | 2 +- core/math/camera_matrix.h | 2 +- drivers/gles3/rasterizer_scene_gles3.cpp | 196 +++++++++++++++++++++++++++++- drivers/gles3/rasterizer_scene_gles3.h | 31 ++++- drivers/gles3/shaders/effect_blur.glsl | 177 +++++++++++++++++++++++---- drivers/gles3/shaders/tonemap.glsl | 99 ++++++++++++++-- scene/resources/environment.cpp | 198 +++++++++++++++++++++++++++++-- scene/resources/environment.h | 53 ++++++++- servers/visual/rasterizer.h | 4 +- servers/visual/visual_server_raster.h | 5 +- servers/visual_server.h | 11 +- 11 files changed, 731 insertions(+), 47 deletions(-) (limited to 'core/math/camera_matrix.h') diff --git a/core/math/camera_matrix.cpp b/core/math/camera_matrix.cpp index fc35908fa..89f3ee1ad 100644 --- a/core/math/camera_matrix.cpp +++ b/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; diff --git a/core/math/camera_matrix.h b/core/math/camera_matrix.h index 7fcff6376..c597ec403 100644 --- a/core/math/camera_matrix.h +++ b/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; diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index ec304e7a4..2c6c9dd9b 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/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) { diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index 6ca4529ed..78e8b3e47 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/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); diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index 589af64d4..89afa12f6 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/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;i0.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> 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 diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index eb393f2ad..71a711dc7 100644 --- a/scene/resources/environment.cpp +++ b/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<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; } diff --git a/scene/resources/environment.h b/scene/resources/environment.h index 50c48165e..fcf3e1edc 100644 --- a/scene/resources/environment.h +++ b/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 diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 2b1829283..228afffdb 100644 --- a/servers/visual/rasterizer.h +++ b/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; diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 52c156cd6..78b0e3cad 100644 --- a/servers/visual/visual_server_raster.h +++ b/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 ) diff --git a/servers/visual_server.h b/servers/visual_server.h index adc9f4960..7558fbf81 100644 --- a/servers/visual_server.h +++ b/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; -- cgit v1.2.3-70-g09d2