diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index c7cf9ecca6..f45f644fb6 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -265,7 +265,6 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::Type::FinishTileRead: { - if (m_apiVersion == dp::ApiVersion::Metal) return; // TODO(@darina, @rokuz): TEMPORARY ref_ptr msg = message; bool changed = false; for (auto const & tileKey : msg->GetTiles()) @@ -470,7 +469,6 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::Type::FlushTransitScheme: { - if (m_apiVersion == dp::ApiVersion::Metal) return; // TODO(@darina, @rokuz): TEMPORARY ref_ptr msg = message; auto renderData = msg->AcceptRenderData(); CHECK(m_context != nullptr, ()); diff --git a/drape_frontend/transit_scheme_renderer.cpp b/drape_frontend/transit_scheme_renderer.cpp index a3f7ab0915..a85ac9f7bd 100644 --- a/drape_frontend/transit_scheme_renderer.cpp +++ b/drape_frontend/transit_scheme_renderer.cpp @@ -102,9 +102,11 @@ void TransitSchemeRenderer::AddRenderData(ref_ptr context, PrepareRenderData(context, mng, tree, m_markersRenderData, std::move(renderData)); break; case TransitRenderData::Type::Text: + break; // TODO(@darina): TEMPORARY PrepareRenderData(context, mng, tree, m_textRenderData, std::move(renderData)); break; case TransitRenderData::Type::Stubs: + break; // TODO(@darina): TEMPORARY PrepareRenderData(context, mng, tree, m_colorSymbolRenderData, std::move(renderData)); break; } diff --git a/shaders/GL/transit_marker.fsh.glsl b/shaders/GL/transit_marker.fsh.glsl index 14bea243c0..d50f86528b 100644 --- a/shaders/GL/transit_marker.fsh.glsl +++ b/shaders/GL/transit_marker.fsh.glsl @@ -4,7 +4,6 @@ uniform sampler2D u_colorTex; varying vec4 v_offsets; varying vec4 v_color; -varying float v_scale; void main() { diff --git a/shaders/Metal/shaders_lib.h b/shaders/Metal/shaders_lib.h index cccd8f66dd..23eab3e280 100644 --- a/shaders/Metal/shaders_lib.h +++ b/shaders/Metal/shaders_lib.h @@ -3,6 +3,8 @@ using namespace metal; +constant float kShapeCoordScalar = 1000.0; + float4 ApplyPivotTransform(float4 pivot, float4x4 pivotTransform, float pivotRealZ); // This function calculates transformed position on an axis for line shaders family. diff --git a/shaders/Metal/traffic.metal b/shaders/Metal/traffic.metal new file mode 100644 index 0000000000..87c6fac9e1 --- /dev/null +++ b/shaders/Metal/traffic.metal @@ -0,0 +1,204 @@ +#include +#include +#include "shaders_lib.h" +using namespace metal; + +typedef struct +{ + float4x4 u_modelView; + float4x4 u_projection; + float4x4 u_pivotTransform; + float4 u_trafficParams; + packed_float3 u_outlineColor; + float u_outline; + packed_float3 u_lightArrowColor; + float u_opacity; + packed_float3 u_darkArrowColor; +} Uniforms_T; + +// Traffic + +typedef struct +{ + float3 a_position [[attribute(0)]]; + float4 a_normal [[attribute(1)]]; + float4 a_colorTexCoord [[attribute(2)]]; +} TrafficVertex_T; + +typedef struct +{ + float4 position [[position]]; + float4 color; + float2 maskTexCoord; + float halfLength; +} TrafficFragment_T; + +vertex TrafficFragment_T vsTraffic(const TrafficVertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]], + texture2d u_colorTex [[texture(0)]], + sampler u_colorTexSampler [[sampler(0)]]) +{ + constexpr float kArrowVSize = 0.25; + + TrafficFragment_T out; + + float2 normal = in.a_normal.xy; + float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy; + if (dot(normal, normal) != 0.0) + { + float2 norm = normal * uniforms.u_trafficParams.x; + if (in.a_normal.z < 0.0) + norm = normal * uniforms.u_trafficParams.y; + transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm, + uniforms.u_modelView, length(norm)); + } + + float uOffset = length(float4(kShapeCoordScalar, 0.0, 0.0, 0.0) * uniforms.u_modelView) * in.a_normal.w; + out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord.xy); + float v = mix(in.a_colorTexCoord.z, in.a_colorTexCoord.z + kArrowVSize, 0.5 * in.a_normal.z + 0.5); + out.maskTexCoord = float2(uOffset * uniforms.u_trafficParams.z, v) * uniforms.u_trafficParams.w; + out.maskTexCoord.x *= step(in.a_colorTexCoord.w, out.maskTexCoord.x); + out.halfLength = in.a_normal.z; + float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection; + out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0); + + return out; +} + +fragment float4 fsTraffic(const TrafficFragment_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(0)]], + texture2d u_maskTex [[texture(0)]], + sampler u_maskTexSampler [[sampler(0)]]) +{ + constexpr float kAntialiasingThreshold = 0.92; + + constexpr float kOutlineThreshold1 = 0.8; + constexpr float kOutlineThreshold2 = 0.5; + + constexpr float kMaskOpacity = 0.7; + + float4 color = in.color; + float alphaCode = color.a; + float4 mask = u_maskTex.sample(u_maskTexSampler, in.maskTexCoord); + color.a = uniforms.u_opacity * (1.0 - smoothstep(kAntialiasingThreshold, 1.0, abs(in.halfLength))); + color.rgb = mix(color.rgb, mask.rgb * mix(uniforms.u_lightArrowColor, uniforms.u_darkArrowColor, step(alphaCode, 0.6)), mask.a * kMaskOpacity); + if (uniforms.u_outline > 0.0) + { + color.rgb = mix(color.rgb, uniforms.u_outlineColor, step(kOutlineThreshold1, abs(in.halfLength))); + color.rgb = mix(color.rgb, uniforms.u_outlineColor, smoothstep(kOutlineThreshold2, kOutlineThreshold1, abs(in.halfLength))); + } + + return color; +} + +// TrafficLine + +typedef struct +{ + float3 a_position [[attribute(0)]]; + float2 a_colorTexCoord [[attribute(1)]]; +} TrafficLineVertex_T; + +typedef struct +{ + float4 position [[position]]; + float4 color; +} TrafficLineFragment_T; + +vertex TrafficLineFragment_T vsTrafficLine(const TrafficLineVertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]], + texture2d u_colorTex [[texture(0)]], + sampler u_colorTexSampler [[sampler(0)]]) +{ + TrafficLineFragment_T out; + + float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy; + float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection; + out.color = float4(u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord).rgb, uniforms.u_opacity); + out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0); + + return out; +} + +fragment float4 fsTrafficLine(const TrafficLineFragment_T in [[stage_in]]) +{ + return in.color; +} + +// TrafficCircle + +typedef struct +{ + float4 a_position [[attribute(0)]]; + float4 a_normal [[attribute(1)]]; + float2 a_colorTexCoord [[attribute(2)]]; +} TrafficCircleVertex_T; + +typedef struct +{ + float4 position [[position]]; + float4 color; + float3 radius; +} TrafficCircleFragment_T; + +vertex TrafficCircleFragment_T vsTrafficCircle(const TrafficCircleVertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]], + texture2d u_colorTex [[texture(0)]], + sampler u_colorTexSampler [[sampler(0)]]) +{ + TrafficCircleFragment_T out; + + float2 normal = in.a_normal.xy; + float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy; + int index = int(in.a_position.w); + + float3 leftSizes = uniforms.u_lightArrowColor; + float leftSize = leftSizes[index]; + + float3 rightSizes = uniforms.u_darkArrowColor; + float rightSize = rightSizes[index]; + + if (dot(normal, normal) != 0.0) + { + // offset by normal = rightVec * (rightSize - leftSize) / 2 + float2 norm = normal * 0.5 * (rightSize - leftSize); + transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm, + uniforms.u_modelView, length(norm)); + } + // radius = (leftSize + rightSize) / 2 + out.radius = float3(in.a_normal.zw, 1.0) * 0.5 * (leftSize + rightSize); + + float2 finalPos = transformedAxisPos + out.radius.xy; + out.color = u_colorTex.sample(u_colorTexSampler, in.a_colorTexCoord); + float4 pos = float4(finalPos, in.a_position.z, 1.0) * uniforms.u_projection; + out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0); + + return out; +} + +typedef struct +{ + float4 color [[color(0)]]; + float depth [[depth(any)]]; +} TrafficCircleOut_T; + +fragment TrafficCircleOut_T fsTrafficCircle(const TrafficCircleFragment_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(0)]]) +{ + constexpr float kAntialiasingThreshold = 0.92; + + TrafficCircleOut_T out; + + float4 color = in.color; + + float smallRadius = in.radius.z * kAntialiasingThreshold; + float stepValue = smoothstep(smallRadius * smallRadius, in.radius.z * in.radius.z, + in.radius.x * in.radius.x + in.radius.y * in.radius.y); + color.a = uniforms.u_opacity * (1.0 - stepValue); + if (color.a < 0.001) + out.depth = 1.0; + else + out.depth = in.position.z; + out.color = color; + return out; +} diff --git a/shaders/Metal/transit.metal b/shaders/Metal/transit.metal new file mode 100644 index 0000000000..8411749f0d --- /dev/null +++ b/shaders/Metal/transit.metal @@ -0,0 +1,154 @@ +#include +#include +#include "shaders_lib.h" +using namespace metal; + +typedef struct +{ + float4x4 u_modelView; + float4x4 u_projection; + float4x4 u_pivotTransform; + packed_float3 u_params; + float u_lineHalfWidth; + float u_maxRadius; +} Uniforms_T; + +typedef struct +{ + float3 a_position [[attribute(0)]]; + float4 a_normal [[attribute(1)]]; + float4 a_color [[attribute(2)]]; +} TransitVertex_T; + +// Transit + +typedef struct +{ + float4 position [[position]]; + float4 color; +} TransitFragment_T; + +vertex TransitFragment_T vsTransit(const TransitVertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]]) +{ + TransitFragment_T out; + + float2 normal = in.a_normal.xy; + float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy; + if (dot(normal, normal) != 0.0) + { + float2 norm = normal * uniforms.u_lineHalfWidth; + transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm, + uniforms.u_modelView, length(norm)); + } + out.color = in.a_color; + float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection; + out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0); + return out; +} + +fragment float4 fsTransit(const TransitFragment_T in [[stage_in]]) +{ + return in.color; +} + +// Transit marker + +typedef struct +{ + float4 position [[position]]; + float4 offsets; + float4 color; +} TransitMarkerFragment_T; + +vertex TransitMarkerFragment_T vsTransitMarker(const TransitVertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]]) +{ + TransitMarkerFragment_T out; + + float4 pos = float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView; + float3 params = uniforms.u_params; + float2 normal = float2(in.a_normal.x * params.x - in.a_normal.y * params.y, + in.a_normal.x * params.y + in.a_normal.y * params.x); + float2 shiftedPos = normal * params.z + pos.xy; + pos = float4(shiftedPos, in.a_position.z, 1.0) * uniforms.u_projection; + + float2 offsets = abs(in.a_normal.zw); + out.offsets = float4(in.a_normal.zw, offsets - 1.0); + out.color = in.a_color; + out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0); + return out; +} + +fragment float4 fsTransitMarker(const TransitMarkerFragment_T in [[stage_in]]) +{ + float4 finalColor = in.color; + float2 radius; + radius.x = max(0.0, abs(in.offsets.x) - in.offsets.z); + radius.y = max(0.0, abs(in.offsets.y) - in.offsets.w); + + float maxRadius = 1.0; + float aaRadius = 0.9; + float stepValue = 1.0 - smoothstep(aaRadius * aaRadius, maxRadius * maxRadius, dot(radius.xy, radius.xy)); + finalColor.a *= stepValue; + + return finalColor; +} + +// Transit circle + +typedef struct +{ + float4 position [[position]]; + float3 radius; + float4 color; +} TransitCircleFragment_T; + +vertex TransitCircleFragment_T vsTransitCircle(const TransitVertex_T in [[stage_in]], + constant Uniforms_T & uniforms [[buffer(1)]]) +{ + TransitCircleFragment_T out; + + float2 normal = in.a_normal.xy; + float2 transformedAxisPos = (float4(in.a_position.xy, 0.0, 1.0) * uniforms.u_modelView).xy; + if (dot(normal, normal) != 0.0) + { + float2 norm = normal * uniforms.u_lineHalfWidth; + transformedAxisPos = CalcLineTransformedAxisPos(transformedAxisPos, in.a_position.xy + norm, + uniforms.u_modelView, length(norm)); + } + transformedAxisPos += in.a_normal.zw * uniforms.u_lineHalfWidth; + float4 pos = float4(transformedAxisPos, in.a_position.z, 1.0) * uniforms.u_projection; + out.position = ApplyPivotTransform(pos, uniforms.u_pivotTransform, 0.0); + out.color = in.a_color; + out.radius = float3(in.a_normal.zw, uniforms.u_maxRadius) * uniforms.u_lineHalfWidth; + return out; +} + +typedef struct +{ + float4 color [[color(0)]]; + float depth [[depth(any)]]; +} TransitCircleOut_T; + +fragment TransitCircleOut_T fsTransitCircle(const TransitCircleFragment_T in [[stage_in]]) +{ + constexpr float kAntialiasingPixelsCount = 2.5; + + TransitCircleOut_T out; + + float4 finalColor = in.color; + + float smallRadius = in.radius.z - kAntialiasingPixelsCount; + float stepValue = smoothstep(smallRadius * smallRadius, in.radius.z * in.radius.z, + dot(in.radius.xy, in.radius.xy)); + finalColor.a = finalColor.a * (1.0 - stepValue); + if (finalColor.a < 0.001) + out.depth = 1.0; + else + out.depth = in.position.z; + + out.color = finalColor; + + return out; +} diff --git a/shaders/metal_program_pool.mm b/shaders/metal_program_pool.mm index 79bbe03d25..78b4f6284c 100644 --- a/shaders/metal_program_pool.mm +++ b/shaders/metal_program_pool.mm @@ -63,7 +63,7 @@ std::array(Program::ProgramsCount)> const kMeta ProgramInfo("", "", {}), // Area3dOutline ProgramInfo("", "", {}), // Line ProgramInfo("", "", {}), // CapJoin - ProgramInfo("", "", {}), // TransitCircle + ProgramInfo("vsTransitCircle", "fsTransitCircle", {{0, 2}}), // TransitCircle ProgramInfo("", "", {}), // DashedLine ProgramInfo("", "", {}), // PathSymbol ProgramInfo("", "", {}), // HatchingArea @@ -71,8 +71,8 @@ std::array(Program::ProgramsCount)> const kMeta ProgramInfo("vsRuler", "fsRuler", {{0, 2}}), // Ruler ProgramInfo("vsAccuracy", "fsAccuracy", {{0, 1}}), // Accuracy ProgramInfo("vsMyPosition", "fsMyPosition", {{0, 1}}), // MyPosition - ProgramInfo("", "", {}), // Transit - ProgramInfo("", "", {}), // TransitMarker + ProgramInfo("vsTransit", "fsTransit", {{0, 2}}), // Transit + ProgramInfo("vsTransitMarker", "fsTransitMarker", {{0, 2}}), // TransitMarker ProgramInfo("vsRoute", "fsRoute", {{0, 3}}), // Route ProgramInfo("vsRoute", "fsRouteDash", {{0, 3}}), // RouteDash ProgramInfo("vsRouteArrow", "fsRouteArrow", {{0, 2}}), // RouteArrow @@ -91,9 +91,9 @@ std::array(Program::ProgramsCount)> const kMeta ProgramInfo("", "", {}), // TextOutlinedBillboard ProgramInfo("", "", {}), // TextBillboard ProgramInfo("", "", {}), // TextFixedBillboard - ProgramInfo("", "", {}), // Traffic - ProgramInfo("", "", {}), // TrafficLine - ProgramInfo("", "", {}), // TrafficCircle + ProgramInfo("vsTraffic", "fsTraffic", {{0, 2}}), // Traffic + ProgramInfo("vsTrafficLine", "fsTrafficLine", {{0, 1}}), // TrafficLine + ProgramInfo("vsTrafficCircle", "fsTrafficCircle", {{0, 2}}), // TrafficCircle ProgramInfo("", "", {}), // SmaaEdges ProgramInfo("", "", {}), // SmaaBlendingWeight ProgramInfo("", "", {}), // SmaaFinal diff --git a/xcode/shaders/shaders.xcodeproj/project.pbxproj b/xcode/shaders/shaders.xcodeproj/project.pbxproj index 9eea68b702..52174520ab 100644 --- a/xcode/shaders/shaders.xcodeproj/project.pbxproj +++ b/xcode/shaders/shaders.xcodeproj/project.pbxproj @@ -40,6 +40,8 @@ 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 */; }; + BBF7917D214AC41700D27BD8 /* transit.metal in Sources */ = {isa = PBXBuildFile; fileRef = BBF79178214AA92D00D27BD8 /* transit.metal */; }; + BBF7917E214AC41F00D27BD8 /* traffic.metal in Sources */ = {isa = PBXBuildFile; fileRef = BBF79177214AA53C00D27BD8 /* traffic.metal */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -184,6 +186,12 @@ 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 = ""; }; + BBF79177214AA53C00D27BD8 /* traffic.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = traffic.metal; sourceTree = ""; }; + BBF79178214AA92D00D27BD8 /* transit.metal */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.metal; path = transit.metal; sourceTree = ""; }; + BBF79179214AB8B500D27BD8 /* traffic_circle.fsh.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = traffic_circle.fsh.glsl; sourceTree = ""; }; + BBF7917A214AB8B600D27BD8 /* transit_circle.fsh.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = transit_circle.fsh.glsl; sourceTree = ""; }; + BBF7917B214AB8B600D27BD8 /* traffic_circle.vsh.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = traffic_circle.vsh.glsl; sourceTree = ""; }; + BBF7917C214AB8B600D27BD8 /* transit_circle.vsh.glsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = transit_circle.vsh.glsl; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -331,6 +339,10 @@ 4566609520E256470085E8C1 /* traffic_line.vsh.glsl */, 4566608F20E256470085E8C1 /* traffic.fsh.glsl */, 456660BB20E2564E0085E8C1 /* traffic.vsh.glsl */, + BBF79179214AB8B500D27BD8 /* traffic_circle.fsh.glsl */, + BBF7917B214AB8B600D27BD8 /* traffic_circle.vsh.glsl */, + BBF7917A214AB8B600D27BD8 /* transit_circle.fsh.glsl */, + BBF7917C214AB8B600D27BD8 /* transit_circle.vsh.glsl */, 4566609720E256480085E8C1 /* transit_marker.fsh.glsl */, 456660A020E256490085E8C1 /* transit_marker.vsh.glsl */, 4566609A20E256480085E8C1 /* transit.fsh.glsl */, @@ -393,6 +405,8 @@ 451E6930214A8D4200764A97 /* shaders_lib.metal */, BBF7917421495FF900D27BD8 /* shapes.metal */, BBF7916F2146D8EC00D27BD8 /* system.metal */, + BBF79177214AA53C00D27BD8 /* traffic.metal */, + BBF79178214AA92D00D27BD8 /* transit.metal */, ); path = Metal; sourceTree = ""; @@ -554,9 +568,11 @@ 4560F5AB2142AC1300CC736C /* gui.metal in Sources */, 451E692D214A53C000764A97 /* route.metal in Sources */, BBF791702146D8EC00D27BD8 /* system.metal in Sources */, + BBF7917E214AC41F00D27BD8 /* traffic.metal in Sources */, 4560F58A213D57D600CC736C /* debug_rect.metal in Sources */, 451E6931214A8D4200764A97 /* shaders_lib.metal in Sources */, BBF7917321493AFC00D27BD8 /* arrow3d.metal in Sources */, + BBF7917D214AC41700D27BD8 /* transit.metal in Sources */, BBF7917521495FF900D27BD8 /* shapes.metal in Sources */, 4560F58B213D57D600CC736C /* screen_quad.metal in Sources */, );