diff --git a/drape_frontend/arrow3d.cpp b/drape_frontend/arrow3d.cpp index 82e3c9d9e0..3fcf06b67f 100644 --- a/drape_frontend/arrow3d.cpp +++ b/drape_frontend/arrow3d.cpp @@ -121,7 +121,8 @@ void Arrow3d::RenderArrow(ref_ptr context, ref_ptr const modelTransform = CalculateTransform(screen, dz, scaleFactor); + math::Matrix const modelTransform = CalculateTransform(screen, dz, scaleFactor, + context->GetApiVersion()); params.m_transform = glsl::make_mat4(modelTransform.m_data); params.m_color = glsl::ToVec4(color); @@ -130,7 +131,7 @@ void Arrow3d::RenderArrow(ref_ptr context, ref_ptr Arrow3d::CalculateTransform(ScreenBase const & screen, float dz, - float scaleFactor) const + float scaleFactor, dp::ApiVersion apiVersion) const { double arrowScale = VisualParams::Instance().GetVisualScale() * kArrowSize * scaleFactor; if (screen.isPerspective()) @@ -167,6 +168,12 @@ math::Matrix Arrow3d::CalculateTransform(ScreenBase const & screen, if (screen.isPerspective()) return modelTransform * math::Matrix(screen.Pto3dMatrix()); + if (apiVersion == dp::ApiVersion::Metal) + { + modelTransform(3, 2) = modelTransform(3, 2) + 0.5f; + modelTransform(2, 2) = modelTransform(2, 2) * 0.5f; + } + return modelTransform; } } // namespace df diff --git a/drape_frontend/arrow3d.hpp b/drape_frontend/arrow3d.hpp index 97b5e2f619..25f63fd6aa 100644 --- a/drape_frontend/arrow3d.hpp +++ b/drape_frontend/arrow3d.hpp @@ -40,7 +40,7 @@ public: private: math::Matrix CalculateTransform(ScreenBase const & screen, float dz, - float scaleFactor) const; + float scaleFactor, dp::ApiVersion apiVersion) const; void RenderArrow(ref_ptr context, ref_ptr mng, dp::MeshObject & mesh, ScreenBase const & screen, gpu::Program program, dp::Color const & color, float dz, float scaleFactor); diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 8e6c31c4f7..b4a9fb5edf 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -359,7 +359,6 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::Type::MapShapes: { - if (m_apiVersion == dp::ApiVersion::Metal) return; // TODO(@darina, @rokuz): TEMPORARY ref_ptr msg = message; CHECK(m_context != nullptr, ()); m_myPositionController->SetRenderShape(m_context, m_texMng, msg->AcceptShape()); diff --git a/shaders/Metal/arrow3d.metal b/shaders/Metal/arrow3d.metal new file mode 100644 index 0000000000..663eb06b5a --- /dev/null +++ b/shaders/Metal/arrow3d.metal @@ -0,0 +1,72 @@ +#include +#include +using namespace metal; + +typedef struct +{ + float4x4 u_transform; + float4 u_color; +} Uniforms_T; + +typedef struct +{ + float4 a_position [[attribute(0)]]; + float3 a_normal [[attribute(1)]]; +} Vertex_T; + +typedef struct +{ + float4 position [[position]]; + float2 intensity; +} Fragment_T; + +typedef struct +{ + float4 a_position [[attribute(0)]]; +} VertexShadow_T; + +typedef struct +{ + float4 position [[position]]; + float intensity; +} FragmentShadow_T; + +vertex Fragment_T vsArrow3d(const Vertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(2)]]) +{ + constexpr float3 kLightDir = float3(0.316, 0.0, 0.948); + + Fragment_T out; + out.position = uniforms.u_transform * float4(in.a_position.xyz, 1.0); + out.intensity = float2(max(0.0, -dot(kLightDir, in.a_normal)), in.a_position.w); + return out; +} + +fragment float4 fsArrow3d(const Fragment_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(0)]]) +{ + float alpha = smoothstep(0.8, 1.0, in.intensity.y); + return float4((in.intensity.x * 0.5 + 0.5) * uniforms.u_color.rgb, uniforms.u_color.a * alpha); +} + +fragment float4 fsArrow3dOutline(const FragmentShadow_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(0)]]) +{ + float alpha = smoothstep(0.7, 1.0, in.intensity); + return float4(uniforms.u_color.rgb, uniforms.u_color.a * alpha); +} + +vertex FragmentShadow_T vsArrow3dShadow(const VertexShadow_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]]) +{ + FragmentShadow_T out; + out.position = uniforms.u_transform * float4(in.a_position.xy, 0.0, 1.0); + out.intensity = in.a_position.w; + return out; +} + +fragment float4 fsArrow3dShadow(const FragmentShadow_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(0)]]) +{ + return float4(uniforms.u_color.rgb, uniforms.u_color.a * in.intensity); +} diff --git a/shaders/Metal/screen_quad.metal b/shaders/Metal/screen_quad.metal index c864387d6b..0e5695024f 100644 --- a/shaders/Metal/screen_quad.metal +++ b/shaders/Metal/screen_quad.metal @@ -23,7 +23,7 @@ vertex Fragment_T vsScreenQuad(const Vertex_T in [[stage_in]]) { Fragment_T out; out.position = float4(in.a_position, 0.0, 1.0); - out.texCoords = in.a_texCoords; + out.texCoords = float2(in.a_texCoords.x, 1.0 - in.a_texCoords.y); return out; } diff --git a/shaders/Metal/shaders_lib.h b/shaders/Metal/shaders_lib.h new file mode 100644 index 0000000000..83c2bd0a31 --- /dev/null +++ b/shaders/Metal/shaders_lib.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +using namespace metal; + +float4 ApplyPivotTransform(float4 pivot, float4x4 pivotTransform, float pivotRealZ) +{ + float4 transformedPivot = pivot; + float w = transformedPivot.w; + transformedPivot.xyw = (pivotTransform * float4(transformedPivot.xy, pivotRealZ, w)).xyw; + transformedPivot.z *= transformedPivot.w / w; + return transformedPivot; +} diff --git a/shaders/Metal/shapes.metal b/shaders/Metal/shapes.metal new file mode 100644 index 0000000000..c54a6f2755 --- /dev/null +++ b/shaders/Metal/shapes.metal @@ -0,0 +1,93 @@ +#include +#include +#include "shaders_lib.h" + +using namespace metal; + +typedef struct +{ + float4x4 u_modelView; + float4x4 u_projection; + float4x4 u_pivotTransform; + packed_float3 u_position; + float u_accuracy; + float u_zScale; + float u_opacity; + float u_azimut; +} Uniforms_T; + +typedef struct +{ + float2 a_normal [[attribute(0)]]; + float2 a_colorTexCoords [[attribute(1)]]; +} Vertex_T; + +typedef struct +{ + float4 position [[position]]; + half4 color; +} FragmentAccuracy_T; + +typedef struct +{ + float4 position [[position]]; + float2 colorTexCoords; +} FragmentMyPosition_T; + +vertex FragmentAccuracy_T vsAccuracy(const Vertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]], + texture2d u_colorTex [[texture(0)]], + sampler u_colorTexSampler [[sampler(0)]]) +{ + float3 uPosition = uniforms.u_position; + float4 position = float4(uPosition.xy, 0.0, 1.0) * uniforms.u_modelView; + float4 normal = float4(0.0, 0.0, 0.0, 0.0); + if (dot(in.a_normal, in.a_normal) != 0.0) + normal = float4(normalize(in.a_normal) * uniforms.u_accuracy, 0.0, 0.0); + position = (position + normal) * uniforms.u_projection; + + FragmentAccuracy_T out; + out.position = ApplyPivotTransform(position, uniforms.u_pivotTransform, uPosition.z * uniforms.u_zScale); + half4 color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoords); + color.a *= uniforms.u_opacity; + out.color = color; + return out; +} + +fragment half4 fsAccuracy(const FragmentAccuracy_T in [[stage_in]]) +{ + return in.color; +} + +vertex FragmentMyPosition_T vsMyPosition(const Vertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]]) +{ + float cosV; + float sinV = sincos(uniforms.u_azimut, cosV); + + float4x4 rotation; + rotation[0] = float4(cosV, sinV, 0.0, 0.0); + rotation[1] = float4(-sinV, cosV, 0.0, 0.0); + rotation[2] = float4(0.0, 0.0, 1.0, 0.0); + rotation[3] = float4(0.0, 0.0, 0.0, 1.0); + + float4 pos = float4(uniforms.u_position, 1.0) * uniforms.u_modelView; + float4 normal = float4(in.a_normal, 0.0, 0.0); + float4 shiftedPos = normal * rotation + pos; + + FragmentMyPosition_T out; + out.position = ApplyPivotTransform(shiftedPos * uniforms.u_projection, uniforms.u_pivotTransform, 0.0); + out.colorTexCoords = in.a_colorTexCoords; + + return out; +} + +fragment float4 fsMyPosition(const FragmentMyPosition_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(0)]], + texture2d u_colorTex [[texture(0)]], + sampler u_colorTexSampler [[sampler(0)]]) +{ + float4 color = u_colorTex.sample(u_colorTexSampler, in.colorTexCoords); + color.a *= uniforms.u_opacity; + return color; +} diff --git a/shaders/metal_program_pool.mm b/shaders/metal_program_pool.mm index 70e585ae58..49c780e6a3 100644 --- a/shaders/metal_program_pool.mm +++ b/shaders/metal_program_pool.mm @@ -69,8 +69,8 @@ std::array(Program::ProgramsCount)> const kMeta ProgramInfo("", "", {}), // HatchingArea ProgramInfo("vsTexturingGui", "fsTexturingGui", {{0, 1}}), // TexturingGui ProgramInfo("vsRuler", "fsRuler", {{0, 2}}), // Ruler - ProgramInfo("", "", {}), // Accuracy - ProgramInfo("", "", {}), // MyPosition + ProgramInfo("vsAccuracy", "fsAccuracy", {{0, 1}}), // Accuracy + ProgramInfo("vsMyPosition", "fsMyPosition", {{0, 1}}), // MyPosition ProgramInfo("", "", {}), // Transit ProgramInfo("", "", {}), // TransitMarker ProgramInfo("", "", {}), // Route @@ -80,9 +80,9 @@ std::array(Program::ProgramsCount)> const kMeta ProgramInfo("", "", {}), // CirclePoint ProgramInfo("vsDebugRect", "fsDebugRect", {{0, 0}}), // DebugRect ProgramInfo("vsScreenQuad", "fsScreenQuad", {{0, 1}}), // ScreenQuad - ProgramInfo("", "", {}), // Arrow3d - ProgramInfo("", "", {}), // Arrow3dShadow - ProgramInfo("", "", {}), // Arrow3dOutline + ProgramInfo("vsArrow3d", "fsArrow3d", {{0, 0}, {1, 1}}), // Arrow3d + ProgramInfo("vsArrow3dShadow", "fsArrow3dShadow", {{0, 0}}), // Arrow3dShadow + ProgramInfo("vsArrow3dShadow", "fsArrow3dOutline", {{0, 0}}), // Arrow3dOutline ProgramInfo("", "", {}), // ColoredSymbolBillboard ProgramInfo("", "", {}), // TexturingBillboard ProgramInfo("", "", {}), // MaskedTexturingBillboard diff --git a/xcode/shaders/shaders.xcodeproj/project.pbxproj b/xcode/shaders/shaders.xcodeproj/project.pbxproj index 46a63ed36c..226115e6ae 100644 --- a/xcode/shaders/shaders.xcodeproj/project.pbxproj +++ b/xcode/shaders/shaders.xcodeproj/project.pbxproj @@ -35,6 +35,8 @@ 45789EE421353CA3009955CC /* program_manager_metal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45789EE321353CA3009955CC /* program_manager_metal.mm */; }; 45789EE72135464D009955CC /* metal_program_params.mm in Sources */ = {isa = PBXBuildFile; fileRef = 45789EE62135464D009955CC /* metal_program_params.mm */; }; BBF791702146D8EC00D27BD8 /* system.metal in Sources */ = {isa = PBXBuildFile; fileRef = BBF7916F2146D8EC00D27BD8 /* system.metal */; }; + BBF7917321493AFC00D27BD8 /* arrow3d.metal in Sources */ = {isa = PBXBuildFile; fileRef = BBF7917221493AFC00D27BD8 /* arrow3d.metal */; }; + BBF7917521495FF900D27BD8 /* shapes.metal in Sources */ = {isa = PBXBuildFile; fileRef = BBF7917421495FF900D27BD8 /* shapes.metal */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -173,6 +175,9 @@ 45789EE62135464D009955CC /* metal_program_params.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = metal_program_params.mm; sourceTree = ""; }; 4598437C21394BE000F8CAB2 /* shaders_metal.metallib */ = {isa = PBXFileReference; explicitFileType = "archive.metal-library"; includeInIndex = 0; path = shaders_metal.metallib; sourceTree = BUILT_PRODUCTS_DIR; }; BBF7916F2146D8EC00D27BD8 /* system.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = system.metal; sourceTree = ""; }; + BBF7917221493AFC00D27BD8 /* arrow3d.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = arrow3d.metal; sourceTree = ""; }; + BBF7917421495FF900D27BD8 /* shapes.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = shapes.metal; sourceTree = ""; }; + BBF79176214970B600D27BD8 /* shaders_lib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = shaders_lib.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -376,6 +381,9 @@ 4560F582213D44CE00CC736C /* screen_quad.metal */, 4560F5AA2142AC1300CC736C /* gui.metal */, BBF7916F2146D8EC00D27BD8 /* system.metal */, + BBF7917221493AFC00D27BD8 /* arrow3d.metal */, + BBF7917421495FF900D27BD8 /* shapes.metal */, + BBF79176214970B600D27BD8 /* shaders_lib.h */, ); path = Metal; sourceTree = ""; @@ -536,6 +544,8 @@ 4560F5AB2142AC1300CC736C /* gui.metal in Sources */, BBF791702146D8EC00D27BD8 /* system.metal in Sources */, 4560F58A213D57D600CC736C /* debug_rect.metal in Sources */, + BBF7917321493AFC00D27BD8 /* arrow3d.metal in Sources */, + BBF7917521495FF900D27BD8 /* shapes.metal in Sources */, 4560F58B213D57D600CC736C /* screen_quad.metal in Sources */, ); runOnlyForDeploymentPostprocessing = 0;