// Texture store // Copyright (C) 2002 David Rosen // Copyright (C) 2021-2023 Nguyễn Gia Phong // // This file is part of Black Shades. // // Black Shades is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Black Shades is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Black Shades. If not, see . const allocator = std.heap.c_allocator; const c = @import("cimport.zig"); const cwd = std.fs.cwd; const data_dir = misc.data_dir; const formatIntBuf = std.fmt.formatIntBuf; const misc = @import("misc.zig"); const qoi = @import("qoi"); const readFile = misc.readFile; const sep = std.fs.path.sep; const span = std.mem.span; const std = @import("std"); /// Load QOI file into an OpenGL buffer bound to the given texture. fn load(texture: u32, path: [*:0]const u8) !void { const file = try readFile(cwd(), data_dir ++ "textures{c}{s}", .{ sep, path, }); defer allocator.free(file); var image = try qoi.decodeBuffer(allocator, file); defer image.deinit(allocator); const data: [*c]const u8 = @ptrCast(image.pixels.ptr); c.glBindTexture(c.GL_TEXTURE_2D, texture); defer c.glBindTexture(c.GL_TEXTURE_2D, 0); c.glTexEnvi(c.GL_TEXTURE_ENV, c.GL_TEXTURE_ENV_MODE, c.GL_MODULATE); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MAG_FILTER, c.GL_LINEAR); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_TEXTURE_MIN_FILTER, c.GL_LINEAR); c.glTexParameteri(c.GL_TEXTURE_2D, c.GL_GENERATE_MIPMAP, c.GL_TRUE); const width: i32 = @intCast(image.width); const height: i32 = @intCast(image.height); c.glPixelStorei(c.GL_UNPACK_ALIGNMENT, 1); c.glTexImage2D(c.GL_TEXTURE_2D, 0, 4, width, height, 0, c.GL_RGBA, c.GL_UNSIGNED_BYTE, data); } export fn loadTexture(path: [*:0]const u8) u32 { var texture: u32 = undefined; c.glGenTextures(1, &texture); load(texture, path) catch unreachable; return texture; } const Textures = @This(); const size = @sizeOf(Textures) / @sizeOf(u32); bullet_hole: u32, crater: u32, blood_pool: [11]u32, pub fn init() !Textures { var self: Textures = undefined; c.glGenTextures(size, @ptrCast(&self)); try load(self.bullet_hole, "bullet-hole.qoi"); try load(self.crater, "black.qoi"); for (0..11) |i| { var buf: [2]u8 = undefined; _ = formatIntBuf(&buf, i, 10, .lower, .{ .width = 2, .fill = '0' }); try load(self.blood_pool[i], "blood/" ++ buf ++ ".qoi"); } return self; } pub fn deinit(self: Textures) void { c.glDeleteTextures(size, @ptrCast(&self)); }