From 1a1ebbcbe99a80210049bea08045da3ea7835d91 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Wed, 14 Sep 2016 17:25:56 +0300 Subject: [PATCH 1/2] Added outline for houses --- drape/batcher.cpp | 46 +++- drape/batcher.hpp | 18 +- drape/batcher_helpers.cpp | 198 ++++++++++++++---- drape/batcher_helpers.hpp | 53 +++-- drape/color.hpp | 7 + drape/drape.pro | 1 + drape/drape_tests/glfunctions.cpp | 3 +- drape/glconstants.cpp | 1 + drape/glconstants.hpp | 1 + drape/glfunctions.cpp | 4 +- drape/glfunctions.hpp | 2 +- drape/glstate.cpp | 22 +- drape/glstate.hpp | 5 + drape/render_bucket.cpp | 4 +- drape/render_bucket.hpp | 2 +- .../shaders/area3d_outline_vertex_shader.vsh | 28 +++ drape/shaders/shader_index.txt | 2 + drape/vertex_array_buffer.cpp | 12 +- drape/vertex_array_buffer.hpp | 4 +- drape_frontend/apply_feature_functors.cpp | 56 ++--- drape_frontend/apply_feature_functors.hpp | 11 +- drape_frontend/area_shape.cpp | 167 ++++++++++----- drape_frontend/area_shape.hpp | 17 +- drape_frontend/backend_renderer.cpp | 28 ++- drape_frontend/frontend_renderer.cpp | 2 +- drape_frontend/gps_track_renderer.cpp | 5 +- drape_frontend/gui/gui_text.cpp | 1 + drape_frontend/gui/shape.cpp | 2 +- drape_frontend/render_group.cpp | 10 +- drape_frontend/render_node.cpp | 4 +- drape_frontend/route_renderer.cpp | 8 +- drape_frontend/rule_drawer.cpp | 17 +- drape_frontend/shape_view_params.hpp | 2 + drape_head/testing_engine.cpp | 10 +- 34 files changed, 551 insertions(+), 202 deletions(-) create mode 100644 drape/shaders/area3d_outline_vertex_shader.vsh diff --git a/drape/batcher.cpp b/drape/batcher.cpp index ea72fe4f88..c8bc1b548a 100644 --- a/drape/batcher.cpp +++ b/drape/batcher.cpp @@ -53,10 +53,12 @@ public: return m_indexStorage.GetRaw(); } else + { return m_overlay->IndexStorage(size); + } } - void SubmitIndeces() override + void SubmitIndices() override { if (m_overlay == nullptr || !m_overlay->IndexesRequired()) m_buffer->UploadIndexes(m_indexStorage.GetRawConst(), m_indexStorage.Size()); @@ -123,7 +125,7 @@ void Batcher::InsertTriangleList(GLState const & state, ref_ptr params, drape_ptr && handle) { - return InsertTriangles(state, params, move(handle)); + return InsertPrimitives(state, params, move(handle), 0 /* vertexStride */); } void Batcher::InsertTriangleStrip(GLState const & state, ref_ptr params) @@ -134,7 +136,7 @@ void Batcher::InsertTriangleStrip(GLState const & state, ref_ptr params, drape_ptr && handle) { - return InsertTriangles(state, params, move(handle)); + return InsertPrimitives(state, params, move(handle), 0 /* vertexStride */); } void Batcher::InsertTriangleFan(GLState const & state, ref_ptr params) @@ -145,7 +147,7 @@ void Batcher::InsertTriangleFan(GLState const & state, ref_ptr params, drape_ptr && handle) { - return InsertTriangles(state, params, move(handle)); + return InsertPrimitives(state, params, move(handle), 0 /* vertexStride */); } void Batcher::InsertListOfStrip(GLState const & state, ref_ptr params, @@ -157,7 +159,30 @@ void Batcher::InsertListOfStrip(GLState const & state, ref_ptr params, drape_ptr && handle, uint8_t vertexStride) { - return InsertTriangles(state, params, move(handle), vertexStride); + return InsertPrimitives(state, params, move(handle), vertexStride); +} + +void Batcher::InsertLineStrip(GLState const & state, ref_ptr params) +{ + InsertLineStrip(state, params, nullptr); +} + +IndicesRange Batcher::InsertLineStrip(GLState const & state, ref_ptr params, + drape_ptr && handle) +{ + return InsertPrimitives(state, params, move(handle), 0 /* vertexStride */); +} + +void Batcher::InsertLineRaw(GLState const & state, ref_ptr params, + vector const & indices) +{ + InsertLineRaw(state, params, indices, nullptr); +} + +IndicesRange Batcher::InsertLineRaw(GLState const & state, ref_ptr params, + vector const & indices, drape_ptr && handle) +{ + return InsertPrimitives(state, params, move(handle), 0 /* vertexStride */, indices); } void Batcher::StartSession(TFlushFn const & flusher) @@ -228,9 +253,10 @@ void Batcher::Flush() m_buckets.clear(); } -template -IndicesRange Batcher::InsertTriangles(GLState const & state, ref_ptr params, - drape_ptr && transferHandle, uint8_t vertexStride) +template +IndicesRange Batcher::InsertPrimitives(GLState const & state, ref_ptr params, + drape_ptr && transferHandle, uint8_t vertexStride, + TArgs ... batcherArgs) { ref_ptr vao = GetBucket(state)->GetBuffer(); IndicesRange range; @@ -241,8 +267,8 @@ IndicesRange Batcher::InsertTriangles(GLState const & state, ref_ptr params, drape_ptr && handle, uint8_t vertexStride); + void InsertLineStrip(GLState const & state, ref_ptr params); + IndicesRange InsertLineStrip(GLState const & state, ref_ptr params, + drape_ptr && handle); + + void InsertLineRaw(GLState const & state, ref_ptr params, + vector const & indices); + IndicesRange InsertLineRaw(GLState const & state, ref_ptr params, + vector const & indices, drape_ptr && handle); + typedef function &&)> TFlushFn; void StartSession(TFlushFn const & flusher); void EndSession(); @@ -52,9 +61,10 @@ public: void SetFeatureMinZoom(int minZoom); private: - template - IndicesRange InsertTriangles(GLState const & state, ref_ptr params, - drape_ptr && handle, uint8_t vertexStride = 0); + template + IndicesRange InsertPrimitives(GLState const & state, ref_ptr params, + drape_ptr && transferHandle, uint8_t vertexStride, + TArgs ... batcherArgs); class CallbacksWrapper; void ChangeBuffer(ref_ptr wrapper); @@ -63,10 +73,8 @@ private: void FinalizeBucket(GLState const & state); void Flush(); -private: TFlushFn m_flushInterface; -private: using TBuckets = map>; TBuckets m_buckets; diff --git a/drape/batcher_helpers.cpp b/drape/batcher_helpers.cpp index 7fea0d6f82..c35586d064 100644 --- a/drape/batcher_helpers.cpp +++ b/drape/batcher_helpers.cpp @@ -45,22 +45,23 @@ public: IndexGenerator(uint32_t startIndex) : m_startIndex(startIndex) , m_counter(0) - , m_minStriptCounter(0) {} + , m_minStripCounter(0) {} protected: uint32_t GetCounter() { return m_counter++; } + void ResetCounter() { m_counter = 0; - m_minStriptCounter = 0; + m_minStripCounter = 0; } uint32_t const m_startIndex; int16_t GetCWNormalizer() { - int16_t tmp = m_minStriptCounter; - m_minStriptCounter = my::cyclicClamp(m_minStriptCounter + 1, 0, 5); + int16_t tmp = m_minStripCounter; + m_minStripCounter = my::cyclicClamp(m_minStripCounter + 1, 0, 5); switch (tmp) { case 4: return 1; @@ -71,7 +72,7 @@ protected: private: uint32_t m_counter; - uint8_t m_minStriptCounter; + uint8_t m_minStripCounter; }; class ListIndexGenerator : public IndexGenerator @@ -86,21 +87,60 @@ class StripIndexGenerator : public IndexGenerator public: StripIndexGenerator(uint32_t startIndex) : IndexGenerator(startIndex) - , m_minStriptCounter(0) {} + {} + uint32_t operator()() { uint32_t const counter = GetCounter(); return m_startIndex + counter - 2 * (counter / 3) + GetCWNormalizer(); } +}; + +class LineStripIndexGenerator : public IndexGenerator +{ +public: + LineStripIndexGenerator(uint32_t startIndex) + : IndexGenerator(startIndex) + {} + + uint32_t operator()() + { + uint32_t const counter = GetCounter(); + uint32_t const result = m_startIndex + m_counter; + if (counter % 2 == 0) + m_counter++; + + return result; + } private: - uint32_t m_minStriptCounter; + uint32_t m_counter = 0; +}; + +class LineRawIndexGenerator : public IndexGenerator +{ +public: + LineRawIndexGenerator(uint32_t startIndex, vector const & indices) + : IndexGenerator(startIndex) + , m_indices(indices) + {} + + uint32_t operator()() + { + uint32_t const counter = GetCounter(); + ASSERT_LESS(counter, m_indices.size(), ()); + return static_cast(m_startIndex + m_indices[counter]); + } + +private: + vector const & m_indices; }; class FanIndexGenerator : public IndexGenerator { public: FanIndexGenerator(uint32_t startIndex) : IndexGenerator(startIndex) {} + uint32_t operator()() { uint32_t const counter = GetCounter(); @@ -110,14 +150,15 @@ public: } }; -class ListOfStriptGenerator : public IndexGenerator +class ListOfStripGenerator : public IndexGenerator { public: - ListOfStriptGenerator(uint32_t startIndex, uint32_t vertexStride, uint32_t indexPerStrip) + ListOfStripGenerator(uint32_t startIndex, uint32_t vertexStride, uint32_t indexPerStrip) : IndexGenerator(startIndex) , m_vertexStride(vertexStride) , m_indexPerStrip(indexPerStrip) - , m_base(0) {} + , m_base(0) + {} uint32_t operator()() { @@ -140,74 +181,83 @@ private: } // namespace -TriangleBatch::TriangleBatch(BatchCallbacks & callbacks) +UniversalBatch::UniversalBatch(BatchCallbacks & callbacks, uint8_t minVerticesCount, + uint8_t minIndicesCount) : m_callbacks(callbacks) , m_canDevideStreams(true) -{ -} + , m_minVerticesCount(minVerticesCount) + , m_minIndicesCount(minIndicesCount) +{} -void TriangleBatch::SetIsCanDevideStreams(bool canDevide) +void UniversalBatch::SetCanDevideStreams(bool canDevide) { m_canDevideStreams = canDevide; } -bool TriangleBatch::IsCanDevideStreams() const +bool UniversalBatch::CanDevideStreams() const { return m_canDevideStreams; } -void TriangleBatch::SetVertexStride(uint8_t vertexStride) +void UniversalBatch::SetVertexStride(uint8_t vertexStride) { m_vertexStride = vertexStride; } -void TriangleBatch::FlushData(ref_ptr streams, uint32_t vertexCount) const +void UniversalBatch::FlushData(ref_ptr streams, + uint32_t vertexCount) const { for (uint8_t i = 0; i < streams->GetStreamCount(); ++i) FlushData(streams->GetBindingInfo(i), streams->GetRawPointer(i), vertexCount); } -void TriangleBatch::FlushData(BindingInfo const & info, void const * data, uint32_t elementCount) const +void UniversalBatch::FlushData(BindingInfo const & info, void const * data, + uint32_t elementCount) const { m_callbacks.FlushData(info, data, elementCount); } -void * TriangleBatch::GetIndexStorage(uint32_t indexCount, uint32_t & startIndex) +void * UniversalBatch::GetIndexStorage(uint32_t indexCount, uint32_t & startIndex) { return m_callbacks.GetIndexStorage(indexCount, startIndex); } -void TriangleBatch::SubmitIndex() +void UniversalBatch::SubmitIndex() { - m_callbacks.SubmitIndeces(); + m_callbacks.SubmitIndices(); } -uint32_t TriangleBatch::GetAvailableVertexCount() const +uint32_t UniversalBatch::GetAvailableVertexCount() const { return m_callbacks.GetAvailableVertexCount(); } -uint32_t TriangleBatch::GetAvailableIndexCount() const +uint32_t UniversalBatch::GetAvailableIndexCount() const { return m_callbacks.GetAvailableIndexCount(); } -void TriangleBatch::ChangeBuffer() const +void UniversalBatch::ChangeBuffer() const { return m_callbacks.ChangeBuffer(); } -uint8_t TriangleBatch::GetVertexStride() const +uint8_t UniversalBatch::GetVertexStride() const { return m_vertexStride; } -bool TriangleBatch::IsBufferFilled(uint32_t availableVerticesCount, uint32_t availableIndicesCount) const +bool UniversalBatch::IsBufferFilled(uint32_t availableVerticesCount, + uint32_t availableIndicesCount) const { - return availableVerticesCount < 3 || availableIndicesCount < 3; + return availableVerticesCount < m_minVerticesCount || + availableIndicesCount < m_minIndicesCount; } -TriangleListBatch::TriangleListBatch(BatchCallbacks & callbacks) : TBase(callbacks) {} + +TriangleListBatch::TriangleListBatch(BatchCallbacks & callbacks) + : TBase(callbacks, 3 /* minVerticesCount */, 3 /* minIndicesCount */) +{} void TriangleListBatch::BatchData(ref_ptr streams) { @@ -220,7 +270,7 @@ void TriangleListBatch::BatchData(ref_ptr streams) uint32_t avIndex = GetAvailableIndexCount(); uint32_t vertexCount = streams->GetVertexCount(); - if (IsCanDevideStreams()) + if (CanDevideStreams()) { vertexCount = min(vertexCount, avVertex); vertexCount = min(vertexCount, avIndex); @@ -246,12 +296,86 @@ void TriangleListBatch::BatchData(ref_ptr streams) } } -FanStripHelper::FanStripHelper(BatchCallbacks & callbacks) - : TBase(callbacks) - , m_isFullUploaded(false) + +LineStripBatch::LineStripBatch(BatchCallbacks & callbacks) + : TBase(callbacks, 2 /* minVerticesCount */, 2 /* minIndicesCount */) +{} + +void LineStripBatch::BatchData(ref_ptr streams) { + while (streams->IsDataExists()) + { + if (IsBufferFilled(GetAvailableVertexCount(), GetAvailableIndexCount())) + ChangeBuffer(); + + uint32_t avVertex = GetAvailableVertexCount(); + uint32_t avIndex = GetAvailableIndexCount(); + uint32_t vertexCount = streams->GetVertexCount(); + ASSERT_GREATER_OR_EQUAL(vertexCount, 2, ()); + uint32_t indexCount = (vertexCount - 1) * 2; + + if (!IsEnoughMemory(avVertex, vertexCount, avIndex, indexCount)) + { + ChangeBuffer(); + avVertex = GetAvailableVertexCount(); + avIndex = GetAvailableIndexCount(); + ASSERT(IsEnoughMemory(avVertex, vertexCount, avIndex, indexCount), ()); + } + + uint32_t startIndex = 0; + void * indicesStorage = GetIndexStorage(indexCount, startIndex); + GenerateIndices(indicesStorage, indexCount, startIndex); + SubmitIndex(); + + FlushData(streams, vertexCount); + streams->Advance(vertexCount); + } } + +LineRawBatch::LineRawBatch(BatchCallbacks & callbacks, vector const & indices) + : TBase(callbacks, 2 /* minVerticesCount */, 2 /* minIndicesCount */) + , m_indices(indices) +{} + +void LineRawBatch::BatchData(ref_ptr streams) +{ + while (streams->IsDataExists()) + { + if (IsBufferFilled(GetAvailableVertexCount(), GetAvailableIndexCount())) + ChangeBuffer(); + + uint32_t avVertex = GetAvailableVertexCount(); + uint32_t avIndex = GetAvailableIndexCount(); + uint32_t vertexCount = streams->GetVertexCount(); + ASSERT_GREATER_OR_EQUAL(vertexCount, 2, ()); + uint32_t indexCount = static_cast(m_indices.size()); + + if (!IsEnoughMemory(avVertex, vertexCount, avIndex, indexCount)) + { + ChangeBuffer(); + avVertex = GetAvailableVertexCount(); + avIndex = GetAvailableIndexCount(); + ASSERT(IsEnoughMemory(avVertex, vertexCount, avIndex, indexCount), ()); + } + + uint32_t startIndex = 0; + void * indicesStorage = GetIndexStorage(indexCount, startIndex); + LineRawIndexGenerator generator(startIndex, m_indices); + GenerateIndices(indicesStorage, indexCount, generator); + SubmitIndex(); + + FlushData(streams, vertexCount); + streams->Advance(vertexCount); + } +} + + +FanStripHelper::FanStripHelper(BatchCallbacks & callbacks) + : TBase(callbacks, 3 /* minVerticesCount */, 3 /* minIndicesCount */) + , m_isFullUploaded(false) +{} + uint32_t FanStripHelper::BatchIndexes(uint32_t vertexCount) { uint32_t avVertex = GetAvailableVertexCount(); @@ -261,7 +385,7 @@ uint32_t FanStripHelper::BatchIndexes(uint32_t vertexCount) uint32_t batchIndexCount = 0; CalcBatchPortion(vertexCount, avVertex, avIndex, batchVertexCount, batchIndexCount); - if (!IsFullUploaded() && !IsCanDevideStreams()) + if (!IsFullUploaded() && !CanDevideStreams()) { ChangeBuffer(); avVertex = GetAvailableVertexCount(); @@ -332,8 +456,7 @@ uint32_t FanStripHelper::AlignICount(uint32_t iCount) const TriangleStripBatch::TriangleStripBatch(BatchCallbacks & callbacks) : TBase(callbacks) -{ -} +{} void TriangleStripBatch::BatchData(ref_ptr streams) { @@ -465,8 +588,7 @@ void TriangleFanBatch::GenerateIndexes(void * indexStorage, uint32_t count, uint TriangleListOfStripBatch::TriangleListOfStripBatch(BatchCallbacks & callbacks) : TBase(callbacks) -{ -} +{} void TriangleListOfStripBatch::BatchData(ref_ptr streams) { @@ -526,7 +648,7 @@ uint32_t TriangleListOfStripBatch::AlignICount(uint32_t iCount) const void TriangleListOfStripBatch::GenerateIndexes(void * indexStorage, uint32_t count, uint32_t startIndex) const { uint8_t const vertexStride = GetVertexStride(); - GenerateIndices(indexStorage, count, ListOfStriptGenerator(startIndex, vertexStride, VtoICount(vertexStride))); + GenerateIndices(indexStorage, count, ListOfStripGenerator(startIndex, vertexStride, VtoICount(vertexStride))); } } // namespace dp diff --git a/drape/batcher_helpers.hpp b/drape/batcher_helpers.hpp index b099c2314d..8ccc53d286 100644 --- a/drape/batcher_helpers.hpp +++ b/drape/batcher_helpers.hpp @@ -15,21 +15,21 @@ class BatchCallbacks public: virtual void FlushData(BindingInfo const & binding, void const * data, uint32_t count) = 0; virtual void * GetIndexStorage(uint32_t indexCount, uint32_t & startIndex) = 0; - virtual void SubmitIndeces() = 0; + virtual void SubmitIndices() = 0; virtual uint32_t GetAvailableVertexCount() const = 0; virtual uint32_t GetAvailableIndexCount() const = 0; virtual void ChangeBuffer() = 0; }; -class TriangleBatch +class UniversalBatch { public: - TriangleBatch(BatchCallbacks & callbacks); - virtual ~TriangleBatch(){} + UniversalBatch(BatchCallbacks & callbacks, uint8_t minVerticesCount, uint8_t minIndicesCount); + virtual ~UniversalBatch(){} virtual void BatchData(ref_ptr streams) = 0; - void SetIsCanDevideStreams(bool canDevide); - bool IsCanDevideStreams() const; + void SetCanDevideStreams(bool canDevide); + bool CanDevideStreams() const; void SetVertexStride(uint8_t vertexStride); protected: @@ -48,21 +48,46 @@ private: BatchCallbacks & m_callbacks; bool m_canDevideStreams; uint8_t m_vertexStride; + uint8_t const m_minVerticesCount; + uint8_t const m_minIndicesCount; }; -class TriangleListBatch : public TriangleBatch +class TriangleListBatch : public UniversalBatch { - typedef TriangleBatch TBase; + using TBase = UniversalBatch; public: TriangleListBatch(BatchCallbacks & callbacks); - virtual void BatchData(ref_ptr streams); + void BatchData(ref_ptr streams) override; }; -class FanStripHelper : public TriangleBatch +class LineStripBatch : public UniversalBatch { - typedef TriangleBatch TBase; + using TBase = UniversalBatch; + +public: + LineStripBatch(BatchCallbacks & callbacks); + + void BatchData(ref_ptr streams) override; +}; + +class LineRawBatch : public UniversalBatch +{ + using TBase = UniversalBatch; + +public: + LineRawBatch(BatchCallbacks & callbacks, vector const & indices); + + void BatchData(ref_ptr streams) override; + +private: + vector const & m_indices; +}; + +class FanStripHelper : public UniversalBatch +{ + using TBase = UniversalBatch; public: FanStripHelper(BatchCallbacks & callbacks); @@ -85,7 +110,7 @@ private: class TriangleStripBatch : public FanStripHelper { - typedef FanStripHelper TBase; + using TBase = FanStripHelper; public: TriangleStripBatch(BatchCallbacks & callbacks); @@ -97,7 +122,7 @@ protected: class TriangleFanBatch : public FanStripHelper { - typedef FanStripHelper TBase; + using TBase = FanStripHelper; public: TriangleFanBatch(BatchCallbacks & callbacks); @@ -109,7 +134,7 @@ protected: class TriangleListOfStripBatch : public FanStripHelper { - typedef FanStripHelper TBase; + using TBase = FanStripHelper; public: TriangleListOfStripBatch(BatchCallbacks & callbacks); diff --git a/drape/color.hpp b/drape/color.hpp index 3bdd95a911..6726812266 100644 --- a/drape/color.hpp +++ b/drape/color.hpp @@ -24,6 +24,13 @@ struct Color bool operator==(Color const & other) const { return m_rgba == other.m_rgba; } bool operator< (Color const & other) const { return m_rgba < other.m_rgba; } + Color operator*(float s) const + { + return Color(static_cast(GetRed() * s), + static_cast(GetGreen() * s), + static_cast(GetBlue() * s), + GetAlfa()); + } static Color Black() { return Color(0, 0, 0, 255); } static Color White() { return Color(255, 255, 255, 255); } diff --git a/drape/drape.pro b/drape/drape.pro index 323eacc8f2..0253766c1f 100644 --- a/drape/drape.pro +++ b/drape/drape.pro @@ -13,6 +13,7 @@ SOURCES += glfunctions.cpp OTHER_FILES += \ shaders/area3d_vertex_shader.vsh \ + shaders/area3d_outline_vertex_shader.vsh \ shaders/area_vertex_shader.vsh \ shaders/arrow3d_fragment_shader.fsh \ shaders/arrow3d_shadow_fragment_shader.fsh \ diff --git a/drape/drape_tests/glfunctions.cpp b/drape/drape_tests/glfunctions.cpp index 46cbeb24ae..d92fb43f6e 100644 --- a/drape/drape_tests/glfunctions.cpp +++ b/drape/drape_tests/glfunctions.cpp @@ -264,7 +264,8 @@ void * GLFunctions::glMapBuffer(glConst, glConst) { return 0; } void GLFunctions::glUnmapBuffer(glConst target) {} -void GLFunctions::glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex) {} +void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, + uint32_t indexCount, uint32_t startIndex) {} void GLFunctions::glDrawArrays(glConst mode, int32_t first, uint32_t count) {} diff --git a/drape/glconstants.cpp b/drape/glconstants.cpp index 56823129f6..e934c7be71 100644 --- a/drape/glconstants.cpp +++ b/drape/glconstants.cpp @@ -201,6 +201,7 @@ const glConst GLAlways = GL_ALWAYS; const glConst GLActiveUniforms = GL_ACTIVE_UNIFORMS; +const glConst GLLines = GL_LINES; const glConst GLLineStrip = GL_LINE_STRIP; const glConst GLTriangles = GL_TRIANGLES; const glConst GLTriangleStrip = GL_TRIANGLE_STRIP; diff --git a/drape/glconstants.hpp b/drape/glconstants.hpp index aee0b8c37f..1dccc60bb8 100644 --- a/drape/glconstants.hpp +++ b/drape/glconstants.hpp @@ -153,6 +153,7 @@ extern const glConst GLAlways; extern const glConst GLActiveUniforms; /// Draw primitives +extern const glConst GLLines; extern const glConst GLLineStrip; extern const glConst GLTriangles; extern const glConst GLTriangleStrip; diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp index 93f4e39f34..68ed7f15a5 100644 --- a/drape/glfunctions.cpp +++ b/drape/glfunctions.cpp @@ -994,9 +994,9 @@ void GLFunctions::glTexParameter(glConst param, glConst value) GLCHECK(::glTexParameteri(GL_TEXTURE_2D, param, value)); } -void GLFunctions::glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex) +void GLFunctions::glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex) { - GLCHECK(::glDrawElements(GL_TRIANGLES, indexCount, sizeOfIndex == sizeof(uint32_t) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, + GLCHECK(::glDrawElements(primitive, indexCount, sizeOfIndex == sizeof(uint32_t) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, reinterpret_cast(startIndex * sizeOfIndex))); } diff --git a/drape/glfunctions.hpp b/drape/glfunctions.hpp index aaf38e80bb..b775f41ab9 100644 --- a/drape/glfunctions.hpp +++ b/drape/glfunctions.hpp @@ -133,7 +133,7 @@ public: static void glTexParameter(glConst param, glConst value); // Draw support - static void glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex = 0); + static void glDrawElements(glConst primitive, uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex = 0); static void glDrawArrays(glConst mode, int32_t first, uint32_t count); // FBO support diff --git a/drape/glstate.cpp b/drape/glstate.cpp index 091ba984c3..cdcfff2538 100644 --- a/drape/glstate.cpp +++ b/drape/glstate.cpp @@ -52,6 +52,7 @@ GLState::GLState(uint32_t gpuProgramIndex, DepthLayer depthLayer) , m_textureFilter(gl_const::GLLinear) , m_colorTexture(nullptr) , m_maskTexture(nullptr) + , m_drawAsLine(false) { } @@ -75,6 +76,16 @@ void GLState::SetTextureFilter(glConst filter) m_textureFilter = filter; } +bool GLState::GetDrawAsLine() const +{ + return m_drawAsLine; +} + +void GLState::SetDrawAsLine(bool drawAsLine) +{ + m_drawAsLine = drawAsLine; +} + bool GLState::operator<(GLState const & other) const { if (m_depthLayer != other.m_depthLayer) @@ -89,8 +100,12 @@ bool GLState::operator<(GLState const & other) const return m_depthFunction < other.m_depthFunction; if (m_colorTexture != other.m_colorTexture) return m_colorTexture < other.m_colorTexture; + if (m_maskTexture != other.m_maskTexture) + return m_maskTexture < other.m_maskTexture; + if (m_textureFilter != other.m_textureFilter) + return m_textureFilter < other.m_textureFilter; - return m_maskTexture < other.m_maskTexture; + return m_drawAsLine < other.m_drawAsLine; } bool GLState::operator==(GLState const & other) const @@ -100,7 +115,10 @@ bool GLState::operator==(GLState const & other) const m_gpuProgram3dIndex == other.m_gpuProgram3dIndex && m_blending == other.m_blending && m_colorTexture == other.m_colorTexture && - m_maskTexture == other.m_maskTexture; + m_maskTexture == other.m_maskTexture && + m_textureFilter == other.m_textureFilter && + m_depthFunction == other.m_depthFunction && + m_drawAsLine == other.m_drawAsLine; } bool GLState::operator!=(GLState const & other) const diff --git a/drape/glstate.hpp b/drape/glstate.hpp index 5946d6f493..661461ebf4 100644 --- a/drape/glstate.hpp +++ b/drape/glstate.hpp @@ -67,6 +67,9 @@ public: glConst GetTextureFilter() const; void SetTextureFilter(glConst filter); + bool GetDrawAsLine() const; + void SetDrawAsLine(bool drawAsLine); + bool operator<(GLState const & other) const; bool operator==(GLState const & other) const; bool operator!=(GLState const & other) const; @@ -81,6 +84,8 @@ private: ref_ptr m_colorTexture; ref_ptr m_maskTexture; + + bool m_drawAsLine; }; void ApplyUniforms(UniformValuesStorage const & uniforms, ref_ptr program); diff --git a/drape/render_bucket.cpp b/drape/render_bucket.cpp index 7684ad5484..b0b732e37c 100644 --- a/drape/render_bucket.cpp +++ b/drape/render_bucket.cpp @@ -77,7 +77,7 @@ void RenderBucket::RemoveOverlayHandles(ref_ptr tree) tree->Remove(make_ref(overlayHandle)); } -void RenderBucket::Render() +void RenderBucket::Render(bool drawAsLine) { ASSERT(m_buffer != nullptr, ()); @@ -105,7 +105,7 @@ void RenderBucket::Render() m_buffer->ApplyMutation(hasIndexMutation ? rfpIndex : nullptr, rfpAttrib); } - m_buffer->Render(); + m_buffer->Render(drawAsLine); } void RenderBucket::SetFeatureMinZoom(int minZoom) diff --git a/drape/render_bucket.hpp b/drape/render_bucket.hpp index 5669603a1d..7c3d9a0e73 100644 --- a/drape/render_bucket.hpp +++ b/drape/render_bucket.hpp @@ -37,7 +37,7 @@ public: void Update(ScreenBase const & modelView); void CollectOverlayHandles(ref_ptr tree); void RemoveOverlayHandles(ref_ptr tree); - void Render(); + void Render(bool drawAsLine); // Only for testing! Don't use this function in production code! void RenderDebug(ScreenBase const & screen) const; diff --git a/drape/shaders/area3d_outline_vertex_shader.vsh b/drape/shaders/area3d_outline_vertex_shader.vsh new file mode 100644 index 0000000000..7c1fa01717 --- /dev/null +++ b/drape/shaders/area3d_outline_vertex_shader.vsh @@ -0,0 +1,28 @@ +attribute vec3 a_position; +attribute vec2 a_colorTexCoords; + +uniform mat4 modelView; +uniform mat4 projection; +uniform mat4 pivotTransform; +uniform float zScale; + +#ifdef ENABLE_VTF +uniform sampler2D u_colorTex; +varying lowp vec4 v_color; +#else +varying vec2 v_colorTexCoords; +#endif + +void main(void) +{ + vec4 pos = vec4(a_position, 1.0) * modelView; + pos.xyw = (pos * projection).xyw; + pos.z = a_position.z * zScale; + gl_Position = pivotTransform * pos; + +#ifdef ENABLE_VTF + v_color = texture2D(u_colorTex, a_colorTexCoords); +#else + v_colorTexCoords = a_colorTexCoords; +#endif +} diff --git a/drape/shaders/shader_index.txt b/drape/shaders/shader_index.txt index 2b191117d5..62b1ad476e 100644 --- a/drape/shaders/shader_index.txt +++ b/drape/shaders/shader_index.txt @@ -2,7 +2,9 @@ TEXT_OUTLINED_PROGRAM text_outlined_vertex_shader.vsh text_fragment_shader.fsh TEXT_PROGRAM text_vertex_shader.vsh text_fragment_shader.fsh TEXT_OUTLINED_GUI_PROGRAM text_outlined_gui_vertex_shader.vsh text_fragment_shader.fsh AREA_PROGRAM area_vertex_shader.vsh solid_color_fragment_shader.fsh +AREA_OUTLINE_PROGRAM area_vertex_shader.vsh solid_color_fragment_shader.fsh AREA_3D_PROGRAM area3d_vertex_shader.vsh texturing3d_fragment_shader.fsh +AREA_3D_OUTLINE_PROGRAM area3d_outline_vertex_shader.vsh solid_color_fragment_shader.fsh TEXTURING_PROGRAM texturing_vertex_shader.vsh texturing_fragment_shader.fsh MASKED_TEXTURING_PROGRAM masked_texturing_vertex_shader.vsh masked_texturing_fragment_shader.fsh LINE_PROGRAM line_vertex_shader.vsh line_fragment_shader.fsh diff --git a/drape/vertex_array_buffer.cpp b/drape/vertex_array_buffer.cpp index e4dab7b1af..b812881732 100644 --- a/drape/vertex_array_buffer.cpp +++ b/drape/vertex_array_buffer.cpp @@ -67,12 +67,12 @@ void VertexArrayBuffer::PreflushImpl() m_isPreflushed = true; } -void VertexArrayBuffer::Render() +void VertexArrayBuffer::Render(bool drawAsLine) { - RenderRange(IndicesRange(0, GetIndexBuffer()->GetCurrentSize())); + RenderRange(drawAsLine, IndicesRange(0, GetIndexBuffer()->GetCurrentSize())); } -void VertexArrayBuffer::RenderRange(IndicesRange const & range) +void VertexArrayBuffer::RenderRange(bool drawAsLine, IndicesRange const & range) { if (!(m_staticBuffers.empty() && m_dynamicBuffers.empty()) && GetIndexCount() > 0) { @@ -84,7 +84,9 @@ void VertexArrayBuffer::RenderRange(IndicesRange const & range) BindDynamicBuffers(); GetIndexBuffer()->Bind(); - GLFunctions::glDrawElements(dp::IndexStorage::SizeOfIndex(), range.m_idxCount, range.m_idxStart); + GLFunctions::glDrawElements(drawAsLine ? gl_const::GLLines : gl_const::GLTriangles, + dp::IndexStorage::SizeOfIndex(), + range.m_idxCount, range.m_idxStart); Unbind(); } @@ -224,7 +226,7 @@ uint32_t VertexArrayBuffer::GetIndexCount() const void VertexArrayBuffer::UploadIndexes(void const * data, uint32_t count) { - ASSERT(count <= GetIndexBuffer()->GetAvailableSize(), ()); + ASSERT_LESS_OR_EQUAL(count, GetIndexBuffer()->GetAvailableSize(), ()); GetIndexBuffer()->UploadData(data, count); } diff --git a/drape/vertex_array_buffer.hpp b/drape/vertex_array_buffer.hpp index 8ba2db50f2..baab293954 100644 --- a/drape/vertex_array_buffer.hpp +++ b/drape/vertex_array_buffer.hpp @@ -49,8 +49,8 @@ public: /// On devices where implemented OES_vertex_array_object extensions we use it for build VertexArrayBuffer /// OES_vertex_array_object create OpenGL resource that belong only one GL context (which was created by) /// by this reason Build/Bind and Render must be called only on Frontendrendere thread - void Render(); - void RenderRange(IndicesRange const & range); + void Render(bool drawAsLine); + void RenderRange(bool drawAsLine, IndicesRange const & range); void Build(ref_ptr program); ///@} diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 0710a5716f..4acaa2810c 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -1,5 +1,4 @@ #include "drape_frontend/apply_feature_functors.hpp" -#include "drape_frontend/shape_view_params.hpp" #include "drape_frontend/visual_params.hpp" #include "drape_frontend/area_shape.hpp" @@ -424,12 +423,12 @@ void ApplyPointFeature::Finish() ApplyAreaFeature::ApplyAreaFeature(m2::PointD const & tileCenter, TInsertShapeFn const & insertShape, FeatureID const & id, - m2::RectD const & clipRect, float minPosZ, + m2::RectD const & clipRect, bool isBuilding, float minPosZ, float posZ, int minVisibleScale, uint8_t rank, CaptionDescription const & captions) : TBase(tileCenter, insertShape, id, minVisibleScale, rank, captions, posZ) , m_minPosZ(minPosZ) - , m_isBuilding(posZ > 0.0f) + , m_isBuilding(isBuilding) , m_clipRect(clipRect) {} @@ -497,19 +496,13 @@ void ApplyAreaFeature::ProcessBuildingPolygon(m2::PointD const & p1, m2::PointD int ApplyAreaFeature::GetIndex(m2::PointD const & pt) { - int maxIndex = -1; - for (auto it = m_indices.begin(); it != m_indices.end(); ++it) + for (size_t i = 0; i < m_points.size(); i++) { - if (it->first > maxIndex) - maxIndex = it->first; - - if (pt.EqualDxDy(it->second, 1e-7)) - return it->first; + if (pt.EqualDxDy(m_points[i], 1e-7)) + return static_cast(i); } - - int const newIndex = maxIndex + 1; - m_indices.insert(make_pair(newIndex, pt)); - return newIndex; + m_points.push_back(pt); + return static_cast(m_points.size()) - 1; } bool ApplyAreaFeature::EqualEdges(TEdge const & edge1, TEdge const & edge2) const @@ -561,17 +554,27 @@ void ApplyAreaFeature::BuildEdges(int vertexIndex1, int vertexIndex2, int vertex m_edges.push_back(make_pair(move(edge3), vertexIndex2)); } -void ApplyAreaFeature::CalculateBuildingEdges(vector & edges) +void ApplyAreaFeature::CalculateBuildingOutline(bool calculateNormals, BuildingOutline & outline) { + outline.m_vertices = move(m_points); + outline.m_indices.reserve(m_edges.size() * 2); + if (calculateNormals) + outline.m_normals.reserve(m_edges.size()); + for (auto & e : m_edges) { if (e.second < 0) continue; - BuildingEdge edge; - edge.m_startVertex = m_indices[e.first.first]; - edge.m_endVertex = m_indices[e.first.second]; - edge.m_normal = CalculateNormal(edge.m_startVertex, edge.m_endVertex, m_indices[e.second]); - edges.push_back(move(edge)); + + outline.m_indices.push_back(e.first.first); + outline.m_indices.push_back(e.first.second); + + if (calculateNormals) + { + outline.m_normals.emplace_back(CalculateNormal(outline.m_vertices[e.first.first], + outline.m_vertices[e.first.second], + outline.m_vertices[e.second])); + } } } @@ -592,17 +595,18 @@ void ApplyAreaFeature::ProcessRule(Stylist::TRuleWrapper const & rule) params.m_minPosZ = m_minPosZ; params.m_posZ = m_posZ; - vector edges; + BuildingOutline outline; + bool const calculateNormals = m_posZ > 0.0; if (m_isBuilding) - { - edges.reserve(m_edges.size()); - CalculateBuildingEdges(edges); - } + CalculateBuildingOutline(calculateNormals, outline); + params.m_is3D = !outline.m_indices.empty() && calculateNormals; - m_insertShape(make_unique_dp(move(m_triangles), move(edges), params)); + m_insertShape(make_unique_dp(move(m_triangles), move(outline), params)); } else + { TBase::ProcessRule(rule); + } } ApplyLineFeature::ApplyLineFeature(m2::PointD const & tileCenter, double currentScaleGtoP, diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index e95efe075c..c41d4ff9a9 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -2,6 +2,7 @@ #include "drape_frontend/stylist.hpp" #include "drape_frontend/tile_key.hpp" +#include "drape_frontend/shape_view_params.hpp" #include "drape/pointers.hpp" @@ -24,7 +25,7 @@ namespace df struct TextViewParams; class MapShape; -struct BuildingEdge; +struct BuildingOutline; using TInsertShapeFn = function && shape)>; @@ -99,7 +100,7 @@ class ApplyAreaFeature : public ApplyPointFeature public: ApplyAreaFeature(m2::PointD const & tileCenter, TInsertShapeFn const & insertShape, FeatureID const & id, - m2::RectD const & clipRect, float minPosZ, + m2::RectD const & clipRect, bool isBuilding, float minPosZ, float posZ, int minVisibleScale, uint8_t rank, CaptionDescription const & captions); @@ -112,7 +113,7 @@ private: using TEdge = pair; void ProcessBuildingPolygon(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3); - void CalculateBuildingEdges(vector & edges); + void CalculateBuildingOutline(bool calculateNormals, BuildingOutline & outline); int GetIndex(m2::PointD const & pt); void BuildEdges(int vertexIndex1, int vertexIndex2, int vertexIndex3); bool EqualEdges(TEdge const & edge1, TEdge const & edge2) const; @@ -121,8 +122,8 @@ private: vector m_triangles; - unordered_map m_indices; - vector> m_edges; + buffer_vector m_points; + buffer_vector, kBuildingOutlineSize> m_edges; float const m_minPosZ; bool const m_isBuilding; m2::RectD m_clipRect; diff --git a/drape_frontend/area_shape.cpp b/drape_frontend/area_shape.cpp index 44c7f9b459..d6ab5b0b65 100644 --- a/drape_frontend/area_shape.cpp +++ b/drape_frontend/area_shape.cpp @@ -15,72 +15,137 @@ namespace df { -AreaShape::AreaShape(vector && triangleList, vector && buildingEdges, +AreaShape::AreaShape(vector && triangleList, BuildingOutline && buildingOutline, AreaViewParams const & params) : m_vertexes(move(triangleList)) - , m_buildingEdges(move(buildingEdges)) + , m_buildingOutline(move(buildingOutline)) , m_params(params) -{ -} +{} void AreaShape::Draw(ref_ptr batcher, ref_ptr textures) const { dp::TextureManager::ColorRegion region; textures->GetColorRegion(m_params.m_color, region); - glsl::vec2 const colorPoint = glsl::ToVec2(region.GetTexRect().Center()); + dp::TextureManager::ColorRegion outlineRegion; + textures->GetColorRegion(m_params.m_color * 0.75, outlineRegion); + ASSERT_EQUAL(region.GetTexture(), outlineRegion.GetTexture(), ()); - if (!m_buildingEdges.empty()) - { - vector vertexes; - vertexes.reserve(m_vertexes.size() + m_buildingEdges.size() * 6); - - for (auto const & edge : m_buildingEdges) - { - glsl::vec2 const startPt = glsl::ToVec2(ConvertToLocal(edge.m_startVertex, m_params.m_tileCenter, kShapeCoordScalar)); - glsl::vec2 const endPt = glsl::ToVec2(ConvertToLocal(edge.m_endVertex, m_params.m_tileCenter, kShapeCoordScalar)); - - glsl::vec3 normal(glsl::ToVec2(edge.m_normal), 0.0f); - vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_minPosZ), normal, colorPoint)); - vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_minPosZ), normal, colorPoint)); - vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_posZ), normal, colorPoint)); - - vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_posZ), normal, colorPoint)); - vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_minPosZ), normal, colorPoint)); - vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_posZ), normal, colorPoint)); - } - - glsl::vec3 normal(0.0f, 0.0f, -1.0f); - for (auto const & vertex : m_vertexes) - { - glsl::vec2 const pt = glsl::ToVec2(ConvertToLocal(vertex, m_params.m_tileCenter, kShapeCoordScalar)); - vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(pt, -m_params.m_posZ), normal, colorPoint)); - } - - dp::GLState state(gpu::AREA_3D_PROGRAM, dp::GLState::GeometryLayer); - state.SetColorTexture(region.GetTexture()); - state.SetBlending(dp::Blending(false /* isEnabled */)); - - dp::AttributeProvider provider(1, vertexes.size()); - provider.InitStream(0, gpu::Area3dVertex::GetBindingInfo(), make_ref(vertexes.data())); - batcher->InsertTriangleList(state, make_ref(&provider)); - } + if (m_params.m_is3D) + DrawArea3D(batcher, region.GetTexRect().Center(), outlineRegion.GetTexRect().Center(), region.GetTexture()); else + DrawArea(batcher, region.GetTexRect().Center(), outlineRegion.GetTexRect().Center(), region.GetTexture()); +} + +void AreaShape::DrawArea(ref_ptr batcher, m2::PointD const & colorUv, m2::PointD const & outlineUv, + ref_ptr texture) const +{ + glsl::vec2 const uv = glsl::ToVec2(colorUv); + + buffer_vector vertexes; + vertexes.resize(m_vertexes.size()); + transform(m_vertexes.begin(), m_vertexes.end(), vertexes.begin(), [&uv, this](m2::PointF const & vertex) { - buffer_vector vertexes; - vertexes.resize(m_vertexes.size()); - transform(m_vertexes.begin(), m_vertexes.end(), vertexes.begin(), [&colorPoint, this](m2::PointF const & vertex) + return gpu::AreaVertex(glsl::vec3(glsl::ToVec2(ConvertToLocal(vertex, m_params.m_tileCenter, kShapeCoordScalar)), + m_params.m_depth), uv); + }); + + dp::GLState state(gpu::AREA_PROGRAM, dp::GLState::GeometryLayer); + state.SetColorTexture(texture); + + dp::AttributeProvider provider(1, m_vertexes.size()); + provider.InitStream(0, gpu::AreaVertex::GetBindingInfo(), make_ref(vertexes.data())); + batcher->InsertTriangleList(state, make_ref(&provider)); + + // Generate outline. + if (!m_buildingOutline.m_indices.empty()) + { + glsl::vec2 const ouv = glsl::ToVec2(outlineUv); + + vector vertices; + vertices.reserve(m_buildingOutline.m_vertices.size()); + for (size_t i = 0; i < m_buildingOutline.m_vertices.size(); i++) { - return gpu::AreaVertex(glsl::vec3(glsl::ToVec2(ConvertToLocal(vertex, m_params.m_tileCenter, kShapeCoordScalar)), - m_params.m_depth), colorPoint); - }); + glsl::vec2 const pos = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[i], + m_params.m_tileCenter, kShapeCoordScalar)); + vertices.emplace_back(gpu::AreaVertex(glsl::vec3(pos, m_params.m_depth), ouv)); + } - dp::GLState state(gpu::AREA_PROGRAM, dp::GLState::GeometryLayer); - state.SetColorTexture(region.GetTexture()); + dp::GLState state(gpu::AREA_OUTLINE_PROGRAM, dp::GLState::GeometryLayer); + state.SetColorTexture(texture); + state.SetDrawAsLine(true); - dp::AttributeProvider provider(1, m_vertexes.size()); - provider.InitStream(0, gpu::AreaVertex::GetBindingInfo(), make_ref(vertexes.data())); - batcher->InsertTriangleList(state, make_ref(&provider)); + dp::AttributeProvider outlineProvider(1, vertices.size()); + outlineProvider.InitStream(0, gpu::AreaVertex::GetBindingInfo(), make_ref(vertices.data())); + batcher->InsertLineRaw(state, make_ref(&outlineProvider), m_buildingOutline.m_indices); } } +void AreaShape::DrawArea3D(ref_ptr batcher, m2::PointD const & colorUv, m2::PointD const & outlineUv, + ref_ptr texture) const +{ + ASSERT(!m_buildingOutline.m_indices.empty(), ()); + ASSERT(!m_buildingOutline.m_normals.empty(), ()); + + glsl::vec2 const uv = glsl::ToVec2(colorUv); + + vector vertexes; + vertexes.reserve(m_vertexes.size() + m_buildingOutline.m_normals.size() * 6); + + for (size_t i = 0; i < m_buildingOutline.m_normals.size(); i++) + { + size_t const startIndex = m_buildingOutline.m_indices[i * 2]; + size_t const endIndex = m_buildingOutline.m_indices[i * 2 + 1]; + + glsl::vec2 const startPt = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[startIndex], + m_params.m_tileCenter, kShapeCoordScalar)); + glsl::vec2 const endPt = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[endIndex], + m_params.m_tileCenter, kShapeCoordScalar)); + + glsl::vec3 normal(glsl::ToVec2(m_buildingOutline.m_normals[i]), 0.0f); + vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_minPosZ), normal, uv)); + vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_minPosZ), normal, uv)); + vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_posZ), normal, uv)); + + vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(startPt, -m_params.m_posZ), normal, uv)); + vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_minPosZ), normal, uv)); + vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_posZ), normal, uv)); + } + + glsl::vec3 normal(0.0f, 0.0f, -1.0f); + for (auto const & vertex : m_vertexes) + { + glsl::vec2 const pt = glsl::ToVec2(ConvertToLocal(vertex, m_params.m_tileCenter, kShapeCoordScalar)); + vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(pt, -m_params.m_posZ), normal, uv)); + } + + dp::GLState state(gpu::AREA_3D_PROGRAM, dp::GLState::GeometryLayer); + state.SetColorTexture(texture); + state.SetBlending(dp::Blending(false /* isEnabled */)); + + dp::AttributeProvider provider(1, vertexes.size()); + provider.InitStream(0, gpu::Area3dVertex::GetBindingInfo(), make_ref(vertexes.data())); + batcher->InsertTriangleList(state, make_ref(&provider)); + + // Generate outline. + glsl::vec2 const ouv = glsl::ToVec2(outlineUv); + + dp::GLState outlineState(gpu::AREA_3D_OUTLINE_PROGRAM, dp::GLState::GeometryLayer); + outlineState.SetColorTexture(texture); + outlineState.SetBlending(dp::Blending(false /* isEnabled */)); + outlineState.SetDrawAsLine(true); + + vector vertices; + vertices.reserve(m_buildingOutline.m_vertices.size()); + for (size_t i = 0; i < m_buildingOutline.m_vertices.size(); i++) + { + glsl::vec2 const pos = glsl::ToVec2(ConvertToLocal(m_buildingOutline.m_vertices[i], + m_params.m_tileCenter, kShapeCoordScalar)); + vertices.emplace_back(gpu::AreaVertex(glsl::vec3(pos, -m_params.m_posZ), ouv)); + } + + dp::AttributeProvider outlineProvider(1, vertices.size()); + outlineProvider.InitStream(0, gpu::AreaVertex::GetBindingInfo(), make_ref(vertices.data())); + batcher->InsertLineRaw(outlineState, make_ref(&outlineProvider), m_buildingOutline.m_indices); +} + } // namespace df diff --git a/drape_frontend/area_shape.hpp b/drape_frontend/area_shape.hpp index c6ae7d1579..32e5db7ba0 100644 --- a/drape_frontend/area_shape.hpp +++ b/drape_frontend/area_shape.hpp @@ -11,24 +11,29 @@ namespace df { -struct BuildingEdge +struct BuildingOutline { - m2::PointD m_startVertex; - m2::PointD m_endVertex; - m2::PointD m_normal; + buffer_vector m_vertices; + vector m_indices; + vector m_normals; }; class AreaShape : public MapShape { public: - AreaShape(vector && triangleList, vector && buildingEdges, + AreaShape(vector && triangleList, BuildingOutline && buildingOutline, AreaViewParams const & params); void Draw(ref_ptr batcher, ref_ptr textures) const override; private: + void DrawArea(ref_ptr batcher, m2::PointD const & colorUv, + m2::PointD const & outlineUv, ref_ptr texture) const; + void DrawArea3D(ref_ptr batcher, m2::PointD const & colorUv, + m2::PointD const & outlineUv, ref_ptr texture) const; + vector m_vertexes; - vector m_buildingEdges; + BuildingOutline m_buildingOutline; AreaViewParams m_params; }; diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index a93ba86fda..ce46e5a973 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -113,6 +113,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) } break; } + case Message::InvalidateReadManagerRect: { ref_ptr msg = message; @@ -122,11 +123,13 @@ void BackendRenderer::AcceptMessage(ref_ptr message) m_readManager->Invalidate(msg->GetTilesForInvalidate()); break; } + case Message::ShowChoosePositionMark: { RecacheChoosePositionMark(); break; } + case Message::GuiRecache: { ref_ptr msg = message; @@ -137,6 +140,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) #endif break; } + case Message::GuiLayerLayout: { ref_ptr msg = message; @@ -145,17 +149,21 @@ void BackendRenderer::AcceptMessage(ref_ptr message) MessagePriority::Normal); break; } + case Message::TileReadStarted: { - m_batchersPool->ReserveBatcher(static_cast>(message)->GetKey()); + ref_ptr msg = message; + m_batchersPool->ReserveBatcher(msg->GetKey()); break; } + case Message::TileReadEnded: { ref_ptr msg = message; m_batchersPool->ReleaseBatcher(msg->GetKey()); break; } + case Message::FinishTileRead: { ref_ptr msg = message; @@ -164,6 +172,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) MessagePriority::Normal); break; } + case Message::FinishReading: { TOverlaysRenderData overlays; @@ -176,11 +185,13 @@ void BackendRenderer::AcceptMessage(ref_ptr message) } break; } + case Message::MapShapesRecache: { RecacheMapShapes(); break; } + case Message::MapShapeReaded: { ref_ptr msg = message; @@ -196,6 +207,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) } break; } + case Message::OverlayMapShapeReaded: { ref_ptr msg = message; @@ -218,6 +230,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) } break; } + case Message::UpdateUserMarkLayer: { ref_ptr msg = message; @@ -238,6 +251,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) msg->EndProcess(); break; } + case Message::AddRoute: { ref_ptr msg = message; @@ -245,18 +259,21 @@ void BackendRenderer::AcceptMessage(ref_ptr message) msg->GetColor(), msg->GetPattern(), m_texMng, msg->GetRecacheId()); break; } + case Message::CacheRouteSign: { ref_ptr msg = message; m_routeBuilder->BuildSign(msg->GetPosition(), msg->IsStart(), msg->IsValid(), m_texMng, msg->GetRecacheId()); break; } + case Message::CacheRouteArrows: { ref_ptr msg = message; m_routeBuilder->BuildArrows(msg->GetRouteIndex(), msg->GetBorders(), m_texMng, msg->GetRecacheId()); break; } + case Message::RemoveRoute: { ref_ptr msg = message; @@ -268,12 +285,14 @@ void BackendRenderer::AcceptMessage(ref_ptr message) MessagePriority::Normal); break; } + case Message::InvalidateTextures: { m_texMng->Invalidate(VisualParams::Instance().GetResourcePostfix()); RecacheMapShapes(); break; } + case Message::CacheGpsTrackPoints: { ref_ptr msg = message; @@ -285,12 +304,14 @@ void BackendRenderer::AcceptMessage(ref_ptr message) MessagePriority::Normal); break; } + case Message::Allow3dBuildings: { ref_ptr msg = message; m_readManager->Allow3dBuildings(msg->Allow3dBuildings()); break; } + case Message::RequestSymbolsSize: { ref_ptr msg = message; @@ -307,6 +328,7 @@ void BackendRenderer::AcceptMessage(ref_ptr message) break; } + default: ASSERT(false, ()); break; @@ -366,8 +388,8 @@ void BackendRenderer::Routine::Do() void BackendRenderer::InitGLDependentResource() { - m_batchersPool = make_unique_dp(ReadManager::ReadCount(), bind(&BackendRenderer::FlushGeometry, this, _1)); - + m_batchersPool = make_unique_dp(ReadManager::ReadCount(), + bind(&BackendRenderer::FlushGeometry, this, _1)); dp::TextureManager::Params params; params.m_resPostfix = VisualParams::Instance().GetResourcePostfix(); params.m_visualScale = df::VisualParams::Instance().GetVisualScale(); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 61182eee24..9abb4d2496 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -1774,7 +1774,7 @@ FrontendRenderer::RenderLayer::RenderLayerID FrontendRenderer::RenderLayer::GetL if (state.GetDepthLayer() == dp::GLState::OverlayLayer) return OverlayID; - if (state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM) + if (state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM || state.GetProgram3dIndex() == gpu::AREA_3D_OUTLINE_PROGRAM) return Geometry3dID; return Geometry2dID; diff --git a/drape_frontend/gps_track_renderer.cpp b/drape_frontend/gps_track_renderer.cpp index def40a6c10..39a7e314c7 100644 --- a/drape_frontend/gps_track_renderer.cpp +++ b/drape_frontend/gps_track_renderer.cpp @@ -308,12 +308,13 @@ void GpsTrackRenderer::RenderTrack(ScreenBase const & screen, int zoomLevel, program->Bind(); ASSERT_GREATER(m_renderData.size(), 0, ()); - dp::ApplyState(m_renderData.front()->m_state, program); + dp::GLState const & state = m_renderData.front()->m_state; + dp::ApplyState(state, program); dp::ApplyUniforms(uniforms, program); for (size_t i = 0; i < m_renderData.size(); i++) if (m_handlesCache[i].second != 0) - m_renderData[i]->m_bucket->Render(); + m_renderData[i]->m_bucket->Render(state.GetDrawAsLine()); } void GpsTrackRenderer::Update() diff --git a/drape_frontend/gui/gui_text.cpp b/drape_frontend/gui/gui_text.cpp index c00408e332..e92b01c2f5 100644 --- a/drape_frontend/gui/gui_text.cpp +++ b/drape_frontend/gui/gui_text.cpp @@ -296,6 +296,7 @@ void MutableLabel::SetMaxLength(uint16_t maxLength) ref_ptr MutableLabel::SetAlphabet(string const & alphabet, ref_ptr mng) { strings::UniString str = strings::MakeUniString(alphabet + "."); + sort(str.begin(), str.end()); strings::UniString::iterator it = unique(str.begin(), str.end()); str.resize(distance(str.begin(), it)); diff --git a/drape_frontend/gui/shape.cpp b/drape_frontend/gui/shape.cpp index 3499b32b31..89d496b0ae 100644 --- a/drape_frontend/gui/shape.cpp +++ b/drape_frontend/gui/shape.cpp @@ -120,7 +120,7 @@ void ShapeRenderer::Render(ScreenBase const & screen, ref_ptrApplyMutation(nullptr, mutatorRef); } - info.m_buffer->Render(); + info.m_buffer->Render(info.m_state.GetDrawAsLine()); }); } diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index ac5e7b63b2..4199936a10 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -105,13 +105,13 @@ void RenderGroup::Render(ScreenBase const & screen) dp::ApplyUniforms(m_uniforms, shader); for(auto & renderBucket : m_renderBuckets) - renderBucket->Render(); + renderBucket->Render(m_state.GetDrawAsLine()); m_uniforms.SetFloatValue("u_contrastGamma", params.m_contrast, params.m_gamma); m_uniforms.SetFloatValue("u_isOutlinePass", 0.0f); dp::ApplyUniforms(m_uniforms, shader); for(auto & renderBucket : m_renderBuckets) - renderBucket->Render(); + renderBucket->Render(m_state.GetDrawAsLine()); } else if (programIndex == gpu::TEXT_PROGRAM || program3dIndex == gpu::TEXT_BILLBOARD_PROGRAM) @@ -119,14 +119,14 @@ void RenderGroup::Render(ScreenBase const & screen) m_uniforms.SetFloatValue("u_contrastGamma", params.m_contrast, params.m_gamma); dp::ApplyUniforms(m_uniforms, shader); for(auto & renderBucket : m_renderBuckets) - renderBucket->Render(); + renderBucket->Render(m_state.GetDrawAsLine()); } else { dp::ApplyUniforms(m_uniforms, shader); for(drape_ptr & renderBucket : m_renderBuckets) - renderBucket->Render(); + renderBucket->Render(m_state.GetDrawAsLine()); } #ifdef RENDER_DEBUG_RECTS @@ -233,7 +233,7 @@ void UserMarkRenderGroup::Render(ScreenBase const & screen) if (m_renderBucket != nullptr) { m_renderBucket->GetBuffer()->Build(shader); - m_renderBucket->Render(); + m_renderBucket->Render(m_state.GetDrawAsLine()); } } diff --git a/drape_frontend/render_node.cpp b/drape_frontend/render_node.cpp index ffc907d963..3792708e85 100644 --- a/drape_frontend/render_node.cpp +++ b/drape_frontend/render_node.cpp @@ -17,13 +17,13 @@ void RenderNode::Render(ref_ptr mng, dp::UniformValuesSto dp::IndicesRange const & range) { Apply(mng, uniforms); - m_buffer->RenderRange(range); + m_buffer->RenderRange(m_state.GetDrawAsLine(), range); } void RenderNode::Render(ref_ptr mng, dp::UniformValuesStorage const & uniforms) { Apply(mng, uniforms); - m_buffer->Render(); + m_buffer->Render(m_state.GetDrawAsLine()); } void RenderNode::Apply(ref_ptr mng, dp::UniformValuesStorage const & uniforms) diff --git a/drape_frontend/route_renderer.cpp b/drape_frontend/route_renderer.cpp index 7c07b75c14..3dc7497cdf 100644 --- a/drape_frontend/route_renderer.cpp +++ b/drape_frontend/route_renderer.cpp @@ -262,7 +262,7 @@ void RouteRenderer::RenderRoute(ScreenBase const & screen, ref_ptr const & bucket : m_routeData->m_route.m_buckets) - bucket->Render(); + bucket->Render(state.GetDrawAsLine()); } // Render arrows. @@ -282,7 +282,7 @@ void RouteRenderer::RenderRoute(ScreenBase const & screen, ref_ptr const & bucket : m_routeArrows->m_arrows.m_buckets) - bucket->Render(); + bucket->Render(state.GetDrawAsLine()); } } @@ -319,13 +319,13 @@ void RouteRenderer::RenderRouteSign(drape_ptr const & sign, Scree : mng->GetProgram(state.GetProgramIndex()); program->Bind(); - dp::ApplyState(sign->m_sign.m_state, program); + dp::ApplyState(state, program); dp::ApplyUniforms(uniforms, program); for (auto const & bucket : sign->m_sign.m_buckets) { bucket->GetBuffer()->Build(program); - bucket->Render(); + bucket->Render(state.GetDrawAsLine()); } } diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index e65a9eeabc..84ad111adc 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -155,16 +155,17 @@ void RuleDrawer::operator()(FeatureType const & f) if (s.AreaStyleExists()) { - bool is3dBuilding = false; - if (m_is3dBuidings && f.GetLayer() >= 0) + bool isBuilding = false; + if (f.GetLayer() >= 0) { // Looks like nonsense, but there are some osm objects with types // highway-path-bridge and building (sic!) at the same time (pedestrian crossing). - is3dBuilding = (ftypes::IsBuildingChecker::Instance()(f) || - ftypes::IsBuildingPartChecker::Instance()(f)) && - !ftypes::IsBridgeChecker::Instance()(f) && - !ftypes::IsTunnelChecker::Instance()(f); + isBuilding = (ftypes::IsBuildingChecker::Instance()(f) || + ftypes::IsBuildingPartChecker::Instance()(f)) && + !ftypes::IsBridgeChecker::Instance()(f) && + !ftypes::IsTunnelChecker::Instance()(f); } + bool const is3dBuilding = m_is3dBuidings && isBuilding; m2::PointD featureCenter; @@ -221,8 +222,8 @@ void RuleDrawer::operator()(FeatureType const & f) minVisibleScale = feature::GetMinDrawableScale(f); ApplyAreaFeature apply(m_globalRect.Center(), insertShape, f.GetID(), m_globalRect, - areaMinHeight, areaHeight, minVisibleScale, f.GetRank(), - s.GetCaptionDescription()); + isBuilding, areaMinHeight, areaHeight, minVisibleScale, + f.GetRank(), s.GetCaptionDescription()); f.ForEachTriangle(apply, zoomLevel); apply.SetHotelData(ExtractHotelData(f)); if (applyPointStyle) diff --git a/drape_frontend/shape_view_params.hpp b/drape_frontend/shape_view_params.hpp index 51036d8eac..f5c084c288 100644 --- a/drape_frontend/shape_view_params.hpp +++ b/drape_frontend/shape_view_params.hpp @@ -13,6 +13,7 @@ namespace df { double const kShapeCoordScalar = 1000; +int constexpr kBuildingOutlineSize = 16; struct CommonViewParams { @@ -51,6 +52,7 @@ struct AreaViewParams : CommonViewParams dp::Color m_color; float m_minPosZ = 0.0f; float m_posZ = 0.0f; + bool m_is3D = false; }; struct LineViewParams : CommonViewParams diff --git a/drape_head/testing_engine.cpp b/drape_head/testing_engine.cpp index 162073862b..3b9eb8c7e0 100644 --- a/drape_head/testing_engine.cpp +++ b/drape_head/testing_engine.cpp @@ -120,7 +120,7 @@ public: { } - void Draw(ref_ptr batcher, ref_ptr textures) const + void Draw(ref_ptr batcher, ref_ptr textures) const override { dp::TextureManager::TStipplePattern key; key.push_back(10); @@ -165,7 +165,7 @@ class DummyColorElement : public MapShape public: DummyColorElement() { } - void Draw(ref_ptr batcher, ref_ptr textures) const + void Draw(ref_ptr batcher, ref_ptr textures) const override { dp::TextureManager::ColorRegion region; textures->GetColorRegion(dp::Color(rand() % 256, rand() % 256, rand() % 256, 255), region); @@ -398,7 +398,7 @@ void TestingEngine::Draw() for (size_t i = 0; i < buckets.size(); ++i) buckets[i]->CollectOverlayHandles(make_ref(&tree)); for (size_t i = 0; i < buckets.size(); ++i) - buckets[i]->Render(); + buckets[i]->Render(state.GetDrawAsLine()); tree.EndOverlayPlacing(); } } @@ -508,13 +508,13 @@ void TestingEngine::DrawImpl() { vector trg{ m2::PointD(110.0, 30.0), m2::PointD(112.0, 30.0), m2::PointD(112.0, 28.0), m2::PointD(110.0, 30.0), m2::PointD(112.0, 28.0), m2::PointD(110.0, 28.0) }; - vector edges; + df::BuildingOutline outline; AreaViewParams p; p.m_color = dp::Color::White(); p.m_depth = 0.0f; params.m_minVisibleScale = 1; params.m_rank = 0; - AreaShape(move(trg), move(edges), p).Draw(make_ref(m_batcher), make_ref(m_textures)); + AreaShape(move(trg), move(outline), p).Draw(make_ref(m_batcher), make_ref(m_textures)); } m_batcher->EndSession(); From 06cf7a28debe3d2c922e8d7114f06c154356e360 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Thu, 15 Sep 2016 13:04:36 +0300 Subject: [PATCH 2/2] Added line simplification --- drape/batcher_helpers.cpp | 2 +- drape/color.hpp | 8 +- drape/drape_tests/glfunctions.cpp | 12 +- drape/drape_tests/glmock_functions.hpp | 3 + drape/glfunctions.cpp | 22 ++++ drape/glfunctions.hpp | 4 + drape/glstate.cpp | 22 +++- drape/glstate.hpp | 3 + drape/support_manager.cpp | 10 ++ drape/support_manager.hpp | 4 + drape_frontend/apply_feature_functors.cpp | 12 +- drape_frontend/apply_feature_functors.hpp | 3 +- drape_frontend/area_shape.cpp | 17 ++- drape_frontend/line_shape.cpp | 133 ++++++++++++++++++---- drape_frontend/line_shape.hpp | 3 + drape_frontend/rule_drawer.cpp | 11 +- drape_frontend/shape_view_params.hpp | 1 + 17 files changed, 222 insertions(+), 48 deletions(-) diff --git a/drape/batcher_helpers.cpp b/drape/batcher_helpers.cpp index c35586d064..e15a3840a0 100644 --- a/drape/batcher_helpers.cpp +++ b/drape/batcher_helpers.cpp @@ -349,7 +349,7 @@ void LineRawBatch::BatchData(ref_ptr streams) uint32_t avIndex = GetAvailableIndexCount(); uint32_t vertexCount = streams->GetVertexCount(); ASSERT_GREATER_OR_EQUAL(vertexCount, 2, ()); - uint32_t indexCount = static_cast(m_indices.size()); + uint32_t const indexCount = static_cast(m_indices.size()); if (!IsEnoughMemory(avVertex, vertexCount, avIndex, indexCount)) { diff --git a/drape/color.hpp b/drape/color.hpp index 6726812266..bd51571259 100644 --- a/drape/color.hpp +++ b/drape/color.hpp @@ -1,5 +1,7 @@ #pragma once +#include "base/math.hpp" + #include "std/cstdint.hpp" #include "std/sstream.hpp" #include "std/string.hpp" @@ -26,9 +28,9 @@ struct Color bool operator< (Color const & other) const { return m_rgba < other.m_rgba; } Color operator*(float s) const { - return Color(static_cast(GetRed() * s), - static_cast(GetGreen() * s), - static_cast(GetBlue() * s), + return Color(my::clamp(static_cast(GetRed() * s), 0, 255), + my::clamp(static_cast(GetGreen() * s), 0, 255), + my::clamp(static_cast(GetBlue() * s), 0, 255), GetAlfa()); } diff --git a/drape/drape_tests/glfunctions.cpp b/drape/drape_tests/glfunctions.cpp index d92fb43f6e..ad78bd869b 100644 --- a/drape/drape_tests/glfunctions.cpp +++ b/drape/drape_tests/glfunctions.cpp @@ -11,7 +11,6 @@ using namespace emul; void GLFunctions::glFlush() { - } uint32_t GLFunctions::glGenVertexArray() @@ -111,7 +110,6 @@ int8_t GLFunctions::glGetAttribLocation(uint32_t programID, string const & name) void GLFunctions::glBindAttribLocation(uint32_t programID, uint8_t index, string const & name) { - } /// enable vertex attribute binding. To get attributeLocation need to call glGetAttributeLocation @@ -246,6 +244,16 @@ string GLFunctions::glGetString(glConst pname) return MOCK_CALL(glGetString(pname)); } +int32_t GLFunctions::glGetMaxLineWidth() +{ + return MOCK_CALL(glGetMaxLineWidth()); +} + +void GLFunctions::glLineWidth(uint32_t value) +{ + return MOCK_CALL(glLineWidth(value)); +} + void CheckGLError(my::SrcPoint const & /*srcPt*/) {} void GLFunctions::glEnable(glConst mode) {} diff --git a/drape/drape_tests/glmock_functions.hpp b/drape/drape_tests/glmock_functions.hpp index 7c80ac36b5..399dabe8d0 100644 --- a/drape/drape_tests/glmock_functions.hpp +++ b/drape/drape_tests/glmock_functions.hpp @@ -82,6 +82,9 @@ public: MOCK_METHOD1(glGetInteger, int32_t(glConst)); MOCK_METHOD1(glGetString, string(glConst)); + MOCK_METHOD0(glGetMaxLineWidth, int32_t()); + + MOCK_METHOD1(glLineWidth, void(uint32_t value)); private: static GLMockFunctions * m_mock; diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp index 68ed7f15a5..41ec7c1632 100644 --- a/drape/glfunctions.cpp +++ b/drape/glfunctions.cpp @@ -190,6 +190,7 @@ public: m_glBindTextureCache = CachedParam(); m_glActiveTextureCache = CachedParam(); m_glUseProgramCache = CachedParam(); + m_glLineWidthCache = CachedParam(); m_glStateCache.clear(); m_uniformsCache.clear(); } @@ -250,6 +251,14 @@ public: } } + void glLineWidth(uint32_t value) + { + if (!IsCachedThread() || m_glLineWidthCache.Assign(value)) + { + GLCHECK(::glLineWidth(static_cast(value))); + } + } + private: template @@ -326,6 +335,7 @@ private: CachedParam m_glActiveTextureCache; CachedParam m_glUseProgramCache; StateParams m_glStateCache; + CachedParam m_glLineWidthCache; map m_uniformsCache; @@ -573,6 +583,13 @@ string GLFunctions::glGetString(glConst pname) return string(str); } +int32_t GLFunctions::glGetMaxLineWidth() +{ + GLint range[2]; + GLCHECK(::glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, range)); + return max(range[0], range[1]); +} + int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name) { GLint result; @@ -1037,6 +1054,11 @@ uint32_t GLFunctions::glCheckFramebufferStatus() return result; } +void GLFunctions::glLineWidth(uint32_t value) +{ + s_cache.glLineWidth(value); +} + namespace { diff --git a/drape/glfunctions.hpp b/drape/glfunctions.hpp index b775f41ab9..dab34efe89 100644 --- a/drape/glfunctions.hpp +++ b/drape/glfunctions.hpp @@ -40,6 +40,8 @@ public: static string glGetString(glConst pname); + static int32_t glGetMaxLineWidth(); + static void glEnable(glConst mode); static void glDisable(glConst mode); static void glClearDepthValue(double depth); @@ -48,6 +50,8 @@ public: static void glBlendEquation(glConst function); static void glBlendFunc(glConst srcFactor, glConst dstFactor); + static void glLineWidth(uint32_t value); + /// VAO support static uint32_t glGenVertexArray(); static void glBindVertexArray(uint32_t vao); diff --git a/drape/glstate.cpp b/drape/glstate.cpp index cdcfff2538..a13b8fea7f 100644 --- a/drape/glstate.cpp +++ b/drape/glstate.cpp @@ -53,8 +53,8 @@ GLState::GLState(uint32_t gpuProgramIndex, DepthLayer depthLayer) , m_colorTexture(nullptr) , m_maskTexture(nullptr) , m_drawAsLine(false) -{ -} + , m_lineWidth(1) +{} glConst GLState::GetDepthFunction() const { @@ -86,6 +86,16 @@ void GLState::SetDrawAsLine(bool drawAsLine) m_drawAsLine = drawAsLine; } +int GLState::GetLineWidth() const +{ + return m_lineWidth; +} + +void GLState::SetLineWidth(int width) +{ + m_lineWidth = width; +} + bool GLState::operator<(GLState const & other) const { if (m_depthLayer != other.m_depthLayer) @@ -104,8 +114,10 @@ bool GLState::operator<(GLState const & other) const return m_maskTexture < other.m_maskTexture; if (m_textureFilter != other.m_textureFilter) return m_textureFilter < other.m_textureFilter; + if (m_drawAsLine != other.m_drawAsLine) + return m_drawAsLine < other.m_drawAsLine; - return m_drawAsLine < other.m_drawAsLine; + return m_lineWidth < other.m_lineWidth; } bool GLState::operator==(GLState const & other) const @@ -118,7 +130,8 @@ bool GLState::operator==(GLState const & other) const m_maskTexture == other.m_maskTexture && m_textureFilter == other.m_textureFilter && m_depthFunction == other.m_depthFunction && - m_drawAsLine == other.m_drawAsLine; + m_drawAsLine == other.m_drawAsLine && + m_lineWidth == other.m_lineWidth; } bool GLState::operator!=(GLState const & other) const @@ -205,6 +218,7 @@ void ApplyState(GLState state, ref_ptr program) ApplyTextures(state, program); ApplyBlending(state, program); GLFunctions::glDepthFunc(state.GetDepthFunction()); + GLFunctions::glLineWidth(state.GetLineWidth()); } } diff --git a/drape/glstate.hpp b/drape/glstate.hpp index 661461ebf4..cf42cec1e4 100644 --- a/drape/glstate.hpp +++ b/drape/glstate.hpp @@ -69,6 +69,8 @@ public: bool GetDrawAsLine() const; void SetDrawAsLine(bool drawAsLine); + int GetLineWidth() const; + void SetLineWidth(int width); bool operator<(GLState const & other) const; bool operator==(GLState const & other) const; @@ -86,6 +88,7 @@ private: ref_ptr m_maskTexture; bool m_drawAsLine; + int m_lineWidth; }; void ApplyUniforms(UniformValuesStorage const & uniforms, ref_ptr program); diff --git a/drape/support_manager.cpp b/drape/support_manager.cpp index 812bbe693e..516f5fa41b 100644 --- a/drape/support_manager.cpp +++ b/drape/support_manager.cpp @@ -3,6 +3,8 @@ #include "base/logging.hpp" +#include "std/algorithm.hpp" + #include "3party/Alohalytics/src/alohalytics.h" namespace dp @@ -43,6 +45,9 @@ void SupportManager::Init() m_isTegra = (renderer.find("Tegra") != string::npos); if (m_isTegra) LOG(LINFO, ("NVidia Tegra device detected.")); + + m_maxLineWidth = max(1, GLFunctions::glGetMaxLineWidth()); + LOG(LINFO, ("Max line width =", m_maxLineWidth)); } bool SupportManager::IsSamsungGoogleNexus() const @@ -60,6 +65,11 @@ bool SupportManager::IsTegraDevice() const return m_isTegra; } +int SupportManager::GetMaxLineWidth() const +{ + return m_maxLineWidth; +} + SupportManager & SupportManager::Instance() { static SupportManager manager; diff --git a/drape/support_manager.hpp b/drape/support_manager.hpp index ec45097d84..bac71bd2e1 100644 --- a/drape/support_manager.hpp +++ b/drape/support_manager.hpp @@ -17,6 +17,8 @@ public: bool IsAdreno200Device() const; bool IsTegraDevice() const; + int GetMaxLineWidth() const; + private: SupportManager() = default; ~SupportManager() = default; @@ -24,6 +26,8 @@ private: bool m_isSamsungGoogleNexus = false; bool m_isAdreno200 = false; bool m_isTegra = false; + + int m_maxLineWidth = 1; }; } // namespace dp diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 4acaa2810c..b5982bca70 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -37,6 +37,9 @@ double const kMinVisibleFontSize = 8.0; string const kStarSymbol = "★"; string const kPriceSymbol = "$"; +int const kLineSimplifyLevelStart = 10; +int const kLineSimplifyLevelEnd = 12; + dp::Color ToDrapeColor(uint32_t src) { return dp::Extract(src, 255 - (src >> 24)); @@ -107,8 +110,7 @@ private: }; #endif -void Extract(::LineDefProto const * lineRule, - df::LineViewParams & params) +void Extract(::LineDefProto const * lineRule, df::LineViewParams & params) { float const scale = df::VisualParams::Instance().GetVisualScale(); params.m_color = ToDrapeColor(lineRule->color()); @@ -612,11 +614,12 @@ void ApplyAreaFeature::ProcessRule(Stylist::TRuleWrapper const & rule) ApplyLineFeature::ApplyLineFeature(m2::PointD const & tileCenter, double currentScaleGtoP, TInsertShapeFn const & insertShape, FeatureID const & id, m2::RectD const & clipRect, int minVisibleScale, uint8_t rank, - CaptionDescription const & captions, bool simplify, size_t pointsCount) + CaptionDescription const & captions, int zoomLevel, size_t pointsCount) : TBase(tileCenter, insertShape, id, minVisibleScale, rank, captions) , m_currentScaleGtoP(currentScaleGtoP) , m_sqrScale(math::sqr(m_currentScaleGtoP)) - , m_simplify(simplify) + , m_simplify(zoomLevel >= kLineSimplifyLevelStart && zoomLevel <= kLineSimplifyLevelEnd) + , m_zoomLevel(zoomLevel) , m_initialPointsCount(pointsCount) , m_shieldDepth(0.0) , m_shieldRule(nullptr) @@ -727,6 +730,7 @@ void ApplyLineFeature::ProcessRule(Stylist::TRuleWrapper const & rule) params.m_minVisibleScale = m_minVisibleScale; params.m_rank = m_rank; params.m_baseGtoPScale = m_currentScaleGtoP; + params.m_zoomLevel = m_zoomLevel; for (auto const & spline : m_clippedSplines) m_insertShape(make_unique_dp(spline, params)); diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index c41d4ff9a9..a88792e0e4 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -137,7 +137,7 @@ public: ApplyLineFeature(m2::PointD const & tileCenter, double currentScaleGtoP, TInsertShapeFn const & insertShape, FeatureID const & id, m2::RectD const & clipRect, int minVisibleScale, uint8_t rank, - CaptionDescription const & captions, bool simplify, size_t pointsCount); + CaptionDescription const & captions, int zoomLevel, size_t pointsCount); void operator() (m2::PointD const & point); bool HasGeometry() const; @@ -151,6 +151,7 @@ private: double m_sqrScale; m2::PointD m_lastAddedPoint; bool m_simplify; + int m_zoomLevel; size_t m_initialPointsCount; double m_shieldDepth; ShieldRuleProto const * m_shieldRule; diff --git a/drape_frontend/area_shape.cpp b/drape_frontend/area_shape.cpp index d6ab5b0b65..57d82f80f3 100644 --- a/drape_frontend/area_shape.cpp +++ b/drape_frontend/area_shape.cpp @@ -7,11 +7,21 @@ #include "drape/texture_manager.hpp" #include "drape/utils/vertex_decl.hpp" +#include "indexer/map_style_reader.hpp" + #include "base/buffer_vector.hpp" #include "base/logging.hpp" #include "std/algorithm.hpp" +namespace +{ + +float const kLightOutlineColorFactor = 0.8; +float const kDarkOutlineColorFactor = 1.4; + +} // namespace + namespace df { @@ -24,10 +34,13 @@ AreaShape::AreaShape(vector && triangleList, BuildingOutline && buil void AreaShape::Draw(ref_ptr batcher, ref_ptr textures) const { + auto const style = GetStyleReader().GetCurrentStyle(); + float const colorFactor = (style == MapStyleDark) ? kDarkOutlineColorFactor : kLightOutlineColorFactor; + dp::TextureManager::ColorRegion region; textures->GetColorRegion(m_params.m_color, region); dp::TextureManager::ColorRegion outlineRegion; - textures->GetColorRegion(m_params.m_color * 0.75, outlineRegion); + textures->GetColorRegion(m_params.m_color * colorFactor, outlineRegion); ASSERT_EQUAL(region.GetTexture(), outlineRegion.GetTexture(), ()); if (m_params.m_is3D) @@ -111,7 +124,7 @@ void AreaShape::DrawArea3D(ref_ptr batcher, m2::PointD const & colo vertexes.emplace_back(gpu::Area3dVertex(glsl::vec3(endPt, -m_params.m_posZ), normal, uv)); } - glsl::vec3 normal(0.0f, 0.0f, -1.0f); + glsl::vec3 const normal(0.0f, 0.0f, -1.0f); for (auto const & vertex : m_vertexes) { glsl::vec2 const pt = glsl::ToVec2(ConvertToLocal(vertex, m_params.m_tileCenter, kShapeCoordScalar)); diff --git a/drape_frontend/line_shape.cpp b/drape_frontend/line_shape.cpp index 8130117f56..4f92d2e266 100644 --- a/drape_frontend/line_shape.cpp +++ b/drape_frontend/line_shape.cpp @@ -1,14 +1,18 @@ #include "drape_frontend/line_shape.hpp" #include "drape_frontend/line_shape_helper.hpp" +#include "drape_frontend/visual_params.hpp" -#include "drape/utils/vertex_decl.hpp" +#include "drape/attribute_provider.hpp" +#include "drape/batcher.hpp" #include "drape/glsl_types.hpp" #include "drape/glsl_func.hpp" #include "drape/shader_def.hpp" -#include "drape/attribute_provider.hpp" -#include "drape/batcher.hpp" +#include "drape/support_manager.hpp" #include "drape/texture_manager.hpp" +#include "drape/utils/vertex_decl.hpp" + +#include "indexer/scales.hpp" #include "base/logging.hpp" @@ -263,6 +267,36 @@ private: TCapBuffer m_capGeometry; }; +class SimpleSolidLineBuilder : public BaseLineBuilder +{ + using TBase = BaseLineBuilder; + +public: + using BuilderParams = BaseBuilderParams; + + SimpleSolidLineBuilder(BuilderParams const & params, size_t pointsInSpline, int lineWidth) + : TBase(params, pointsInSpline, 0) + , m_lineWidth(lineWidth) + {} + + dp::GLState GetState() override + { + dp::GLState state(gpu::AREA_OUTLINE_PROGRAM, dp::GLState::GeometryLayer); + state.SetColorTexture(m_params.m_color.GetTexture()); + state.SetDrawAsLine(true); + state.SetLineWidth(m_lineWidth); + return state; + } + + void SubmitVertex(glsl::vec3 const & pivot) + { + m_geometry.emplace_back(V(pivot, m_colorCoord)); + } + +private: + int m_lineWidth; +}; + class DashedLineBuilder : public BaseLineBuilder { using TBase = BaseLineBuilder; @@ -313,6 +347,7 @@ private: LineShape::LineShape(m2::SharedSpline const & spline, LineViewParams const & params) : m_params(params) , m_spline(spline) + , m_isSimple(false) { ASSERT_GREATER(m_spline->GetPath().size(), 1, ()); } @@ -415,11 +450,44 @@ void LineShape::Construct(SolidLineBuilder & builder) const } } +// Specialization optimized for simple solid lines. +template <> +void LineShape::Construct(SimpleSolidLineBuilder & builder) const +{ + vector const & path = m_spline->GetPath(); + ASSERT_GREATER(path.size(), 1, ()); + + // Build geometry. + for (size_t i = 0; i < path.size(); ++i) + { + glsl::vec2 const p = glsl::ToVec2(ConvertToLocal(path[i], m_params.m_tileCenter, kShapeCoordScalar)); + builder.SubmitVertex(glsl::vec3(p, m_params.m_depth)); + } +} + +bool LineShape::CanBeSimplified(int & lineWidth) const +{ + // Disable simplification for world map. + if (m_params.m_zoomLevel > 0 && m_params.m_zoomLevel <= scales::GetUpperCountryScale()) + return false; + + static float width = min(2.5f, static_cast(dp::SupportManager::Instance().GetMaxLineWidth())); + if (m_params.m_width <= width) + { + lineWidth = max(1, static_cast(m_params.m_width)); + return true; + } + + lineWidth = 1; + return false; +} + void LineShape::Prepare(ref_ptr textures) const { + float const pxHalfWidth = m_params.m_width / 2.0f; + dp::TextureManager::ColorRegion colorRegion; textures->GetColorRegion(m_params.m_color, colorRegion); - float const pxHalfWidth = m_params.m_width / 2.0f; auto commonParamsBuilder = [&](BaseBuilderParams & p) { @@ -432,12 +500,25 @@ void LineShape::Prepare(ref_ptr textures) const if (m_params.m_pattern.empty()) { - SolidLineBuilder::BuilderParams p; - commonParamsBuilder(p); + int lineWidth = 1; + m_isSimple = CanBeSimplified(lineWidth); + if (m_isSimple) + { + SimpleSolidLineBuilder::BuilderParams p; + commonParamsBuilder(p); - auto builder = make_unique(p, m_spline->GetPath().size()); - Construct(*builder); - m_lineShapeInfo = move(builder); + auto builder = make_unique(p, m_spline->GetPath().size(), lineWidth); + Construct(*builder); + m_lineShapeInfo = move(builder); + } + else + { + SolidLineBuilder::BuilderParams p; + commonParamsBuilder(p); + auto builder = make_unique(p, m_spline->GetPath().size()); + Construct(*builder); + m_lineShapeInfo = move(builder); + } } else { @@ -463,25 +544,31 @@ void LineShape::Draw(ref_ptr batcher, ref_ptr t ASSERT(m_lineShapeInfo != nullptr, ()); dp::GLState state = m_lineShapeInfo->GetState(); - dp::AttributeProvider provider(1, m_lineShapeInfo->GetLineSize()); provider.InitStream(0, m_lineShapeInfo->GetBindingInfo(), m_lineShapeInfo->GetLineData()); - batcher->InsertListOfStrip(state, make_ref(&provider), dp::Batcher::VertexPerQuad); - - size_t joinSize = m_lineShapeInfo->GetJoinSize(); - if (joinSize > 0) + if (!m_isSimple) { - dp::AttributeProvider joinsProvider(1, joinSize); - joinsProvider.InitStream(0, m_lineShapeInfo->GetBindingInfo(), m_lineShapeInfo->GetJoinData()); - batcher->InsertTriangleList(state, make_ref(&joinsProvider)); + batcher->InsertListOfStrip(state, make_ref(&provider), dp::Batcher::VertexPerQuad); + + size_t const joinSize = m_lineShapeInfo->GetJoinSize(); + if (joinSize > 0) + { + dp::AttributeProvider joinsProvider(1, joinSize); + joinsProvider.InitStream(0, m_lineShapeInfo->GetBindingInfo(), m_lineShapeInfo->GetJoinData()); + batcher->InsertTriangleList(state, make_ref(&joinsProvider)); + } + + size_t const capSize = m_lineShapeInfo->GetCapSize(); + if (capSize > 0) + { + dp::AttributeProvider capProvider(1, capSize); + capProvider.InitStream(0, m_lineShapeInfo->GetCapBindingInfo(), m_lineShapeInfo->GetCapData()); + batcher->InsertListOfStrip(m_lineShapeInfo->GetCapState(), make_ref(&capProvider), dp::Batcher::VertexPerQuad); + } } - - size_t capSize = m_lineShapeInfo->GetCapSize(); - if (capSize > 0) + else { - dp::AttributeProvider capProvider(1, capSize); - capProvider.InitStream(0, m_lineShapeInfo->GetCapBindingInfo(), m_lineShapeInfo->GetCapData()); - batcher->InsertListOfStrip(m_lineShapeInfo->GetCapState(), make_ref(&capProvider), dp::Batcher::VertexPerQuad); + batcher->InsertLineStrip(state, make_ref(&provider)); } } diff --git a/drape_frontend/line_shape.hpp b/drape_frontend/line_shape.hpp index b1f583e645..fee0c814ec 100644 --- a/drape_frontend/line_shape.hpp +++ b/drape_frontend/line_shape.hpp @@ -45,9 +45,12 @@ private: template void Construct(TBuilder & builder) const; + bool CanBeSimplified(int & lineWidth) const; + LineViewParams m_params; m2::SharedSpline m_spline; mutable unique_ptr m_lineShapeInfo; + mutable bool m_isSimple; }; } // namespace df diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index 84ad111adc..ce9fa8fe10 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -44,9 +44,6 @@ df::BaseApplyFeature::HotelData ExtractHotelData(FeatureType const & f) namespace df { -int const kLineSimplifyLevelStart = 10; -int const kLineSimplifyLevelEnd = 12; - RuleDrawer::RuleDrawer(TDrawerCallback const & fn, TCheckCancelledCallback const & checkCancelled, TIsCountryLoadedByNameFn const & isLoadedFn, @@ -237,11 +234,9 @@ void RuleDrawer::operator()(FeatureType const & f) } else if (s.LineStyleExists()) { - ApplyLineFeature apply(m_globalRect.Center(), m_currentScaleGtoP, - insertShape, f.GetID(), m_globalRect, minVisibleScale, - f.GetRank(), s.GetCaptionDescription(), - zoomLevel >= kLineSimplifyLevelStart && zoomLevel <= kLineSimplifyLevelEnd, - f.GetPointsCount()); + ApplyLineFeature apply(m_globalRect.Center(), m_currentScaleGtoP, insertShape, f.GetID(), + m_globalRect, minVisibleScale, f.GetRank(), s.GetCaptionDescription(), + zoomLevel, f.GetPointsCount()); f.ForEachPoint(apply, zoomLevel); if (CheckCancelled()) diff --git a/drape_frontend/shape_view_params.hpp b/drape_frontend/shape_view_params.hpp index f5c084c288..6341e80829 100644 --- a/drape_frontend/shape_view_params.hpp +++ b/drape_frontend/shape_view_params.hpp @@ -63,6 +63,7 @@ struct LineViewParams : CommonViewParams dp::LineJoin m_join; buffer_vector m_pattern; float m_baseGtoPScale = 1.0f; + int m_zoomLevel = -1; }; struct TextViewParams : CommonViewParams