hedgewars/uRender.pas
changeset 10330 3ec09243cb55
parent 10328 1eaae604d7a4
child 10331 cb6c33839d2a
equal deleted inserted replaced
10328:1eaae604d7a4 10330:3ec09243cb55
    53 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
    53 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
    54 procedure DrawRect              (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
    54 procedure DrawRect              (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
    55 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    55 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
    56 procedure DrawScreenWidget      (widget: POnScreenWidget);
    56 procedure DrawScreenWidget      (widget: POnScreenWidget);
    57 procedure DrawWater             (Alpha: byte; OffsetY, OffsetX: LongInt);
    57 procedure DrawWater             (Alpha: byte; OffsetY, OffsetX: LongInt);
       
    58 procedure DrawWaves             (Dir, dX, dY, oX: LongInt; tnt: Byte);
    58 
    59 
    59 procedure RenderClear           ();
    60 procedure RenderClear           ();
    60 procedure RenderSetClearColor      (r, g, b, a: real);
    61 procedure RenderSetClearColor      (r, g, b, a: real);
    61 procedure Tint                  (r, g, b, a: Byte); inline;
    62 procedure Tint                  (r, g, b, a: Byte); inline;
    62 procedure Tint                  (c: Longword); inline;
    63 procedure Tint                  (c: Longword); inline;
  1297 begin
  1298 begin
  1298 {$IFDEF GL2}
  1299 {$IFDEF GL2}
  1299     glUseProgram(shaderWater);
  1300     glUseProgram(shaderWater);
  1300     uCurrentMVPLocation:=uWaterMVPLocation;
  1301     uCurrentMVPLocation:=uWaterMVPLocation;
  1301     UpdateModelviewProjection;
  1302     UpdateModelviewProjection;
  1302     glDisableVertexAttribArray(aTexCoord);
       
  1303     glEnableVertexAttribArray(aColor);
       
  1304 {$ENDIF}
  1303 {$ENDIF}
  1305 
  1304 
  1306     openglUseColorOnly(true);
  1305     openglUseColorOnly(true);
  1307 end;
  1306 end;
  1308 
  1307 
  1310 begin
  1309 begin
  1311 {$IFDEF GL2}
  1310 {$IFDEF GL2}
  1312     glUseProgram(shaderMain);
  1311     glUseProgram(shaderMain);
  1313     uCurrentMVPLocation:=uMainMVPLocation;
  1312     uCurrentMVPLocation:=uMainMVPLocation;
  1314     UpdateModelviewProjection;
  1313     UpdateModelviewProjection;
  1315     glDisableVertexAttribArray(aColor);
       
  1316     glEnableVertexAttribArray(aTexCoord);
       
  1317 {$ENDIF}
  1314 {$ENDIF}
  1318 
  1315 
  1319     openglUseColorOnly(false);
  1316     openglUseColorOnly(false);
  1320 end;
  1317 end;
  1321 
  1318 
  1322 procedure DrawWater(Alpha: byte; OffsetY, OffsetX: LongInt);
  1319 procedure PrepareVbForWater(
  1323 var watertop, lx, rx, firsti, afteri, n: LongInt;
  1320     WithWalls: Boolean;
  1324 begin
  1321     InTopY, OutTopY, InLeftX, OutLeftX, InRightX, OutRightX, BottomY: LongInt;
  1325 
  1322     out first, count: LongInt);
  1326 // those
  1323 
       
  1324 var firsti, afteri: LongInt;
       
  1325 begin
       
  1326 
       
  1327     // We will draw both bottom water and the water walls with a single call,
       
  1328     // by rendering a GL_TRIANGLE_STRIP of eight points.
       
  1329     //
       
  1330     // GL_TRIANGLE_STRIP works like this: "always create triangle between
       
  1331     // newest point and the two points that were specified before it."
       
  1332     //
       
  1333     // To get the result we want we will order the points like this:
       
  1334     //                                                                     ^ -Y
       
  1335     //                                                                     |
       
  1336     //       0-------1         7-------6   <--------------------- OutTopY -|
       
  1337     //       |      /|         |     _/|                                   |
       
  1338     //       |     / |         |    /  |                                   |
       
  1339     //       |    /  |         |  _/   |                                   |
       
  1340     //       |   /   |         | /     |                                   |
       
  1341     //       |  /  _.3---------5{      |   <--------------------- InTopY --|
       
  1342     //       | / _/   `---.___   `--._ |                                   |
       
  1343     //       |/_/             `---.___\|                                   |
       
  1344     //       2-------------------------4   <--------------------- BottomY -|
       
  1345     //                                                                     |
       
  1346     //       ^       ^         ^       ^                                   V +Y
       
  1347     //       |       |         |       |
       
  1348     //       |       |         |       |
       
  1349     //       |       |         |       |
       
  1350     //       |       |         |       |
       
  1351     //       |       |         |       |
       
  1352     //       |       |         |       |
       
  1353     //       |       |         |       |
       
  1354     //  OutLeftX  InLeftX  InRightX  OutRightX
       
  1355     //       |       |         |       |
       
  1356     // <---------------------------------------->
       
  1357     //     -X                              +X
       
  1358     //
       
  1359 
  1327 firsti:= -1;
  1360 firsti:= -1;
  1328 afteri:=  0;
  1361 afteri:=  0;
  1329 
  1362 
  1330 watertop:= OffsetY + WorldDy + cWaterLine;
  1363 if InTopY < 0 then
  1331 
  1364     InTopY:= 0;
  1332 if watertop < 0 then
  1365 
  1333     watertop:= 0;
  1366 if not WithWalls then
  1334 
  1367     begin
  1335 // if no walls are needed, then bottom water surface spans full view width
  1368     // if no walls are needed, then bottom water surface spans full length
  1336 if (WorldEdge <> weSea) then
  1369     InLeftX := OutLeftX;
  1337     begin
  1370     InRightX:= OutRightX;
  1338     lx:= ViewLeftX;
       
  1339     rx:= ViewRightX;
       
  1340     end
  1371     end
  1341 else
  1372 else
  1342     begin
  1373     begin
  1343     lx:= LeftX  + WorldDx - OffsetX;
  1374     if InLeftX > OutLeftX then
  1344     rx:= RightX + WorldDx + OffsetX;
  1375         begin
  1345 
  1376         VertexBuffer[0].X:= OutLeftX;
  1346     if lx > ViewLeftX then
  1377         VertexBuffer[0].Y:= OutTopY;
  1347         begin
  1378         VertexBuffer[1].X:= InLeftX;
  1348         VertexBuffer[0].X:= ViewLeftX;
  1379         VertexBuffer[1].Y:= OutTopY;
  1349         VertexBuffer[0].Y:= ViewTopY;
       
  1350         VertexBuffer[1].X:= lx;
       
  1351         VertexBuffer[1].Y:= ViewTopY;
       
  1352         // shares vertices 2 and 3 with bottom water
  1380         // shares vertices 2 and 3 with bottom water
  1353         firsti:= 0;
  1381         firsti:= 0;
  1354         afteri:= 4;
  1382         afteri:= 4;
  1355         end;
  1383         end;
  1356 
  1384 
  1357     if rx < ViewRightX then
  1385     if InRightX < OutRightX then
  1358         begin
  1386         begin
  1359         VertexBuffer[6].X:= ViewRightX;
  1387         VertexBuffer[6].X:= OutRightX;
  1360         VertexBuffer[6].Y:= ViewTopY;
  1388         VertexBuffer[6].Y:= OutTopY;
  1361         VertexBuffer[7].X:= rx;
  1389         VertexBuffer[7].X:= InRightX;
  1362         VertexBuffer[7].Y:= ViewTopY;
  1390         VertexBuffer[7].Y:= OutTopY;
  1363         // shares vertices 4 and 5 with bottom water
  1391         // shares vertices 4 and 5 with bottom water
  1364         if firsti < 0 then
  1392         if firsti < 0 then
  1365             firsti:= 4;
  1393             firsti:= 4;
  1366         afteri:= 8;
  1394         afteri:= 8;
  1367         end;
  1395         end;
  1368     end;
  1396     end;
  1369 
  1397 
  1370 if watertop < ViewBottomY then
  1398 if InTopY < BottomY then
  1371     begin
  1399     begin
  1372     // shares vertices 2-5 with water walls
  1400     // shares vertices 2-5 with water walls
  1373 
  1401 
  1374     // starts at vertex 2
  1402     // starts at vertex 2
  1375     if (firsti < 0) or (firsti > 2) then
  1403     if (firsti < 0) or (firsti > 2) then
  1378     if afteri < 6 then
  1406     if afteri < 6 then
  1379         afteri:= 6;
  1407         afteri:= 6;
  1380     end;
  1408     end;
  1381 
  1409 
  1382 if firsti < 0 then
  1410 if firsti < 0 then
  1383     exit; // nothing to draw at all!
  1411     begin
       
  1412     // nothing to draw at all!
       
  1413     first:= -1;
       
  1414     count:= 0;
       
  1415     exit;
       
  1416     end;
  1384 
  1417 
  1385 if firsti < 4 then
  1418 if firsti < 4 then
  1386     begin
  1419     begin
  1387     VertexBuffer[2].X:= ViewLeftX;
  1420     VertexBuffer[2].X:= OutLeftX;
  1388     VertexBuffer[2].Y:= ViewBottomY;
  1421     VertexBuffer[2].Y:= BottomY;
  1389     VertexBuffer[3].X:= lx;
  1422     VertexBuffer[3].X:= InLeftX;
  1390     VertexBuffer[3].Y:= watertop;
  1423     VertexBuffer[3].Y:= InTopY;
  1391     end;
  1424     end;
  1392 
  1425 
  1393 if afteri > 4 then
  1426 if afteri > 4 then
  1394     begin
  1427     begin
  1395     VertexBuffer[4].X:= ViewRightX;
  1428     VertexBuffer[4].X:= OutRightX;
  1396     VertexBuffer[4].Y:= ViewBottomY;
  1429     VertexBuffer[4].Y:= BottomY;
  1397     VertexBuffer[5].X:= rx;
  1430     VertexBuffer[5].X:= InRightX;
  1398     VertexBuffer[5].Y:= watertop;
  1431     VertexBuffer[5].Y:= InTopY;
  1399     end;
  1432     end;
  1400 
  1433 
       
  1434 // first index to draw in vertex buffer
       
  1435 first:= firsti;
  1401 // number of points to draw
  1436 // number of points to draw
  1402 n:= afteri - firsti;
  1437 count:= afteri - firsti;
       
  1438 
       
  1439 end;
       
  1440 
       
  1441 procedure DrawWater(Alpha: byte; OffsetY, OffsetX: LongInt);
       
  1442 var first, count: LongInt;
       
  1443 begin
       
  1444 
       
  1445 if (WorldEdge <> weSea) then
       
  1446     PrepareVbForWater(false,
       
  1447         OffsetY + WorldDy + cWaterLine, 0,
       
  1448         0, ViewLeftX,
       
  1449         0, ViewRightX,
       
  1450         ViewBottomY,
       
  1451         first, count)
       
  1452 else
       
  1453     PrepareVbForWater(true,
       
  1454         OffsetY + WorldDy + cWaterLine, ViewTopY,
       
  1455         LeftX  + WorldDx - OffsetX, ViewLeftX,
       
  1456         RightX + WorldDx + OffsetX, ViewRightX,
       
  1457         ViewBottomY,
       
  1458         first, count);
       
  1459 
       
  1460 // quit if there's nothing to draw (nothing in view)
       
  1461 if count < 1 then
       
  1462     exit;
  1403 
  1463 
  1404 // drawing time
  1464 // drawing time
  1405 
  1465 
  1406 UpdateModelviewProjection;
  1466 UpdateModelviewProjection;
  1407 
  1467 
  1438     SetColorPointer(@WaterColorArray[0], 8);
  1498     SetColorPointer(@WaterColorArray[0], 8);
  1439     end;
  1499     end;
  1440 
  1500 
  1441 SetVertexPointer(@VertexBuffer[0], 8);
  1501 SetVertexPointer(@VertexBuffer[0], 8);
  1442 
  1502 
  1443 glDrawArrays(GL_TRIANGLE_STRIP, firsti, n);
  1503 glDrawArrays(GL_TRIANGLE_STRIP, first, count);
  1444 
  1504 
  1445 EndWater;
  1505 EndWater;
  1446 
       
  1447 
  1506 
  1448 {$IFNDEF GL2}
  1507 {$IFNDEF GL2}
  1449 // must not be Tint() as color array seems to stay active and color reset is required
  1508 // must not be Tint() as color array seems to stay active and color reset is required
  1450 glColor4ub($FF, $FF, $FF, $FF);
  1509 glColor4ub($FF, $FF, $FF, $FF);
  1451 {$ENDIF}
  1510 {$ENDIF}
       
  1511 end;
       
  1512 
       
  1513 procedure DrawWaves(Dir, dX, dY, oX: LongInt; tnt: Byte);
       
  1514 var first, count, topy, lx, rx, spriteHeight, spriteWidth: LongInt;
       
  1515     lw, nWaves, shift: GLfloat;
       
  1516     sprite: TSprite;
       
  1517 begin
       
  1518 
       
  1519 // note: spriteHeight is the Height of the wave sprite while
       
  1520 //       cWaveHeight describes how many pixels of it will be above waterline
       
  1521 
       
  1522 if SuddenDeathDmg then
       
  1523     sprite:= sprSDWater
       
  1524 else
       
  1525     sprite:= sprWater;
       
  1526 
       
  1527 spriteHeight:= SpritesData[sprite].Height;
       
  1528 
       
  1529 // shift parameters by wave height
       
  1530 // ( ox and dy are used to create different horizontal and vertical offsets
       
  1531 //   between wave layers )
       
  1532 dY:= -cWaveHeight + dy;
       
  1533 ox:= -cWaveHeight + ox;
       
  1534 
       
  1535 lx:= LeftX  + WorldDx - ox;
       
  1536 rx:= RightX + WorldDx + ox;
       
  1537 
       
  1538 topy:= cWaterLine + WorldDy + dY;
       
  1539 
       
  1540 
       
  1541 if (WorldEdge <> weSea) then
       
  1542     PrepareVbForWater(false,
       
  1543         topy, 0,
       
  1544         0, ViewLeftX,
       
  1545         0, ViewRightX,
       
  1546         topy + spriteHeight,
       
  1547         first, count)
       
  1548 else
       
  1549     PrepareVbForWater(true,
       
  1550         topy, ViewTopY,
       
  1551         lx, lx - spriteHeight,
       
  1552         rx, rx + spriteHeight,
       
  1553         topy + spriteHeight,
       
  1554         first, count);
       
  1555 
       
  1556 // quit if there's nothing to draw (nothing in view)
       
  1557 if count < 1 then
       
  1558     exit;
       
  1559 
       
  1560 if SuddenDeathDmg then
       
  1561     Tint(LongInt(tnt) * SDWaterColorArray[1].r div 255 + 255 - tnt,
       
  1562          LongInt(tnt) * SDWaterColorArray[1].g div 255 + 255 - tnt,
       
  1563          LongInt(tnt) * SDWaterColorArray[1].b div 255 + 255 - tnt,
       
  1564          255
       
  1565     )
       
  1566 else
       
  1567     Tint(LongInt(tnt) * WaterColorArray[1].r div 255 + 255 - tnt,
       
  1568          LongInt(tnt) * WaterColorArray[1].g div 255 + 255 - tnt,
       
  1569          LongInt(tnt) * WaterColorArray[1].b div 255 + 255 - tnt,
       
  1570          255
       
  1571     );
       
  1572 
       
  1573 if WorldEdge = weSea then
       
  1574     begin
       
  1575     lw:= playWidth;
       
  1576     dX:= ox;
       
  1577     end
       
  1578 else
       
  1579     begin
       
  1580     lw:= ViewWidth;
       
  1581     dx:= dx - WorldDx;
       
  1582     end;
       
  1583 
       
  1584 spriteWidth:= SpritesData[sprite].Width;
       
  1585 nWaves:= lw / spriteWidth;
       
  1586     shift:= - nWaves / 2;
       
  1587 
       
  1588 TextureBuffer[3].X:= shift + ((LongInt(RealTicks shr 6) * Dir + dX) mod spriteWidth) / (spriteWidth - 1);
       
  1589 TextureBuffer[3].Y:= 0;
       
  1590 TextureBuffer[5].X:= TextureBuffer[3].X + nWaves;
       
  1591 TextureBuffer[5].Y:= 0;
       
  1592 TextureBuffer[4].X:= TextureBuffer[5].X;
       
  1593 TextureBuffer[4].Y:= SpritesData[sprite].Texture^.ry;
       
  1594 TextureBuffer[2].X:= TextureBuffer[3].X;
       
  1595 TextureBuffer[2].Y:= SpritesData[sprite].Texture^.ry;
       
  1596 
       
  1597 if (WorldEdge = weSea) then
       
  1598     begin
       
  1599     nWaves:= (topy - ViewTopY) / spriteWidth;
       
  1600 
       
  1601     // left side
       
  1602     TextureBuffer[1].X:= TextureBuffer[3].X - nWaves;
       
  1603     TextureBuffer[1].Y:= 0;
       
  1604     TextureBuffer[0].X:= TextureBuffer[1].X;
       
  1605     TextureBuffer[0].Y:= SpritesData[sprite].Texture^.ry;
       
  1606 
       
  1607     // right side
       
  1608     TextureBuffer[7].X:= TextureBuffer[5].X + nWaves;
       
  1609     TextureBuffer[7].Y:= 0;
       
  1610     TextureBuffer[6].X:= TextureBuffer[7].X;
       
  1611     TextureBuffer[6].Y:= SpritesData[sprite].Texture^.ry;
       
  1612     end;
       
  1613 
       
  1614 glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
       
  1615 
       
  1616 SetVertexPointer(@VertexBuffer[0], 8);
       
  1617 SetTexCoordPointer(@TextureBuffer[0], 8);
       
  1618 
       
  1619 UpdateModelviewProjection;
       
  1620 
       
  1621 glDrawArrays(GL_TRIANGLE_STRIP, first, count);
       
  1622 
       
  1623 untint;
       
  1624 
  1452 end;
  1625 end;
  1453 
  1626 
  1454 procedure openglTint(r, g, b, a: Byte); inline;
  1627 procedure openglTint(r, g, b, a: Byte); inline;
  1455 {$IFDEF GL2}
  1628 {$IFDEF GL2}
  1456 const
  1629 const