Pārlūkot izejas kodu

Fixed double-lighting bug in light pre-pass mode.

Lasse Öörni 14 gadi atpakaļ
vecāks
revīzija
d53e808ece
3 mainītis faili ar 31 papildinājumiem un 16 dzēšanām
  1. 9 3
      Engine/Graphics/Drawable.cpp
  2. 2 2
      Engine/Graphics/Drawable.h
  3. 20 11
      Engine/Graphics/View.cpp

+ 9 - 3
Engine/Graphics/Drawable.cpp

@@ -254,11 +254,17 @@ void Drawable::LimitLights()
     }
 }
 
-void Drawable::LimitVertexLights()
+void Drawable::LimitVertexLights(bool removeConvertedLights)
 {
     const BoundingBox& box = GetWorldBoundingBox();
-    for (unsigned i = 0; i < vertexLights_.Size(); ++i)
-        vertexLights_[i]->SetIntensitySortValue(box);
+    for (unsigned i = vertexLights_.Size() - 1; i < vertexLights_.Size(); --i)
+    {
+        // If necessary (light pre-pass rendering), remove lights that were converted to per-vertex
+        if (removeConvertedLights && !vertexLights_[i]->GetPerVertex())
+            vertexLights_.Erase(i);
+        else
+            vertexLights_[i]->SetIntensitySortValue(box);
+    }
     
     Sort(vertexLights_.Begin(), vertexLights_.End(), CompareDrawables);
     

+ 2 - 2
Engine/Graphics/Drawable.h

@@ -94,7 +94,7 @@ public:
     virtual void ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results);
     /// Update before octree reinsertion. Is called from a worker thread. Needs to be requested with MarkForUpdate().
     virtual void Update(const FrameInfo& frame) {}
-    /// Calculate distance and LOD level for rendering.  May be called from worker thread(s), possibly re-entrantly.
+    /// Calculate distance and LOD level for rendering.May be called from worker thread(s), possibly re-entrantly.
     virtual void UpdateDistance(const FrameInfo& frame);
     /// Prepare geometry for rendering.
     virtual void UpdateGeometry(const FrameInfo& frame) {}
@@ -178,7 +178,7 @@ public:
     /// Sort and limit per-pixel lights to maximum allowed.
     void LimitLights();
     /// Sort and limit per-vertex lights to maximum allowed.
-    void LimitVertexLights();
+    void LimitVertexLights(bool removeConvertedLights);
     /// %Set base pass flag for a batch.
     void SetBasePass(unsigned batchIndex) { basePassFlags_ |= (1 << batchIndex); }
     /// Return octree octant.

+ 20 - 11
Engine/Graphics/View.cpp

@@ -739,20 +739,29 @@ void View::GetBatches()
                     const PODVector<Light*>& vertexLights = drawable->GetVertexLights();
                     if (!vertexLights.Empty())
                     {
-                        drawable->LimitVertexLights();
+                        // In light pre-pass mode, check if this is an opaque object that has converted its lights to per-vertex
+                        // due to overflowing the pixel light count. These need to be skipped as the per-pixel accumulation
+                        // already renders the light
+                        /// \todo Sub-geometries might need different interpretation if opaque & alpha are mixed
+                        if (!j)
+                            drawable->LimitVertexLights(prepass && pass->GetBlendMode() == BLEND_REPLACE);
                         
-                        // Find a vertex light queue. If not found, create new
-                        unsigned long long hash = GetVertexLightQueueHash(vertexLights);
-                        HashMap<unsigned long long, LightBatchQueue>::Iterator i = vertexLightQueues_.Find(hash);
-                        if (i == vertexLightQueues_.End())
+                        // The vertex light vector possibly became empty, so re-check
+                        if (!vertexLights.Empty())
                         {
-                            i = vertexLightQueues_.Insert(MakePair(hash, LightBatchQueue()));
-                            i->second_.light_ = 0;
-                            i->second_.shadowMap_ = 0;
-                            i->second_.vertexLights_ = vertexLights;
+                            // Find a vertex light queue. If not found, create new
+                            unsigned long long hash = GetVertexLightQueueHash(vertexLights);
+                            HashMap<unsigned long long, LightBatchQueue>::Iterator i = vertexLightQueues_.Find(hash);
+                            if (i == vertexLightQueues_.End())
+                            {
+                                i = vertexLightQueues_.Insert(MakePair(hash, LightBatchQueue()));
+                                i->second_.light_ = 0;
+                                i->second_.shadowMap_ = 0;
+                                i->second_.vertexLights_ = vertexLights;
+                            }
+                            
+                            baseBatch.lightQueue_ = &(i->second_);
                         }
-                        
-                        baseBatch.lightQueue_ = &(i->second_);
                     }
                     
                     if (pass->GetBlendMode() == BLEND_REPLACE)