Пример #1
0
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();
        }
    }
}
Пример #2
0
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();
        }
    }
}