Use castle's stbi instead of zstbi

This commit is contained in:
2026-02-06 23:27:21 +01:00
parent 33a0b241ef
commit 39712e359d
10 changed files with 73 additions and 75 deletions

View File

@@ -3,7 +3,7 @@
const Textures = @This();
const std = @import("std");
const stbi = @import("zstbi");
const media = @import("media");
const Atom = @import("../engine/Atom.zig").Atom;
const Engine = @import("../engine/Engine.zig");
@@ -172,14 +172,7 @@ pub fn getAtom(self: *const Textures, filename: Atom, usage: Texture.Usage) ?Id
/// if necessary. Will not return any error if the texture already exists. When
/// the filename is `null`, returns an empty texture ID appropriate for given
/// usage.
///
/// When a texture is being loaded, `temp_allocator` is used for temporary
/// allocations necessary to perform all operations. No memory allocated with
/// `temp_allocator` is retained, so the allocator can be deinitialized or reset
/// after this function returns. Note that during loading the engine will make
/// its own persistent allocations, so an out of memory error is not necessarily
/// related to `temp_allocator`.
pub fn getOrLoad(self: *Textures, engine: *Engine, maybe_filename: ?[]const u8, usage: Texture.Usage, temp_allocator: std.mem.Allocator) !Id {
pub fn getOrLoad(self: *Textures, engine: *Engine, stbi: *media.stbi, maybe_filename: ?[]const u8, usage: Texture.Usage) !Id {
if (maybe_filename) |filename| {
const key: Key = .{
// If the texture already exists, then the atom must exist and the
@@ -197,7 +190,7 @@ pub fn getOrLoad(self: *Textures, engine: *Engine, maybe_filename: ?[]const u8,
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
error.Overflow => return error.OutOfTextures,
};
const texture = try loadTexture(engine, filename, usage, temp_allocator);
const texture = try loadTexture(engine, stbi, filename, usage);
self.map.putAssumeCapacityNoClobber(key, id);
self.array.appendAssumeCapacity(texture);
@@ -214,14 +207,7 @@ pub fn getOrLoad(self: *Textures, engine: *Engine, maybe_filename: ?[]const u8,
/// if necessary. Will not return any error if the texture already exists. When
/// the filename is `.empty`, returns an empty texture ID appropriate for given
/// usage.
///
/// When a texture is being loaded, `temp_allocator` is used for temporary
/// allocations necessary to perform all operations. No memory allocated with
/// `temp_allocator` is retained, so the allocator can be deinitialized or reset
/// after this function returns. Note that during loading the engine will make
/// its own persistent allocations, so an out of memory is not necessarily
/// related to `temp_allocator`.
pub fn getOrLoadAtom(self: *Textures, engine: *Engine, filename: Atom, usage: Texture.Usage, temp_allocator: std.mem.Allocator) !Id {
pub fn getOrLoadAtom(self: *Textures, engine: *Engine, stbi: *media.stbi, filename: Atom, usage: Texture.Usage) !Id {
if (filename != .empty) {
const key: Key = .{
.filename = filename,
@@ -237,7 +223,7 @@ pub fn getOrLoadAtom(self: *Textures, engine: *Engine, filename: Atom, usage: Te
const id = Id.fromIndexSafe(self.array.items.len) catch |err| switch (err) {
error.Overflow => return error.OutOfTextures,
};
const texture = try loadTexture(engine, filename.toString(), usage, temp_allocator);
const texture = try loadTexture(engine, stbi, filename.toString(), usage);
self.map.putAssumeCapacityNoClobber(key, id);
self.array.appendAssumeCapacity(texture);
@@ -249,7 +235,7 @@ pub fn getOrLoadAtom(self: *Textures, engine: *Engine, filename: Atom, usage: Te
}
}
fn loadTexture(engine: *Engine, filename: []const u8, usage: Texture.Usage, temp_allocator: std.mem.Allocator) !Texture {
fn loadTexture(engine: *Engine, stbi: *media.stbi, filename: []const u8, usage: Texture.Usage) !Texture {
std.log.debug("Loading texture \"{s}\" as {s}...", .{ filename, @tagName(usage) });
const cwd = std.fs.cwd();
@@ -257,15 +243,25 @@ fn loadTexture(engine: *Engine, filename: []const u8, usage: Texture.Usage, temp
var dir = try cwd.openDir("assets/textures", .{});
defer dir.close();
const file_buf = try dir.readFileAlloc(temp_allocator, filename, std.math.maxInt(usize));
defer temp_allocator.free(file_buf);
var file = try dir.openFile(filename, .{});
defer file.close();
// The textures are expected to be small; a standard block base color as a
// PNG takes well below 1 kiB.
var buf: [4096]u8 = undefined;
var reader = file.reader(&buf);
const img = try stbi.loadDynamicIo(&reader.interface);
defer stbi.freeDynamic(img);
const data = img.data[0 .. img.width * img.height];
var img = try stbi.Image.loadFromMemory(file_buf, usage.samplesPerTexel());
defer img.deinit();
std.debug.assert(img.num_components == usage.samplesPerTexel());
if (usage == .normal) {
for (img.data) |*sample| {
sample.* = sample.* +% 128;
for (data) |*pixel| {
pixel.r = pixel.r +% 128;
pixel.g = pixel.g +% 128;
pixel.b = pixel.b +% 128;
pixel.a = pixel.a +% 128;
}
}
@@ -278,7 +274,7 @@ fn loadTexture(engine: *Engine, filename: []const u8, usage: Texture.Usage, temp
});
errdefer texture.deinit(engine);
try texture.writeRaw(engine, img.data);
try texture.writeRaw(engine, @ptrCast(data));
return texture;
}