Color mixing using alpha channel now spans map blocks. So for instance, water is partly translucent to great depths. Water (or other translucent material) now also becomes darker with depth.
102 lines
2.5 KiB
C
102 lines
2.5 KiB
C
|
|
#ifndef PIXELCACHEINFO_H
|
|
#define PIXELCACHEINFO_H
|
|
|
|
#include<cmath>
|
|
#include"Color.h"
|
|
|
|
struct PixelCacheEntry {
|
|
PixelCacheEntry();
|
|
PixelCacheEntry(unsigned int color, double height=NAN);
|
|
PixelCacheEntry(const Color &color, double height=NAN);
|
|
PixelCacheEntry(const ColorEntry &entry, double height=NAN);
|
|
Color to_color(void) const;
|
|
ColorEntry to_colorEntry(void) const;
|
|
void reset(void);
|
|
void mixUnder(const PixelCacheEntry &p);
|
|
uint8_t red(void) const { return int(r*255+0.5); }
|
|
uint8_t green(void) const { return int(g*255+0.5); }
|
|
uint8_t blue(void) const { return int(b*255+0.5); }
|
|
uint8_t alpha(void) const { return int(a*255+0.5); }
|
|
uint8_t thicken(void) const { return int(t*255+0.5); }
|
|
int height(void) const { return int(h+0.5); }
|
|
|
|
double r;
|
|
double g;
|
|
double b;
|
|
double a;
|
|
double t;
|
|
double h;
|
|
int n;
|
|
};
|
|
|
|
inline PixelCacheEntry::PixelCacheEntry() :
|
|
r(0), g(0), b(0), a(0), t(0), h(NAN), n(0)
|
|
{
|
|
}
|
|
|
|
inline PixelCacheEntry::PixelCacheEntry(unsigned int color, double height) :
|
|
r(((color>>16)&0xff)/255.0), g(((color>>8)&0xff)/255.0), b((color&0xff)/255.0),
|
|
a(((color>>24)&0xff)/255.0), t(0), h(height), n(1)
|
|
{
|
|
}
|
|
|
|
inline PixelCacheEntry::PixelCacheEntry(const Color &color, double height) :
|
|
r(color.r/255.0), g(color.g/255.0), b(color.b/255.0),
|
|
a(color.a/255.0), t(0), h(height), n(1)
|
|
{
|
|
}
|
|
|
|
inline PixelCacheEntry::PixelCacheEntry(const ColorEntry &entry, double height) :
|
|
r(entry.r/255.0), g(entry.g/255.0), b(entry.b/255.0),
|
|
a(entry.a/255.0), t(entry.t/255.0), h(height), n(1)
|
|
{
|
|
}
|
|
|
|
inline Color PixelCacheEntry::to_color(void)
|
|
{
|
|
return Color(int(r*255+0.5),int(g*255+0.5),int(b*255+0.5),int(a*255+0.5));
|
|
}
|
|
|
|
inline ColorEntry PixelCacheEntry::to_colorEntry(void)
|
|
{
|
|
return ColorEntry(int(r*255+0.5),int(g*255+0.5),int(b*255+0.5),int(a*255+0.5),int(t*255+0.5));
|
|
}
|
|
|
|
inline void PixelCacheEntry::reset(void)
|
|
{
|
|
r=0; g=0; b=0; a=0; t=0; h=NAN; n=0;
|
|
}
|
|
|
|
inline void PixelCacheEntry::mixUnder(const PixelCacheEntry &p)
|
|
{
|
|
int prev_alpha = alpha();
|
|
if (!n || a==0) {
|
|
r = p.r;
|
|
g = p.g;
|
|
b = p.b;
|
|
a = p.a;
|
|
t = p.t;
|
|
h = p.h;
|
|
n = p.n;
|
|
}
|
|
else {
|
|
// Regular mix
|
|
r = (a * r + p.a * (1 - a) * p.r);
|
|
g = (a * g + p.a * (1 - a) * p.g);
|
|
b = (a * b + p.a * (1 - a) * p.b);
|
|
a = (a + (1 - a) * p.a);
|
|
t = (t + p.t) / 2;
|
|
h = p.h;
|
|
}
|
|
if (prev_alpha == 255 && p.alpha() < 255) {
|
|
// Darken
|
|
// Parameters make deep water look good :-)
|
|
r = r * (0.85 + 0.1 * (1 - p.a));
|
|
g = g * (0.85 + 0.1 * (1 - p.a));
|
|
b = b * (0.85 + 0.1 * (1 - p.a));
|
|
}
|
|
}
|
|
|
|
#endif // PIXELCACHEINFO_H
|