From 97392162506951b508621c7ad837bf0f37f50eb6 Mon Sep 17 00:00:00 2001 From: jay3d Date: Tue, 29 Nov 2016 23:01:20 +0800 Subject: [PATCH] Massive improvemnts to shadows quality/flexibility --- drivers/gles2/rasterizer_gles2.cpp | 14 ++-- drivers/gles2/rasterizer_gles2.h | 1 + drivers/gles2/shaders/canvas.glsl | 86 +++++++++++++++++------ drivers/gles2/shaders/material.glsl | 93 +++++++++++++++++++------ scene/2d/light_2d.cpp | 16 +++++ scene/2d/light_2d.h | 4 ++ scene/3d/light.cpp | 4 ++ scene/3d/light.h | 1 + servers/visual/rasterizer.h | 8 ++- servers/visual/visual_server_raster.cpp | 8 +++ servers/visual/visual_server_raster.h | 1 + servers/visual/visual_server_wrap_mt.h | 1 + servers/visual_server.h | 2 + 13 files changed, 184 insertions(+), 55 deletions(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index a7edc8d935ae..0565363a287d 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -4208,8 +4208,8 @@ void RasterizerGLES2::begin_frame() { shadow_filter=ShadowFilterTechnique(int(Globals::get_singleton()->get("rasterizer/shadow_filter"))); #endif - canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF5,shadow_filter==SHADOW_FILTER_PCF5); - canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF13,shadow_filter==SHADOW_FILTER_PCF13); + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF_MEDIUM,shadow_filter==SHADOW_FILTER_PCF_MEDIUM); + canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_PCF_HIGH,shadow_filter==SHADOW_FILTER_PCF_HIGH); canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM); window_size = Size2( OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height ); @@ -5166,8 +5166,8 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material //all goes to false by default material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PASS,shadow!=NULL); - material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,shadow_filter==SHADOW_FILTER_PCF5 || shadow_filter==SHADOW_FILTER_PCF13); - material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF13); + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF,shadow_filter==SHADOW_FILTER_PCF_MEDIUM || shadow_filter==SHADOW_FILTER_PCF_HIGH); + material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_PCF_HQ,shadow_filter==SHADOW_FILTER_PCF_HIGH); material_shader.set_conditional(MaterialShaderGLES2::USE_SHADOW_ESM,shadow_filter==SHADOW_FILTER_ESM); material_shader.set_conditional(MaterialShaderGLES2::USE_LIGHTMAP_ON_UV2,p_material->flags[VS::MATERIAL_FLAG_LIGHTMAP_ON_UV2]); material_shader.set_conditional(MaterialShaderGLES2::USE_COLOR_ATTRIB_SRGB_TO_LINEAR,p_material->flags[VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB] && current_env && current_env->fx_enabled[VS::ENV_FX_SRGB]); @@ -5429,6 +5429,7 @@ void RasterizerGLES2::_setup_light(uint16_t p_light) { material_shader.set_uniform(MaterialShaderGLES2::SHADOW_MATRIX,li->shadow_projection[0]); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXEL_SIZE,Vector2(1.0,1.0)/li->near_shadow_buffer->size); material_shader.set_uniform(MaterialShaderGLES2::SHADOW_TEXTURE,max_texture_units-1); + material_shader.set_uniform(MaterialShaderGLES2::SHADOW_FILTER_RADIUS,float(li->base->vars[VS::LIGHT_PARAM_SHADOW_FILTER_RADIUS])); if (shadow_filter==SHADOW_FILTER_ESM) material_shader.set_uniform(MaterialShaderGLES2::ESM_MULTIPLIER,float(li->base->vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER])); @@ -9744,6 +9745,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list,int p_z,const canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_TEXTURE,max_texture_units-3); canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX,light->shadow_matrix_cache); + canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_FILTER_RADIUS,light->shadow_filter_radius); canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_ESM_MULTIPLIER,light->shadow_esm_mult); canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR,light->shadow_color); @@ -11451,8 +11453,8 @@ RasterizerGLES2::RasterizerGLES2(bool p_compress_arrays,bool p_keep_ram_copy,boo p_default_fragment_lighting=false; fragment_lighting=GLOBAL_DEF("rasterizer/use_fragment_lighting",true); read_depth_supported=true; //todo check for extension - shadow_filter=ShadowFilterTechnique((int)(GLOBAL_DEF("rasterizer/shadow_filter",SHADOW_FILTER_PCF5))); - Globals::get_singleton()->set_custom_property_info("rasterizer/shadow_filter",PropertyInfo(Variant::INT,"rasterizer/shadow_filter",PROPERTY_HINT_ENUM,"None,PCF5,PCF13,ESM")); + shadow_filter=ShadowFilterTechnique((int)(GLOBAL_DEF("rasterizer/shadow_filter",SHADOW_FILTER_PCF_MEDIUM))); + Globals::get_singleton()->set_custom_property_info("rasterizer/shadow_filter",PropertyInfo(Variant::INT,"rasterizer/shadow_filter",PROPERTY_HINT_ENUM,"Low,Medium,High,ESM")); use_fp16_fb=bool(GLOBAL_DEF("rasterizer/fp16_framebuffer",true)); use_shadow_mapping=true; use_fast_texture_filter=!bool(GLOBAL_DEF("rasterizer/trilinear_mipmap_filter",true)); diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index b18f89d8e754..71a04ce04309 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -653,6 +653,7 @@ class RasterizerGLES2 : public Rasterizer { vars[VS::LIGHT_PARAM_SHADOW_DARKENING]=0.0; vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.2; vars[VS::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE]=1.4; + vars[VS::LIGHT_PARAM_SHADOW_FILTER_RADIUS]=5.0; vars[VS::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER]=60.0; vars[VS::LIGHT_PARAM_SHADOW_BLUR_PASSES]=1; colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 5f4767940d46..ae00615deb03 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -185,6 +185,30 @@ uniform vec2 texpixel_size; FRAGMENT_SHADER_GLOBALS +uniform float shadow_filter_radius; + +uniform vec2 kern[16] = vec2[] +( + vec2(0.151205, 0.340969), + vec2(0.349872, -0.70755), + vec2(0.946959, 0.663325), + vec2(0.849958, -0.760292), + vec2(-0.792296, 0.463846), + vec2(0.45069, 0.832586), + vec2(-0.637487, -0.522192), + vec2(0.0185288, -0.162319), + vec2(0.622725, -0.289341), + vec2(-0.265502, 0.0830657), + vec2(-0.604604, 0.99042), + vec2(-0.228469, -0.911768), + vec2(-0.486144, -0.481575), + vec2(-0.0477502, 0.603215), + vec2(0.727942, 0.152266), + vec2(-0.890052, -0.0117375) +); + +#define KERNWIDTH 4 + void main() { @@ -328,34 +352,45 @@ LIGHT_SHADER_CODE #endif +#ifdef SHADOW_PCF_MEDIUM + + for (int iy = 0; iy < 2; iy++) + { + int y = int(mod(gl_FragCoord.y + iy, KERNWIDTH)); + for (int ix = 0; ix < 2; ix++) + { + int x = int(mod(gl_FragCoord.x + ix, KERNWIDTH)); -#ifdef SHADOW_PCF5 + vec2 sample = kern[y * KERNWIDTH + x]; + vec2 offset = ((sample - 1.0) * 0.5 + vec2(ix, iy)) * shadowpixel_size * shadow_filter_radius; - shadow_attenuation += SHADOW_DEPTH(shadow_texture,vec2(su,sh))canvas_light_set_shadow_filter_radius(canvas_light,p_filter_radius); +} + +float Light2D::get_shadow_filter_radius() const{ + + return shadow_filter_radius; +} + void Light2D::set_shadow_esm_multiplier( float p_multiplier) { shadow_esm_multiplier=p_multiplier; @@ -405,6 +416,9 @@ void Light2D::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_shadow_buffer_size","size"),&Light2D::set_shadow_buffer_size); ObjectTypeDB::bind_method(_MD("get_shadow_buffer_size"),&Light2D::get_shadow_buffer_size); + ObjectTypeDB::bind_method(_MD("set_shadow_filter_radius","filter_radius"),&Light2D::set_shadow_filter_radius); + ObjectTypeDB::bind_method(_MD("get_shadow_filter_radius"),&Light2D::get_shadow_filter_radius); + ObjectTypeDB::bind_method(_MD("set_shadow_esm_multiplier","multiplier"),&Light2D::set_shadow_esm_multiplier); ObjectTypeDB::bind_method(_MD("get_shadow_esm_multiplier"),&Light2D::get_shadow_esm_multiplier); @@ -429,6 +443,7 @@ void Light2D::_bind_methods() { ADD_PROPERTY( PropertyInfo(Variant::BOOL,"shadow/enabled"),_SCS("set_shadow_enabled"),_SCS("is_shadow_enabled")); ADD_PROPERTY( PropertyInfo(Variant::COLOR,"shadow/color"),_SCS("set_shadow_color"),_SCS("get_shadow_color")); ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/buffer_size",PROPERTY_HINT_RANGE,"32,16384,1"),_SCS("set_shadow_buffer_size"),_SCS("get_shadow_buffer_size")); + ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/filter_radius",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_filter_radius"),_SCS("get_shadow_filter_radius")); ADD_PROPERTY( PropertyInfo(Variant::REAL,"shadow/esm_multiplier",PROPERTY_HINT_RANGE,"1,4096,0.1"),_SCS("set_shadow_esm_multiplier"),_SCS("get_shadow_esm_multiplier")); ADD_PROPERTY( PropertyInfo(Variant::INT,"shadow/item_mask",PROPERTY_HINT_ALL_FLAGS),_SCS("set_item_shadow_mask"),_SCS("get_item_shadow_mask")); @@ -457,6 +472,7 @@ Light2D::Light2D() { item_shadow_mask=1; mode=MODE_ADD; shadow_buffer_size=2048; + shadow_filter_radius=5.0; shadow_esm_multiplier=80; energy=1.0; shadow_color=Color(0,0,0,0); diff --git a/scene/2d/light_2d.h b/scene/2d/light_2d.h index 57c89b15e7c8..b81b9c3f490a 100644 --- a/scene/2d/light_2d.h +++ b/scene/2d/light_2d.h @@ -59,6 +59,7 @@ class Light2D : public Node2D { int item_mask; int item_shadow_mask; int shadow_buffer_size; + float shadow_filter_radius; float shadow_esm_multiplier; Mode mode; Ref texture; @@ -127,6 +128,9 @@ class Light2D : public Node2D { void set_shadow_buffer_size( int p_size ); int get_shadow_buffer_size() const; + void set_shadow_filter_radius( float p_filter_radius); + float get_shadow_filter_radius() const; + void set_shadow_esm_multiplier( float p_multiplier); float get_shadow_esm_multiplier() const; diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp index 5b221d1574cf..fbfce050180d 100644 --- a/scene/3d/light.cpp +++ b/scene/3d/light.cpp @@ -41,6 +41,7 @@ static const char* _light_param_names[VS::LIGHT_PARAM_MAX]={ "shadow/darkening", "shadow/z_offset", "shadow/z_slope_scale", + "shadow/filter_radius", "shadow/esm_multiplier", "shadow/blur_passes" }; @@ -530,6 +531,7 @@ void Light::_bind_methods() { ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/darkening", PROPERTY_HINT_RANGE, "0,1,0.01"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_DARKENING ); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_offset", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_OFFSET); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/z_slope_scale", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_Z_SLOPE_SCALE); + ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/filter_radius", PROPERTY_HINT_RANGE, "0,128,0.001"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_FILTER_RADIUS); ADD_PROPERTYI( PropertyInfo( Variant::REAL, "shadow/esm_multiplier", PROPERTY_HINT_RANGE, "1.0,512.0,0.1"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_ESM_MULTIPLIER); ADD_PROPERTYI( PropertyInfo( Variant::INT, "shadow/blur_passes", PROPERTY_HINT_RANGE, "0,4,1"), _SCS("set_parameter"), _SCS("get_parameter"), PARAM_SHADOW_BLUR_PASSES); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "projector",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_projector"), _SCS("get_projector")); @@ -543,6 +545,7 @@ void Light::_bind_methods() { BIND_CONSTANT( PARAM_SPOT_ATTENUATION ); BIND_CONSTANT( PARAM_SHADOW_DARKENING ); BIND_CONSTANT( PARAM_SHADOW_Z_OFFSET ); + BIND_CONSTANT( PARAM_SHADOW_FILTER_RADIUS ); BIND_CONSTANT( COLOR_DIFFUSE ); @@ -570,6 +573,7 @@ Light::Light(VisualServer::LightType p_type) { set_parameter(PARAM_SHADOW_DARKENING,0.0); set_parameter(PARAM_SHADOW_Z_OFFSET,0.05); set_parameter(PARAM_SHADOW_Z_SLOPE_SCALE,0); + set_parameter(PARAM_SHADOW_FILTER_RADIUS,5.0); set_parameter(PARAM_SHADOW_ESM_MULTIPLIER,60); set_parameter(PARAM_SHADOW_BLUR_PASSES,1); diff --git a/scene/3d/light.h b/scene/3d/light.h index b25c6a44b534..eee84d98013e 100644 --- a/scene/3d/light.h +++ b/scene/3d/light.h @@ -53,6 +53,7 @@ class Light : public VisualInstance { PARAM_SHADOW_DARKENING=VisualServer::LIGHT_PARAM_SHADOW_DARKENING, PARAM_SHADOW_Z_OFFSET=VisualServer::LIGHT_PARAM_SHADOW_Z_OFFSET, PARAM_SHADOW_Z_SLOPE_SCALE=VisualServer::LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE, + PARAM_SHADOW_FILTER_RADIUS=VisualServer::LIGHT_PARAM_SHADOW_FILTER_RADIUS, PARAM_SHADOW_ESM_MULTIPLIER=VisualServer::LIGHT_PARAM_SHADOW_ESM_MULTIPLIER, PARAM_SHADOW_BLUR_PASSES=VisualServer::LIGHT_PARAM_SHADOW_BLUR_PASSES, PARAM_MAX=VisualServer::LIGHT_PARAM_MAX diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index 8cc567072f47..1cb48aa3dd27 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -166,9 +166,9 @@ class Rasterizer { public: enum ShadowFilterTechnique { - SHADOW_FILTER_NONE, - SHADOW_FILTER_PCF5, - SHADOW_FILTER_PCF13, + SHADOW_FILTER_PCF_LOW, + SHADOW_FILTER_PCF_MEDIUM, + SHADOW_FILTER_PCF_HIGH, SHADOW_FILTER_ESM, SHADOW_FILTER_VSM, }; @@ -603,6 +603,7 @@ class Rasterizer { RID canvas; RID shadow_buffer; int shadow_buffer_size; + float shadow_filter_radius; float shadow_esm_mult; Color shadow_color; @@ -640,6 +641,7 @@ class Rasterizer { mask_next_ptr=NULL; filter_next_ptr=NULL; shadow_buffer_size=2048; + shadow_filter_radius=5.0; shadow_esm_mult=80; } diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index 1df0aafb23dd..844cc1fef7d2 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -4207,6 +4207,14 @@ void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_ } +void VisualServerRaster::canvas_light_set_shadow_filter_radius(RID p_light, float p_filter_radius) { + + Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); + ERR_FAIL_COND(!clight); + clight->shadow_filter_radius=p_filter_radius; + +} + void VisualServerRaster::canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier) { Rasterizer::CanvasLight *clight = canvas_light_owner.get(p_light); diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 1f22e31ab0d9..194cb58751ce 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1207,6 +1207,7 @@ class VisualServerRaster : public VisualServer { virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode); virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); + virtual void canvas_light_set_shadow_filter_radius(RID p_light, float p_filter_radius); virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier); virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index f0fe80d100e8..7e46bde0b397 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -650,6 +650,7 @@ class VisualServerWrapMT : public VisualServer { FUNC2(canvas_light_set_mode,RID,CanvasLightMode); FUNC2(canvas_light_set_shadow_enabled,RID,bool); FUNC2(canvas_light_set_shadow_buffer_size,RID,int); + FUNC2(canvas_light_set_shadow_filter_radius,RID,float); FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float); FUNC2(canvas_light_set_shadow_color,RID,const Color&); diff --git a/servers/visual_server.h b/servers/visual_server.h index 844da2d24578..4148dd2f40f3 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -505,6 +505,7 @@ class VisualServer : public Object { LIGHT_PARAM_SHADOW_DARKENING, LIGHT_PARAM_SHADOW_Z_OFFSET, LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE, + LIGHT_PARAM_SHADOW_FILTER_RADIUS, LIGHT_PARAM_SHADOW_ESM_MULTIPLIER, LIGHT_PARAM_SHADOW_BLUR_PASSES, LIGHT_PARAM_MAX @@ -1070,6 +1071,7 @@ class VisualServer : public Object { virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0; virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0; virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0; + virtual void canvas_light_set_shadow_filter_radius(RID p_light, float p_filter_radius)=0; virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0; virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color)=0;