// // renderer.cxx // graphics // // Created by Sam Jaffe on 5/19/19. // Copyright © 2019 Sam Jaffe. All rights reserved. // #include "game/graphics/renderer.hpp" #include #include #include #include "game/graphics/exception.h" #include "game/graphics/object.hpp" #include "game/graphics/vertex.h" #include "renderer_impl.hpp" using namespace graphics; INSTANTIATE_PROTOTYPE_FACTORY(renderer_impl *); renderer_impl * get_renderer_impl(std::string const & id) { renderer_impl * rval = renderer_impl_factory::instance().get(id); if (rval == nullptr) throw unmapped_enum(id); return rval; } namespace { const math::matr4 identity4 = math::matrix::identity(); } direct_renderer::direct_renderer(std::string const & driver_id) : direct_renderer(::get_renderer_impl(driver_id)) {} direct_renderer::direct_renderer(renderer_impl * pi) : pimpl(pi) {} std::shared_ptr direct_renderer::manager() const { return pimpl->manager(); } void direct_renderer::draw(object const & obj) { std::vector verts; vertices(verts, obj); draw(obj.material, identity4, verts); } void direct_renderer::draw(identity material, math::matr4 const & object_to_world, std::vector const & verts) { pimpl->draw(material, object_to_world, verts); } void direct_renderer::clear() { pimpl->clear(); } void direct_renderer::flush() { pimpl->flush(); } batch_renderer::batch_renderer(renderer * impl, std::size_t batch_size) : batch_renderer(impl, identity4, batch_size) {} batch_renderer::batch_renderer(renderer * impl, math::matr4 const & to_world, std::size_t batch_size) : impl_(impl), batches_(), object_to_world_(to_world), batch_size_(batch_size), elements_(0) {} batch_renderer::~batch_renderer() { flush(); } void batch_renderer::draw(object const & obj) { std::vector & batch_verts = batches_[obj.material]; auto old_size = batch_verts.size(); vertices(batch_verts, obj); elements_ += batch_verts.size() - old_size; check(); } // TODO (sjaffe): object-to-world matrix... void batch_renderer::draw(identity material, math::matr4 const &, std::vector const & verts) { auto & batch_verts = batches_[material]; batch_verts.insert(batch_verts.end(), verts.begin(), verts.end()); elements_ += verts.size(); check(); } void batch_renderer::flush() { write(); // impl_->flush(); } void batch_renderer::check() { if (batch_size_ && elements_ >= batch_size_) { write(); } } void batch_renderer::write() { for (auto & pair : batches_) { impl_->draw(pair.first, object_to_world_, pair.second); pair.second.clear(); } elements_ = 0; }