diff --git a/assets/fonts/Amiri/Amiri-Bold.ttf b/assets/fonts/Amiri/Amiri-Bold.ttf new file mode 100644 index 0000000..49600cb Binary files /dev/null and b/assets/fonts/Amiri/Amiri-Bold.ttf differ diff --git a/assets/fonts/Amiri/Amiri-BoldItalic.ttf b/assets/fonts/Amiri/Amiri-BoldItalic.ttf new file mode 100644 index 0000000..1d89e4f Binary files /dev/null and b/assets/fonts/Amiri/Amiri-BoldItalic.ttf differ diff --git a/assets/fonts/Amiri/Amiri-Italic.ttf b/assets/fonts/Amiri/Amiri-Italic.ttf new file mode 100644 index 0000000..13e3ec3 Binary files /dev/null and b/assets/fonts/Amiri/Amiri-Italic.ttf differ diff --git a/assets/fonts/Amiri/Amiri-Regular.ttf b/assets/fonts/Amiri/Amiri-Regular.ttf new file mode 100644 index 0000000..df5e1df Binary files /dev/null and b/assets/fonts/Amiri/Amiri-Regular.ttf differ diff --git a/assets/fonts/Amiri/OFL.txt b/assets/fonts/Amiri/OFL.txt new file mode 100644 index 0000000..4f0bc3c --- /dev/null +++ b/assets/fonts/Amiri/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2010-2022 The Amiri Project Authors (https://github.com/aliftype/amiri). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/build.zig b/build.zig index 513e7a1..aa7daaf 100644 --- a/build.zig +++ b/build.zig @@ -81,6 +81,14 @@ pub fn build(b: *std.Build) void { .use_llvm = true, }); + const ztracy = b.dependency("ztracy", .{ + .enable_ztracy = true, + .enable_fibers = false, + .on_demand = false, + }); + client.root_module.addImport("ztracy", ztracy.module("root")); + client.linkLibrary(ztracy.artifact("tracy")); + const freetype_module = b.addModule("mach-freetype", .{ .root_source_file = b.path("vendor/mach-freetype/src/freetype.zig"), }); diff --git a/build.zig.zon b/build.zig.zon index 6dbf504..8e10082 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -56,6 +56,10 @@ .url = "git+https://github.com/hexops/freetype#972cd37bccecae2cc9f54cf0b562263a13209d02", .hash = "freetype-0.0.0-AAAAAA5JcwBMujojfNLEq5g_WijZtU56mRLYx8bjjiMU", }, + .ztracy = .{ + .url = "git+https://github.com/zig-gamedev/ztracy#d95d2a193b9f97944a17026c9a42b5d0f9a88c94", + .hash = "ztracy-0.14.0-dev-zHJSqzUHGQAmhJybhlwtl1QKevUBw4M5YKZqPfWx2y99", + }, }, .paths = .{ "build.zig", diff --git a/src/client/font.zig b/src/client/font.zig index dbb0179..4633370 100644 --- a/src/client/font.zig +++ b/src/client/font.zig @@ -3,6 +3,7 @@ const rl = @import("raylib"); const kb = @import("kb"); const ft = @import("freetype"); const rp = @import("stb_rect_pack"); +const ztracy = @import("ztracy"); pub var ft_lib : ft.Library = undefined; pub var shader : rl.Shader = undefined; @@ -196,6 +197,13 @@ pub const Font = struct { if (text.len == 0) return; + const zone = ztracy.ZoneNC(@src(), "render_text", 0x00_ff_00_00); + defer zone.End(); + + rl.beginShaderMode(shader); + rl.gl.rlSetTexture(self.texture.id); + rl.gl.rlBegin(rl.gl.rl_quads); + if (nice_background) { self.render_text( text, @@ -224,21 +232,31 @@ pub const Font = struct { return; } + const zone2 = ztracy.ZoneNC(@src(), "ShapeUtf8", 0x00_ff_00_00); kb.kbts_ShapeBegin(Context, kb.KBTS_DIRECTION_DONT_KNOW, kb.KBTS_LANGUAGE_DONT_KNOW); kb.kbts_ShapeUtf8(Context, text.ptr, @intCast(text.len), kb.KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX); kb.kbts_ShapeEnd(Context); + zone2.End(); - var x_offset : f32 = 0; - var y_offset : f32 = 0; + var cursor_x : f32 = 0; + var cursor_y : f32 = 0; var Run = kb.kbts_run{}; while (kb.kbts_ShapeRun(Context, &Run) != 0) { + const zone3 = ztracy.ZoneNC(@src(), "shape run", 0x00_ff_00_00); + defer zone3.End(); if ((Run.Flags & kb.KBTS_BREAK_FLAG_LINE_HARD) != 0) { + const font_linegap : f32 = @floatFromInt(self.face.size().metrics().height >> 6); + const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y; + cursor_y += dpi_font_linegap; + cursor_x = 0; } var g : [*c]kb.kbts_glyph = null; while (kb.kbts_GlyphIteratorNext(&Run.Glyphs, &g) != 0) { + const zone4 = ztracy.ZoneNC(@src(), "glyph iterator", 0x00_ff_00_00); + defer zone4.End(); const RunGlyph : *kb.kbts_glyph = g.?; const CodepointIndex : i32 = RunGlyph.UserIdOrCodepointIndex; var ShapeCodepoint : kb.kbts_shape_codepoint = undefined; @@ -251,19 +269,28 @@ pub const Font = struct { const dpi_advance_x = advance_x / rl.getWindowScaleDPI().x; const dpi_advance_y = advance_y / rl.getWindowScaleDPI().y; + const offset_x : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetX, @intCast(self.face.size().metrics().x_scale)) >> 6); + const offset_y : f32 = @floatFromInt(ft.mulFix(RunGlyph.OffsetY, @intCast(self.face.size().metrics().y_scale)) >> 6); + const dpi_offset_x = offset_x / rl.getWindowScaleDPI().x; + const dpi_offset_y = offset_y / rl.getWindowScaleDPI().y; + if (self.glyphs.getPtr(RunGlyph.Id)) |glyph| { + if (RunGlyph.OffsetX != 0) { + std.log.info("font bearing ({}, {}), kb offset ({}, {})", .{glyph.bearing_x, glyph.bearing_y, RunGlyph.OffsetX, RunGlyph.OffsetX}); + } + var v0 = rl.Vector2.zero(); var v1 = rl.Vector2.zero(); - v0 = render_pos.add(.{ .x = x_offset + glyph.dpi_bearing_x, - .y = y_offset - glyph.dpi_bearing_y }); + v0 = render_pos.add(.{ .x = cursor_x + glyph.dpi_bearing_x + dpi_offset_x, + .y = cursor_y - glyph.dpi_bearing_y - dpi_offset_y }); v1 = v0.add(rl.Vector2{ .x = glyph.dpi_width, .y = glyph.dpi_height }); const p0 : rl.Vector4 = .{ .x = v0.x, .y = v0.y, .z = 0.0, .w = 1.0 }; const p1 : rl.Vector4 = .{ .x = v1.x, .y = v1.y, .z = 0.0, .w = 1.0 }; - x_offset += dpi_advance_x; - y_offset += dpi_advance_y; + cursor_x += dpi_advance_x; + cursor_y += dpi_advance_y; const st0 = glyph.st0; const st1 = glyph.st1; @@ -279,12 +306,15 @@ pub const Font = struct { } else { std.log.warn("kb_text_shape found the glyph, but we didn't load it from the font. index {}", .{RunGlyph.Id}); std.log.warn("advance_x {}", .{advance_x}); - x_offset += dpi_advance_x; - y_offset += dpi_advance_y; - continue; + cursor_x += dpi_advance_x; + cursor_y += dpi_advance_y; } } } + + rl.gl.rlEnd(); + rl.gl.rlSetTexture(0); + rl.endShaderMode(); } pub fn size_row(self: *Font, str: []const u8, n: i32, max_width: f32) struct {rl.Vector2, f32, i32} { diff --git a/src/client/main.zig b/src/client/main.zig index 5674a57..9ee37f3 100644 --- a/src/client/main.zig +++ b/src/client/main.zig @@ -3,14 +3,15 @@ const zm = @import("zmath"); const znet = @import("znet"); const rl = @import("raylib"); const bufzilla = @import("bufzilla"); -const ft = @import("freetype"); +const ft = @import("freetype"); +const ztracy = @import("ztracy"); -const shared = @import("shared"); +const shared = @import("shared"); -const client = @import("client.zig"); -const entity = @import("entity.zig"); -const misc = @import("misc.zig"); -const font = @import("font.zig"); +const client = @import("client.zig"); +const entity = @import("entity.zig"); +const misc = @import("misc.zig"); +const font = @import("font.zig"); const dt : f32 = 1.0 / 200.0; var t : f32 = 0; @@ -29,6 +30,8 @@ var dbg_allocator = std.heap.DebugAllocator(.{}){}; // var connection: ?std.net.Stream = undefined; pub fn main() !void { + const tracy_zone = ztracy.ZoneNC(@src(), "main", 0x00_ff_00_00); + defer tracy_zone.End(); const allocator = dbg_allocator.allocator(); defer { @@ -53,25 +56,41 @@ pub fn main() !void { font.ft_lib = try ft.Library.init(); const sizes = [_]i32{ - 12, 14, 16, 18, 20, + 26, }; var vollkorn: [sizes.len]font.Font = undefined; var inconsolata: [sizes.len]font.Font = undefined; - // var arabic: [sizes.len]font.Font = undefined; + var arabic: [sizes.len]font.Font = undefined; // var japanese: [sizes.len]font.Font = undefined; for (sizes, 0..) |pt, i| { - vollkorn[i] = try font.Font.init("assets/fonts/Vollkorn/static/Vollkorn-Regular.ttf", pt, allocator); - inconsolata[i] = try font.Font.init("assets/fonts/Inconsolata/static/Inconsolata-Regular.ttf", @intCast(pt), allocator); - // arabic[i] = try font.Font.init("assets/fonts/Noto_Sans_Arabic/static/NotoSansArabic-Regular.ttf", @intCast(pt), allocator); - // japanese[i] = try font.Font.init("assets/fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf", @intCast(pt), allocator); + vollkorn[i] = try font.Font.init( + "assets/fonts/Vollkorn/static/Vollkorn-Regular.ttf", + pt, + allocator + ); + inconsolata[i] = try font.Font.init( + "assets/fonts/Inconsolata/static/Inconsolata-Regular.ttf", + @intCast(pt), + allocator + ); + arabic[i] = try font.Font.init( + "assets/fonts/Amiri/Amiri-Regular.ttf", + @intCast(pt), + allocator + ); + // japanese[i] = try font.Font.init( + // "assets/fonts/Noto_Sans_JP/static/NotoSansJP-Regular.ttf", + // @intCast(pt), + // allocator + // ); } defer { for (&vollkorn) |*f| f.deinit(allocator); for (&inconsolata) |*f| f.deinit(allocator); - // for (&arabic) |*f| f.deinit(allocator); + for (&arabic) |*f| f.deinit(allocator); // for (&japanese) |*f| f.deinit(allocator); } @@ -134,7 +153,13 @@ pub fn main() !void { // const line = try reader.interface().takeDelimiterExclusive('\n'); // std.log.info("{s}", .{line}); - // const camera = rl.Camera{ .fovy = 45, .position = .{ .x = 0, .y = 0, .z = 10 }, .projection = .perspective, .target = .{ .x = 0, .y = 0, .z = 0 }, .up = .{ .x = 0, .y = 1, .z = 0 } }; + // const camera = rl.Camera{ + // .fovy = 45, + // .position = .{ .x = 0, .y = 0, .z = 10 }, + // .projection = .perspective, + // .target = .{ .x = 0, .y = 0, .z = 0 }, + // .up = .{ .x = 0, .y = 1, .z = 0 } + // }; // rl.initAudioDevice(); @@ -153,7 +178,9 @@ pub fn main() !void { // var old_time : f32 = @floatCast(rl.getTime()); while (!rl.windowShouldClose()) { - // while (!rl.windowShouldClose()) { // Detect window close button or ESC key + const tracy_main_zone = ztracy.ZoneNC(@src(), "loop", 0x00_ff_00_00); + defer tracy_main_zone.End(); + const new_time : f32 = @floatCast(rl.getTime()); // const new_time : f32 = @floatCast(rl.getTime()); var frame_time = new_time - old_time; @@ -208,34 +235,46 @@ pub fn main() !void { rl.beginDrawing(); rl.clearBackground(.sky_blue); - rl.beginShaderMode(font.shader); - rl.gl.rlSetTexture(vollkorn[0].texture.id); - rl.gl.rlBegin(rl.gl.rl_quads); + // const lorem = @embedFile("embeds/lorem.txt"); - const lorem = @embedFile("embeds/lorem.txt"); + // vollkorn[0].render_text( + // lorem, + // rl.Vector2{ .x = 0, .y = 0 }, + // true, + // .white, + // .blank, + // false, + // true + // ); - var y : f32 = 0; - var it = std.mem.splitScalar(u8, lorem, '\n'); - while (it.next()) |line| { - vollkorn[0].render_text( - line, - rl.Vector2{ .x = 0, .y = y}, - true, - .white, - .blank, - false, - true - ); + arabic[0].render_text( + "الليل طويل وبارد في الخارج", + rl.Vector2{ .x = 0, .y = 100}, + true, + .white, + .blank, + false, + true + ); - const font_linegap : f32 = @floatFromInt(vollkorn[0].face.size().metrics().height >> 6); - const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y; + // var y : f32 = 0; + // var it = std.mem.splitScalar(u8, lorem, '\n'); + // while (it.next()) |line| { + // vollkorn[0].render_text( + // line, + // rl.Vector2{ .x = 0, .y = y}, + // true, + // .white, + // .blank, + // false, + // true + // ); - y += dpi_font_linegap; - } + // const font_linegap : f32 = @floatFromInt(vollkorn[0].face.size().metrics().height >> 6); + // const dpi_font_linegap = font_linegap / rl.getWindowScaleDPI().y; - rl.gl.rlEnd(); - rl.gl.rlSetTexture(0); - rl.endShaderMode(); + // y += dpi_font_linegap; + // } // for (&vollkorn) |*f| { @@ -302,15 +341,7 @@ pub fn main() !void { // } // for (&arabic) |*f| { - // f.render_text( - // "الليل طويل وبارد في الخارج", - // rl.Vector2{ .x = 0, .y = y}, - // true, - // .white, - // .blank, - // false, - // true - // ); + // const font_ascent : f32 = @floatFromInt(f.face.size().metrics().ascender >> 6); // const dpi_font_ascent = font_ascent / rl.getWindowScaleDPI().y; @@ -331,8 +362,14 @@ pub fn main() !void { // rl.gl.rlBegin(rl.gl.rl_quads); // { - // const topLeft : rl.Vector2 = .{ .x = 0.0, .y = 0.0 }; - // const bottomRight : rl.Vector2 = .{ .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0, .y = @as(f32, @floatFromInt(rl.getScreenHeight())) }; + // const topLeft : rl.Vector2 = .{ + // .x = 0.0, + // .y = 0.0 + // }; + // const bottomRight : rl.Vector2 = .{ + // .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0, + // .y = @as(f32, @floatFromInt(rl.getScreenHeight())) + // }; // rl.gl.rlVertex2f(topLeft.x, topLeft.y); // rl.gl.rlVertex2f(topLeft.x, bottomRight.y); @@ -348,8 +385,14 @@ pub fn main() !void { // rl.gl.rlBegin(rl.gl.rl_quads); // { - // const topLeft : rl.Vector2 = .{ .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0, .y = 0 }; - // const bottomRight : rl.Vector2 = .{ .x = @floatFromInt(rl.getScreenWidth()), .y = @floatFromInt(rl.getScreenHeight()) }; + // const topLeft : rl.Vector2 = .{ + // .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0, + // .y = 0 + // }; + // const bottomRight : rl.Vector2 = .{ + // .x = @floatFromInt(rl.getScreenWidth()), + // .y = @floatFromInt(rl.getScreenHeight()) + // }; // rl.gl.rlVertex2f(topLeft.x, topLeft.y); // rl.gl.rlVertex2f(topLeft.x, bottomRight.y); @@ -365,7 +408,10 @@ pub fn main() !void { // { // const topLeft : rl.Vector2 = .{ .x = @as(f32, @floatFromInt(rl.getScreenWidth())) / 2.0, .y = 0 }; - // const bottomRight : rl.Vector2 = .{ .x = @floatFromInt(rl.getScreenWidth()), .y = @floatFromInt(rl.getScreenHeight()) }; + // const bottomRight : rl.Vector2 = .{ + // .x = @floatFromInt(rl.getScreenWidth()), + // .y = @floatFromInt(rl.getScreenHeight()) + // }; // rl.gl.rlVertex2f(topLeft.x, topLeft.y); // rl.gl.rlVertex2f(topLeft.x, bottomRight.y); @@ -388,8 +434,20 @@ pub fn main() !void { //const not_connected_text = "Not Connected"; // switch (peer.state()) { - // .connected => rl.drawText(connected_text, @divFloor(rl.getScreenWidth(), 2) - @divFloor(rl.measureText(connected_text, f.baseSize), 2), 50, 20, .white), - // else => rl.drawText(not_connected_text, @divFloor(rl.getScreenWidth(), 2) - @divFloor(rl.measureText(not_connected_text, f.baseSize), 1), 50, 20, .white), + // .connected => rl.drawText( + // connected_text, + // @divFloor(rl.getScreenWidth(), 2) - @divFloor(rl.measureText(connected_text, f.baseSize), 2), + // 50, + // 20, + // .white + // ), + // else => rl.drawText( + // not_connected_text, + // @divFloor(rl.getScreenWidth(), 2) - @divFloor(rl.measureText(not_connected_text, f.baseSize), 1), + // 50, + // 20, + // .white + // ), // } //@divFloor(rl.getScreenWidth(), 2) - @divFloor(rl.measureText(connected_text, f.baseSize), 2), 50 @@ -397,7 +455,8 @@ pub fn main() !void { // const font_size : i32 = 180; - // const text_size = rl.Vector2{.x = @floatFromInt(rl.measureText(connected_text, font_size)), .y = font_size};//rl.measureTextEx(try rl.getFontDefault(), connected_text, font_size, font_size / 10); + // const text_size = rl.Vector2{.x = @floatFromInt(rl.measureText(connected_text, font_size)), + // .y = font_size};//rl.measureTextEx(try rl.getFontDefault(), connected_text, font_size, font_size / 10); // const pos = rl.Vector2{.x = 0, .y = 0}; // rl.drawText(connected_text, pos.x, pos.y, font_size, .white); // rl.drawRectangleLines(pos.x, pos.y, @intFromFloat(text_size.x), @intFromFloat(text_size.y), .red); @@ -409,7 +468,8 @@ pub fn main() !void { // 0, // .white); - //rl.drawLineV(.{.x = @floatFromInt(@divFloor(rl.getScreenWidth(), 2)), .y = 0}, .{.x = @floatFromInt(@divFloor(rl.getScreenWidth(), 2)), .y = @floatFromInt(rl.getScreenHeight())}, .red); + //rl.drawLineV(.{.x = @floatFromInt(@divFloor(rl.getScreenWidth(), 2)), .y = 0}, .{.x = @floatFromInt(@divFloor(rl.getScreenWidth(), 2)), + // .y = @floatFromInt(rl.getScreenHeight())}, .red); //rl.drawText("Congrats! You created your first window!", rl.getMouseX(), rl.getMouseY(), 20, .white); //rl.drawRectangleLines(0, 0, 100, 100, .red); @@ -426,6 +486,8 @@ pub fn main() !void { rl.swapScreenBuffer(); frame += 1; + + ztracy.FrameMark(); } } diff --git a/src/client/misc.zig b/src/client/misc.zig index 8a82902..083e599 100644 --- a/src/client/misc.zig +++ b/src/client/misc.zig @@ -39,13 +39,11 @@ pub fn getFPS(fpsFrame : f32) i32 { last = @floatCast(rl.getTime()); index = (index + 1) % FPS_CAPTURE_FRAMES_COUNT; average -= history[index]; - history[index] = fpsFrame; + history[index] = fpsFrame / FPS_CAPTURE_FRAMES_COUNT; average += history[index]; } - const meanFrameTime = average / @as(f32, @floatFromInt(FPS_CAPTURE_FRAMES_COUNT)); - - fps = @intFromFloat(1.0 / meanFrameTime); + fps = @intFromFloat(1.0 / average); return fps; }