ref: 7240eb5e3f0f766939ab5f14add6384b286d253a
dir: /d_alpha.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "quakedef.h" #include "fns.h" /* FIXME(sigrid): this is super dumb. * * how it SHOULD be done: * 1) no point in 256 alphamaps, a'=255-a → (x->a->y) ≡ (y->a'->x) * 1.1) these are 8-bit colors, no way there are *different* variations for each alpha * eg: x=3, y=9 → a≠a' → there is a very high chance (x->a->y) = (x->a'->y) if a is close to a' * 2) use k-d (3-d in this case) tree to look up colors faster * 3) if it's fast enough, can build all alpha maps just once on startup * 4) try different color models, this alpha blending looks like crap with liquids */ byte *alphamap[256]; void buildalpha(int alpha) { extern s32int fbpal[256]; int a, b; byte *ca, *cb, *p; int rr, gg, bb; int i, dst, x, best; if(alphamap[alpha] != nil) return; alphamap[alpha] = malloc(256*256); p = (byte*)fbpal; ca = p; for(a = 0; a < 256; a++, ca += 4){ cb = p; for(b = 0; b < 256; b++, cb++){ rr = (alpha*ca[0] + (255 - alpha)*(*cb++))>>8; gg = (alpha*ca[1] + (255 - alpha)*(*cb++))>>8; bb = (alpha*ca[2] + (255 - alpha)*(*cb++))>>8; dst = 9999999; best = 255; for(i = 0; i < 768; i += 4){ x = (rr-p[i+0])*(rr-p[i+0]) + (gg-p[i+1])*(gg-p[i+1]) + (bb-p[i+2])*(bb-p[i+2]); if(x < dst){ dst = x; best = i; } } alphamap[alpha][a<<8 | b] = best/4; } } } float alphafor(int flags) { if(flags & (SURF_TELE|SURF_FENCE)) return 1.0; if(flags & SURF_LAVA) return r_lavaalpha.value; if(flags & SURF_SLIME) return r_slimealpha.value; return r_wateralpha.value; }