# HG changeset patch # User sheepluva # Date 1403128671 -7200 # Node ID 3ec09243cb55f5dc593786de0a3f11982b6a67c1 # Parent 1eaae604d7a43537edf6cfaa097fa66b37c76c41 move DrawWaves to uRender diff -r 1eaae604d7a4 -r 3ec09243cb55 hedgewars/uRender.pas --- 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 diff -r 1eaae604d7a4 -r 3ec09243cb55 hedgewars/uVariables.pas --- a/hedgewars/uVariables.pas Wed Jun 18 17:23:43 2014 +0200 +++ b/hedgewars/uVariables.pas Wed Jun 18 23:57:51 2014 +0200 @@ -162,6 +162,7 @@ CrosshairY : LongInt; CursorMovementX : LongInt; CursorMovementY : LongInt; + cWaveHeight : LongInt; cDrownSpeed : hwFloat; cDrownSpeedf : real; cMaxWindSpeed : hwFloat; @@ -2516,6 +2517,7 @@ WaterOpacity:= $80; + cWaveHeight := 32; cDrownSpeed.QWordValue := 257698038; // 0.06 cDrownSpeedf := 0.06; cMaxWindSpeed.QWordValue:= 1073742; // 0.00025 diff -r 1eaae604d7a4 -r 3ec09243cb55 hedgewars/uWorld.pas --- 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