Просмотр исходного кода

Add max extrusion parameter for directional lights. Default to 1000. This prevents large far clip causing poor shadow map depth resolution and too strong effect of depth bias parameters, but can be increased if very tall shadows are needed.

Lasse Öörni 9 лет назад
Родитель
Сommit
2fe4cb0131

+ 3 - 1
Docs/Reference.dox

@@ -1623,7 +1623,7 @@ Shadow rendering is easily the most complex aspect of using lights, and therefor
 
 - FocusParameters: these have effect for directional and spot lights, and control techniques to increase shadow map resolution. They consist of focus enable flag (allows focusing the shadow camera on the visible shadow casters & receivers), nonuniform scale enable flag (allows better resolution), automatic size reduction flag (reduces shadow map resolution when the light is far away), and quantization & minimum size parameters for the shadow camera view.
 
-Additionally there are shadow fade distance, shadow intensity, shadow resolution and shadow near/far ratio parameters:
+Additionally there are shadow fade distance, shadow intensity, shadow resolution, shadow near/far ratio and shadow max extrusion parameters:
 
 - If both shadow distance and shadow fade distance are greater than zero, shadows start to fade at the shadow fade distance, and vanish completely at the shadow distance.
 
@@ -1633,6 +1633,8 @@ Additionally there are shadow fade distance, shadow intensity, shadow resolution
 
 - The shadow near/far ratio controls shadow camera near clip distance for point & spot lights. The default ratio is 0.002, which means a light with range 100 would have its shadow camera near plane set at the distance of 0.2. Set this as high as you can for better shadow depth resolution, but note that the bias parameters will likely have to be adjusted as well.
 
+- The shadow max extrusion distance controls how far from the view position directional light shadow cameras are positioned. The effective value will be the minimum of this parameter and the camera far clip distance. The default is 1000; increase this if you have shadow cascades to a far distance and are using tall objects, and notice missing shadows. The extrusion distance affects shadow map depth resolution and therefore the effect of shadow bias parameters.
+
 \section Lights_ShadowGlobal Global shadow settings
 
 The shadow map base resolution and quality (bit depth & sampling mode) are set through functions in the Renderer subsystem, see \ref Renderer::SetShadowMapSize "SetShadowMapSize()" and \ref Renderer::SetShadowQuality "SetShadowQuality()".

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

@@ -1237,6 +1237,8 @@ static void RegisterLight(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Light", "float get_shadowResolution() const", asMETHOD(Light, GetShadowResolution), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void set_shadowNearFarRatio(float)", asMETHOD(Light, SetShadowNearFarRatio), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "float get_shadowNearFarRatio() const", asMETHOD(Light, GetShadowNearFarRatio), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Light", "void set_shadowMaxExtrusion(float)", asMETHOD(Light, SetShadowMaxExtrusion), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Light", "float get_shadowMaxExtrusion() const", asMETHOD(Light, GetShadowMaxExtrusion), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void set_rampTexture(Texture@+)", asMETHOD(Light, SetRampTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "Texture@+ get_rampTexture() const", asMETHOD(Light, GetRampTexture), asCALL_THISCALL);
     engine->RegisterObjectMethod("Light", "void set_shapeTexture(Texture@+)", asMETHOD(Light, SetShapeTexture), asCALL_THISCALL);

+ 9 - 0
Source/Urho3D/Graphics/Light.cpp

@@ -55,6 +55,7 @@ static const float DEFAULT_SHADOWFADESTART = 0.8f;
 static const float DEFAULT_SHADOWQUANTIZE = 0.5f;
 static const float DEFAULT_SHADOWMINVIEW = 3.0f;
 static const float DEFAULT_SHADOWNEARFARRATIO = 0.002f;
+static const float DEFAULT_SHADOWMAXEXTRUSION = 1000.0f;
 static const float DEFAULT_SHADOWSPLIT = 1000.0f;
 static const float DEFAULT_TEMPERATURE = 6590.0f;
 
@@ -104,6 +105,7 @@ Light::Light(Context* context) :
     shadowIntensity_(0.0f),
     shadowResolution_(1.0f),
     shadowNearFarRatio_(DEFAULT_SHADOWNEARFARRATIO),
+    shadowMaxExtrusion_(DEFAULT_SHADOWMAXEXTRUSION),
     perVertex_(false),
     usePhysicalValues_(false)
 {
@@ -153,6 +155,7 @@ void Light::RegisterObject(Context* context)
     URHO3D_ATTRIBUTE("Depth Slope Bias", float, shadowBias_.slopeScaledBias_, DEFAULT_SLOPESCALEDBIAS, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Normal Offset", float, shadowBias_.normalOffset_, DEFAULT_NORMALOFFSET, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Near/Farclip Ratio", float, shadowNearFarRatio_, DEFAULT_SHADOWNEARFARRATIO, AM_DEFAULT);
+    URHO3D_ACCESSOR_ATTRIBUTE("Max Extrusion", GetShadowMaxExtrusion, SetShadowMaxExtrusion, float, DEFAULT_SHADOWMAXEXTRUSION, AM_DEFAULT);
     URHO3D_ATTRIBUTE("View Mask", int, viewMask_, DEFAULT_VIEWMASK, AM_DEFAULT);
     URHO3D_ATTRIBUTE("Light Mask", int, lightMask_, DEFAULT_LIGHTMASK, AM_DEFAULT);
 }
@@ -346,6 +349,12 @@ void Light::SetShadowNearFarRatio(float nearFarRatio)
     MarkNetworkUpdate();
 }
 
+void Light::SetShadowMaxExtrusion(float extrusion)
+{
+    shadowMaxExtrusion_ = Max(extrusion, 0.0f);
+    MarkNetworkUpdate();
+}
+
 void Light::SetFadeDistance(float distance)
 {
     fadeDistance_ = Max(distance, 0.0f);

+ 8 - 1
Source/Urho3D/Graphics/Light.h

@@ -206,8 +206,10 @@ public:
     void SetShadowIntensity(float intensity);
     /// Set shadow resolution between 0.25 - 1.0. Determines the shadow map to use.
     void SetShadowResolution(float resolution);
-    /// Set shadow camera near/far clip distance ratio.
+    /// Set shadow camera near/far clip distance ratio for spot and point lights. Does not affect directional lights, since they are orthographic and have near clip 0.
     void SetShadowNearFarRatio(float nearFarRatio);
+    /// Set maximum shadow extrusion for directional lights. The actual extrusion will be the smaller of this and camera far clip. Default 1000.
+    void SetShadowMaxExtrusion(float extrusion);
     /// Set range attenuation texture.
     void SetRampTexture(Texture* texture);
     /// Set spotlight attenuation texture.
@@ -276,6 +278,9 @@ public:
     /// Return shadow camera near/far clip distance ratio.
     float GetShadowNearFarRatio() const { return shadowNearFarRatio_; }
 
+    /// Return maximum shadow extrusion distance for directional lights.
+    float GetShadowMaxExtrusion() const { return shadowMaxExtrusion_; }
+
     /// Return range attenuation texture.
     Texture* GetRampTexture() const { return rampTexture_; }
 
@@ -368,6 +373,8 @@ private:
     float shadowResolution_;
     /// Shadow camera near/far clip distance ratio.
     float shadowNearFarRatio_;
+    /// Directional shadow max. extrusion distance.
+    float shadowMaxExtrusion_;
     /// Per-vertex lighting flag.
     bool perVertex_;
     /// Use physical light values flag.

+ 1 - 1
Source/Urho3D/Graphics/View.cpp

@@ -2551,7 +2551,7 @@ void View::SetupDirLightShadowCamera(Camera* shadowCamera, Light* light, float n
 {
     Node* shadowCameraNode = shadowCamera->GetNode();
     Node* lightNode = light->GetNode();
-    float extrusionDistance = cullCamera_->GetFarClip();
+    float extrusionDistance = Min(cullCamera_->GetFarClip(), light->GetShadowMaxExtrusion());
     const FocusParameters& parameters = light->GetShadowFocus();
 
     // Calculate initial position & rotation

+ 3 - 0
Source/Urho3D/LuaScript/pkgs/Graphics/Light.pkg

@@ -61,6 +61,7 @@ class Light : public Drawable
     void SetShadowIntensity(float intensity);
     void SetShadowResolution(float resolution);
     void SetShadowNearFarRatio(float nearFarRatio);
+    void SetShadowMaxExtrusion(float extrusion);
     void SetRampTexture(Texture* texture);
     void SetShapeTexture(Texture* texture);
 
@@ -85,6 +86,7 @@ class Light : public Drawable
     float GetShadowIntensity() const;
     float GetShadowResolution() const;
     float GetShadowNearFarRatio() const;
+    float GetShadowMaxExtrusion() const;
     Texture* GetRampTexture() const;
     Texture* GetShapeTexture() const;
     Frustum GetFrustum() const;
@@ -109,6 +111,7 @@ class Light : public Drawable
     tolua_property__get_set float shadowIntensity;
     tolua_property__get_set float shadowResolution;
     tolua_property__get_set float shadowNearFarRatio;
+    tolua_property__get_set float shadowMaxExtrusion;
     tolua_property__get_set Texture* rampTexture;
     tolua_property__get_set Texture* shapeTexture;
     tolua_readonly tolua_property__get_set Frustum frustum;