summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorquou <quou@disroot.org>2024-12-25 21:59:36 +1100
committerquou <quou@disroot.org>2024-12-25 21:59:36 +1100
commitb16885555b024172f010e7d1b9865f6341ba3d43 (patch)
tree70897cd2faf05fdadc5e047f3bbbf8ef1db5c9a4
parent51ee5b67b65a8409da3b5ddd8a61c4237cf2adef (diff)
fix BC1 compressor
-rw-r--r--convtexture.c76
-rw-r--r--intermediate/triangle.glsl2
-rw-r--r--testbc1.c82
3 files changed, 138 insertions, 22 deletions
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 <stdio.h>
+#include <stdlib.h>
+
+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);
+ }
+ }
+}