Better submerge effect: transparency of water decrease with depth...

...(feet are less visible)

Parameters probably need tuning, but currently hardcoded (as the old
effect was)
This commit is contained in:
Ali El Gariani 2010-09-15 05:24:59 +00:00
parent c7ee3061a2
commit fc99eb2592
3 changed files with 77 additions and 1 deletions

View File

@ -1170,12 +1170,16 @@ void display::render_image(int x, int y, const display::tdrawing_layer drawing_l
if(submerged > 0.0) {
// divide the surface into 2 parts
const int submerge_height = std::max<int>(0, surf->h*(1.0-submerged));
const int depth = surf->h - submerge_height;
SDL_Rect srcrect = create_rect(0, 0, surf->w, submerge_height);
drawing_buffer_add(drawing_layer, loc, x, y, surf, srcrect);
if(submerge_height != surf->h) {
//the lower part will be transparent
surf.assign(adjust_surface_alpha(surf,ftofxp(0.2),false));
float alpha_base = 0.3; // 30% alpha at surface of water
float alpha_delta = 0.015; // lose 1.5% per pixel depth
alpha_delta *= zoom_ / DefaultZoom; // adjust with zoom
surf = submerge_alpha(surf, depth, alpha_base, alpha_delta, false);
srcrect.y = submerge_height;
srcrect.h = surf->h-submerge_height;

View File

@ -1018,6 +1018,69 @@ bool in_mask_surface(const surface &surf, const surface &mask)
return true;
}
surface submerge_alpha(const surface &surf, int depth, float alpha_base, float alpha_delta, bool optimize)
{
if(surf== NULL) {
return NULL;
}
surface nsurf(make_neutral_surface(surf));
{
surface_lock lock(nsurf);
Uint32* beg = lock.pixels();
Uint32* limit = beg + (nsurf->h-depth) * nsurf->w ;
Uint32* end = beg + nsurf->w * nsurf->h;
beg = limit; // directlt jump to the bottom part
while(beg != end){
Uint8 alpha = (*beg) >> 24;
if(alpha) {
Uint8 r, g, b;
r = (*beg) >> 16;
g = (*beg) >> 8;
b = (*beg);
int d = (beg-limit)/nsurf->w; // current depth in pixels
float a = alpha_base - d * alpha_delta;
fixed_t amount = ftofxp(a<0?0:a);
alpha = std::min<unsigned>(unsigned(fxpmult(alpha,amount)),255);
*beg = (alpha << 24) + (r << 16) + (g << 8) + b;
}
++beg;
}
/*
for(int y = submerge_height; y < nsurf->h; ++y) {
Uint32* cur = beg + y * nsurf->w;
Uint32* row_end = beg + (y+1) * nsurf->w;
float d = y * 1.0 / depth;
double a = 0.2;//std::max<double>(0, (1-d)*0.3);
fixed_t amount = ftofxp(a);
while(cur != row_end) {
Uint8 alpha = (*cur) >> 24;
if(alpha) {
Uint8 r, g, b;
r = (*cur) >> 16;
g = (*cur) >> 8;
b = (*cur);
alpha = std::min<unsigned>(unsigned(fxpmult(alpha,amount)),255);
*cur = (alpha << 24) + (r << 16) + (g << 8) + b;
}
++cur;
}
}*/
}
return optimize ? create_optimized_surface(nsurf) : nsurf;
}
surface light_surface(const surface &surf, const surface &lightmap, bool optimize)
{
if(surf == NULL) {

View File

@ -240,6 +240,15 @@ surface mask_surface(const surface &surf, const surface &mask);
/** Check if a surface fit into a mask */
bool in_mask_surface(const surface &surf, const surface &mask);
/** Progressively reduce alpha of bottom part of the surface
* @param surf The source surface.
* @param depth The height of the bottom part in pixels
* @param alpha_base The alpha adjustement at the interface
* @param alpha_delta The alpha adjustement reduction rate by pixel depth
* @param optimize_format Optimize by converting to result to display
*/
surface submerge_alpha(const surface &surf, int depth, float alpha_base, float alpha_delta, bool optimize=true);
/** Light surf using lightmap (RGB=128,128,128 means no change) */
surface light_surface(const surface &surf, const surface &lightmap, bool optimize=true);