shithub: qk1

ref: e7c5e21800899bc725cf85d5c1e766ddc3efc187
dir: /r_fog.h/

View raw version
typedef struct fog_t fog_t;

struct fog_t {
	pixel64_t v;
	pixel64_t d;
};

#define fogstep(f) do{ \
		(f).v += (f).d; \
	}while(0)

static inline byte
z2foga(uzint z)
{
	float d;
	unsigned x;

	if(z <= 0)
		return 0;
	x = 0xffffffffU / z;
	d = exp2f(-fogvars.density * x * x);
	return 255 - 255*d;
}

static inline pixel64_t
pixto64(pixel_t p)
{
	return
		(pixel64_t)((p>>24)&0xff)<<56 |
		(pixel64_t)((p>>16)&0xff)<<40 |
		(pixel64_t)((p>> 8)&0xff)<<24 |
		(pixel64_t)((p>> 0)&0xff)<< 8;
}

static inline pixel_t
pixfrom64(pixel64_t p)
{
	return ((p>>56)&0xff)<<24 | ((p>>40)&0xff)<<16 | ((p>>24)&0xff)<<8 | ((p>>8)&0xff)<<0;
}

static inline pixel_t
blendfog(pixel_t pix, fog_t fog)
{
	pixel_t a = pixfrom64(fog.v);
	pixel_t b = mulalpha(pix, 0xff - (fog.v>>56));
	return a + b;
}

static inline bool
fogcalc(uzint zi0, uzint zi1, int cnt, fog_t *f)
{
	int v, e;
	pixel64_t x;

	if((v = z2foga(zi0)) == 0 || (e = z2foga(zi1)) == 0)
		return false;

	f->v = pixto64(mulalpha(fogvars.pix, v));
	x = pixto64(mulalpha(fogvars.pix, (e<v ? v-e : e-v)));
	f->d =
		(((x & (0xffffULL<<48))/cnt) & (0xffffULL<<48)) |
		(((x & (0xffffULL<<32))/cnt) & (0xffffULL<<32)) |
		(((x & (0xffffULL<<16))/cnt) & (0xffffULL<<16)) |
		(((x & (0xffffULL<< 0))/cnt) & (0xffffULL<< 0));
	if(e < v)
		f->d = -f->d;

	return true;
}