--- a/hedgewars/uRender.pas Wed Jun 18 17:23:43 2014 +0200
+++ b/hedgewars/uRender.pas Wed Jun 18 23:57:51 2014 +0200
@@ -55,6 +55,7 @@
procedure DrawHedgehog (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
procedure DrawScreenWidget (widget: POnScreenWidget);
procedure DrawWater (Alpha: byte; OffsetY, OffsetX: LongInt);
+procedure DrawWaves (Dir, dX, dY, oX: LongInt; tnt: Byte);
procedure RenderClear ();
procedure RenderSetClearColor (r, g, b, a: real);
@@ -1299,8 +1300,6 @@
glUseProgram(shaderWater);
uCurrentMVPLocation:=uWaterMVPLocation;
UpdateModelviewProjection;
- glDisableVertexAttribArray(aTexCoord);
- glEnableVertexAttribArray(aColor);
{$ENDIF}
openglUseColorOnly(true);
@@ -1312,54 +1311,83 @@
glUseProgram(shaderMain);
uCurrentMVPLocation:=uMainMVPLocation;
UpdateModelviewProjection;
- glDisableVertexAttribArray(aColor);
- glEnableVertexAttribArray(aTexCoord);
{$ENDIF}
openglUseColorOnly(false);
end;
-procedure DrawWater(Alpha: byte; OffsetY, OffsetX: LongInt);
-var watertop, lx, rx, firsti, afteri, n: LongInt;
+procedure PrepareVbForWater(
+ WithWalls: Boolean;
+ InTopY, OutTopY, InLeftX, OutLeftX, InRightX, OutRightX, BottomY: LongInt;
+ out first, count: LongInt);
+
+var firsti, afteri: LongInt;
begin
-// those
+ // We will draw both bottom water and the water walls with a single call,
+ // by rendering a GL_TRIANGLE_STRIP of eight points.
+ //
+ // GL_TRIANGLE_STRIP works like this: "always create triangle between
+ // newest point and the two points that were specified before it."
+ //
+ // To get the result we want we will order the points like this:
+ // ^ -Y
+ // |
+ // 0-------1 7-------6 <--------------------- OutTopY -|
+ // | /| | _/| |
+ // | / | | / | |
+ // | / | | _/ | |
+ // | / | | / | |
+ // | / _.3---------5{ | <--------------------- InTopY --|
+ // | / _/ `---.___ `--._ | |
+ // |/_/ `---.___\| |
+ // 2-------------------------4 <--------------------- BottomY -|
+ // |
+ // ^ ^ ^ ^ V +Y
+ // | | | |
+ // | | | |
+ // | | | |
+ // | | | |
+ // | | | |
+ // | | | |
+ // | | | |
+ // OutLeftX InLeftX InRightX OutRightX
+ // | | | |
+ // <---------------------------------------->
+ // -X +X
+ //
+
firsti:= -1;
afteri:= 0;
-watertop:= OffsetY + WorldDy + cWaterLine;
-
-if watertop < 0 then
- watertop:= 0;
+if InTopY < 0 then
+ InTopY:= 0;
-// if no walls are needed, then bottom water surface spans full view width
-if (WorldEdge <> weSea) then
+if not WithWalls then
begin
- lx:= ViewLeftX;
- rx:= ViewRightX;
+ // if no walls are needed, then bottom water surface spans full length
+ InLeftX := OutLeftX;
+ InRightX:= OutRightX;
end
else
begin
- lx:= LeftX + WorldDx - OffsetX;
- rx:= RightX + WorldDx + OffsetX;
-
- if lx > ViewLeftX then
+ if InLeftX > OutLeftX then
begin
- VertexBuffer[0].X:= ViewLeftX;
- VertexBuffer[0].Y:= ViewTopY;
- VertexBuffer[1].X:= lx;
- VertexBuffer[1].Y:= ViewTopY;
+ VertexBuffer[0].X:= OutLeftX;
+ VertexBuffer[0].Y:= OutTopY;
+ VertexBuffer[1].X:= InLeftX;
+ VertexBuffer[1].Y:= OutTopY;
// shares vertices 2 and 3 with bottom water
firsti:= 0;
afteri:= 4;
end;
- if rx < ViewRightX then
+ if InRightX < OutRightX then
begin
- VertexBuffer[6].X:= ViewRightX;
- VertexBuffer[6].Y:= ViewTopY;
- VertexBuffer[7].X:= rx;
- VertexBuffer[7].Y:= ViewTopY;
+ VertexBuffer[6].X:= OutRightX;
+ VertexBuffer[6].Y:= OutTopY;
+ VertexBuffer[7].X:= InRightX;
+ VertexBuffer[7].Y:= OutTopY;
// shares vertices 4 and 5 with bottom water
if firsti < 0 then
firsti:= 4;
@@ -1367,7 +1395,7 @@
end;
end;
-if watertop < ViewBottomY then
+if InTopY < BottomY then
begin
// shares vertices 2-5 with water walls
@@ -1380,26 +1408,58 @@
end;
if firsti < 0 then
- exit; // nothing to draw at all!
+ begin
+ // nothing to draw at all!
+ first:= -1;
+ count:= 0;
+ exit;
+ end;
if firsti < 4 then
begin
- VertexBuffer[2].X:= ViewLeftX;
- VertexBuffer[2].Y:= ViewBottomY;
- VertexBuffer[3].X:= lx;
- VertexBuffer[3].Y:= watertop;
+ VertexBuffer[2].X:= OutLeftX;
+ VertexBuffer[2].Y:= BottomY;
+ VertexBuffer[3].X:= InLeftX;
+ VertexBuffer[3].Y:= InTopY;
end;
if afteri > 4 then
begin
- VertexBuffer[4].X:= ViewRightX;
- VertexBuffer[4].Y:= ViewBottomY;
- VertexBuffer[5].X:= rx;
- VertexBuffer[5].Y:= watertop;
+ VertexBuffer[4].X:= OutRightX;
+ VertexBuffer[4].Y:= BottomY;
+ VertexBuffer[5].X:= InRightX;
+ VertexBuffer[5].Y:= InTopY;
end;
+// first index to draw in vertex buffer
+first:= firsti;
// number of points to draw
-n:= afteri - firsti;
+count:= afteri - firsti;
+
+end;
+
+procedure DrawWater(Alpha: byte; OffsetY, OffsetX: LongInt);
+var first, count: LongInt;
+begin
+
+if (WorldEdge <> weSea) then
+ PrepareVbForWater(false,
+ OffsetY + WorldDy + cWaterLine, 0,
+ 0, ViewLeftX,
+ 0, ViewRightX,
+ ViewBottomY,
+ first, count)
+else
+ PrepareVbForWater(true,
+ OffsetY + WorldDy + cWaterLine, ViewTopY,
+ LeftX + WorldDx - OffsetX, ViewLeftX,
+ RightX + WorldDx + OffsetX, ViewRightX,
+ ViewBottomY,
+ first, count);
+
+// quit if there's nothing to draw (nothing in view)
+if count < 1 then
+ exit;
// drawing time
@@ -1440,17 +1500,130 @@
SetVertexPointer(@VertexBuffer[0], 8);
-glDrawArrays(GL_TRIANGLE_STRIP, firsti, n);
+glDrawArrays(GL_TRIANGLE_STRIP, first, count);
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 DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
+var first, count, topy, lx, rx, spriteHeight, spriteWidth: LongInt;
+ lw, nWaves, shift: GLfloat;
+ sprite: TSprite;
+begin
+
+// note: spriteHeight is the Height of the wave sprite while
+// cWaveHeight describes how many pixels of it will be above waterline
+
+if SuddenDeathDmg then
+ sprite:= sprSDWater
+else
+ sprite:= sprWater;
+
+spriteHeight:= SpritesData[sprite].Height;
+
+// shift parameters by wave height
+// ( ox and dy are used to create different horizontal and vertical offsets
+// between wave layers )
+dY:= -cWaveHeight + dy;
+ox:= -cWaveHeight + ox;
+
+lx:= LeftX + WorldDx - ox;
+rx:= RightX + WorldDx + ox;
+
+topy:= cWaterLine + WorldDy + dY;
+
+
+if (WorldEdge <> weSea) then
+ PrepareVbForWater(false,
+ topy, 0,
+ 0, ViewLeftX,
+ 0, ViewRightX,
+ topy + spriteHeight,
+ first, count)
+else
+ PrepareVbForWater(true,
+ topy, ViewTopY,
+ lx, lx - spriteHeight,
+ rx, rx + spriteHeight,
+ topy + spriteHeight,
+ first, count);
+
+// quit if there's nothing to draw (nothing in view)
+if count < 1 then
+ exit;
+
+if SuddenDeathDmg then
+ Tint(LongInt(tnt) * SDWaterColorArray[1].r div 255 + 255 - tnt,
+ LongInt(tnt) * SDWaterColorArray[1].g div 255 + 255 - tnt,
+ LongInt(tnt) * SDWaterColorArray[1].b div 255 + 255 - tnt,
+ 255
+ )
+else
+ Tint(LongInt(tnt) * WaterColorArray[1].r div 255 + 255 - tnt,
+ LongInt(tnt) * WaterColorArray[1].g div 255 + 255 - tnt,
+ LongInt(tnt) * WaterColorArray[1].b div 255 + 255 - tnt,
+ 255
+ );
+
+if WorldEdge = weSea then
+ begin
+ lw:= playWidth;
+ dX:= ox;
+ end
+else
+ begin
+ lw:= ViewWidth;
+ dx:= dx - WorldDx;
+ end;
+
+spriteWidth:= SpritesData[sprite].Width;
+nWaves:= lw / spriteWidth;
+ shift:= - nWaves / 2;
+
+TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
+TextureBuffer[3].Y:= 0;
+TextureBuffer[5].X:= TextureBuffer[3].X + nWaves;
+TextureBuffer[5].Y:= 0;
+TextureBuffer[4].X:= TextureBuffer[5].X;
+TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry;
+TextureBuffer[2].X:= TextureBuffer[3].X;
+TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
+
+if (WorldEdge = weSea) then
+ begin
+ nWaves:= (topy - ViewTopY) / spriteWidth;
+
+ // left side
+ TextureBuffer[1].X:= TextureBuffer[3].X - nWaves;
+ TextureBuffer[1].Y:= 0;
+ TextureBuffer[0].X:= TextureBuffer[1].X;
+ TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry;
+
+ // right side
+ TextureBuffer[7].X:= TextureBuffer[5].X + nWaves;
+ TextureBuffer[7].Y:= 0;
+ TextureBuffer[6].X:= TextureBuffer[7].X;
+ TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry;
+ end;
+
+glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
+
+SetVertexPointer(@VertexBuffer[0], 8);
+SetTexCoordPointer(@TextureBuffer[0], 8);
+
+UpdateModelviewProjection;
+
+glDrawArrays(GL_TRIANGLE_STRIP, first, count);
+
+untint;
+
+end;
+
procedure openglTint(r, g, b, a: Byte); inline;
{$IFDEF GL2}
const
--- a/hedgewars/uWorld.pas Wed Jun 18 17:23:43 2014 +0200
+++ b/hedgewars/uWorld.pas Wed Jun 18 23:57:51 2014 +0200
@@ -66,7 +66,7 @@
{$ENDIF}
;
-var cWaveWidth, cWaveHeight: LongInt;
+var cWaveWidth: LongInt;
AMShiftTargetX, AMShiftTargetY, AMShiftX, AMShiftY, SlotsNum: LongInt;
AMAnimStartTime, AMState : LongInt;
AMAnimState: Single;
@@ -790,185 +790,6 @@
{$ENDIF}
end;
-procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
-var VertexBuffer, TextureBuffer: array [0..7] of TVertex2f;
- lw, waves, shift: GLfloat;
- sprite: TSprite;
- topy: LongInt;
-begin
-
-dY:= -cWaveHeight + dy;
-ox:= -cWaveHeight + ox;
-
-topy:= cWaterLine + WorldDy + dY;
-
-if (WorldEdge <> weSea) and (topY > ViewBottomY) then
- exit;
-
-if SuddenDeathDmg then
- sprite:= sprSDWater
-else
- sprite:= sprWater;
-
-cWaveWidth:= SpritesData[sprite].Width;
-
-if WorldEdge = weSea then
- lw:= playWidth div 2
-else
- lw:= ViewWidth;
-
-if SuddenDeathDmg then
- Tint(LongInt(tnt) * SDWaterColorArray[2].r div 255 + 255 - tnt,
- LongInt(tnt) * SDWaterColorArray[2].g div 255 + 255 - tnt,
- LongInt(tnt) * SDWaterColorArray[2].b div 255 + 255 - tnt,
- 255
- )
-else
- Tint(LongInt(tnt) * WaterColorArray[2].r div 255 + 255 - tnt,
- LongInt(tnt) * WaterColorArray[2].g div 255 + 255 - tnt,
- LongInt(tnt) * WaterColorArray[2].b div 255 + 255 - tnt,
- 255
- );
-
-glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
-
-if WorldEdge <> weSea then
- begin
- if topY < ViewBottomY then
- begin
- VertexBuffer[0].X:= -lw;
- VertexBuffer[0].Y:= cWaterLine + WorldDy + dY;
- VertexBuffer[1].X:= lw;
- VertexBuffer[1].Y:= VertexBuffer[0].Y;
- VertexBuffer[2].X:= lw;
- VertexBuffer[2].Y:= VertexBuffer[0].Y + SpritesData[sprite].Height;
- VertexBuffer[3].X:= -lw;
- VertexBuffer[3].Y:= VertexBuffer[2].Y;
-
- waves:= lw * 2 / cWaveWidth;
- shift:= - lw / cWaveWidth;
- TextureBuffer[0].X:= shift + (( - WorldDx + LongInt(RealTicks shr 6) * Dir + dX) mod cWaveWidth) / (cWaveWidth - 1);
- TextureBuffer[0].Y:= 0;
- TextureBuffer[1].X:= TextureBuffer[0].X + waves;
- TextureBuffer[1].Y:= TextureBuffer[0].Y;
- TextureBuffer[2].X:= TextureBuffer[1].X;
- TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
- TextureBuffer[3].X:= TextureBuffer[0].X;
- TextureBuffer[3].Y:= TextureBuffer[2].Y;
-
-
- SetVertexPointer(@VertexBuffer[0], 4);
- SetTexCoordPointer(@TextureBuffer[0], 4);
-
- {$IFDEF GL2}
- UpdateModelviewProjection;
- {$ENDIF}
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- end;
- end
-else // weSea: with waterwalls
- begin
- topy := cWaterLine + WorldDy;
-
- // We will draw both bottom water and the water walls with a single call,
- // by rendering a GL_TRIANGLE_STRIP of eight points.
- //
- // GL_TRIANGLE_STRIP works like this: "always create triangle between
- // newest point and the two points that were specified before it."
- //
- // To get the result we want we will order the points like this:
- // ^ -Y
- // |
- // 0-------1 7-------6 <---------------------- ViewTopY -|
- // | /| | _/| |
- // | / | | / | |
- // | / | | _/ | |
- // | / | | / | |
- // | / _.3---------5{ | <--- topy = cWaterLine + WorldDy -|
- // | / _/ `---.___ `--._ | |
- // |/_/ `---.___\| |
- // 2-------------------------4 <------------ topy + wave height -|
- // |
- // ^ ^ ^ ^ V +Y
- // | | | |
- // | | | RightX + WorldDx + wave height
- // | | | .
- // | | RightX + WorldDx.
- // | | . .
- // | LeftX + WorldDx . .
- // | . . .
- // LeftX - wave height + WorldDx
- // | . . .
- // <-------------------------------->
- // -X +X
- //
- // Note: additionally the parameters ox and dy are used to create different
- // horizontal and vertical offsets between wave layers
-
-
- VertexBuffer[0].X:= LeftX + WorldDx - SpritesData[sprite].Height - ox;
- VertexBuffer[0].Y:= ViewTopY;
- VertexBuffer[1].X:= LeftX + WorldDx - ox;
- VertexBuffer[1].Y:= ViewTopY;
- VertexBuffer[2].X:= VertexBuffer[0].X;
- VertexBuffer[2].Y:= topy + SpritesData[sprite].Height + dy;
- VertexBuffer[3].X:= VertexBuffer[1].X;
- VertexBuffer[3].Y:= topy + dy;
- VertexBuffer[4].X:= RightX + WorldDx + SpritesData[sprite].Height + ox;
- VertexBuffer[4].Y:= topy + SpritesData[sprite].Height + dy;
- VertexBuffer[5].X:= RightX + WorldDx + ox;
- VertexBuffer[5].Y:= topy + dy;
- VertexBuffer[6].X:= VertexBuffer[4].X;
- VertexBuffer[6].Y:= ViewTopY;
- VertexBuffer[7].X:= VertexBuffer[5].X;
- VertexBuffer[7].Y:= ViewTopY;
-
- waves:= 2 * lw / cWaveWidth;
- shift:= - lw / cWaveWidth;
- TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + ox) mod cWaveWidth) / (cWaveWidth - 1);
- TextureBuffer[3].Y:= 0;
- TextureBuffer[5].X:= TextureBuffer[3].X + waves;
- TextureBuffer[5].Y:= 0;
- TextureBuffer[4].X:= TextureBuffer[5].X;
- TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry;
- TextureBuffer[2].X:= TextureBuffer[3].X;
- TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
-
- waves:= (topy + dy - ViewTopY) / cWaveWidth;
-
- // left side
- TextureBuffer[1].X:= TextureBuffer[3].X - waves;
- TextureBuffer[1].Y:= 0;
- TextureBuffer[0].X:= TextureBuffer[1].X;
- TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry;
-
- // right side
- TextureBuffer[7].X:= TextureBuffer[5].X + waves;
- TextureBuffer[7].Y:= 0;
- TextureBuffer[6].X:= TextureBuffer[7].X;
- TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry;
-
-
- SetVertexPointer(@VertexBuffer[0], 8);
- SetTexCoordPointer(@TextureBuffer[0], 8);
-
- {$IFDEF GL2}
- UpdateModelviewProjection;
- {$ENDIF}
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 8);
- end;
-
-untint;
-
-{for i:= -1 to cWaterSprCount do
- DrawSprite(sprWater,
- i * cWaveWidth + ((WorldDx + (RealTicks shr 6) * Dir + dX) mod cWaveWidth) - (cScreenWidth div 2),
- cWaterLine + WorldDy + dY,
- 0)}
-end;
-
procedure DrawRepeated(spr, sprL, sprR: TSprite; Shift, OffsetY: LongInt);
var i, w, h, lw, lh, rw, rh, sw: LongInt;
begin