tweak/refactor how water is drawn
authorsheepluva
Wed, 18 Jun 2014 15:42:01 +0200
changeset 10325 7315870716f2
parent 10324 5d90d8ca9657
child 10326 1748eed62a95
tweak/refactor how water is drawn
hedgewars/uLandObjects.pas
hedgewars/uRender.pas
hedgewars/uVariables.pas
hedgewars/uWorld.pas
--- a/hedgewars/uLandObjects.pas	Wed Jun 18 01:37:28 2014 +0200
+++ b/hedgewars/uLandObjects.pas	Wed Jun 18 15:42:01 2014 +0200
@@ -471,7 +471,7 @@
 // Set default water greyscale values
 if GrayScale then
     begin
-    for i:= 0 to 3 do
+    for i:= Low(SDWaterColorArray) to High(SDWaterColorArray) do
         begin
         t:= round(SDWaterColorArray[i].r * RGB_LUMINANCE_RED + SDWaterColorArray[i].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[i].b * RGB_LUMINANCE_BLUE);
         if t > 255 then
@@ -480,7 +480,7 @@
         SDWaterColorArray[i].g:= t;
         SDWaterColorArray[i].b:= t
         end;
-    for i:= 0 to 1 do
+    for i:= Low(WaterColorArray) to High(WaterColorArray) do
         begin
         t:= round(WaterColorArray[i].r * RGB_LUMINANCE_RED + WaterColorArray[i].g * RGB_LUMINANCE_GREEN + WaterColorArray[i].b * RGB_LUMINANCE_BLUE);
         if t > 255 then
@@ -558,6 +558,29 @@
     else if key = 'water-top' then
         begin
         i:= Pos(',', s);
+        WaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+        Delete(s, 1, i);
+        i:= Pos(',', s);
+        WaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+        Delete(s, 1, i);
+        WaterColorArray[1].b:= StrToInt(Trim(s));
+        WaterColorArray[1].a := 255;
+        if GrayScale then
+            begin
+            t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE);
+            if t > 255 then
+                t:= 255;
+            WaterColorArray[1].r:= t;
+            WaterColorArray[1].g:= t;
+            WaterColorArray[1].b:= t
+            end;
+        WaterColorArray[3]:= WaterColorArray[1];
+        WaterColorArray[5]:= WaterColorArray[1];
+        WaterColorArray[7]:= WaterColorArray[1];
+        end
+    else if key = 'water-bottom' then
+        begin
+        i:= Pos(',', s);
         WaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
         Delete(s, 1, i);
         i:= Pos(',', s);
@@ -567,35 +590,16 @@
         WaterColorArray[0].a := 255;
         if GrayScale then
             begin
-            t:= round(WaterColorArray[0].r * RGB_LUMINANCE_RED + WaterColorArray[0].g * RGB_LUMINANCE_GREEN + WaterColorArray[0].b * RGB_LUMINANCE_BLUE);
+            t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE);
             if t > 255 then
                 t:= 255;
             WaterColorArray[0].r:= t;
             WaterColorArray[0].g:= t;
             WaterColorArray[0].b:= t
             end;
-        WaterColorArray[1]:= WaterColorArray[0];
-        end
-    else if key = 'water-bottom' then
-        begin
-        i:= Pos(',', s);
-        WaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
-        Delete(s, 1, i);
-        i:= Pos(',', s);
-        WaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
-        Delete(s, 1, i);
-        WaterColorArray[2].b:= StrToInt(Trim(s));
-        WaterColorArray[2].a := 255;
-        if GrayScale then
-            begin
-            t:= round(WaterColorArray[2].r * RGB_LUMINANCE_RED + WaterColorArray[2].g * RGB_LUMINANCE_GREEN + WaterColorArray[2].b * RGB_LUMINANCE_BLUE);
-            if t > 255 then
-                t:= 255;
-            WaterColorArray[2].r:= t;
-            WaterColorArray[2].g:= t;
-            WaterColorArray[2].b:= t
-            end;
-        WaterColorArray[3]:= WaterColorArray[2];
+        WaterColorArray[2]:= WaterColorArray[0];
+        WaterColorArray[4]:= WaterColorArray[0];
+        WaterColorArray[6]:= WaterColorArray[0];
         end
     else if key = 'water-opacity' then
         begin
@@ -713,6 +717,29 @@
     else if key = 'sd-water-top' then
         begin
         i:= Pos(',', s);
+        SDWaterColorArray[1].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+        Delete(s, 1, i);
+        i:= Pos(',', s);
+        SDWaterColorArray[1].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
+        Delete(s, 1, i);
+        SDWaterColorArray[1].b:= StrToInt(Trim(s));
+        SDWaterColorArray[1].a := 255;
+        if GrayScale then
+            begin
+            t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE);
+            if t > 255 then
+                t:= 255;
+            SDWaterColorArray[1].r:= t;
+            SDWaterColorArray[1].g:= t;
+            SDWaterColorArray[1].b:= t
+            end;
+        SDWaterColorArray[3]:= SDWaterColorArray[1];
+        SDWaterColorArray[5]:= SDWaterColorArray[1];
+        SDWaterColorArray[7]:= SDWaterColorArray[1];
+        end
+    else if key = 'sd-water-bottom' then
+        begin
+        i:= Pos(',', s);
         SDWaterColorArray[0].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
         Delete(s, 1, i);
         i:= Pos(',', s);
@@ -722,35 +749,16 @@
         SDWaterColorArray[0].a := 255;
         if GrayScale then
             begin
-            t:= round(SDWaterColorArray[0].r * RGB_LUMINANCE_RED + SDWaterColorArray[0].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[0].b * RGB_LUMINANCE_BLUE);
+            t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE);
             if t > 255 then
                 t:= 255;
             SDWaterColorArray[0].r:= t;
             SDWaterColorArray[0].g:= t;
             SDWaterColorArray[0].b:= t
             end;
-        SDWaterColorArray[1]:= SDWaterColorArray[0];
-        end
-    else if key = 'sd-water-bottom' then
-        begin
-        i:= Pos(',', s);
-        SDWaterColorArray[2].r:= StrToInt(Trim(Copy(s, 1, Pred(i))));
-        Delete(s, 1, i);
-        i:= Pos(',', s);
-        SDWaterColorArray[2].g:= StrToInt(Trim(Copy(s, 1, Pred(i))));
-        Delete(s, 1, i);
-        SDWaterColorArray[2].b:= StrToInt(Trim(s));
-        SDWaterColorArray[2].a := 255;
-        if GrayScale then
-            begin
-            t:= round(SDWaterColorArray[2].r * RGB_LUMINANCE_RED + SDWaterColorArray[2].g * RGB_LUMINANCE_GREEN + SDWaterColorArray[2].b * RGB_LUMINANCE_BLUE);
-            if t > 255 then
-                t:= 255;
-            SDWaterColorArray[2].r:= t;
-            SDWaterColorArray[2].g:= t;
-            SDWaterColorArray[2].b:= t
-            end;
-        SDWaterColorArray[3]:= SDWaterColorArray[2];
+        SDWaterColorArray[2]:= SDWaterColorArray[0];
+        SDWaterColorArray[4]:= SDWaterColorArray[0];
+        SDWaterColorArray[6]:= SDWaterColorArray[0];
         end
     else if key = 'sd-water-opacity' then
         SDWaterOpacity:= StrToInt(Trim(s))
--- a/hedgewars/uRender.pas	Wed Jun 18 01:37:28 2014 +0200
+++ b/hedgewars/uRender.pas	Wed Jun 18 15:42:01 2014 +0200
@@ -54,7 +54,7 @@
 procedure DrawRect              (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
 procedure DrawScreenWidget      (widget: POnScreenWidget);
-procedure DrawWaterBody         (pVertexBuffer: Pointer);
+procedure DrawWater             (Alpha: byte; OffsetY, OffsetX: LongInt);
 
 procedure RenderClear           ();
 procedure RenderSetClearColor      (r, g, b, a: real);
@@ -1290,22 +1290,137 @@
     openglUseColorOnly(false);
 end;
 
-procedure DrawWaterBody(pVertexBuffer: Pointer);
+procedure DrawWater(Alpha: byte; OffsetY, OffsetX: LongInt);
+var VertexBuffer : array [0..7] of TVertex2f;
+    watertop, lx, rx, firsti, afteri, n: LongInt;
 begin
-        UpdateModelviewProjection;
+
+// those
+firsti:= -1;
+afteri:=  0;
+
+watertop:= OffsetY + WorldDy + cWaterLine;
+
+if watertop < 0 then
+    watertop:= 0;
+
+// if no walls are needed, then bottom water surface spans full view width
+if (WorldEdge <> weSea) then
+    begin
+    lx:= ViewLeftX;
+    rx:= ViewRightX;
+    end
+else
+    begin
+    lx:= LeftX  + WorldDx - OffsetX;
+    rx:= RightX + WorldDx + OffsetX;
 
-        BeginWater;
+    if lx > ViewLeftX then
+        begin
+        VertexBuffer[0].X:= ViewLeftX;
+        VertexBuffer[0].Y:= ViewTopY;
+        VertexBuffer[1].X:= lx;
+        VertexBuffer[1].Y:= ViewTopY;
+        // shares vertices 2 and 3 with bottom water
+        firsti:= 0;
+        afteri:= 4;
+        end;
+
+    if rx < ViewRightX then
+        begin
+        VertexBuffer[6].X:= ViewRightX;
+        VertexBuffer[6].Y:= ViewTopY;
+        VertexBuffer[7].X:= rx;
+        VertexBuffer[7].Y:= ViewTopY;
+        // shares vertices 4 and 5 with bottom water
+        if firsti < 0 then
+            firsti:= 4;
+        afteri:= 8;
+        end;
+    end;
+
+if watertop < ViewBottomY then
+    begin
+    // shares vertices 2-5 with water walls
+
+    // starts at vertex 2
+    if (firsti < 0) or (firsti > 2) then
+        firsti:= 2;
+    // ends at vertex 5
+    if afteri < 6 then
+        afteri:= 6;
+    end;
+
+if firsti < 0 then
+    exit; // nothing to draw at all!
 
-        if SuddenDeathDmg then
-            SetColorPointer(@SDWaterColorArray[0], 4)
-        else
-            SetColorPointer(@WaterColorArray[0], 4);
+if firsti < 4 then
+    begin
+    VertexBuffer[2].X:= ViewLeftX;
+    VertexBuffer[2].Y:= ViewBottomY;
+    VertexBuffer[3].X:= lx;
+    VertexBuffer[3].Y:= watertop;
+    end;
+
+if afteri > 4 then
+    begin
+    VertexBuffer[4].X:= ViewRightX;
+    VertexBuffer[4].Y:= ViewBottomY;
+    VertexBuffer[5].X:= rx;
+    VertexBuffer[5].Y:= watertop;
+    end;
+
+// number of points to draw
+n:= afteri - firsti;
+
+// drawing time
+
+UpdateModelviewProjection;
+
+BeginWater;
 
-        SetVertexPointer(pVertexBuffer, 4);
+if SuddenDeathDmg then
+    begin // only set alpha if it differs from what we want
+    if SDWaterColorArray[0].a <> Alpha then
+        begin
+        SDWaterColorArray[0].a := Alpha;
+        SDWaterColorArray[1].a := Alpha;
+        SDWaterColorArray[2].a := Alpha;
+        SDWaterColorArray[3].a := Alpha;
+        SDWaterColorArray[4].a := Alpha;
+        SDWaterColorArray[5].a := Alpha;
+        SDWaterColorArray[6].a := Alpha;
+        SDWaterColorArray[7].a := Alpha;
+        end;
+    SetColorPointer(@SDWaterColorArray[0], 8);
+    end
+else
+    begin
+    if WaterColorArray[0].a <> Alpha then
+        begin
+        WaterColorArray[0].a := Alpha;
+        WaterColorArray[1].a := Alpha;
+        WaterColorArray[2].a := Alpha;
+        WaterColorArray[3].a := Alpha;
+        WaterColorArray[4].a := Alpha;
+        WaterColorArray[5].a := Alpha;
+        WaterColorArray[6].a := Alpha;
+        WaterColorArray[7].a := Alpha;
+        end;
+    SetColorPointer(@WaterColorArray[0], 8);
+    end;
 
-        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+SetVertexPointer(@VertexBuffer[0], 8);
+
+glDrawArrays(GL_TRIANGLE_STRIP, firsti, n);
+
+EndWater;
 
-        EndWater;
+
+{$IFNDEF GL2}
+// must not be Tint() as color array seems to stay active and color reset is required
+glColor4ub($FF, $FF, $FF, $FF);
+{$ENDIF}
 end;
 
 procedure openglTint(r, g, b, a: Byte); inline;
--- a/hedgewars/uVariables.pas	Wed Jun 18 01:37:28 2014 +0200
+++ b/hedgewars/uVariables.pas	Wed Jun 18 15:42:01 2014 +0200
@@ -190,8 +190,8 @@
     RealTicks       : Longword;
     AttackBar       : LongInt;
 
-    WaterColorArray : array[0..3] of HwColor4f;
-    SDWaterColorArray : array[0..3] of HwColor4f;
+    WaterColorArray : array[0..7] of HwColor4f;
+    SDWaterColorArray : array[0..7] of HwColor4f;
     SDTint          : LongInt;
 
     TargetCursorPoint     : TPoint;
@@ -2488,17 +2488,27 @@
         LAND_HEIGHT_MASK:= $FFFFF800
         end;
 
-    SDWaterColorArray[0].r := 182;
-    SDWaterColorArray[0].g := 144;
-    SDWaterColorArray[0].b := 201;
+    // default sudden death water
+
+    // deep water
+    SDWaterColorArray[0].r := 150;
+    SDWaterColorArray[0].g := 112;
+    SDWaterColorArray[0].b := 169;
     SDWaterColorArray[0].a := 255;
-    SDWaterColorArray[2].r := 150;
-    SDWaterColorArray[2].g := 112;
-    SDWaterColorArray[2].b := 169;
-    SDWaterColorArray[2].a := 255;
-    SDWaterColorArray[1]:= SDWaterColorArray[0];
-    SDWaterColorArray[3]:= SDWaterColorArray[2];
+    SDWaterColorArray[2]:= SDWaterColorArray[0];
+    SDWaterColorArray[4]:= SDWaterColorArray[0];
+    SDWaterColorArray[6]:= SDWaterColorArray[0];
+    // water surface
+    SDWaterColorArray[1].r := 182;
+    SDWaterColorArray[1].g := 144;
+    SDWaterColorArray[1].b := 201;
+    SDWaterColorArray[1].a := 255;
+    SDWaterColorArray[3]:= SDWaterColorArray[1];
+    SDWaterColorArray[5]:= SDWaterColorArray[1];
+    SDWaterColorArray[7]:= SDWaterColorArray[1];
+
     SDWaterOpacity:= $80;
+
     SDTint:= $80;
     ExplosionBorderColor:= $FF808080;
     IceColor:= ($44 shl RShift) or ($97 shl GShift) or ($A9 shl BShift) or ($A0 shl AShift);
--- a/hedgewars/uWorld.pas	Wed Jun 18 01:37:28 2014 +0200
+++ b/hedgewars/uWorld.pas	Wed Jun 18 15:42:01 2014 +0200
@@ -790,102 +790,6 @@
 {$ENDIF}
 end;
 
-procedure DrawWater(Alpha: byte; OffsetY, OffsetX: LongInt);
-var VertexBuffer : array [0..3] of TVertex2f;
-    topy, lx, rx: LongInt;
-begin
-
-    // Water
-topy:= OffsetY + WorldDy + cWaterLine;
-
-if SuddenDeathDmg then
-    begin
-    SDWaterColorArray[0].a := Alpha;
-    SDWaterColorArray[1].a := Alpha;
-    SDWaterColorArray[2].a := Alpha;
-    SDWaterColorArray[3].a := Alpha
-    end
-else
-    begin
-    WaterColorArray[0].a := Alpha;
-    WaterColorArray[1].a := Alpha;
-    WaterColorArray[2].a := Alpha;
-    WaterColorArray[3].a := Alpha
-    end;
-
-if topy < 0 then
-    topy:= 0;
-
-// glDisable(GL_TEXTURE_2D);
-
-if (topy < ViewBottomY) and (WorldEdge <> weSea) then
-    begin
-    VertexBuffer[0].X:= ViewLeftX;
-    VertexBuffer[0].Y:= topy;
-    VertexBuffer[1].X:= ViewRightX;
-    VertexBuffer[1].Y:= topy;
-    VertexBuffer[2].X:= ViewRightX;
-    VertexBuffer[2].Y:= ViewBottomY;
-    VertexBuffer[3].X:= ViewLeftX;
-    VertexBuffer[3].Y:= ViewBottomY;
-    DrawWaterBody(@VertexBuffer[0]);
-    end;
-
-// water world edges? draw water body on the sides too
-if WorldEdge = weSea then
-    begin
-
-    lx:= LeftX  + WorldDx - OffsetX;
-    rx:= RightX + WorldDx + OffsetX;
-
-    if topy < ViewBottomY then
-        begin
-        VertexBuffer[0].X:= lx;
-        VertexBuffer[0].Y:= topy;
-        VertexBuffer[1].X:= rx;
-        VertexBuffer[1].Y:= topy;
-        VertexBuffer[2].X:= ViewRightX;
-        VertexBuffer[2].Y:= ViewBottomY;
-        VertexBuffer[3].X:= ViewLeftX;
-        VertexBuffer[3].Y:= ViewBottomY;
-        DrawWaterBody(@VertexBuffer[0]);
-        end;
-
-    if lx > ViewLeftX then
-        begin
-        VertexBuffer[0].X:= lx;
-        VertexBuffer[0].Y:= ViewTopY;
-        VertexBuffer[1].X:= lx;
-        VertexBuffer[1].Y:= topy;
-        VertexBuffer[2].X:= ViewLeftX;
-        VertexBuffer[2].Y:= ViewBottomY;
-        VertexBuffer[3].X:= ViewLeftX;
-        VertexBuffer[3].Y:= ViewTopY;
-        DrawWaterBody(@VertexBuffer[0]);
-        end;
-
-
-    if rx < ViewRightX then
-        begin
-        VertexBuffer[0].X:= rx;
-        VertexBuffer[0].Y:= topy;
-        VertexBuffer[1].X:= rx;
-        VertexBuffer[1].Y:= ViewTopY;
-        VertexBuffer[2].X:= ViewRightX;
-        VertexBuffer[2].Y:= ViewTopY;
-        VertexBuffer[3].X:= ViewRightX;
-        VertexBuffer[3].Y:= ViewBottomY;
-        DrawWaterBody(@VertexBuffer[0]);
-        end;
-    end;
-
-{$IFNDEF GL2}
-// must not be Tint() as color array seems to stay active and color reset is required
-glColor4ub($FF, $FF, $FF, $FF);
-{$ENDIF}
-//glEnable(GL_TEXTURE_2D);}
-end;
-
 procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
 var VertexBuffer, TextureBuffer: array [0..7] of TVertex2f;
     lw, waves, shift: GLfloat;