From b16885555b024172f010e7d1b9865f6341ba3d43 Mon Sep 17 00:00:00 2001 From: quou Date: Wed, 25 Dec 2024 21:59:36 +1100 Subject: fix BC1 compressor --- convtexture.c | 76 ++++++++++++++++++++++++++++++------------ intermediate/triangle.glsl | 2 +- testbc1.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 22 deletions(-) create mode 100644 testbc1.c diff --git a/convtexture.c b/convtexture.c index a04e3c9..2670b59 100644 --- a/convtexture.c +++ b/convtexture.c @@ -29,10 +29,19 @@ const char* format_names[] = { #undef x }; +unsigned encode_endpoint(const vec3* v) { + return + ((unsigned)(v->r * 31.9999f) << 11) | + ((unsigned)(v->g * 63.9999f) << 5) | + ((unsigned)(v->b * 31.9999f)); +} + void get_block(Block* block, Colour* pixels, int stride) { int x, y, i; vec3 cols[4 * 4]; + vec3 palette[3]; vec3 s, e; + unsigned es, ee; float cd; for (y = 0; y < 4; y++) { for (x = 0; x < 4; x++) { @@ -61,19 +70,48 @@ void get_block(Block* block, Colour* pixels, int stride) { } } } + es = encode_endpoint(&s); + ee = encode_endpoint(&e); + if (es == ee) { + block->start = s; + block->end.r = 0.0f; + block->end.g = 0.0f; + block->end.b = 0.0f; + for (i = 0; i < 16; i++) { + block->indices[i] = 0; + } + return; + } + if (es < ee) { + /* todo alpha */ + vec3 t = s; + s = e; + e = t; + } + palette[0] = s; + palette[1] = e; + palette[2].r = 0.666666f*palette[0].r + 0.333333f*palette[1].r; + palette[2].g = 0.666666f*palette[0].g + 0.333333f*palette[1].g; + palette[2].b = 0.666666f*palette[0].b + 0.333333f*palette[1].b; + palette[3].r = 0.333333f*palette[0].r + 0.666666f*palette[1].r; + palette[3].g = 0.333333f*palette[0].g + 0.666666f*palette[1].g; + palette[3].b = 0.333333f*palette[0].b + 0.666666f*palette[1].b; for (i = 0; i < 4 * 4; i++) { vec3* col = &cols[i]; - float d; - d = - (e.r - col->r) * (e.r - col->r) + - (e.g - col->g) * (e.g - col->g) + - (e.b - col->b) * (e.b - col->b); - if (cd < 0.0001f) - block->indices[i] = 0; - else { - d = d / cd; - block->indices[i] = (int)((1.0f - d) * 3.1f); + int closest = 0, j; + float cd = 99999.0f; + for (j = 0; j < 4; j++) { + vec3* p = &palette[j]; + float d = + (p->r - col->r) * (p->r - col->r) + + (p->g - col->g) * (p->g - col->g) + + (p->b - col->b) * (p->b - col->b); + if (d < cd) { + cd = d; + closest = j; + } } + block->indices[i] = closest; } block->start = s; block->end = e; @@ -81,19 +119,15 @@ void get_block(Block* block, Colour* pixels, int stride) { void compress_block(const Block* block, FILE* f) { int i; - unsigned start = - ((unsigned)(block->start.r * 31.9999f) << 11) | - ((unsigned)(block->start.g * 63.9999f) << 5) | - ((unsigned)(block->start.b * 31.9999f)); - unsigned end = - ((unsigned)(block->end.r * 31.9999f) << 11) | - ((unsigned)(block->end.g * 63.9999f) << 5) | - ((unsigned)(block->end.b * 31.9999f)); - unsigned palette = (start << 16) | end; + unsigned start = encode_endpoint(&block->start); + unsigned end = encode_endpoint(&block->end); unsigned indices = 0; - fwrite(&palette, 1, 4, f); + fwrite(&start, 1, 2, f); + fwrite(&end, 1, 2, f); for (i = 0; i < 4 * 4; i++) { - indices |= block->indices[i] << (i * 2); + int idx = (4 * 4 - 1) - i; + idx = i; + indices |= block->indices[i] << (idx * 2); } fwrite(&indices, 1, 4, f); } diff --git a/intermediate/triangle.glsl b/intermediate/triangle.glsl index beee129..8f3b586 100644 --- a/intermediate/triangle.glsl +++ b/intermediate/triangle.glsl @@ -49,7 +49,7 @@ void main() { void main() { vec3 c = texture(colour_texture, interpolator.uv).rgb; -// c *= interpolator.colour; + c *= interpolator.colour; colour = vec4(c, 1.0); } diff --git a/testbc1.c b/testbc1.c new file mode 100644 index 0000000..1ae5a3e --- /dev/null +++ b/testbc1.c @@ -0,0 +1,82 @@ +#include +#include + +typedef struct { + unsigned char r, g, b, a; +} Colour; + +typedef struct { + float r, g, b; +} vec3; + +void lerp(vec3* d, const vec3* a, const vec3* b, float t) { + d->r = a->r + t * (b->r - a->r); + d->g = a->g + t * (b->g - a->g); + d->b = a->b + t * (b->b - a->b); +} + +Colour get_pixel(unsigned* data, int x, int y, int w) { + vec3 c[4]; + float t; + int i; + Colour r = { 0 }; + unsigned palette = data[(x / 4 + y / 4 * (w / 4)) * 2]; + unsigned indices = data[(x / 4 + y / 4 * (w / 4)) * 2 + 1]; + c[0].r = (float)((palette & (31 << 11)) >> 11) / 32.0f; + c[0].g = (float)((palette & (63 << 5)) >> 5) / 64.0f; + c[0].b = (float)((palette & (31 )) ) / 32.0f; + c[1].r = (float)((palette & (31 << 27)) >> 27) / 32.0f; + c[1].g = (float)((palette & (63 << 21)) >> 21) / 64.0f; + c[1].b = (float)((palette & (31 << 16)) >> 16) / 32.0f; + c[2].r = 2.0f/3.0f*c[0].r + 1.0f/3.0f*c[1].r; + c[2].g = 2.0f/3.0f*c[0].g + 1.0f/3.0f*c[1].g; + c[2].b = 2.0f/3.0f*c[0].b + 1.0f/3.0f*c[1].b; + c[3].r = 1.0f/3.0f*c[0].r + 2.0f/3.0f*c[1].r; + c[3].g = 1.0f/3.0f*c[0].g + 2.0f/3.0f*c[1].g; + c[3].b = 1.0f/3.0f*c[0].b + 2.0f/3.0f*c[1].b; + i = x % 4 + (y % 4) * 4; + i = (indices & (3 << i * 2)) >> i * 2; + r.r = (int)(c[i].r * 255.0f); + r.g = (int)(c[i].g * 255.0f); + r.b = (int)(c[i].b * 255.0f); + return r; +} + +int main(int argc, const char** argv) { + FILE* infile, * outfile; + unsigned* data; + int w, h, x, y, cw, ch; + unsigned palette, indices; + vec3 colour; + if (argc < 3) { + fprintf(stderr, "Usage: %s infile outfile.\n", argv[0]); + return 1; + } + infile = fopen(argv[1], "rb"); + if (!infile) { + fprintf(stderr, "Failed to open %s.\n", argv[1]); + return 2; + } + outfile = fopen(argv[2], "w"); + if (!infile) { + fprintf(stderr, "Failed to open %s.\n", argv[2]); + return 3; + } + fseek(infile, 4, SEEK_SET); + fread(&w, 1, 4, infile); + fread(&h, 1, 4, infile); + fseek(infile, 4, SEEK_CUR); + cw = w / 4; + ch = h / 4; + data = malloc(cw * ch * 8); + fread(data, 1, cw * ch * 8, infile); + fprintf(outfile, "P3\n"); + fprintf(outfile, "%d %d\n", w, h); + fprintf(outfile, "255\n"); + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + Colour c = get_pixel(data, x, y, w); + fprintf(outfile, "%d %d %d\n", c.r, c.g, c.b); + } + } +} -- cgit v1.2.3-54-g00ecf