void BatchGroup::Draw(View* view, Camera* camera, bool allowDepthWrite) const { Graphics* graphics = view->GetGraphics(); Renderer* renderer = view->GetRenderer(); if (instances_.Size() && !geometry_->IsEmpty()) { // Draw as individual objects if instancing not supported or could not fill the instancing buffer VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer(); if (!instanceBuffer || geometryType_ != GEOM_INSTANCED || startIndex_ == M_MAX_UNSIGNED) { Batch::Prepare(view, camera, false, allowDepthWrite); graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(geometry_->GetVertexBuffers()); for (unsigned i = 0; i < instances_.Size(); ++i) { if (graphics->NeedParameterUpdate(SP_OBJECT, instances_[i].worldTransform_)) graphics->SetShaderParameter(VSP_MODEL, *instances_[i].worldTransform_); graphics->Draw(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount()); } } else { Batch::Prepare(view, camera, false, allowDepthWrite); // 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()); vertexBuffers.Push(SharedPtr<VertexBuffer>(instanceBuffer)); graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(vertexBuffers, startIndex_); graphics->DrawInstanced(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount(), instances_.Size()); // Remove the instancing buffer & element mask now vertexBuffers.Pop(); } } }
void BatchGroup::Draw(View* view) const { Graphics* graphics = view->GetGraphics(); Renderer* renderer = view->GetRenderer(); if (instances_.Size() && !geometry_->IsEmpty()) { // Draw as individual objects if instancing not supported VertexBuffer* instanceBuffer = renderer->GetInstancingBuffer(); if (!instanceBuffer || geometryType_ != GEOM_INSTANCED) { Batch::Prepare(view, false); graphics->SetIndexBuffer(geometry_->GetIndexBuffer()); graphics->SetVertexBuffers(geometry_->GetVertexBuffers(), geometry_->GetVertexElementMasks()); for (unsigned i = 0; i < instances_.Size(); ++i) { if (graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, instances_[i].worldTransform_)) graphics->SetShaderParameter(VSP_MODEL, *instances_[i].worldTransform_); graphics->Draw(geometry_->GetPrimitiveType(), geometry_->GetIndexStart(), geometry_->GetIndexCount(), geometry_->GetVertexStart(), geometry_->GetVertexCount()); } } else { Batch::Prepare(view, 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 startIndex = 0; while (startIndex < instances_.Size()) { 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); } 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(); } } }