Quellcode durchsuchen

add functions in Renderer to set shadow softness and VSM shadow parameters

Xavier Maupeu vor 10 Jahren
Ursprung
Commit
cf501d9585

+ 4 - 0
Source/Urho3D/AngelScript/GraphicsAPI.cpp

@@ -1715,6 +1715,10 @@ static void RegisterRenderer(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Renderer", "int get_shadowMapSize() const", asMETHOD(Renderer, GetShadowMapSize), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_shadowQuality(ShadowQuality)", asMETHOD(Renderer, SetShadowQuality), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_shadowQuality() const", asMETHOD(Renderer, GetShadowQuality), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Renderer", "void set_shadowSoftness(float)", asMETHOD(Renderer, SetShadowSoftness), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Renderer", "float get_shadowSoftness() const", asMETHOD(Renderer, GetShadowSoftness), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Renderer", "void set_vsmShadowParameters(float, float)", asMETHOD(Renderer, SetVsmShadowParameters), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Renderer", "Vector2 get_vsmShadowParameters() const", asMETHOD(Renderer, GetVsmShadowParameters), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_maxShadowMaps(int)", asMETHOD(Renderer, SetMaxShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "int get_maxShadowMaps() const", asMETHOD(Renderer, GetMaxShadowMaps), asCALL_THISCALL);
     engine->RegisterObjectMethod("Renderer", "void set_reuseShadowMaps(bool)", asMETHOD(Renderer, SetReuseShadowMaps), asCALL_THISCALL);

+ 5 - 0
Source/Urho3D/Graphics/Batch.cpp

@@ -506,6 +506,11 @@ void Batch::Prepare(View* view, Camera* camera, bool setModelTransform, bool all
                     lightSplits.z_ = lightQueue_->shadowSplits_[2].farSplit_ / camera->GetFarClip();
 
                 graphics->SetShaderParameter(PSP_SHADOWSPLITS, lightSplits);
+
+                if (graphics->HasShaderParameter(PSP_VSMSHADOWPARAMS))
+                {
+                    graphics->SetShaderParameter(PSP_VSMSHADOWPARAMS, renderer->GetVsmShadowParameters());
+                }
             }
         }
         else if (lightQueue_->vertexLights_.Size() && graphics->HasShaderParameter(VSP_VERTEXLIGHTS) &&

+ 1 - 0
Source/Urho3D/Graphics/GraphicsDefs.cpp

@@ -79,6 +79,7 @@ extern URHO3D_API const StringHash PSP_SHADOWINTENSITY("ShadowIntensity");
 extern URHO3D_API const StringHash PSP_SHADOWMAPINVSIZE("ShadowMapInvSize");
 extern URHO3D_API const StringHash PSP_SHADOWSPLITS("ShadowSplits");
 extern URHO3D_API const StringHash PSP_LIGHTMATRICES("LightMatricesPS");
+extern URHO3D_API const StringHash PSP_VSMSHADOWPARAMS("VsmShadowParams");
 
 extern URHO3D_API const Vector3 DOT_SCALE(1 / 3.0f, 1 / 3.0f, 1 / 3.0f);
 

+ 1 - 0
Source/Urho3D/Graphics/GraphicsDefs.h

@@ -333,6 +333,7 @@ extern URHO3D_API const StringHash PSP_SHADOWINTENSITY;
 extern URHO3D_API const StringHash PSP_SHADOWMAPINVSIZE;
 extern URHO3D_API const StringHash PSP_SHADOWSPLITS;
 extern URHO3D_API const StringHash PSP_LIGHTMATRICES;
+extern URHO3D_API const StringHash PSP_VSMSHADOWPARAMS;
 
 // Scale calculation from bounding box diagonal.
 extern URHO3D_API const Vector3 DOT_SCALE;

+ 15 - 3
Source/Urho3D/Graphics/Renderer.cpp

@@ -250,6 +250,8 @@ Renderer::Renderer(Context* context) :
     materialQuality_(QUALITY_HIGH),
     shadowMapSize_(1024),
     shadowQuality_(SHADOWQUALITY_PCF_16BIT),
+    shadowSoftness_(2.0f),
+    vsmShadowParams_(0.0000001f, 0.2f),
     maxShadowMaps_(1),
     minInstances_(2),
     maxSortedInstances_(1000),
@@ -410,6 +412,17 @@ void Renderer::SetShadowQuality(ShadowQuality quality)
     }
 }
 
+void Renderer::SetShadowSoftness(float shadowSoftness)
+{
+    shadowSoftness_ = Max(shadowSoftness, 0.0f);
+}
+
+void Renderer::SetVsmShadowParameters(float minVariance, float lightBleedingReduction)
+{
+    vsmShadowParams_.x_ = Max(minVariance, 0.0f);
+    vsmShadowParams_.y_ = Clamp(lightBleedingReduction, 0.0f, 1.0f);
+}
+
 void Renderer::SetShadowMapFilter(Object* instance, ShadowMapFilter functionPtr)
 {
     shadowMapFilterInstance_ = instance;
@@ -1887,9 +1900,8 @@ void Renderer::BlurShadowMap(View* view, Texture2D* shadowMap)
     view->SetGBufferShaderParameters(IntVector2(shadowMap->GetWidth(), shadowMap->GetHeight()), IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
 
     // Horizontal blur of the shadow map
-    float shadowSoftness = 2.f;
     static const StringHash blurOffsetParam("BlurOffsets");
-    graphics_->SetShaderParameter(blurOffsetParam, Vector2(shadowSoftness / shadowMap->GetWidth(), 0.0f));
+    graphics_->SetShaderParameter(blurOffsetParam, Vector2(shadowSoftness_ / shadowMap->GetWidth(), 0.0f));
 
     graphics_->SetTexture(TU_DIFFUSE, shadowMap);
     view->DrawFullscreenQuad(false);
@@ -1898,7 +1910,7 @@ void Renderer::BlurShadowMap(View* view, Texture2D* shadowMap)
     graphics_->SetRenderTarget(0, shadowMap);
     graphics_->SetViewport(IntRect(0, 0, shadowMap->GetWidth(), shadowMap->GetHeight()));
 
-    graphics_->SetShaderParameter(blurOffsetParam, Vector2(0.0f, shadowSoftness / shadowMap->GetHeight()));
+    graphics_->SetShaderParameter(blurOffsetParam, Vector2(0.0f, shadowSoftness_ / shadowMap->GetHeight()));
 
     graphics_->SetTexture(TU_DIFFUSE, tmpBuffer);
     view->DrawFullscreenQuad(false);

+ 14 - 0
Source/Urho3D/Graphics/Renderer.h

@@ -186,6 +186,10 @@ public:
     void SetShadowMapSize(int size);
     /// Set shadow quality mode. See the SHADOWQUALITY constants in GraphicsDefs.h.
     void SetShadowQuality(ShadowQuality quality);
+    /// Set shadow softness, only works when SHADOWQUALITY_BLUR_VSM is used.
+    void SetShadowSoftness(float shadowSoftness);
+    /// Set shadow parameters when VSM is used, they help to reduce light bleeding. LightBleeding must be in [0, 1[
+    void SetVsmShadowParameters(float minVariance, float lightBleedingReduction);
     /// Set post processing filter to the shadow map
     void SetShadowMapFilter(Object* instance, ShadowMapFilter functionPtr);
     /// Set reuse of shadow maps. Default is true. If disabled, also transparent geometry can be shadowed.
@@ -251,6 +255,12 @@ public:
     /// Return shadow quality.
     ShadowQuality GetShadowQuality() const { return shadowQuality_; }
 
+    /// Return shadow softness.
+    float GetShadowSoftness() const { return shadowSoftness_; }
+
+    /// Return VSM shadow parameters
+    Vector2 GetVsmShadowParameters() const { return vsmShadowParams_; };
+
     /// Return whether shadow maps are reused.
     bool GetReuseShadowMaps() const { return reuseShadowMaps_; }
 
@@ -493,6 +503,10 @@ private:
     int shadowMapSize_;
     /// Shadow quality.
     ShadowQuality shadowQuality_;
+    /// Shadow softness, only works when SHADOWQUALITY_BLUR_VSM is used.
+    float shadowSoftness_;
+    /// Shadow parameters when VSM is used, they help to reduce light bleeding.
+    Vector2 vsmShadowParams_;
     /// Maximum number of shadow maps per resolution.
     int maxShadowMaps_;
     /// Minimum number of instances required in a batch group to render as instanced.

+ 4 - 0
Source/Urho3D/LuaScript/pkgs/Graphics/Renderer.pkg

@@ -15,6 +15,8 @@ class Renderer
     void SetDrawShadows(bool enable);
     void SetShadowMapSize(int size);
     void SetShadowQuality(ShadowQuality quality);
+    void SetShadowSoftness(float shadowSoftness);
+    void SetVsmShadowParameters(float minVariance, float lightBleedingReduction);
     void SetReuseShadowMaps(bool enable);
     void SetMaxShadowMaps(int shadowMaps);
     void SetDynamicInstancing(bool enable);
@@ -40,6 +42,8 @@ class Renderer
     int GetMaterialQuality() const;
     int GetShadowMapSize() const;
     ShadowQuality GetShadowQuality() const;
+    float GetShadowSoftness() const;
+    Vector2 GetVsmShadowParameters() const;
     bool GetReuseShadowMaps() const;
     int GetMaxShadowMaps() const;
     bool GetDynamicInstancing() const;

+ 6 - 11
bin/CoreData/Shaders/GLSL/Lighting.glsl

@@ -141,16 +141,10 @@ float GetIntensity(vec3 color)
 #endif
 
 #ifdef VSM_SHADOW
-float linstep(float min, float max, float v)  
+float ReduceLightBleeding(float min, float p_max)  
 {  
-    return clamp((v - min) / (max - min), 0.0, 1.0);  
-}  
-
-float ReduceLightBleeding(float p_max, float Amount)  
-{  
-    // Remove the [0, Amount] tail and linearly rescale (Amount, 1].  
-    return linstep(Amount, 1.0, p_max); 
-}  
+    return clamp((p_max - min) / (1.0 - min), 0.0, 1.0);  
+}
 
 float Chebyshev(vec2 Moments, float depth)  
 {  
@@ -159,12 +153,13 @@ float Chebyshev(vec2 Moments, float depth)
     //Compute variance.  
     float Variance = Moments.y - (Moments.x * Moments.x); 
 
-    float minVariance = 0.0000001;
+    float minVariance = cVsmShadowParams.x;
     Variance = max(Variance, minVariance);  
     //Compute probabilistic upper bound.  
     float d = depth - Moments.x;  
     float p_max = Variance / (Variance + d*d); 
-    p_max = ReduceLightBleeding(p_max, 0.2);
+    // Prevent light bleeding
+    p_max = ReduceLightBleeding(cVsmShadowParams.y, p_max);
 
     return max(p, p_max);
 }

+ 6 - 1
bin/CoreData/Shaders/GLSL/Uniforms.glsl

@@ -73,7 +73,9 @@ uniform vec2 cShadowIntensity;
 uniform vec2 cShadowMapInvSize;
 uniform vec4 cShadowSplits;
 uniform mat4 cLightMatricesPS[4];
-
+#ifdef VSM_SHADOW
+uniform vec2 cVsmShadowParams;
+#endif
 #endif
 
 #else
@@ -176,6 +178,9 @@ uniform LightPS
     vec2 cShadowMapInvSize;
     vec4 cShadowSplits;
     mat4 cLightMatricesPS[4];
+#ifdef VSM_SHADOW
+    vec2 cVsmShadowParams;
+#endif
 };
 
 #ifndef CUSTOM_MATERIAL_CBUFFER

+ 6 - 11
bin/CoreData/Shaders/HLSL/Lighting.hlsl

@@ -148,16 +148,10 @@ float GetIntensity(float3 color)
 #endif
 
 #ifdef VSM_SHADOW
-float linstep(float min, float max, float v)  
+float ReduceLightBleeding(float min, float p_max)  
 {  
-    return clamp((v - min) / (max - min), 0.0, 1.0);  
-}  
-
-float ReduceLightBleeding(float p_max, float Amount)  
-{  
-    // Remove the [0, Amount] tail and linearly rescale (Amount, 1].  
-    return linstep(Amount, 1.0, p_max); 
-}  
+    return clamp((p_max - min) / (1.0 - min), 0.0, 1.0);  
+}
 
 float Chebyshev(float2 Moments, float depth)  
 {  
@@ -166,12 +160,13 @@ float Chebyshev(float2 Moments, float depth)
     //Compute variance.  
     float Variance = Moments.y - (Moments.x * Moments.x); 
 
-    float minVariance = 0.0000001;
+    float minVariance = cVsmShadowParams.x;
     Variance = max(Variance, minVariance);  
     //Compute probabilistic upper bound.  
     float d = depth - Moments.x;  
     float p_max = Variance / (Variance + d*d); 
-    p_max = ReduceLightBleeding(p_max, 0.2);
+    // Prevent light bleeding
+    p_max = ReduceLightBleeding(cVsmShadowParams.y, p_max);
 
     return max(p, p_max);
 }

+ 3 - 0
bin/CoreData/Shaders/HLSL/Uniforms.hlsl

@@ -62,6 +62,9 @@ uniform float2 cShadowIntensity;
 uniform float2 cShadowMapInvSize;
 uniform float4 cShadowSplits;
 uniform float4x4 cLightMatricesPS[4];
+#ifdef VSM_SHADOW
+uniform float2 cVsmShadowParams;
+#endif
 #endif
 
 #else