Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/texture.h

248 lines
7.7 KiB
C
Raw Normal View History

2025-09-02 14:43:36 +02:00
void tex_gen_checkerboard(byte *data, int w, int h, uint color1, uint color2) {
byte color[8];
color1 = (color1 << 8) | (color1 >> 24);
color2 = (color2 << 8) | (color2 >> 24);
for(int z = 0; z < 4; z++) {
color[z] = (uint)((color1 >> ((3 - z) * 8)) & 0xff);
color[z+4] = (uint)((color2 >> ((3 - z) * 8)) & 0xff);
}
for(int x = 0; x < w; x++) {
for(int y = 0; y < h; y++) {
memcpy(&data[(y*w+x) << 2], &color[((x & 1) ^ (y & 1)) << 2], 4);
}
}
}
float tri(float x, float p, float a) {
return ((4.0f * a) / p) * fabsf(fmodf(x - p / 4.0f, p) - p / 2.0f) - a;
}
void tex_gen_triwave(byte *data, int w, int h, uint color1, uint color2, uint color3, uint color4, uint color5, uint color6) {
byte color[16];
color1 = (color1 << 8) | (color1 >> 24);
color2 = (color2 << 8) | (color2 >> 24);
color3 = (color3 << 8) | (color3 >> 24);
color4 = (color4 << 8) | (color4 >> 24);
color5 = (color5 << 8) | (color5 >> 24);
color6 = (color6 << 8) | (color6 >> 24);
for(int z = 0; z < 4; z++) {
color[z] = (uint)((color1 >> ((3 - z) * 8)) & 0xff);
color[z+4] = (uint)((color2 >> ((3 - z) * 8)) & 0xff);
color[z+8] = (uint)((color3 >> ((3 - z) * 8)) & 0xff);
color[z+12] = (uint)((color4 >> ((3 - z) * 8)) & 0xff);
color[z+16] = (uint)((color5 >> ((3 - z) * 8)) & 0xff);
color[z+20] = (uint)((color6 >> ((3 - z) * 8)) & 0xff);
}
for(int y = 0; y < h; y++) {
int offs = ((y / 2 == h / 16) || (y / 2 == (h / 2 - h / 16) - 1)) ? 16 : (((y / 2 == h / 16 + 1) || (y / 2 == (h / 2 - h / 16) - 2)) ? 20 : 0);
for(int x = 0; x < w; x++) {
memcpy(&data[(y*w+x) << 2], &color[offs], 4);
}
}
for(int x = 0; x < w; x++) {
int y = ((x < w / 8) || (x >= w - w / 8)) ? (h / 2) : (h / 2 + (int)tri((float)(w / 4 + x), (float)((w * 3) / 4), (float)(((h * 3) / 4) / 2)));
sys_assert(y - 8 >= 0 && y + 7 < h)
memcpy(&data[((y-8)*w+x) << 2], &color[0], 4);
memcpy(&data[((y-7)*w+x) << 2], &color[0], 4);
memcpy(&data[((y-6)*w+x) << 2], &color[0], 4);
memcpy(&data[((y-5)*w+x) << 2], &color[4], 4);
memcpy(&data[((y-4)*w+x) << 2], &color[4], 4);
memcpy(&data[((y-3)*w+x) << 2], &color[0], 4);
memcpy(&data[((y-2)*w+x) << 2], &color[0], 4);
memcpy(&data[((y-1)*w+x) << 2], &color[8], 4);
memcpy(&data[((y+0)*w+x) << 2], &color[8], 4);
memcpy(&data[((y+1)*w+x) << 2], &color[0], 4);
memcpy(&data[((y+2)*w+x) << 2], &color[0], 4);
memcpy(&data[((y+3)*w+x) << 2], &color[12], 4);
memcpy(&data[((y+4)*w+x) << 2], &color[12], 4);
memcpy(&data[((y+5)*w+x) << 2], &color[0], 4);
memcpy(&data[((y+6)*w+x) << 2], &color[0], 4);
memcpy(&data[((y+7)*w+x) << 2], &color[0], 4);
}
}
/*
void tex_pack_1bit(const byte *data, byte *pack, uint size) {
for(int z = 0; z < size; z++) {
pack[z >> 3] &= ~(1 << (z & 7));
if(data[(z << 2) | 3])
pack[z >> 3] |= 1 << (z & 7);
}
}
void tex_unpack_1bit(byte *data, const byte *pack, uint size) {
for(int z = 0; z < size; z++) {
memset(&data[z << 2], (pack[z >> 3] & (1 << (z & 7))) ? 0xff : 0x00, 4);
}
}
*/
void tex_param(tex_t *tex) {
byte mipmap = (gdr.tex_miptype < tex->mipmap) ? gdr.tex_miptype : tex->mipmap;
glBindTexture(GL_TEXTURE_2D, *(tex->id));
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (gdr.tex_filter && tex->filter)
? (mipmap ? ((mipmap == 1) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR) : GL_LINEAR)
: (mipmap ? ((mipmap == 1) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST_MIPMAP_LINEAR) : GL_NEAREST));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (gdr.tex_filter && tex->filter) ? GL_LINEAR : GL_NEAREST);
// if(gdr.aniso_avail)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, tex->filter ? MIN_VALUE(gdr.tex_aniso, gdr.aniso_max) : 1.0f);
}
int tex_config() {
int done = 0;
ulong iter = 0;
tex_t *tex;
while(tex = tbl_iter(&gdr.textures, &iter)) {
tex_param(tex);
done += 1;
}
logd(LOG_GFX, STR_TEX_PARAMS, done);
return done;
}
void tex_delete(uint *tex) {
// uint *tex;
// for(int z = 0; z < gdr.tex_loaded; z++) {
// tex = gdr.textures[z];
if(*tex) {
glDeleteTextures(1, tex);
logd(LOG_GFX, STR_TEX_IUNLOADED, *tex);
*tex = 0;
}
// }
}
byte tex_unload(tex_t *tex) {
if(!(*(tex->id))) {
return 0;
}
glDeleteTextures(1, tex->id);
gdr.tex_mem -= tex->width * tex->height * 4;
logd(LOG_GFX, STR_TEX_UNLOADED, tex->path ? tex->path : "[built-in]", *(tex->id));
*(tex->id) = 0;
return 1;
}
void tex_remove(tex_t *tex) {
if(tex_unload(tex)) {
// tbl_pop(&gdr.textures, tex);
gdr.tex_loaded -= 1;
}
}
int tex_clear() {
return tbl_clear_func(&gdr.textures, (clear_func*)tex_remove);
}
byte *img_load(const char *filename, int *width, int *height, byte flip, byte ignmiss) {
byte *data;
int err;
FILE *fd;
if(!(fd = fopen(filename, "rb"))) {
err = errno;
if(err != ENOENT || !ignmiss)
loge(LOG_GFX, STR_TEX_EOPEN, filename, strerror(err), err);
return 0;
}
data = stbi_load(fd, width, height, flip);
fclose(fd);
if(!data) {
loge(LOG_GFX, STR_TEX_ELOAD, filename, stbi_failure_desc(), stbi_failure_reason());
}
return data;
}
void tex_push(uint *tex, const byte *data, int width, int height) {
glGenTextures(1, tex);
glBindTexture(GL_TEXTURE_2D, *tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
gdr.tex_mem += width * height * 4;
gdr.tex_peak = gdr.tex_mem > gdr.tex_peak ? gdr.tex_mem : gdr.tex_peak;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
void tex_gen_fallback(uint *id, int size) {
byte *data = mem_alloc(size * size * 4, MEM_IMAGE);
tex_gen_checkerboard(data, size, size, 0xff000000, 0xffff00ff);
tex_push(id, data, size, size);
mem_free(data);
logd(LOG_GFX, STR_TEX_ILOADED, "fallback", *id);
}
void tex_push_par(uint *tex, const byte *data, const char *filename, int width, int height, byte filter, byte mipmap) {
tex_t *bind;
sys_assert(bind = (tex_t*)tbl_push(&gdr.textures));
tex_push(tex, data, width, height);
glGenerateMipmap(GL_TEXTURE_2D);
// mem_free(data);
bind->id = tex;
bind->width = width;
bind->height = height;
bind->filter = filter;
bind->mipmap = mipmap;
bind->path = filename;
tex_param(bind);
}
/*
byte tex_load_sys(uint *tex, const char *filename, byte flip) {
byte *data;
int width, height;
if(!(data = img_load(filename, &width, &height, flip, 0))) {
*tex = sys.tex_fallback;
return 0;
}
tex_push(tex, data, width, height);
mem_free(data);
logd(LOG_GFX, STR_TEX_ILOADED, filename, *tex);
return 1;
}
*/
byte tex_load(uint *tex, const char *filename, byte flags) {
byte *data;
int width, height;
if(!(data = img_load(filename, &width, &height, (flags & TEX_FLAG_FLIP) != 0, 0))) {
*tex = gdr.tex_fallback;
return 0;
}
tex_push_par(tex, data, filename, width, height, (flags & TEX_FLAG_FILTER) != 0, ((flags & TEX_FLAG_MIPMAP) != 0) ? 2 :
((flags & TEX_FLAG_NMIPMAP) != 0));
gdr.tex_loaded += 1;
mem_free(data);
logd(LOG_GFX, STR_TEX_LOADED, filename, *tex);
return 1;
}
byte img_save(const char *filename, int x, int y, byte alpha, byte flip, int stride, const byte *data) {
int len;
byte *png;
int err;
FILE *fd;
if(!(png = stbi_write_png_to_mem(data, stride, x, y, alpha ? 4 : 3, &len, flip))) {
loge(LOG_GFX, STR_TEX_ESAVE, filename);
return 0;
}
if(!(fd = fopen(filename, "wb"))) {
err = errno;
loge(LOG_GFX, STR_TEX_EWOPEN, filename, strerror(err), err);
mem_free(png);
return 0;
}
if(fwrite(png, 1, len, fd) != len) {
loge(LOG_GFX, STR_TEX_EWRITE, filename);
fclose(fd);
mem_free(png);
return 0;
}
fclose(fd);
mem_free(png);
return 1;
}