improve sw renderer
This commit is contained in:
parent
415d424057
commit
39ee0fefb7
89 changed files with 9380 additions and 2307 deletions
|
|
@ -5,10 +5,18 @@
|
|||
|
||||
#include "pxl8_ase.h"
|
||||
#include "pxl8_color.h"
|
||||
#include "pxl8_colormap.h"
|
||||
#include "pxl8_log.h"
|
||||
#include "pxl8_mem.h"
|
||||
|
||||
#define PXL8_PALETTE_HASH_SIZE 512
|
||||
|
||||
struct pxl8_palette_cube {
|
||||
u8 colors[PXL8_PALETTE_SIZE * 3];
|
||||
u8 table[PXL8_CUBE_ENTRIES];
|
||||
u8 stable[PXL8_CUBE_ENTRIES];
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u32 color;
|
||||
i16 index;
|
||||
|
|
@ -200,7 +208,7 @@ static void update_cycle_colors(pxl8_palette* pal, u8 slot) {
|
|||
}
|
||||
|
||||
pxl8_palette* pxl8_palette_create(void) {
|
||||
pxl8_palette* pal = calloc(1, sizeof(pxl8_palette));
|
||||
pxl8_palette* pal = pxl8_calloc(1, sizeof(pxl8_palette));
|
||||
if (!pal) return NULL;
|
||||
|
||||
pal->colors[0] = 0x00000000;
|
||||
|
|
@ -221,7 +229,7 @@ pxl8_palette* pxl8_palette_create(void) {
|
|||
}
|
||||
|
||||
void pxl8_palette_destroy(pxl8_palette* pal) {
|
||||
free(pal);
|
||||
pxl8_free(pal);
|
||||
}
|
||||
|
||||
pxl8_result pxl8_palette_load_ase(pxl8_palette* pal, const char* path) {
|
||||
|
|
@ -332,10 +340,6 @@ void pxl8_palette_get_rgba(const pxl8_palette* pal, u8 idx, u8* r, u8* g, u8* b,
|
|||
unpack_rgba(pal->colors[idx], r, g, b, a);
|
||||
}
|
||||
|
||||
void pxl8_palette_set(pxl8_palette* pal, u8 idx, u32 color) {
|
||||
if (pal) pal->colors[idx] = color;
|
||||
}
|
||||
|
||||
void pxl8_palette_set_rgb(pxl8_palette* pal, u8 idx, u8 r, u8 g, u8 b) {
|
||||
if (pal) pal->colors[idx] = pack_rgb(r, g, b);
|
||||
}
|
||||
|
|
@ -344,6 +348,17 @@ void pxl8_palette_set_rgba(pxl8_palette* pal, u8 idx, u8 r, u8 g, u8 b, u8 a) {
|
|||
if (pal) pal->colors[idx] = pack_rgba(r, g, b, a);
|
||||
}
|
||||
|
||||
void pxl8_set_palette(pxl8_palette* pal, const u32* colors, u16 count) {
|
||||
if (!pal || !colors) return;
|
||||
for (u16 i = 0; i < count; i++) {
|
||||
u32 rgb = colors[i];
|
||||
u8 r = (rgb >> 16) & 0xFF;
|
||||
u8 g = (rgb >> 8) & 0xFF;
|
||||
u8 b = rgb & 0xFF;
|
||||
pal->colors[i] = pack_rgb(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
void pxl8_palette_fill_gradient(pxl8_palette* pal, u8 start, u8 count, u32 from, u32 to) {
|
||||
if (!pal || count == 0) return;
|
||||
|
||||
|
|
@ -472,3 +487,91 @@ pxl8_cycle_range pxl8_cycle_range_disabled(void) {
|
|||
};
|
||||
return range;
|
||||
}
|
||||
|
||||
static u8 find_closest_stable(const pxl8_palette* pal, u8 r, u8 g, u8 b) {
|
||||
u8 best_idx = 1;
|
||||
u32 best_dist = 0xFFFFFFFF;
|
||||
|
||||
u8 dynamic_end = PXL8_DYNAMIC_RANGE_START + PXL8_DYNAMIC_RANGE_COUNT;
|
||||
|
||||
for (u32 i = 1; i < PXL8_FULLBRIGHT_START; i++) {
|
||||
if (i >= PXL8_DYNAMIC_RANGE_START && i < dynamic_end) {
|
||||
continue;
|
||||
}
|
||||
|
||||
u8 pr, pg, pb;
|
||||
pxl8_palette_get_rgb(pal, (u8)i, &pr, &pg, &pb);
|
||||
|
||||
i32 dr = (i32)r - (i32)pr;
|
||||
i32 dg = (i32)g - (i32)pg;
|
||||
i32 db = (i32)b - (i32)pb;
|
||||
u32 dist = (u32)(dr * dr + dg * dg + db * db);
|
||||
|
||||
if (dist < best_dist) {
|
||||
best_dist = dist;
|
||||
best_idx = (u8)i;
|
||||
if (dist == 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
return best_idx;
|
||||
}
|
||||
|
||||
pxl8_palette_cube* pxl8_palette_cube_create(const pxl8_palette* pal) {
|
||||
pxl8_palette_cube* cube = pxl8_calloc(1, sizeof(pxl8_palette_cube));
|
||||
if (!cube) return NULL;
|
||||
pxl8_palette_cube_rebuild(cube, pal);
|
||||
return cube;
|
||||
}
|
||||
|
||||
void pxl8_palette_cube_destroy(pxl8_palette_cube* cube) {
|
||||
pxl8_free(cube);
|
||||
}
|
||||
|
||||
void pxl8_palette_cube_rebuild(pxl8_palette_cube* cube, const pxl8_palette* pal) {
|
||||
if (!cube || !pal) return;
|
||||
|
||||
for (u32 i = 0; i < PXL8_PALETTE_SIZE; i++) {
|
||||
u8 r, g, b;
|
||||
pxl8_palette_get_rgb(pal, (u8)i, &r, &g, &b);
|
||||
cube->colors[i * 3 + 0] = r;
|
||||
cube->colors[i * 3 + 1] = g;
|
||||
cube->colors[i * 3 + 2] = b;
|
||||
}
|
||||
|
||||
for (u32 bi = 0; bi < PXL8_CUBE_SIZE; bi++) {
|
||||
for (u32 gi = 0; gi < PXL8_CUBE_SIZE; gi++) {
|
||||
for (u32 ri = 0; ri < PXL8_CUBE_SIZE; ri++) {
|
||||
u32 idx = (bi * PXL8_CUBE_SIZE * PXL8_CUBE_SIZE) + (gi * PXL8_CUBE_SIZE) + ri;
|
||||
u8 r8 = (u8)((ri * 255) / (PXL8_CUBE_SIZE - 1));
|
||||
u8 g8 = (u8)((gi * 255) / (PXL8_CUBE_SIZE - 1));
|
||||
u8 b8 = (u8)((bi * 255) / (PXL8_CUBE_SIZE - 1));
|
||||
|
||||
cube->table[idx] = pxl8_palette_find_closest(pal, r8, g8, b8);
|
||||
cube->stable[idx] = find_closest_stable(pal, r8, g8, b8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 pxl8_palette_cube_lookup(const pxl8_palette_cube* cube, u8 r, u8 g, u8 b) {
|
||||
u32 ri = (r * (PXL8_CUBE_SIZE - 1)) / 255;
|
||||
u32 gi = (g * (PXL8_CUBE_SIZE - 1)) / 255;
|
||||
u32 bi = (b * (PXL8_CUBE_SIZE - 1)) / 255;
|
||||
u32 idx = (bi * PXL8_CUBE_SIZE * PXL8_CUBE_SIZE) + (gi * PXL8_CUBE_SIZE) + ri;
|
||||
return cube->table[idx];
|
||||
}
|
||||
|
||||
u8 pxl8_palette_cube_lookup_stable(const pxl8_palette_cube* cube, u8 r, u8 g, u8 b) {
|
||||
u32 ri = (r * (PXL8_CUBE_SIZE - 1)) / 255;
|
||||
u32 gi = (g * (PXL8_CUBE_SIZE - 1)) / 255;
|
||||
u32 bi = (b * (PXL8_CUBE_SIZE - 1)) / 255;
|
||||
u32 idx = (bi * PXL8_CUBE_SIZE * PXL8_CUBE_SIZE) + (gi * PXL8_CUBE_SIZE) + ri;
|
||||
return cube->stable[idx];
|
||||
}
|
||||
|
||||
void pxl8_palette_cube_get_rgb(const pxl8_palette_cube* cube, u8 idx, u8* r, u8* g, u8* b) {
|
||||
*r = cube->colors[idx * 3 + 0];
|
||||
*g = cube->colors[idx * 3 + 1];
|
||||
*b = cube->colors[idx * 3 + 2];
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue