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; |
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 |