Преглед изворни кода

Further optimization and improvement of light intensity sorting.

Lasse Öörni пре 14 година
родитељ
комит
563ad416e9
2 измењених фајлова са 16 додато и 6 уклоњено
  1. 1 0
      Engine/Core/MiniDump.cpp
  2. 15 6
      Engine/Graphics/Light.cpp

+ 1 - 0
Engine/Core/MiniDump.cpp

@@ -41,6 +41,7 @@ static bool miniDumpWritten = false;
 int WriteMiniDump(const char* applicationName, void* exceptionPointers)
 {
     // In case of recursive or repeating exceptions, only write the dump once
+    /// \todo This function should not allocate any dynamic memory
     if (miniDumpWritten)
         return EXCEPTION_EXECUTE_HANDLER;
     

+ 15 - 6
Engine/Graphics/Light.cpp

@@ -412,6 +412,11 @@ void Light::OnWorldBoundingBoxUpdate()
 void Light::SetIntensitySortValue(const Vector3& position, bool forDrawable)
 {
     // Store inverse intensity at point as the sort value
+    // For drawables we are comparing with the bounding box center, so limit the attenuation slightly
+    // to make sure light (particularly spotlights) does not cut off unrealistically early
+    float maxSpotAtt = 0.9f;
+    float maxPointAtt = 0.9f;
+    
     switch (lightType_)
     {
     case LIGHT_DIRECTIONAL:
@@ -424,20 +429,24 @@ void Light::SetIntensitySortValue(const Vector3& position, bool forDrawable)
     
     case LIGHT_SPOT:
         {
-            // Spot light: calculate deviation from the spot center
+            // Spot light: calculate deviation from the spot center, then add range-based attenuation
             /// \todo Optimize/correct this
+            float scale = tanf(fov_ * M_DEGTORAD * 0.5f);
             float angle = 1.0f - node_->GetWorldDirection().DotProduct((position - node_->GetWorldPosition()).NormalizedFast());
-            float spotMaxAngle = 1.0f - Vector3::FORWARD.DotProduct(Vector3(0, tanf(fov_ * M_DEGTORAD * 0.5f), 1.0f).NormalizedFast());
-            float spotAtt = FastSqrt(1.0f - Clamp(angle / spotMaxAngle, 0.0f, 0.9f));
-            float pointAtt = FastSqrt(Clamp(1.0f - (GetWorldPosition() - position).LengthFast() / range_, 0.25f, 1.0f));
+            float spotMaxAngle = 1.0f - Vector3::FORWARD.DotProduct(Vector3(scale, scale, 1.0f).NormalizedFast());
+            float spotAtt = Clamp(angle / spotMaxAngle, 0.0f, maxSpotAtt);
+            float pointAtt = Clamp((GetWorldPosition() - position).LengthFast() / range_, 0.0f, maxPointAtt);
+            spotAtt = 1.0f - spotAtt * spotAtt;
+            pointAtt = 1.0f - pointAtt * pointAtt;
             sortValue_ = 1.0f / (color_.Intensity() * spotAtt * pointAtt);
         }
         break;
         
     case LIGHT_POINT:
         {
-            // Point light: range-based attenuation
-            float pointAtt = FastSqrt(Clamp(1.0f - (GetWorldPosition() - position).LengthFast() / range_, 0.1f, 1.0f));
+            // Point light: range-based attenuation only
+            float pointAtt = Clamp((GetWorldPosition() - position).LengthFast() / range_, 0.0f, maxPointAtt);
+            pointAtt = 1.0f - pointAtt * pointAtt;
             sortValue_ = 1.0f / (color_.Intensity() * pointAtt);
         }
         break;