From cd1ef15605f819f44913c5b76136c07a7680e89e Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Thu, 14 Jul 2016 17:10:00 +0300 Subject: [PATCH] Added arrow shadow --- drape/drape.pro | 2 + .../arrow3d_shadow_fragment_shader.fsh | 24 +++++ .../shaders/arrow3d_shadow_vertex_shader.vsh | 13 +++ drape/shaders/shader_index.txt | 1 + drape_frontend/arrow3d.cpp | 92 ++++++++++--------- drape_frontend/arrow3d.hpp | 12 +-- drape_frontend/my_position.cpp | 14 +-- drape_frontend/my_position.hpp | 4 +- 8 files changed, 100 insertions(+), 62 deletions(-) create mode 100644 drape/shaders/arrow3d_shadow_fragment_shader.fsh create mode 100644 drape/shaders/arrow3d_shadow_vertex_shader.vsh diff --git a/drape/drape.pro b/drape/drape.pro index 0678215e26..e9c3bea4e1 100644 --- a/drape/drape.pro +++ b/drape/drape.pro @@ -16,6 +16,8 @@ OTHER_FILES += \ shaders/area_vertex_shader.vsh \ shaders/arrow3d_fragment_shader.fsh \ shaders/arrow3d_vertex_shader.vsh \ + shaders/arrow3d_shadow_fragment_shader.fsh \ + shaders/arrow3d_shadow_vertex_shader.vsh \ shaders/circle_shader.fsh \ shaders/circle_shader.vsh \ shaders/compass_vertex_shader.vsh \ diff --git a/drape/shaders/arrow3d_shadow_fragment_shader.fsh b/drape/shaders/arrow3d_shadow_fragment_shader.fsh new file mode 100644 index 0000000000..52b57d1247 --- /dev/null +++ b/drape/shaders/arrow3d_shadow_fragment_shader.fsh @@ -0,0 +1,24 @@ +varying float v_intensity; + +#ifdef SAMSUNG_GOOGLE_NEXUS +uniform sampler2D u_colorTex; +#endif + +uniform vec4 u_color; + +void main() +{ +#ifdef SAMSUNG_GOOGLE_NEXUS + // Because of a bug in OpenGL driver on Samsung Google Nexus this workaround is here. + const float kFakeColorScalar = 0.0; + lowp vec4 fakeColor = texture2D(u_colorTex, vec2(0.0, 0.0)) * kFakeColorScalar; +#endif + + vec4 resColor = vec4(u_color.rgb, u_color.a * v_intensity); + +#ifdef SAMSUNG_GOOGLE_NEXUS + gl_FragColor = resColor + fakeColor; +#else + gl_FragColor = resColor; +#endif +} diff --git a/drape/shaders/arrow3d_shadow_vertex_shader.vsh b/drape/shaders/arrow3d_shadow_vertex_shader.vsh new file mode 100644 index 0000000000..26656d8e46 --- /dev/null +++ b/drape/shaders/arrow3d_shadow_vertex_shader.vsh @@ -0,0 +1,13 @@ +attribute vec4 a_pos; +attribute vec3 a_normal; + +uniform mat4 m_transform; + +varying float v_intensity; + +void main() +{ + vec4 position = m_transform * vec4(a_pos.x, a_pos.y, 0.0, 1.0); + v_intensity = a_pos.w; + gl_Position = position; +} diff --git a/drape/shaders/shader_index.txt b/drape/shaders/shader_index.txt index ab22b90d05..e269c386fc 100644 --- a/drape/shaders/shader_index.txt +++ b/drape/shaders/shader_index.txt @@ -21,6 +21,7 @@ TRACK_POINT_PROGRAM trackpoint_vertex_shader.vsh trackpoint_fragment_shader.fsh DEBUG_RECT_PROGRAM debug_rect_vertex_shader.vsh debug_rect_fragment_shader.fsh TRANSPARENT_LAYER_PROGRAM transparent_layer_vertex_shader.vsh transparent_layer_fragment_shader.fsh ARROW_3D_PROGRAM arrow3d_vertex_shader.vsh arrow3d_fragment_shader.fsh +ARROW_3D_SHADOW_PROGRAM arrow3d_shadow_vertex_shader.vsh arrow3d_shadow_fragment_shader.fsh TEXTURING_BILLBOARD_PROGRAM texturing_billboard_vertex_shader.vsh texturing_fragment_shader.fsh MASKED_TEXTURING_BILLBOARD_PROGRAM masked_texturing_billboard_vertex_shader.vsh masked_texturing_fragment_shader.fsh TEXT_OUTLINED_BILLBOARD_PROGRAM text_outlined_billboard_vertex_shader.vsh text_fragment_shader.fsh diff --git a/drape_frontend/arrow3d.cpp b/drape_frontend/arrow3d.cpp index 5453040db5..ef413eda02 100644 --- a/drape_frontend/arrow3d.cpp +++ b/drape_frontend/arrow3d.cpp @@ -91,34 +91,20 @@ void Arrow3d::SetAzimuth(double azimuth) m_azimuth = azimuth; } -void Arrow3d::SetSize(uint32_t width, uint32_t height) -{ - m_pixelWidth = width; - m_pixelHeight = height; -} - void Arrow3d::SetTexture(ref_ptr texMng) { m_state.SetColorTexture(texMng->GetSymbolsTexture()); } -void Arrow3d::Build(ref_ptr prg) +void Arrow3d::Build() { m_bufferId = GLFunctions::glGenBuffer(); GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); - - m_attributePosition = prg->GetAttributeLocation("a_pos"); - ASSERT_NOT_EQUAL(m_attributePosition, -1, ()); - GLFunctions::glBufferData(gl_const::GLArrayBuffer, m_vertices.size() * sizeof(m_vertices[0]), m_vertices.data(), gl_const::GLStaticDraw); m_bufferNormalsId = GLFunctions::glGenBuffer(); GLFunctions::glBindBuffer(m_bufferNormalsId, gl_const::GLArrayBuffer); - - m_attributeNormal = prg->GetAttributeLocation("a_normal"); - ASSERT_NOT_EQUAL(m_attributeNormal, -1, ()); - GLFunctions::glBufferData(gl_const::GLArrayBuffer, m_normals.size() * sizeof(m_normals[0]), m_normals.data(), gl_const::GLStaticDraw); @@ -136,17 +122,58 @@ void Arrow3d::Render(ScreenBase const & screen, ref_ptr m if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject)) GLFunctions::glBindVertexArray(0); - ref_ptr prg = mng->GetProgram(gpu::ARROW_3D_PROGRAM); - prg->Bind(); - if (!m_isInitialized) { - Build(prg); + Build(); m_isInitialized = true; } - dp::ApplyState(m_state, prg); + // Render shadow. + if (screen.isPerspective()) + { + ref_ptr shadowProgram = mng->GetProgram(gpu::ARROW_3D_SHADOW_PROGRAM); + RenderArrow(screen, shadowProgram, dp::Color(60, 60, 60, 60), 0.05f); + } + // Render arrow. + ref_ptr arrowProgram = mng->GetProgram(gpu::ARROW_3D_PROGRAM); + RenderArrow(screen, arrowProgram, + df::GetColorConstant(GetStyleReader().GetCurrentStyle(), + m_obsoletePosition ? df::Arrow3DObsolete : df::Arrow3D), 0.0f); + + arrowProgram->Unbind(); + GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); +} + +void Arrow3d::RenderArrow(ScreenBase const & screen, ref_ptr program, + dp::Color const & color, float dz) +{ + program->Bind(); + + GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); + uint32_t const attributePosition = program->GetAttributeLocation("a_pos"); + ASSERT_NOT_EQUAL(attributePosition, -1, ()); + GLFunctions::glEnableVertexAttribute(attributePosition); + GLFunctions::glVertexAttributePointer(attributePosition, 4, gl_const::GLFloatType, false, 0, 0); + + GLFunctions::glBindBuffer(m_bufferNormalsId, gl_const::GLArrayBuffer); + uint32_t const attributeNormal = program->GetAttributeLocation("a_normal"); + ASSERT_NOT_EQUAL(attributeNormal, -1, ()); + GLFunctions::glEnableVertexAttribute(attributeNormal); + GLFunctions::glVertexAttributePointer(attributeNormal, 3, gl_const::GLFloatType, false, 0, 0); + + dp::UniformValuesStorage uniforms; + math::Matrix const modelTransform = CalculateTransform(screen, dz); + uniforms.SetMatrix4x4Value("m_transform", modelTransform.m_data); + glsl::vec4 const c = glsl::ToVec4(color); + uniforms.SetFloatValue("u_color", c.r, c.g, c.b, c.a); + dp::ApplyState(m_state, program); + dp::ApplyUniforms(uniforms, program); + GLFunctions::glDrawArrays(gl_const::GLTriangles, 0, m_vertices.size() / 4); +} + +math::Matrix Arrow3d::CalculateTransform(ScreenBase const & screen, float dz) const +{ static double const kLog2 = log(2.0); double const kMaxZoom = scales::UPPER_STYLE_SCALE + 1.0; double const zoomLevel = my::clamp(fabs(log(screen.GetScale()) / kLog2), kArrow3dMinZoom, kMaxZoom); @@ -175,32 +202,13 @@ void Arrow3d::Render(ScreenBase const & screen, ref_ptr m math::Matrix translateM = math::Identity(); translateM(3, 0) = dX; translateM(3, 1) = -dY; + translateM(3, 2) = dz; math::Matrix modelTransform = rotateM * scaleM * translateM; if (screen.isPerspective()) - modelTransform = modelTransform * math::Matrix(screen.Pto3dMatrix()); + return modelTransform * math::Matrix(screen.Pto3dMatrix()); - dp::UniformValuesStorage uniforms; - uniforms.SetMatrix4x4Value("m_transform", modelTransform.m_data); - - glsl::vec4 const color = glsl::ToVec4(df::GetColorConstant(GetStyleReader().GetCurrentStyle(), - m_obsoletePosition ? df::Arrow3DObsolete : df::Arrow3D)); - uniforms.SetFloatValue("u_color", color.r, color.g, color.b, color.a); - - dp::ApplyUniforms(uniforms, prg); - - GLFunctions::glBindBuffer(m_bufferId, gl_const::GLArrayBuffer); - GLFunctions::glEnableVertexAttribute(m_attributePosition); - GLFunctions::glVertexAttributePointer(m_attributePosition, 4, gl_const::GLFloatType, false, 0, 0); - - GLFunctions::glBindBuffer(m_bufferNormalsId, gl_const::GLArrayBuffer); - GLFunctions::glEnableVertexAttribute(m_attributeNormal); - GLFunctions::glVertexAttributePointer(m_attributeNormal, 3, gl_const::GLFloatType, false, 0, 0); - - GLFunctions::glDrawArrays(gl_const::GLTriangles, 0, m_vertices.size() / 4); - - prg->Unbind(); - GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); + return modelTransform; } } // namespace df diff --git a/drape_frontend/arrow3d.hpp b/drape_frontend/arrow3d.hpp index 738c344a73..c6916e4197 100644 --- a/drape_frontend/arrow3d.hpp +++ b/drape_frontend/arrow3d.hpp @@ -27,28 +27,24 @@ public: void SetPosition(m2::PointD const & position); void SetAzimuth(double azimuth); - void SetSize(uint32_t width, uint32_t height); void SetTexture(ref_ptr texMng); void SetPositionObsolete(bool obsolete); void Render(ScreenBase const & screen, ref_ptr mng); private: - void Build(ref_ptr prg); + void Build(); + math::Matrix CalculateTransform(ScreenBase const & screen, float dz) const; + void RenderArrow(ScreenBase const & screen, ref_ptr program, + dp::Color const & color, float dz); m2::PointD m_position; double m_azimuth = 0.0; bool m_obsoletePosition = false; - uint32_t m_pixelWidth = 0; - uint32_t m_pixelHeight = 0; - uint32_t m_bufferId = 0; uint32_t m_bufferNormalsId = 0; - int8_t m_attributePosition; - int8_t m_attributeNormal; - vector m_vertices; vector m_normals; diff --git a/drape_frontend/my_position.cpp b/drape_frontend/my_position.cpp index 0724e478dd..358f34a6fa 100644 --- a/drape_frontend/my_position.cpp +++ b/drape_frontend/my_position.cpp @@ -117,7 +117,6 @@ void MyPosition::RenderMyPosition(ScreenBase const & screen, { m_arrow3d.SetPosition(m_position); m_arrow3d.SetAzimuth(m_azimuth); - m_arrow3d.Render(screen, mng); } else @@ -198,13 +197,10 @@ void MyPosition::CacheSymbol(dp::TextureManager::SymbolRegion const & symbol, void MyPosition::CachePointPosition(ref_ptr mng) { - int const kSymbolsCount = 3; - dp::TextureManager::SymbolRegion pointSymbol, arrowSymbol, arrowGraySymbol; + int const kSymbolsCount = 1; + dp::TextureManager::SymbolRegion pointSymbol; mng->GetSymbolRegion("current-position", pointSymbol); - mng->GetSymbolRegion("current-position-compas", arrowSymbol); - mng->GetSymbolRegion("current-position-obsolete", arrowGraySymbol); - m_arrow3d.SetSize(arrowSymbol.GetPixelSize().x, arrowSymbol.GetPixelSize().y); m_arrow3d.SetTexture(mng); ASSERT(pointSymbol.GetTexture() == arrowSymbol.GetTexture(), ()); @@ -212,8 +208,8 @@ void MyPosition::CachePointPosition(ref_ptr mng) dp::GLState state(gpu::MY_POSITION_PROGRAM, dp::GLState::OverlayLayer); state.SetColorTexture(pointSymbol.GetTexture()); - dp::TextureManager::SymbolRegion * symbols[kSymbolsCount] = { &pointSymbol, &arrowSymbol, &arrowGraySymbol }; - EMyPositionPart partIndices[kSymbolsCount] = { MY_POSITION_POINT, MY_POSITION_ARROW, MY_POSITION_ARROW_GRAY }; + dp::TextureManager::SymbolRegion * symbols[kSymbolsCount] = { &pointSymbol }; + EMyPositionPart partIndices[kSymbolsCount] = { MY_POSITION_POINT }; { dp::Batcher batcher(kSymbolsCount * dp::Batcher::IndexPerQuad, kSymbolsCount * dp::Batcher::VertexPerQuad); dp::SessionGuard guard(batcher, [this](dp::GLState const & state, drape_ptr && b) @@ -241,4 +237,4 @@ void MyPosition::RenderPart(ref_ptr mng, m_nodes[p.second].Render(mng, uniforms, p.first); } -} +} // namespace df diff --git a/drape_frontend/my_position.hpp b/drape_frontend/my_position.hpp index 17cfd78fba..65abf0b176 100644 --- a/drape_frontend/my_position.hpp +++ b/drape_frontend/my_position.hpp @@ -44,9 +44,7 @@ private: { // don't change order and values MY_POSITION_ACCURACY = 0, - MY_POSITION_ARROW = 1, - MY_POSITION_POINT = 2, - MY_POSITION_ARROW_GRAY = 3 + MY_POSITION_POINT = 1, }; void RenderPart(ref_ptr mng,