Przeglądaj źródła

Fixed drawing erroneous non-indexed geometry for BillboardSet after all billboards had expired.

Lasse Öörni 13 lat temu
rodzic
commit
a989bb4879
3 zmienionych plików z 82 dodań i 69 usunięć
  1. 67 64
      Engine/Graphics/Batch.cpp
  2. 13 5
      Engine/Graphics/Geometry.cpp
  3. 2 0
      Engine/Graphics/Geometry.h

+ 67 - 64
Engine/Graphics/Batch.cpp

@@ -625,8 +625,11 @@ void Batch::Prepare(Graphics* graphics, Renderer* renderer, bool setModelTransfo
 
 void Batch::Draw(Graphics* graphics, Renderer* renderer) const
 {
-    Prepare(graphics, renderer);
-    geometry_->Draw(graphics);
+    if (!geometry_->IsEmpty())
+    {
+        Prepare(graphics, renderer);
+        geometry_->Draw(graphics);
+    }
 }
 
 void BatchGroup::SetTransforms(Renderer* renderer, void* lockedData, unsigned& freeIndex)
@@ -647,78 +650,78 @@ void BatchGroup::SetTransforms(Renderer* renderer, void* lockedData, unsigned& f
 
 void BatchGroup::Draw(Graphics* graphics, Renderer* renderer) const
 {
-    if (!instances_.Size() || (!geometry_->GetIndexCount() && !geometry_->GetVertexCount()))
-        return;
-    
-    // Draw as individual objects if instancing not supported
-    VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer();
-    if (!instanceBuffer || geometry_->GetIndexCount() > (unsigned)renderer->GetMaxInstanceTriangles() * 3)
+    if (instances_.Size() && !geometry_->IsEmpty())
     {
-        Batch::Prepare(graphics, renderer, false);
-        
-        graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
-        graphics->SetVertexBuffers(geometry_->GetVertexBuffers(), geometry_->GetVertexElementMasks());
-        
-        for (unsigned i = 0; i < instances_.Size(); ++i)
+        // Draw as individual objects if instancing not supported
+        VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer();
+        if (!instanceBuffer || geometry_->GetIndexCount() > (unsigned)renderer->GetMaxInstanceTriangles() * 3)
         {
-            graphics->SetShaderParameter(VSP_MODEL, *instances_[i].worldTransform_);
-            graphics->Draw(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(),
-                geometry_->GetVertexStart(), geometry_->GetVertexCount());
+            Batch::Prepare(graphics, renderer, false);
+            
+            graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
+            graphics->SetVertexBuffers(geometry_->GetVertexBuffers(), geometry_->GetVertexElementMasks());
+            
+            for (unsigned i = 0; i < instances_.Size(); ++i)
+            {
+                graphics->SetShaderParameter(VSP_MODEL, *instances_[i].worldTransform_);
+                graphics->Draw(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(),
+                    geometry_->GetVertexStart(), geometry_->GetVertexCount());
+            }
+            
+            graphics->ClearTransformSources();
         }
-        
-        graphics->ClearTransformSources();
-    }
-    else
-    {
-        Batch::Prepare(graphics, renderer, false);
-        
-        // Get the geometry vertex buffers, then add the instancing stream buffer
-        // Hack: use a const_cast to avoid dynamic allocation of new temp vectors
-        Vector<SharedPtr<VertexBuffer> >& vertexBuffers = const_cast<Vector<SharedPtr<VertexBuffer> >&>
-            (geometry_->GetVertexBuffers());
-        PODVector<unsigned>& elementMasks = const_cast<PODVector<unsigned>&>(geometry_->GetVertexElementMasks());
-        vertexBuffers.Push(SharedPtr<VertexBuffer>(instanceBuffer));
-        elementMasks.Push(instanceBuffer->GetElementMask());
-        
-        // No stream offset support, instancing buffer not pre-filled with transforms: have to fill now
-        if (startIndex_ == M_MAX_UNSIGNED)
+        else
         {
-            unsigned startIndex = 0;
-            while (startIndex < instances_.Size())
+            Batch::Prepare(graphics, renderer, false);
+            
+            // Get the geometry vertex buffers, then add the instancing stream buffer
+            // Hack: use a const_cast to avoid dynamic allocation of new temp vectors
+            Vector<SharedPtr<VertexBuffer> >& vertexBuffers = const_cast<Vector<SharedPtr<VertexBuffer> >&>
+                (geometry_->GetVertexBuffers());
+            PODVector<unsigned>& elementMasks = const_cast<PODVector<unsigned>&>(geometry_->GetVertexElementMasks());
+            vertexBuffers.Push(SharedPtr<VertexBuffer>(instanceBuffer));
+            elementMasks.Push(instanceBuffer->GetElementMask());
+            
+            // No stream offset support, instancing buffer not pre-filled with transforms: have to fill now
+            if (startIndex_ == M_MAX_UNSIGNED)
             {
-                unsigned instances = instances_.Size() - startIndex;
-                if (instances > instanceBuffer->GetVertexCount())
-                    instances = instanceBuffer->GetVertexCount();
-                
-                // Copy the transforms
-                Matrix3x4* dest = (Matrix3x4*)instanceBuffer->Lock(0, instances, true);
-                if (dest)
+                unsigned startIndex = 0;
+                while (startIndex < instances_.Size())
                 {
-                    for (unsigned i = 0; i < instances; ++i)
-                        dest[i] = *instances_[i + startIndex].worldTransform_;
-                    instanceBuffer->Unlock();
+                    unsigned instances = instances_.Size() - startIndex;
+                    if (instances > instanceBuffer->GetVertexCount())
+                        instances = instanceBuffer->GetVertexCount();
+                    
+                    // Copy the transforms
+                    Matrix3x4* dest = (Matrix3x4*)instanceBuffer->Lock(0, instances, true);
+                    if (dest)
+                    {
+                        for (unsigned i = 0; i < instances; ++i)
+                            dest[i] = *instances_[i + startIndex].worldTransform_;
+                        instanceBuffer->Unlock();
+                        
+                        graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
+                        graphics->SetVertexBuffers(vertexBuffers, elementMasks);
+                        graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(),
+                            geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances);
+                    }
                     
-                    graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
-                    graphics->SetVertexBuffers(vertexBuffers, elementMasks);
-                    graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(),
-                        geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances);
+                    startIndex += instances;
                 }
-                
-                startIndex += instances;
             }
+            // Stream offset supported, and instancing buffer has been already filled, so just draw
+            else
+            {
+                graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
+                graphics->SetVertexBuffers(vertexBuffers, elementMasks, startIndex_);
+                graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(),
+                    geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances_.Size());
+            }
+            
+            // Remove the instancing buffer & element mask now
+            vertexBuffers.Pop();
+            elementMasks.Pop();
         }
-        // Stream offset supported, and instancing buffer has been already filled, so just draw
-        else
-        {
-            graphics->SetIndexBuffer(geometry_->GetIndexBuffer());
-            graphics->SetVertexBuffers(vertexBuffers, elementMasks, startIndex_);
-            graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(),
-                geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances_.Size());
-        }
-        
-        // Remove the instancing buffer & element mask now
-        vertexBuffers.Pop();
-        elementMasks.Pop();
     }
 }
 

+ 13 - 5
Engine/Graphics/Geometry.cpp

@@ -114,11 +114,19 @@ bool Geometry::SetDrawRange(PrimitiveType type, unsigned indexStart, unsigned in
     indexCount_ = indexCount;
     
     // Get min.vertex index and num of vertices from index buffer. If it fails, use full range as fallback
-    vertexStart_ = 0;
-    vertexCount_ = vertexBuffers_[0]->GetVertexCount();
-    
-    if (getUsedVertexRange)
-        indexBuffer_->GetUsedVertexRange(indexStart_, indexCount_, vertexStart_, vertexCount_);
+    if (indexCount)
+    {
+        vertexStart_ = 0;
+        vertexCount_ = vertexBuffers_[0]->GetVertexCount();
+        
+        if (getUsedVertexRange)
+            indexBuffer_->GetUsedVertexRange(indexStart_, indexCount_, vertexStart_, vertexCount_);
+    }
+    else
+    {
+        vertexStart_ = 0;
+        vertexCount_ = 0;
+    }
     
     return true;
 }

+ 2 - 0
Engine/Graphics/Geometry.h

@@ -88,6 +88,8 @@ public:
     void GetRawData(const unsigned char*& vertexData, unsigned& vertexSize, const unsigned char*& indexData, unsigned& indexSize, unsigned& elementMask);
     /// Return ray hit distance or infinity if no hit. Requires raw data to be set.
     float GetDistance(const Ray& ray);
+    /// Return whether has empty draw range.
+    bool IsEmpty() const { return indexCount_ == 0 && vertexCount_ == 0; }
     
 private:
     /// Locate vertex buffer with position data.