dtAverage: f64 = 0.0, allocator: std.mem.Allocator, directionalLightSettings: bool = false, ssaoSettings: bool = false, skyboxes: std.ArrayListUnmanaged(core.Name) = .{}, pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "extras.RendererDebug"); pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); self.* = .{ .allocator = allocator }; self.setup(); return self; } // setups are a non-failable functions that get reran after patchStruct() is called pub fn setup(self: *@This()) void { if (core.getEngineObject(igu.TopBar)) |topbar| { topbar.addMenuObject(self, "Renderer Debug") catch {}; } } pub fn windowOpen(entry: *igu.MenuEntry, dt: f64) void { const self: *@This() = @ptrCast(@alignCast(entry.ctx)); core.math.rollingAverage(&self.dtAverage, dt, 50); if (ig.begin("renderer debug", null, .{})) { if (self.dtAverage > 0.000001) { ig.textFmt("frameTime: {d:.2}ms ({d:.2}fps)", .{ self.dtAverage * 1000, @as(u32, @intFromFloat(1 / self.dtAverage)) }) catch unreachable; } _ = ig.checkbox("directional light settings", &self.directionalLightSettings); if (self.directionalLightSettings) { _ = ig.sliderFloat("directional light yaw", &rend.context().directionalLightYaw, 0, 360, null, .{}); _ = ig.sliderFloat("skyboxLevel", &rend.context().skyboxSystem.brightnessFactor, 0, 10, null, .{}); _ = ig.sliderFloat("lightLevel", &rend.context().lightPower, 0, 100, null, .{}); _ = ig.sliderFloat("ortho near", &rend.context().shadowOrthoNear, 0, 200, null, .{}); _ = ig.sliderFloat("ortho far", &rend.context().shadowOrthoFar, 0, 6000, null, .{}); _ = ig.colorPicker4("directionalLightColor", rend.context().directionalLightColor.intoArray(), 0, null); } _ = ig.checkbox("ssao settings", &self.ssaoSettings); if (self.ssaoSettings) { const ssao = rend.context().ssaoSystem; _ = ig.sliderFloat("radius", &ssao.radius, 0.1, 1.0, null, .{}); _ = ig.sliderFloat("bias", &ssao.bias, 0.0025, 1.0, null, .{}); _ = ig.checkbox("enable SSAO", &ssao.enable); } var buffer: [256]u8 = undefined; ig.textFmt("skyboxes", .{}) catch unreachable; ig.separator(); for (self.skyboxes.items) |*name| { const x = std.fmt.bufPrintZ(&buffer, "{s}##button", .{name.utf8()}) catch unreachable; if (ig.smallButton(x)) { rend.setSkyboxTexture(name.utf8()); } } ig.textFmt("textures", .{}) catch unreachable; ig.separator(); { var iter = rend.context().textureList.map.iterator(); while (iter.next()) |n| { ig.textFmt("{s}", .{n.value_ptr.*.name.utf8()}) catch unreachable; } } ig.textFmt("meshes", .{}) catch unreachable; ig.separator(); { var iter = rend.context().meshPool.installedMeshes.iterator(); while (iter.next()) |n| { ig.textFmt("{s}", .{n.value_ptr.*.name.utf8()}) catch unreachable; } } } ig.end(); } pub fn destroy(self: *@This()) void { self.skyboxes.deinit(self.allocator); self.allocator.destroy(self); } const backlog = @import("Backlog"); const core = backlog.core; const rend = backlog.rend; const ig = backlog.imgui.api; const igu = backlog.imgui.utils; const std = @import("std");