GPU-based font rendering (keming edition)
This commit is contained in:
112
src/Game.zig
112
src/Game.zig
@@ -16,6 +16,7 @@ const Chunk = @import("Chunk.zig");
|
||||
const Chunks = @import("Chunks.zig");
|
||||
const CommandBuffer = @import("engine/CommandBuffer.zig");
|
||||
const Engine = @import("engine/Engine.zig");
|
||||
const Fonts = @import("engine/Fonts.zig");
|
||||
const Iterator2 = math.Iterator2;
|
||||
const Materials = @import("engine/Materials.zig");
|
||||
const Player = @import("Player.zig");
|
||||
@@ -47,6 +48,7 @@ blocks: Blocks,
|
||||
chunks: Chunks,
|
||||
skybox: Skybox,
|
||||
player: Player,
|
||||
font: Fonts.Id,
|
||||
|
||||
const max_textures = 1024;
|
||||
const max_point_lights = 1024;
|
||||
@@ -70,6 +72,7 @@ pub fn init() !Game {
|
||||
const swapchain = ctx.swapchain;
|
||||
const textures = ctx.textures;
|
||||
const materials = ctx.materials;
|
||||
const fonts = ctx.fonts;
|
||||
const gui = ctx.gui;
|
||||
|
||||
var blocks = try Blocks.init();
|
||||
@@ -137,7 +140,7 @@ pub fn init() !Game {
|
||||
.descriptor_type = .sampled_image,
|
||||
.descriptor_count = max_textures,
|
||||
.stage_flags = .{ .vertex_bit = true, .fragment_bit = true },
|
||||
.flags = .{ .variable_descriptor_count_bit = true },
|
||||
.flags = .{ .variable_descriptor_count_bit = true }, // TODO Get rid of this AND somehow integrate with Textures module?
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -442,6 +445,13 @@ pub fn init() !Game {
|
||||
const block_stone = try blocks.getOrLoad("Stone.json");
|
||||
const block_bedrock = try blocks.getOrLoad("Bedrock.json");
|
||||
|
||||
const font_id = try fonts.load("FiraMono-Regular.ttf", .{
|
||||
.codepoint_ranges = &.{
|
||||
.{ .start = 32, .end = 127 },
|
||||
},
|
||||
.name = "EB Garamond Regular",
|
||||
});
|
||||
|
||||
// VOLATILE Load all assets before this point
|
||||
|
||||
const descriptor_images = try allocator_frame.alloc(vk.DescriptorImageInfo, textures.array.items.len);
|
||||
@@ -619,6 +629,8 @@ pub fn init() !Game {
|
||||
var skybox = try Skybox.load("skybox.hdr", 512, global_uniforms.buffer);
|
||||
errdefer skybox.deinit();
|
||||
|
||||
const font = &fonts.array.items[@intFromEnum(font_id)];
|
||||
|
||||
// TODO This coupling is not elegant - the game must provide the GUI with
|
||||
// uniform buffer for globals. Maybe GUI should just use their own global
|
||||
// uniform buffer not for any other reason than decoupling. After all, GUI
|
||||
@@ -641,6 +653,66 @@ pub fn init() !Game {
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
.dst_set = gui.text_descriptor_set,
|
||||
.dst_binding = 0,
|
||||
.dst_array_element = 0,
|
||||
.descriptor_type = .uniform_buffer,
|
||||
.descriptor_infos = .{
|
||||
.buffer = &.{
|
||||
.{
|
||||
.buffer = global_uniforms.buffer,
|
||||
.offset = 0,
|
||||
.range = vk.WHOLE_SIZE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
.dst_set = gui.text_descriptor_set,
|
||||
.dst_binding = 2,
|
||||
.dst_array_element = @intFromEnum(font_id),
|
||||
.descriptor_type = .storage_buffer,
|
||||
.descriptor_infos = .{
|
||||
.buffer = &.{
|
||||
.{
|
||||
.buffer = font.glyph_data.buffer,
|
||||
.offset = 0,
|
||||
.range = vk.WHOLE_SIZE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
.dst_set = gui.text_descriptor_set,
|
||||
.dst_binding = 3,
|
||||
.dst_array_element = @intFromEnum(font_id),
|
||||
.descriptor_type = .storage_buffer,
|
||||
.descriptor_infos = .{
|
||||
.buffer = &.{
|
||||
.{
|
||||
.buffer = font.control_points.buffer,
|
||||
.offset = 0,
|
||||
.range = vk.WHOLE_SIZE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
.{
|
||||
.dst_set = gui.text_descriptor_set,
|
||||
.dst_binding = 4,
|
||||
.dst_array_element = @intFromEnum(font_id),
|
||||
.descriptor_type = .storage_buffer,
|
||||
.descriptor_infos = .{
|
||||
.buffer = &.{
|
||||
.{
|
||||
.buffer = font.band_data.buffer,
|
||||
.offset = 0,
|
||||
.range = vk.WHOLE_SIZE,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -667,6 +739,7 @@ pub fn init() !Game {
|
||||
.chunks = .{ .chunks = chunks },
|
||||
.skybox = skybox,
|
||||
.player = .init(player_position_sv, 0, 0),
|
||||
.font = font_id,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -741,6 +814,43 @@ pub fn update(self: *Game, dt: f32) void {
|
||||
.border_radius_px = 0,
|
||||
});
|
||||
|
||||
{
|
||||
const margin: f16 = 8;
|
||||
const font_size: f32 = 16;
|
||||
|
||||
const player_position_sv = self.player.position_sv;
|
||||
|
||||
gui.pushBox(.{
|
||||
.background_color = .init(0, 0, 0, 0.75),
|
||||
.border_color = .init(0, 0, 0, 1),
|
||||
.position_sspx = .init(0, 0),
|
||||
.size_px = .init(157, 4 * margin + 3 * font_size),
|
||||
.border_width_px = 0,
|
||||
.border_radius_px = 0,
|
||||
});
|
||||
|
||||
gui.printLine("X {X:0>8}", .{@as(u32, @bitCast(player_position_sv.x))}, .{
|
||||
.position_sspx = .init(margin, margin + font_size),
|
||||
.font_id = self.font,
|
||||
.cap_height_px = font_size,
|
||||
.color = .init(1, 1, 1, 1),
|
||||
});
|
||||
|
||||
gui.printLine("Y {X:0>8}", .{@as(u32, @bitCast(player_position_sv.y))}, .{
|
||||
.position_sspx = .init(margin, 2 * (margin + font_size)),
|
||||
.font_id = self.font,
|
||||
.cap_height_px = font_size,
|
||||
.color = .init(1, 1, 1, 1),
|
||||
});
|
||||
|
||||
gui.printLine("Z {X:0>8}", .{@as(u32, @bitCast(player_position_sv.z))}, .{
|
||||
.position_sspx = .init(margin, 3 * (margin + font_size)),
|
||||
.font_id = self.font,
|
||||
.cap_height_px = font_size,
|
||||
.color = .init(1, 1, 1, 1),
|
||||
});
|
||||
}
|
||||
|
||||
self.render() catch |err| {
|
||||
std.log.err("Failed to render: {s}", .{@errorName(err)});
|
||||
@panic("Frame update failed");
|
||||
|
||||
Reference in New Issue
Block a user