#include "stb_image.h"
struct Image {
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t levels;
uint32_t layers;
uint32_t internal_format;
union {
struct {
uint32_t image;
} gl;
struct {
uint64_t image;
uint64_t memory;
uint64_t imageview;
} vk;
};
};
void _image_upload_2d(struct Image *image, int width, int height, int channels, const void * data, bool generate_mipmap) {
GLenum internal_format = channels == 3 ? GL_RGB8 : GL_RGBA8;
GLenum external_format = channels == 3 ? GL_RGB : GL_RGBA;
int levels = 1, w = width, h = height;
if(generate_mipmap) {
while(w > 1 && h > 1) {
levels++;
w = w >> (w > 1);
h = h >> (h > 1);
}
}
glCreateTextures(GL_TEXTURE_2D, 1, &image->gl.image);
glTextureStorage2D(image->gl.image, levels, internal_format, width, height);
glTextureSubImage2D(image->gl.image, 0, 0, 0, width, height, external_format, GL_UNSIGNED_BYTE, data);
if(generate_mipmap) {
glGenerateTextureMipmap(image->gl.image);
}
// TODO use sampler for this
glTextureParameteri(image->gl.image, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(image->gl.image, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
image->width = width;
image->height = height;
image->depth = 1;
image->levels = levels;
image->layers = 1;
image->internal_format = internal_format;
}
void _image_load(struct Image *image, const char *path) {
int width, height, channels;
uint8_t *data = stbi_load(path, &width, &height, &channels, 0);
if(data == NULL) {
engine_warning("stb_load: loading %s failed.", path);
return;
}
if(channels != 3 && channels != 4) {
engine_warning("stb_load: invalid channel value %i", channels);
stbi_image_free(data);
return;
}
engine_trace("stb_load: loaded %s", path);
_image_upload_2d(image, width, height, channels, data, true);
stbi_image_free(data);
}
void _image_unload(struct Image *image) {
}