(experimental) make the mysterious borders around land/hats/etc that appear on zoom vanish
authorsheepluva
Sun, 19 Jan 2014 13:41:11 +0100
changeset 10016 59a6d65fcb60
parent 10014 56d2f2d5aad8
child 10018 bdf75f0350bd
(experimental) make the mysterious borders around land/hats/etc that appear on zoom vanish note: not applied to everything yet note: I'll probably merge the two functions that do the same thing (one for 1darray, one for 2darray representation of pixels) into a single function
hedgewars/uLand.pas
hedgewars/uTextures.pas
--- a/hedgewars/uLand.pas	Sun Jan 19 00:18:28 2014 +0400
+++ b/hedgewars/uLand.pas	Sun Jan 19 13:41:11 2014 +0100
@@ -60,6 +60,61 @@
     end;
 end;
 
+{ this will make invisible pixels that have a visible neighbor have the
+  same color as their visible neighbor, so that bilinear filtering won't
+  display a "wrongly" colored border when zoomed in }
+procedure PrettifyLandAlpha();
+var
+    x, y, lastx, lasty: Longword;
+    lpi, cpi, bpi: boolean; // was last/current/bottom neighbor pixel invisible?
+begin
+    lasty:= LAND_HEIGHT - 1;
+    lastx:= LAND_WIDTH - 1;
+    if (cReducedQuality and rqBlurryLand) <> 0 then
+        begin
+        lasty:= lasty div 2;
+        lastx:= lastx div 2;
+        end;
+    for y:= 0 to lasty do
+        for x:= 0 to lastx do
+            begin
+            // use first pixel in row as starting point
+            //LandPixels[y, x]:= (LandPixels[y, x] and (BMask or GMask or AMask));
+            if x = 0 then
+                lpi:= ((LandPixels[y, x] and AMask) = 0)
+            else
+                begin
+                cpi:= ((LandPixels[y, x] and AMask) = 0);
+                if lpi <> cpi then
+                    begin
+                    // invisible pixels get colors from visible neighbors
+                    if cpi then
+                        begin
+                        LandPixels[y, x]:= LandPixels[y, x-1] and not AMask;
+                        // as this pixel is invisible and already colored correctly now, no point in further comparing it
+                        lpi:= cpi;
+                        continue;
+                        end
+                    else
+                        LandPixels[y, x-1]:= LandPixels[y, x] and not AMask;
+                    lpi:= cpi;
+                    end;
+                end;
+            // also check bottom neighbor, lpi is now current pixel info
+            if y < lasty - 1 then
+                begin
+                bpi:= ((LandPixels[y+1, x] and AMask) = 0);
+                if cpi <> bpi then
+                    begin
+                    if cpi then
+                        LandPixels[y, x]:= LandPixels[y+1, x] and not AMask
+                    else
+                        LandPixels[y+1, x]:= LandPixels[y, x] and not AMask;
+                    end;
+                end
+            end;
+end;
+
 
 procedure DrawBorderFromImage(Surface: PSDL_Surface);
 var tmpsurf: PSDL_Surface;
@@ -811,6 +866,8 @@
                 LandPixels[y,x]:= w or (LandPixels[y div 2, x div 2] and AMask)
                 end
     end;
+
+PrettifyLandAlpha();
 end;
 
 procedure GenPreview(out Preview: TPreview);
--- a/hedgewars/uTextures.pas	Sun Jan 19 00:18:28 2014 +0400
+++ b/hedgewars/uTextures.pas	Sun Jan 19 13:41:11 2014 +0100
@@ -25,6 +25,7 @@
 function  NewTexture(width, height: Longword; buf: Pointer): PTexture;
 procedure Surface2GrayScale(surf: PSDL_Surface);
 function  Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
+procedure PrettifySurfaceAlpha(surf: PSDL_Surface; p: PLongwordArray);
 procedure FreeTexture(tex: PTexture);
 procedure FreeAndNilTexture(var tex: PTexture);
 
@@ -121,6 +122,53 @@
     end;
 end;
 
+{ this will make invisible pixels that have a visible neighbor have the
+  same color as their visible neighbor, so that bilinear filtering won't
+  display a "wrongly" colored border when zoomed in }
+procedure PrettifySurfaceAlpha(surf: PSDL_Surface; p: PLongwordArray);
+var
+    i, lasti: Longword;
+    lpi, cpi, bpi: boolean; // was last/current/bottom neighbor pixel invisible?
+begin
+    lasti:= surf^.w * surf^.h - 1;
+    for i:=0 to lasti do
+        begin
+        // use first pixel in row as starting point
+        //p^[i]:= p^[i] and (BMask or GMask);
+        if (i mod surf^.w) = 0 then
+            lpi:= ((p^[i] and AMask) = 0)
+        else
+            begin
+            cpi:= ((p^[i] and AMask) = 0);
+            if cpi <> lpi then
+                begin
+                // invisible pixels get colors from visible neighbors
+                if (p^[i] and AMask) = 0 then
+                    begin
+                    p^[i]:= p^[i-1] and not AMask;
+                    // as this pixel is invisible and already colored correctly now, no point in further comparing it
+                    lpi:= cpi;
+                    continue;
+                    end
+                else
+                    p^[i-1]:= p^[i] and not AMask;
+                lpi:= cpi;
+                end;
+            end;
+        // also check bottom neighbor, lpi is now current pixel info
+        if i < lasti - surf^.w then
+            begin
+            bpi:= ((p^[i + surf^.w] and AMask) = 0);
+            if cpi <> bpi then
+                begin
+                if cpi then
+                    p^[i]:= p^[i + surf^.w] and not AMask
+                else
+                    p^[i + surf^.w]:= p^[i] and not AMask;
+                end;
+            end;
+        end;
+end;
 
 function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
 var tw, th, x, y: Longword;
@@ -148,7 +196,6 @@
     exit
     end;
 
-
 glGenTextures(1, @Surface2Tex^.id);
 
 glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id);
@@ -161,6 +208,8 @@
 if GrayScale then
     Surface2GrayScale(Surf);
 
+PrettifySurfaceAlpha(surf, fromP4);
+
 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then
     begin
     tw:= toPowerOf2(Surf^.w);