diff --git a/drape/CMakeLists.txt b/drape/CMakeLists.txt index d219584a39..cc0acb13d9 100644 --- a/drape/CMakeLists.txt +++ b/drape/CMakeLists.txt @@ -72,6 +72,8 @@ set( ${DRAPE_ROOT}/index_buffer_mutator.hpp ${DRAPE_ROOT}/index_storage.cpp ${DRAPE_ROOT}/index_storage.hpp + ${DRAPE_ROOT}/mesh_object.cpp + ${DRAPE_ROOT}/mesh_object.hpp ${DRAPE_ROOT}/object_pool.hpp ${DRAPE_ROOT}/oglcontext.cpp ${DRAPE_ROOT}/oglcontext.hpp diff --git a/drape/debug_rect_renderer.cpp b/drape/debug_rect_renderer.cpp index efe5638ede..e7b4179a05 100644 --- a/drape/debug_rect_renderer.cpp +++ b/drape/debug_rect_renderer.cpp @@ -3,17 +3,19 @@ #include "drape/glextensions_list.hpp" #include "drape/glfunctions.hpp" -#include +#include namespace dp { namespace { -m2::PointF PixelPointToScreenSpace(ScreenBase const & screen, m2::PointF const & pt) +void PixelPointToScreenSpace(ScreenBase const & screen, m2::PointF const & pt, std::vector & buffer) { auto const szX = static_cast(screen.PixelRectIn3d().SizeX()); auto const szY = static_cast(screen.PixelRectIn3d().SizeY()); - return m2::PointF(pt.x / szX - 0.5f, -pt.y / szY + 0.5f) * 2.0f; + + buffer.push_back(2.0f * (pt.x / szX - 0.5f)); + buffer.push_back(2.0f * (-pt.y / szY + 0.5f)); } } // namespace @@ -24,56 +26,26 @@ DebugRectRenderer & DebugRectRenderer::Instance() } DebugRectRenderer::DebugRectRenderer() - : m_VAO(0) - , m_vertexBuffer(0) - , m_isEnabled(false) -{} + : TBase(DrawPrimitive::LineStrip) +{ + SetBuffer(0 /*bufferInd*/, {} /* vertices */, static_cast(sizeof(float) * 2)); + SetAttribute("a_position", 0 /* bufferInd*/, 0.0f /* offset */, 2 /* componentsCount */); +} DebugRectRenderer::~DebugRectRenderer() { - ASSERT_EQUAL(m_VAO, 0, ()); - ASSERT_EQUAL(m_vertexBuffer, 0, ()); + ASSERT(!IsInitialized(), ()); } void DebugRectRenderer::Init(ref_ptr program, ParamsSetter && paramsSetter) { - m_paramsSetter = std::move(paramsSetter); - if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) - { - m_VAO = GLFunctions::glGenVertexArray(); - GLFunctions::glBindVertexArray(m_VAO); - } - - m_vertexBuffer = GLFunctions::glGenBuffer(); - GLFunctions::glBindBuffer(m_vertexBuffer, gl_const::GLArrayBuffer); m_program = program; - int8_t attributeLocation = m_program->GetAttributeLocation("a_position"); - ASSERT_NOT_EQUAL(attributeLocation, -1, ()); - GLFunctions::glEnableVertexAttribute(attributeLocation); - GLFunctions::glVertexAttributePointer(attributeLocation, 2, gl_const::GLFloatType, false, - sizeof(float) * 2, 0); - - if (m_VAO != 0) - GLFunctions::glBindVertexArray(0); - - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); + m_paramsSetter = std::move(paramsSetter); } void DebugRectRenderer::Destroy() { - if (m_vertexBuffer != 0) - { - GLFunctions::glDeleteBuffer(m_vertexBuffer); - m_vertexBuffer = 0; - } - - if (m_VAO != 0) - { - GLFunctions::glDeleteVertexArray(m_VAO); - m_VAO = 0; - } - - m_program = nullptr; + Reset(); } bool DebugRectRenderer::IsEnabled() const @@ -86,46 +58,51 @@ void DebugRectRenderer::SetEnabled(bool enabled) m_isEnabled = enabled; } +void DebugRectRenderer::SetArrow(m2::PointF const & arrowStart, m2::PointF const & arrowEnd, + dp::Color const & arrowColor, ScreenBase const & screen) +{ + std::vector vertices; + m2::PointF const dir = (arrowEnd - arrowStart).Normalize(); + m2::PointF const side = m2::PointF(-dir.y, dir.x); + PixelPointToScreenSpace(screen, arrowStart, vertices); + PixelPointToScreenSpace(screen, arrowEnd, vertices); + PixelPointToScreenSpace(screen, arrowEnd - dir * 20 + side * 10, vertices); + PixelPointToScreenSpace(screen, arrowEnd, vertices); + PixelPointToScreenSpace(screen, arrowEnd - dir * 20 - side * 10, vertices); + + UpdateBuffer(0 /* bufferInd */, std::move(vertices)); +} + +void DebugRectRenderer::SetRect(m2::RectF const & rect, ScreenBase const & screen) +{ + std::vector vertices; + PixelPointToScreenSpace(screen, rect.LeftBottom(), vertices); + PixelPointToScreenSpace(screen, rect.LeftTop(), vertices); + PixelPointToScreenSpace(screen, rect.RightTop(), vertices); + PixelPointToScreenSpace(screen, rect.RightBottom(), vertices); + PixelPointToScreenSpace(screen, rect.LeftBottom(), vertices); + + UpdateBuffer(0 /* bufferInd */, std::move(vertices)); +} + void DebugRectRenderer::DrawRect(ScreenBase const & screen, m2::RectF const & rect, - dp::Color const & color) const + dp::Color const & color) { if (!m_isEnabled) return; - ASSERT(m_program != nullptr, ()); - m_program->Bind(); + SetRect(rect, screen); - GLFunctions::glBindBuffer(m_vertexBuffer, gl_const::GLArrayBuffer); - - if (m_VAO != 0) - GLFunctions::glBindVertexArray(m_VAO); - - std::array vertices; - vertices[0] = PixelPointToScreenSpace(screen, rect.LeftBottom()); - vertices[1] = PixelPointToScreenSpace(screen, rect.LeftTop()); - vertices[2] = PixelPointToScreenSpace(screen, rect.RightTop()); - vertices[3] = PixelPointToScreenSpace(screen, rect.RightBottom()); - vertices[4] = vertices[0]; - - GLFunctions::glBufferData(gl_const::GLArrayBuffer, - static_cast(vertices.size() * sizeof(vertices[0])), - vertices.data(), gl_const::GLStaticDraw); - - if (m_paramsSetter) - m_paramsSetter(m_program, color); - - GLFunctions::glDrawArrays(gl_const::GLLineStrip, 0, static_cast(vertices.size())); - - if (m_VAO != 0) - GLFunctions::glBindVertexArray(0); - - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); - - m_program->Unbind(); + auto const preRenderFn = [this, color]() + { + if (m_paramsSetter) + m_paramsSetter(m_program, color); + }; + Render(m_program, preRenderFn, nullptr); } void DebugRectRenderer::DrawArrow(ScreenBase const & screen, - OverlayTree::DisplacementData const & data) const + OverlayTree::DisplacementData const & data) { if (!m_isEnabled) return; @@ -133,37 +110,13 @@ void DebugRectRenderer::DrawArrow(ScreenBase const & screen, if (data.m_arrowStart.EqualDxDy(data.m_arrowEnd, 1e-5)) return; - ASSERT(m_program != nullptr, ()); - m_program->Bind(); + SetArrow(data.m_arrowStart, data.m_arrowEnd, data.m_arrowColor, screen); - GLFunctions::glBindBuffer(m_vertexBuffer, gl_const::GLArrayBuffer); - - if (m_VAO != 0) - GLFunctions::glBindVertexArray(m_VAO); - - std::array vertices; - m2::PointF const dir = (data.m_arrowEnd - data.m_arrowStart).Normalize(); - m2::PointF const side = m2::PointF(-dir.y, dir.x); - vertices[0] = PixelPointToScreenSpace(screen, data.m_arrowStart); - vertices[1] = PixelPointToScreenSpace(screen, data.m_arrowEnd); - vertices[2] = PixelPointToScreenSpace(screen, data.m_arrowEnd - dir * 20 + side * 10); - vertices[3] = vertices[1]; - vertices[4] = PixelPointToScreenSpace(screen, data.m_arrowEnd - dir * 20 - side * 10); - - GLFunctions::glBufferData(gl_const::GLArrayBuffer, - static_cast(vertices.size() * sizeof(vertices[0])), - vertices.data(), gl_const::GLStaticDraw); - - if (m_paramsSetter) - m_paramsSetter(m_program, data.m_arrowColor); - - GLFunctions::glDrawArrays(gl_const::GLLineStrip, 0, static_cast(vertices.size())); - - if (m_VAO != 0) - GLFunctions::glBindVertexArray(0); - - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); - - m_program->Unbind(); + auto const preRenderFn = [this, data]() + { + if (m_paramsSetter) + m_paramsSetter(m_program, data.m_arrowColor); + }; + Render(m_program, preRenderFn, nullptr); } } // namespace dp diff --git a/drape/debug_rect_renderer.hpp b/drape/debug_rect_renderer.hpp index 7dc0294c9f..63a02b08ec 100644 --- a/drape/debug_rect_renderer.hpp +++ b/drape/debug_rect_renderer.hpp @@ -1,8 +1,8 @@ #pragma once #include "drape/gpu_program.hpp" +#include "drape/mesh_object.hpp" #include "drape/overlay_tree.hpp" -#include "drape/pointers.hpp" #include "geometry/rect2d.hpp" #include "geometry/screenbase.hpp" @@ -15,8 +15,9 @@ namespace dp { -class DebugRectRenderer +class DebugRectRenderer: public dp::MeshObject { + using TBase = dp::MeshObject; public: static DebugRectRenderer & Instance(); @@ -28,18 +29,20 @@ public: bool IsEnabled() const; void SetEnabled(bool enabled); - void DrawRect(ScreenBase const & screen, m2::RectF const & rect, dp::Color const & color) const; - void DrawArrow(ScreenBase const & screen, OverlayTree::DisplacementData const & data) const; + void DrawRect(ScreenBase const & screen, m2::RectF const & rect, dp::Color const & color); + void DrawArrow(ScreenBase const & screen, OverlayTree::DisplacementData const & data); private: DebugRectRenderer(); - ~DebugRectRenderer(); + ~DebugRectRenderer() override; + + void SetArrow(m2::PointF const & arrowStart, m2::PointF const & arrowEnd, dp::Color const & arrowColor, + ScreenBase const & screen); + void SetRect(m2::RectF const & rect, ScreenBase const & screen); ParamsSetter m_paramsSetter; - uint32_t m_VAO; - uint32_t m_vertexBuffer; ref_ptr m_program; - bool m_isEnabled; + bool m_isEnabled = false; }; } // namespace dp diff --git a/drape/mesh_object.cpp b/drape/mesh_object.cpp new file mode 100644 index 0000000000..2313a97bea --- /dev/null +++ b/drape/mesh_object.cpp @@ -0,0 +1,161 @@ +#include "drape/mesh_object.hpp" + +#include "drape/glconstants.hpp" +#include "drape/glextensions_list.hpp" +#include "drape/glfunctions.hpp" +#include "drape/glsl_func.hpp" +#include "drape/glsl_types.hpp" +#include "drape/gpu_program.hpp" +#include "drape/texture_manager.hpp" + +namespace +{ +glConst GetGLDrawPrimitive(dp::MeshObject::DrawPrimitive drawPrimitive) +{ + switch (drawPrimitive) + { + case dp::MeshObject::DrawPrimitive::Triangles: return gl_const::GLTriangles; + case dp::MeshObject::DrawPrimitive::TriangleStrip: return gl_const::GLTriangleStrip; + case dp::MeshObject::DrawPrimitive::LineStrip: return gl_const::GLLineStrip; + } +} +} // namespace + +namespace dp +{ +MeshObject::MeshObject(DrawPrimitive drawPrimitive) + : m_drawPrimitive(drawPrimitive) +{} + +MeshObject::~MeshObject() +{ + Reset(); +} + +void MeshObject::SetBuffer(uint32_t bufferInd, std::vector && vertices, uint32_t stride) +{ + CHECK_LESS_OR_EQUAL(bufferInd, GetNextBufferIndex(), ()); + + if (bufferInd == GetNextBufferIndex()) + m_buffers.emplace_back(std::move(vertices), stride); + else + m_buffers[bufferInd] = VertexBuffer(std::move(vertices), stride); + + Reset(); +} + +void MeshObject::SetAttribute(std::string const & attributeName, uint32_t bufferInd, uint32_t offset, + uint32_t componentsCount) +{ + CHECK_LESS(bufferInd, m_buffers.size(), ()); + m_buffers[bufferInd].m_attributes.emplace_back(attributeName, offset, componentsCount); + + Reset(); +} + +void MeshObject::Reset() +{ + for (auto & buffer : m_buffers) + { + if (buffer.m_bufferId != 0) + { + GLFunctions::glDeleteBuffer(buffer.m_bufferId); + buffer.m_bufferId = 0; + } + } + + if (m_VAO != 0) + GLFunctions::glDeleteVertexArray(m_VAO); + + m_VAO = 0; + m_initialized = false; +} + +void MeshObject::UpdateBuffer(uint32_t bufferInd, std::vector && vertices) +{ + if (!m_initialized) + Build(); + + CHECK_LESS(bufferInd, static_cast(m_buffers.size()), ()); + CHECK(m_buffers[bufferInd].m_bufferId != 0, ()); + + auto & buffer = m_buffers[bufferInd]; + buffer.m_data = std::move(vertices); + GLFunctions::glBindBuffer(buffer.m_bufferId, gl_const::GLArrayBuffer); + GLFunctions::glBufferData(gl_const::GLArrayBuffer, + static_cast(buffer.m_data.size()) * sizeof(buffer.m_data[0]), + buffer.m_data.data(), gl_const::GLStaticDraw); + GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); +} + +void MeshObject::Build() +{ + Reset(); + + if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) + { + m_VAO = GLFunctions::glGenVertexArray(); + GLFunctions::glBindVertexArray(m_VAO); + } + + for (auto & buffer : m_buffers) + { + buffer.m_bufferId = GLFunctions::glGenBuffer(); + GLFunctions::glBindBuffer(buffer.m_bufferId, gl_const::GLArrayBuffer); + if (buffer.m_data.empty()) + continue; + GLFunctions::glBufferData(gl_const::GLArrayBuffer, + static_cast(buffer.m_data.size()) * sizeof(buffer.m_data[0]), + buffer.m_data.data(), gl_const::GLStaticDraw); + } + + if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) + GLFunctions::glBindVertexArray(0); + GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); + + m_initialized = true; +} + +void MeshObject::Render(ref_ptr program, PreRenderFn const & preRenderFn, + PostRenderFn const & postRenderFn) +{ + program->Bind(); + + if (!m_initialized) + Build(); + + if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) + GLFunctions::glBindVertexArray(m_VAO); + + uint32_t verticesCount = 0; + for (auto const & buffer : m_buffers) + { + verticesCount = static_cast(buffer.m_data.size() * sizeof(buffer.m_data[0]) / buffer.m_stride); + GLFunctions::glBindBuffer(buffer.m_bufferId, gl_const::GLArrayBuffer); + for (auto const & attribute : buffer.m_attributes) + { + int8_t const attributePosition = program->GetAttributeLocation(attribute.m_attributeName); + ASSERT_NOT_EQUAL(attributePosition, -1, ()); + GLFunctions::glEnableVertexAttribute(attributePosition); + GLFunctions::glVertexAttributePointer(attributePosition, attribute.m_componentsCount, + gl_const::GLFloatType, false, + buffer.m_stride, attribute.m_offset); + } + } + + if (preRenderFn) + preRenderFn(); + + GLFunctions::glDrawArrays(GetGLDrawPrimitive(m_drawPrimitive), 0, verticesCount); + + if (postRenderFn) + postRenderFn(); + + program->Unbind(); + + if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) + GLFunctions::glBindVertexArray(0); + GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); +} +} // namespace dp + diff --git a/drape/mesh_object.hpp b/drape/mesh_object.hpp new file mode 100644 index 0000000000..fa5c56a7f3 --- /dev/null +++ b/drape/mesh_object.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include "drape/render_state.hpp" +#include "drape/pointers.hpp" + +#include + +namespace dp +{ +class GpuProgram; + +class MeshObject +{ +public: + enum class DrawPrimitive: uint32_t + { + Triangles, + TriangleStrip, + LineStrip + }; + + using PreRenderFn = std::function; + using PostRenderFn = std::function; + + MeshObject(DrawPrimitive drawPrimitive); + virtual ~MeshObject(); + + void SetBuffer(uint32_t bufferInd, std::vector && vertices, uint32_t stride); + void SetAttribute(std::string const & attributeName, uint32_t bufferInd, uint32_t offset, uint32_t componentsCount); + + void UpdateBuffer(uint32_t bufferInd, std::vector && vertices); + + void Render(ref_ptr program, + PreRenderFn const & preRenderFn, PostRenderFn const & postRenderFn); + + uint32_t GetNextBufferIndex() const { return static_cast(m_buffers.size()); } + + bool IsInitialized() const { return m_initialized; } + void Build(); + void Reset(); + +private: + struct AttributeMapping + { + AttributeMapping() = default; + + AttributeMapping(std::string const & attributeName, uint32_t offset, uint32_t componentsCount) + : m_offset(offset) + , m_componentsCount(componentsCount) + , m_attributeName(attributeName) + {} + + uint32_t m_offset = 0; + uint32_t m_componentsCount = 0; + std::string m_attributeName; + }; + + struct VertexBuffer + { + VertexBuffer() = default; + + VertexBuffer(std::vector && data, uint32_t stride) + : m_data(std::move(data)) + , m_stride(stride) + {} + + std::vector m_data; + uint32_t m_stride = 0; + uint32_t m_bufferId = 0; + + std::vector m_attributes; + }; + + std::vector m_buffers; + DrawPrimitive m_drawPrimitive = DrawPrimitive::Triangles; + + uint32_t m_VAO = 0; + bool m_initialized = false; +}; +} // namespace dp diff --git a/drape_frontend/arrow3d.cpp b/drape_frontend/arrow3d.cpp index b725ef6427..eb1c160cf4 100644 --- a/drape_frontend/arrow3d.cpp +++ b/drape_frontend/arrow3d.cpp @@ -27,6 +27,7 @@ double const kArrow3dMinZoom = 16; float const kOutlineScale = 1.2f; int constexpr kComponentsInVertex = 4; +int constexpr kComponentsInNormal = 3; df::ColorConstant const kArrow3DShadowColor = "Arrow3DShadow"; df::ColorConstant const kArrow3DObsoleteColor = "Arrow3DObsolete"; @@ -34,10 +35,11 @@ df::ColorConstant const kArrow3DColor = "Arrow3D"; df::ColorConstant const kArrow3DOutlineColor = "Arrow3DOutline"; Arrow3d::Arrow3d() - : m_state(CreateRenderState(gpu::Program::Arrow3d, DepthLayer::OverlayLayer)) + : TBase(DrawPrimitive::Triangles) + , m_state(CreateRenderState(gpu::Program::Arrow3d, DepthLayer::OverlayLayer)) { m_state.SetDepthTestEnabled(false); - m_vertices = { + std::vector vertices = { 0.0f, 0.0f, -1.0f, 1.0f, -1.2f, -1.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.2f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, -0.5f, 0.0f, 1.0f, -1.2f, -1.0f, 0.0f, 1.0f, @@ -55,15 +57,16 @@ Arrow3d::Arrow3d() }; int constexpr kVerticesInRow = 12; - m_normals.reserve(m_vertices.size()); - for (size_t triangle = 0; triangle < m_vertices.size() / kVerticesInRow; ++triangle) + std::vector normals; + normals.reserve(vertices.size()); + for (size_t triangle = 0; triangle < vertices.size() / kVerticesInRow; ++triangle) { glsl::vec4 v[3]; for (size_t vertex = 0; vertex < 3; ++vertex) { size_t const offset = triangle * kVerticesInRow + vertex * kComponentsInVertex; - v[vertex] = glsl::vec4(m_vertices[offset], m_vertices[offset + 1], - m_vertices[offset + 2], m_vertices[offset + 3]); + v[vertex] = glsl::vec4(vertices[offset], vertices[offset + 1], + vertices[offset + 2], vertices[offset + 3]); } glsl::vec3 normal = glsl::cross(glsl::vec3(v[1].x - v[0].x, v[1].y - v[0].y, v[1].z - v[0].z), @@ -72,23 +75,19 @@ Arrow3d::Arrow3d() for (size_t vertex = 0; vertex < 3; ++vertex) { - m_normals.push_back(normal.x); - m_normals.push_back(normal.y); - m_normals.push_back(normal.z); + normals.push_back(normal.x); + normals.push_back(normal.y); + normals.push_back(normal.z); } } -} -Arrow3d::~Arrow3d() -{ - if (m_bufferId != 0) - GLFunctions::glDeleteBuffer(m_bufferId); + auto const verticesBufferInd = 0; + SetBuffer(verticesBufferInd, std::move(vertices), sizeof(float) * kComponentsInVertex); + SetAttribute("a_pos", verticesBufferInd, 0 /* offset */, kComponentsInVertex); - if (m_bufferNormalsId != 0) - GLFunctions::glDeleteBuffer(m_bufferNormalsId); - - if (m_VAO != 0) - GLFunctions::glDeleteVertexArray(m_VAO); + auto const normalsBufferInd = 1; + SetBuffer(normalsBufferInd, std::move(normals), sizeof(float) * kComponentsInNormal); + SetAttribute("a_normal", normalsBufferInd, 0 /* offset */, kComponentsInNormal); } void Arrow3d::SetPosition(const m2::PointD & position) @@ -106,28 +105,6 @@ void Arrow3d::SetTexture(ref_ptr texMng) m_state.SetColorTexture(texMng->GetSymbolsTexture()); } -void Arrow3d::Build() -{ - if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) - { - m_VAO = GLFunctions::glGenVertexArray(); - GLFunctions::glBindVertexArray(m_VAO); - } - m_bufferId = GLFunctions::glGenBuffer(); - GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); - GLFunctions::glBufferData(gl_const::GLArrayBuffer, static_cast(m_vertices.size()) * sizeof(m_vertices[0]), - m_vertices.data(), gl_const::GLStaticDraw); - - m_bufferNormalsId = GLFunctions::glGenBuffer(); - GLFunctions::glBindBuffer(m_bufferNormalsId, gl_const::GLArrayBuffer); - GLFunctions::glBufferData(gl_const::GLArrayBuffer, static_cast(m_normals.size()) * sizeof(m_normals[0]), - m_normals.data(), gl_const::GLStaticDraw); - - if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) - GLFunctions::glBindVertexArray(0); - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); -} - void Arrow3d::SetPositionObsolete(bool obsolete) { m_obsoletePosition = obsolete; @@ -135,12 +112,6 @@ void Arrow3d::SetPositionObsolete(bool obsolete) void Arrow3d::Render(ScreenBase const & screen, ref_ptr mng, bool routingMode) { - if (!m_isInitialized) - { - Build(); - m_isInitialized = true; - } - // Render shadow. if (screen.isPerspective()) { @@ -164,49 +135,25 @@ void Arrow3d::Render(ScreenBase const & screen, ref_ptr mng // Render arrow. RenderArrow(screen, mng, gpu::Program::Arrow3d, color, 0.0f /* dz */, 1.0f /* scaleFactor */, true /* hasNormals */); - - if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) - GLFunctions::glBindVertexArray(0); - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); } void Arrow3d::RenderArrow(ScreenBase const & screen, ref_ptr mng, gpu::Program program, dp::Color const & color, float dz, float scaleFactor, bool hasNormals) { - auto prg = mng->GetProgram(program); - - prg->Bind(); - - if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) - GLFunctions::glBindVertexArray(m_VAO); - - GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); - int8_t const attributePosition = prg->GetAttributeLocation("a_pos"); - ASSERT_NOT_EQUAL(attributePosition, -1, ()); - GLFunctions::glEnableVertexAttribute(attributePosition); - GLFunctions::glVertexAttributePointer(attributePosition, kComponentsInVertex, - gl_const::GLFloatType, false, 0, 0); - - if (hasNormals) - { - GLFunctions::glBindBuffer(m_bufferNormalsId, gl_const::GLArrayBuffer); - int8_t const attributeNormal = prg->GetAttributeLocation("a_normal"); - ASSERT_NOT_EQUAL(attributeNormal, -1, ()); - GLFunctions::glEnableVertexAttribute(attributeNormal); - GLFunctions::glVertexAttributePointer(attributeNormal, 3, gl_const::GLFloatType, false, 0, 0); - } - gpu::Arrow3dProgramParams params; math::Matrix const modelTransform = CalculateTransform(screen, dz, scaleFactor); params.m_transform = glsl::make_mat4(modelTransform.m_data); params.m_color = glsl::ToVec4(color); - dp::ApplyState(m_state, prg); - mng->GetParamsSetter()->Apply(prg, params); - GLFunctions::glDrawArrays(gl_const::GLTriangles, 0, - static_cast(m_vertices.size()) / kComponentsInVertex); - prg->Unbind(); + auto gpuProgram = mng->GetProgram(program); + TBase::Render(gpuProgram, + [this, mng, gpuProgram, ¶ms]() + { + dp::ApplyState(m_state, gpuProgram); + mng->GetParamsSetter()->Apply(gpuProgram, params); + }, + nullptr); } math::Matrix Arrow3d::CalculateTransform(ScreenBase const & screen, float dz, float scaleFactor) const diff --git a/drape_frontend/arrow3d.hpp b/drape_frontend/arrow3d.hpp index fbad65540e..3224f8b8fa 100644 --- a/drape_frontend/arrow3d.hpp +++ b/drape_frontend/arrow3d.hpp @@ -3,7 +3,7 @@ #include "drape_frontend/render_state_extension.hpp" #include "drape/color.hpp" -#include "drape/pointers.hpp" +#include "drape/mesh_object.hpp" #include "geometry/rect2d.hpp" @@ -24,11 +24,11 @@ class ScreenBase; namespace df { -class Arrow3d +class Arrow3d: public dp::MeshObject { + using TBase = dp::MeshObject; public: Arrow3d(); - ~Arrow3d(); void SetPosition(m2::PointD const & position); void SetAzimuth(double azimuth); @@ -39,7 +39,6 @@ public: bool routingMode); private: - void Build(); math::Matrix CalculateTransform(ScreenBase const & screen, float dz, float scaleFactor) const; void RenderArrow(ScreenBase const & screen, ref_ptr mng, @@ -50,15 +49,6 @@ private: double m_azimuth = 0.0; bool m_obsoletePosition = false; - uint32_t m_VAO = 0; - uint32_t m_bufferId = 0; - uint32_t m_bufferNormalsId = 0; - - std::vector m_vertices; - std::vector m_normals; - dp::RenderState m_state; - - bool m_isInitialized = false; }; } // namespace df diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index beaa64ddff..1267a01c58 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -1409,11 +1409,8 @@ void FrontendRenderer::RenderTransitBackground() dp::TextureManager::ColorRegion region; m_texMng->GetColorRegion(df::GetColorConstant(kTransitBackgroundColor), region); CHECK(region.GetTexture() != nullptr, ("Texture manager is not initialized")); - if (!m_transitBackground->IsInitialized()) - { - auto prg = m_gpuProgramManager->GetProgram(gpu::Program::ScreenQuad); - m_transitBackground->SetTextureRect(region.GetTexRect(), prg); - } + //if (!m_transitBackground->IsInitialized()) + m_transitBackground->SetTextureRect(region.GetTexRect()); m_transitBackground->RenderTexture(make_ref(m_gpuProgramManager), static_cast(region.GetTexture()->GetID()), 1.0f); } diff --git a/drape_frontend/screen_quad_renderer.cpp b/drape_frontend/screen_quad_renderer.cpp index 80cfff7e9a..dfc8c8ac5c 100644 --- a/drape_frontend/screen_quad_renderer.cpp +++ b/drape_frontend/screen_quad_renderer.cpp @@ -69,75 +69,28 @@ void RendererContext::BindTexture(uint32_t textureId, ref_ptr pr } ScreenQuadRenderer::ScreenQuadRenderer() - : m_textureRendererContext(make_unique_dp()) -{} - -ScreenQuadRenderer::~ScreenQuadRenderer() + : TBase(DrawPrimitive::TriangleStrip) + , m_textureRendererContext(make_unique_dp()) { - if (m_bufferId != 0) - GLFunctions::glDeleteBuffer(m_bufferId); - - if (m_VAO != 0) - GLFunctions::glDeleteVertexArray(m_VAO); + Rebuild(); } -void ScreenQuadRenderer::Build(ref_ptr prg) +void ScreenQuadRenderer::Rebuild() { - if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) - { - m_VAO = GLFunctions::glGenVertexArray(); - GLFunctions::glBindVertexArray(m_VAO); - } - m_attributePosition = prg->GetAttributeLocation("a_pos"); - ASSERT_NOT_EQUAL(m_attributePosition, -1, ()); - - m_attributeTexCoord = prg->GetAttributeLocation("a_tcoord"); - ASSERT_NOT_EQUAL(m_attributeTexCoord, -1, ()); - std::vector vertices = {-1.0f, 1.0f, m_textureRect.minX(), m_textureRect.maxY(), 1.0f, 1.0f, m_textureRect.maxX(), m_textureRect.maxY(), -1.0f, -1.0f, m_textureRect.minX(), m_textureRect.minY(), 1.0f, -1.0f, m_textureRect.maxX(), m_textureRect.minY()}; - - m_bufferId = GLFunctions::glGenBuffer(); - GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); - GLFunctions::glBufferData(gl_const::GLArrayBuffer, - static_cast(vertices.size()) * sizeof(vertices[0]), - vertices.data(), gl_const::GLStaticDraw); - if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) - GLFunctions::glBindVertexArray(0); - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); + auto const bufferIndex = 0; + SetBuffer(bufferIndex, std::move(vertices), sizeof(float) * 4 /* stride */); + SetAttribute("a_pos", bufferIndex, 0 /* offset */, 2 /* componentsCount */); + SetAttribute("a_tcoord", bufferIndex, sizeof(float) * 2 /* offset */, 2 /* componentsCount */); } void ScreenQuadRenderer::Render(ref_ptr mng, ref_ptr context) { ref_ptr prg = mng->GetProgram(context->GetGpuProgram()); - prg->Bind(); - - if (m_bufferId == 0) - Build(prg); - - if (m_VAO != 0) - GLFunctions::glBindVertexArray(m_VAO); - - GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); - - GLFunctions::glEnableVertexAttribute(m_attributePosition); - GLFunctions::glVertexAttributePointer(m_attributePosition, 2, gl_const::GLFloatType, false, - sizeof(float) * 4, 0); - GLFunctions::glEnableVertexAttribute(m_attributeTexCoord); - GLFunctions::glVertexAttributePointer(m_attributeTexCoord, 2, gl_const::GLFloatType, false, - sizeof(float) * 4, sizeof(float) * 2); - - context->PreRender(mng); - GLFunctions::glDrawArrays(gl_const::GLTriangleStrip, 0, 4); - context->PostRender(); - - prg->Unbind(); - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); - - if (m_VAO != 0) - GLFunctions::glBindVertexArray(0); + TBase::Render(prg, [context, mng](){ context->PreRender(mng); }, [context](){ context->PostRender(); }); } void ScreenQuadRenderer::RenderTexture(ref_ptr mng, uint32_t textureId, @@ -151,19 +104,9 @@ void ScreenQuadRenderer::RenderTexture(ref_ptr mng, uint32_ Render(mng, make_ref(m_textureRendererContext)); } -void ScreenQuadRenderer::SetTextureRect(m2::RectF const & rect, ref_ptr prg) +void ScreenQuadRenderer::SetTextureRect(m2::RectF const & rect) { m_textureRect = rect; - Rebuild(prg); -} - -void ScreenQuadRenderer::Rebuild(ref_ptr prg) -{ - if (m_bufferId != 0) - GLFunctions::glDeleteBuffer(m_bufferId); - - prg->Bind(); - Build(prg); - prg->Unbind(); + Rebuild(); } } // namespace df diff --git a/drape_frontend/screen_quad_renderer.hpp b/drape_frontend/screen_quad_renderer.hpp index b467ae038a..6a5fb91fcc 100644 --- a/drape_frontend/screen_quad_renderer.hpp +++ b/drape_frontend/screen_quad_renderer.hpp @@ -2,7 +2,7 @@ #include "shaders/programs.hpp" -#include "drape/pointers.hpp" +#include "drape/mesh_object.hpp" #include "geometry/rect2d.hpp" @@ -33,28 +33,21 @@ protected: uint32_t filteringMode, uint32_t wrappingMode); }; -class ScreenQuadRenderer +class ScreenQuadRenderer: public dp::MeshObject { + using TBase = dp::MeshObject; public: ScreenQuadRenderer(); - ~ScreenQuadRenderer(); - void SetTextureRect(m2::RectF const & rect, ref_ptr prg); - void Rebuild(ref_ptr prg); - - bool IsInitialized() const { return m_bufferId != 0; } + void SetTextureRect(m2::RectF const & rect); m2::RectF const & GetTextureRect() const { return m_textureRect; } void Render(ref_ptr mng, ref_ptr context); void RenderTexture(ref_ptr mng, uint32_t textureId, float opacity); private: - void Build(ref_ptr prg); + void Rebuild(); - uint32_t m_bufferId = 0; - uint32_t m_VAO = 0; - int8_t m_attributePosition = -1; - int8_t m_attributeTexCoord = -1; m2::RectF m_textureRect = m2::RectF(0.0f, 0.0f, 1.0f, 1.0f); drape_ptr m_textureRendererContext; diff --git a/xcode/drape/drape.xcodeproj/project.pbxproj b/xcode/drape/drape.xcodeproj/project.pbxproj index 99a663746c..accab9d453 100644 --- a/xcode/drape/drape.xcodeproj/project.pbxproj +++ b/xcode/drape/drape.xcodeproj/project.pbxproj @@ -110,6 +110,8 @@ BBB72E9A2111CE9100249D4F /* graphics_context.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BBB72E972111CE9100249D4F /* graphics_context.hpp */; }; BBB72E9B2111CE9100249D4F /* graphics_context_factory.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BBB72E982111CE9100249D4F /* graphics_context_factory.hpp */; }; BBB72E9C2111CE9100249D4F /* graphics_context_factory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBB72E992111CE9100249D4F /* graphics_context_factory.cpp */; }; + BBB72E9F2118A45800249D4F /* mesh_object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BBB72E9D2118A45700249D4F /* mesh_object.cpp */; }; + BBB72EA02118A45800249D4F /* mesh_object.hpp in Headers */ = {isa = PBXBuildFile; fileRef = BBB72E9E2118A45800249D4F /* mesh_object.hpp */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -219,6 +221,8 @@ BBB72E972111CE9100249D4F /* graphics_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = graphics_context.hpp; sourceTree = ""; }; BBB72E982111CE9100249D4F /* graphics_context_factory.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = graphics_context_factory.hpp; sourceTree = ""; }; BBB72E992111CE9100249D4F /* graphics_context_factory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = graphics_context_factory.cpp; sourceTree = ""; }; + BBB72E9D2118A45700249D4F /* mesh_object.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mesh_object.cpp; sourceTree = ""; }; + BBB72E9E2118A45800249D4F /* mesh_object.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = mesh_object.hpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -315,6 +319,8 @@ 6729A52B1A69213A007D5872 /* index_buffer.hpp */, 6709471F1BDF9A4F005014C0 /* index_storage.cpp */, 670947201BDF9A4F005014C0 /* index_storage.hpp */, + BBB72E9D2118A45700249D4F /* mesh_object.cpp */, + BBB72E9E2118A45800249D4F /* mesh_object.hpp */, 6729A52C1A69213A007D5872 /* object_pool.hpp */, BBB72E8F2110AF0F00249D4F /* oglcontext.cpp */, 6729A52D1A69213A007D5872 /* oglcontext.hpp */, @@ -395,6 +401,7 @@ 6729A5681A69213A007D5872 /* batcher_helpers.hpp in Headers */, 6729A56A1A69213A007D5872 /* batcher.hpp in Headers */, 45447109211462A300D28C28 /* texture_types.hpp in Headers */, + BBB72EA02118A45800249D4F /* mesh_object.hpp in Headers */, 675D219A1BFB876E00717E4F /* projection.hpp in Headers */, 670947291BDF9A4F005014C0 /* hw_texture_ios.hpp in Headers */, 670947281BDF9A4F005014C0 /* glyph_manager.hpp in Headers */, @@ -496,6 +503,7 @@ 6729A5711A69213A007D5872 /* cpu_buffer.cpp in Sources */, 6729A5631A69213A007D5872 /* attribute_buffer_mutator.cpp in Sources */, 6729A56B1A69213A007D5872 /* binding_info.cpp in Sources */, + BBB72E9F2118A45800249D4F /* mesh_object.cpp in Sources */, 6729A5791A69213A007D5872 /* glconstants.cpp in Sources */, 6729A5941A69213A007D5872 /* overlay_handle.cpp in Sources */, 6709472D1BDF9A4F005014C0 /* index_storage.cpp in Sources */,