--- a/hedgewars/options.inc Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/options.inc Tue Jun 05 22:17:06 2012 +0200
@@ -28,6 +28,8 @@
{$MACRO ON}
{$DEFINE GLunit:=GL}
+{$DEFINE GL2}
+
{$IFDEF ANDROID}
{$DEFINE SDL13}
{$DEFINE HWLIBRARY}
--- a/hedgewars/uGearsRender.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uGearsRender.pas Tue Jun 05 22:17:06 2012 +0200
@@ -54,9 +54,9 @@
glDisable(GL_TEXTURE_2D);
//glEnable(GL_LINE_SMOOTH);
- glPushMatrix;
-
- glTranslatef(WorldDx, WorldDy, 0);
+ ResetRotation;
+ SetOffset(WorldDx, WorldDy);
+ UpdateModelview;
glLineWidth(4.0);
@@ -66,8 +66,6 @@
glDrawArrays(GL_LINE_STRIP, 0, RopePoints.Count + 2);
Tint($FF, $FF, $FF, $FF);
- glPopMatrix;
-
glEnable(GL_TEXTURE_2D);
//glDisable(GL_LINE_SMOOTH)
end
--- a/hedgewars/uLandTexture.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uLandTexture.pas Tue Jun 05 22:17:06 2012 +0200
@@ -99,7 +99,7 @@
with LandTextures[x, y] do
begin
tex:= NewTexture(TEXSIZE, TEXSIZE, Pixels(x, y));
- glBindTexture(GL_TEXTURE_2D, tex^.id);
+ glBindTexture(GL_TEXTURE_2D, tex^.atlas^.id);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, tpHigh);
end
else
@@ -156,7 +156,7 @@
if not isEmpty then
begin
if tex = nil then tex:= NewTexture(TEXSIZE, TEXSIZE, Pixels(x, y));
- glBindTexture(GL_TEXTURE_2D, tex^.id);
+ glBindTexture(GL_TEXTURE_2D, tex^.atlas^.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEXSIZE, TEXSIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, Pixels(x,y));
end
else if tex <> nil then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uMatrix.pas Tue Jun 05 22:17:06 2012 +0200
@@ -0,0 +1,123 @@
+(*
+ * Hedgewars, a free turn based strategy game
+ * Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *)
+
+{$INCLUDE "options.inc"}
+
+unit uMatrix;
+
+interface
+
+uses uTypes, gl;
+
+procedure MatrixLoadIdentity(out Result: TMatrix4x4f);
+procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f);
+
+implementation
+
+procedure MatrixLoadIdentity(out Result: TMatrix4x4f);
+begin
+ Result[0,0]:= 1.0; Result[1,0]:=0.0; Result[2,0]:=0.0; Result[3,0]:=0.0;
+ Result[0,1]:= 0.0; Result[1,1]:=1.0; Result[2,1]:=0.0; Result[3,1]:=0.0;
+ Result[0,2]:= 0.0; Result[1,2]:=0.0; Result[2,2]:=1.0; Result[3,2]:=0.0;
+ Result[0,3]:= 0.0; Result[1,3]:=0.0; Result[2,3]:=0.0; Result[3,3]:=1.0;
+end;
+
+procedure MatrixMultiply(out Result: TMatrix4x4f; const lhs, rhs: TMatrix4x4f);
+var
+ test: TMatrix4x4f;
+ i, j: Integer;
+ error: boolean;
+begin
+ Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3];
+ Result[0,1]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3];
+ Result[0,2]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3];
+ Result[0,3]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3];
+
+ Result[1,0]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3];
+ Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3];
+ Result[1,2]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3];
+ Result[1,3]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3];
+
+ Result[2,0]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3];
+ Result[2,1]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3];
+ Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3];
+ Result[2,3]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3];
+
+ Result[3,0]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3];
+ Result[3,1]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3];
+ Result[3,2]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3];
+ Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3];
+
+{
+ Result[0,0]:=lhs[0,0]*rhs[0,0] + lhs[1,0]*rhs[0,1] + lhs[2,0]*rhs[0,2] + lhs[3,0]*rhs[0,3];
+ Result[0,1]:=lhs[0,0]*rhs[1,0] + lhs[1,0]*rhs[1,1] + lhs[2,0]*rhs[1,2] + lhs[3,0]*rhs[1,3];
+ Result[0,2]:=lhs[0,0]*rhs[2,0] + lhs[1,0]*rhs[2,1] + lhs[2,0]*rhs[2,2] + lhs[3,0]*rhs[2,3];
+ Result[0,3]:=lhs[0,0]*rhs[3,0] + lhs[1,0]*rhs[3,1] + lhs[2,0]*rhs[3,2] + lhs[3,0]*rhs[3,3];
+
+ Result[1,0]:=lhs[0,1]*rhs[0,0] + lhs[1,1]*rhs[0,1] + lhs[2,1]*rhs[0,2] + lhs[3,1]*rhs[0,3];
+ Result[1,1]:=lhs[0,1]*rhs[1,0] + lhs[1,1]*rhs[1,1] + lhs[2,1]*rhs[1,2] + lhs[3,1]*rhs[1,3];
+ Result[1,2]:=lhs[0,1]*rhs[2,0] + lhs[1,1]*rhs[2,1] + lhs[2,1]*rhs[2,2] + lhs[3,1]*rhs[2,3];
+ Result[1,3]:=lhs[0,1]*rhs[3,0] + lhs[1,1]*rhs[3,1] + lhs[2,1]*rhs[3,2] + lhs[3,1]*rhs[3,3];
+
+ Result[2,0]:=lhs[0,2]*rhs[0,0] + lhs[1,2]*rhs[0,1] + lhs[2,2]*rhs[0,2] + lhs[3,2]*rhs[0,3];
+ Result[2,1]:=lhs[0,2]*rhs[1,0] + lhs[1,2]*rhs[1,1] + lhs[2,2]*rhs[1,2] + lhs[3,2]*rhs[1,3];
+ Result[2,2]:=lhs[0,2]*rhs[2,0] + lhs[1,2]*rhs[2,1] + lhs[2,2]*rhs[2,2] + lhs[3,2]*rhs[2,3];
+ Result[2,3]:=lhs[0,2]*rhs[3,0] + lhs[1,2]*rhs[3,1] + lhs[2,2]*rhs[3,2] + lhs[3,2]*rhs[3,3];
+
+ Result[3,0]:=lhs[0,3]*rhs[0,0] + lhs[1,3]*rhs[0,1] + lhs[2,3]*rhs[0,2] + lhs[3,3]*rhs[0,3];
+ Result[3,1]:=lhs[0,3]*rhs[1,0] + lhs[1,3]*rhs[1,1] + lhs[2,3]*rhs[1,2] + lhs[3,3]*rhs[1,3];
+ Result[3,2]:=lhs[0,3]*rhs[2,0] + lhs[1,3]*rhs[2,1] + lhs[2,3]*rhs[2,2] + lhs[3,3]*rhs[2,3];
+ Result[3,3]:=lhs[0,3]*rhs[3,0] + lhs[1,3]*rhs[3,1] + lhs[2,3]*rhs[3,2] + lhs[3,3]*rhs[3,3];
+}
+ glPushMatrix;
+ glLoadMatrixf(@lhs[0, 0]);
+ glMultMatrixf(@rhs[0, 0]);
+ glGetFloatv(GL_MODELVIEW_MATRIX, @test[0, 0]);
+ glPopMatrix;
+
+ error:=false;
+ for i:=0 to 3 do
+ for j:=0 to 3 do
+ if Abs(test[i, j] - Result[i, j]) > 0.000001 then
+ error:=true;
+
+ if error then
+ begin
+ writeln('shall:');
+ for i:=0 to 3 do
+ begin
+ for j:=0 to 3 do
+ write(test[i, j]);
+ writeln;
+ end;
+
+ writeln('is:');
+ for i:=0 to 3 do
+ begin
+ for j:=0 to 3 do
+ write(Result[i, j]);
+ writeln;
+ end;
+ halt(0);
+ end;
+
+
+end;
+
+
+end.
--- a/hedgewars/uRender.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uRender.pas Tue Jun 05 22:17:06 2012 +0200
@@ -22,7 +22,7 @@
interface
-uses SDLh, uTypes, GLunit, uConsts;
+uses SDLh, uTypes, GLunit, uConsts, uTextures, math;
procedure DrawSprite (Sprite: TSprite; X, Y, Frame: LongInt);
procedure DrawSprite (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
@@ -51,12 +51,81 @@
procedure Tint (r, g, b, a: Byte); inline;
procedure Tint (c: Longword); inline;
+// This is just temporary and becomes non public once everything changed to GL2
+procedure UpdateModelview;
+procedure ResetModelview;
+procedure SetOffset(X, Y: Longint);
+procedure ResetRotation;
+
implementation
-uses uVariables;
+uses uVariables, uStore;
var LastTint: LongWord = 0;
+const DegToRad = 0.01745329252; // 2PI / 360
+
+procedure UpdateModelview;
+begin
+{$IFDEF GL2}
+ UpdateModelviewProjection;
+{$ELSE}
+ glLoadMatrixf(@mModelview[0,0]);
+{$ENDIF}
+end;
+
+procedure ResetModelview;
+begin
+ mModelview[0,0]:= 1.0; mModelview[1,0]:=0.0; mModelview[3,0]:= 0;
+ mModelview[0,1]:= 0.0; mModelview[1,1]:=1.0; mModelview[3,1]:= 0;
+ UpdateModelview;
+end;
+
+procedure SetOffset(X, Y: Longint);
+begin
+ mModelview[3,0]:= X;
+ mModelview[3,1]:= Y;
+end;
+
+procedure AddOffset(X, Y: GLfloat); // probably want to refactor this to use integers
+begin
+ mModelview[3,0]:=mModelview[3,0] + mModelview[0,0]*X + mModelview[1,0]*Y;
+ mModelview[3,1]:=mModelview[3,1] + mModelview[0,1]*X + mModelview[1,1]*Y;
+end;
+
+procedure SetScale(Scale: GLfloat);
+begin
+ mModelview[0,0]:= Scale;
+ mModelview[1,1]:= Scale;
+end;
+
+procedure AddScale(Scale: GLfloat);
+begin
+ mModelview[0,0]:= mModelview[0,0]*Scale; mModelview[1,0]:= mModelview[1,0]*Scale;
+ mModelview[0,1]:= mModelview[0,1]*Scale; mModelview[1,1]:= mModelview[1,1]*Scale;
+end;
+
+procedure AddScale(X, Y: GLfloat);
+begin
+ mModelview[0,0]:= mModelview[0,0]*X; mModelview[1,0]:= mModelview[1,0]*Y;
+ mModelview[0,1]:= mModelview[0,1]*X; mModelview[1,1]:= mModelview[1,1]*Y;
+end;
+
+
+procedure SetRotation(Angle, ZAxis: GLfloat);
+var s, c: Extended;
+begin
+ SinCos(Angle*DegToRad, s, c);
+ mModelview[0,0]:= c; mModelview[1,0]:=-s*ZAxis;
+ mModelview[0,1]:= s*ZAxis; mModelview[1,1]:= c;
+end;
+
+procedure ResetRotation;
+begin
+ mModelview[0,0]:= 1.0; mModelview[1,0]:=0.0;
+ mModelview[0,1]:= 0.0; mModelview[1,1]:=1.0;
+end;
+
procedure DrawSpriteFromRect(Sprite: TSprite; r: TSDL_Rect; X, Y, Height, Position: LongInt);
begin
r.y:= r.y + Height * Position;
@@ -71,8 +140,7 @@
procedure DrawTextureFromRect(X, Y, W, H: LongInt; r: PSDL_Rect; SourceTexture: PTexture);
var rr: TSDL_Rect;
- _l, _r, _t, _b: real;
- VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
+ VertexBuffer, TextureBuffer: TVertexRect;
begin
if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then
exit;
@@ -88,12 +156,9 @@
rr.w:= W;
rr.h:= H;
-_l:= r^.x / SourceTexture^.w * SourceTexture^.rx;
-_r:= (r^.x + r^.w) / SourceTexture^.w * SourceTexture^.rx;
-_t:= r^.y / SourceTexture^.h * SourceTexture^.ry;
-_b:= (r^.y + r^.h) / SourceTexture^.h * SourceTexture^.ry;
+glBindTexture(GL_TEXTURE_2D, SourceTexture^.atlas^.id);
-glBindTexture(GL_TEXTURE_2D, SourceTexture^.id);
+ComputeTexcoords(SourceTexture, r, @TextureBuffer);
VertexBuffer[0].X:= X;
VertexBuffer[0].Y:= Y;
@@ -104,15 +169,6 @@
VertexBuffer[3].X:= X;
VertexBuffer[3].Y:= rr.h + Y;
-TextureBuffer[0].X:= _l;
-TextureBuffer[0].Y:= _t;
-TextureBuffer[1].X:= _r;
-TextureBuffer[1].Y:= _t;
-TextureBuffer[2].X:= _r;
-TextureBuffer[2].Y:= _b;
-TextureBuffer[3].X:= _l;
-TextureBuffer[3].Y:= _b;
-
glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
@@ -125,18 +181,17 @@
procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
begin
+SetOffset(X, Y);
+ResetRotation;
+SetScale(Scale);
+UpdateModelview;
-glPushMatrix;
-glTranslatef(X, Y, 0);
-glScalef(Scale, Scale, 1);
-
-glBindTexture(GL_TEXTURE_2D, Texture^.id);
+glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
glVertexPointer(2, GL_FLOAT, 0, @Texture^.vb);
glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
-
-glPopMatrix
+ResetModelview;
end;
procedure DrawTextureF(Texture: PTexture; Scale: GLfloat; X, Y, Frame, Dir, w, h: LongInt);
@@ -145,8 +200,8 @@
end;
procedure DrawTextureRotatedF(Texture: PTexture; Scale, OffsetX, OffsetY: GLfloat; X, Y, Frame, Dir, w, h: LongInt; Angle: real);
-var ft, fb, fl, fr: GLfloat;
- hw, nx, ny: LongInt;
+var hw, nx, ny: LongInt;
+ r: TSDL_Rect;
VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
begin
// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
@@ -155,14 +210,13 @@
if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then
exit;
-glPushMatrix;
-glTranslatef(X, Y, 0);
+SetOffset(X, Y);
if Dir = 0 then Dir:= 1;
-glRotatef(Angle, 0, 0, Dir);
-
-glTranslatef(Dir*OffsetX, OffsetY, 0);
-glScalef(Scale, Scale, 1);
+SetRotation(Angle, Dir);
+AddOffset(Dir*OffsetX, OffsetY);
+AddScale(Scale);
+UpdateModelview;
// Any reason for this call? And why only in t direction, not s?
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -172,12 +226,13 @@
nx:= round(Texture^.w / w); // number of horizontal frames
ny:= round(Texture^.h / h); // number of vertical frames
-ft:= (Frame mod ny) * Texture^.ry / ny;
-fb:= ((Frame mod ny) + 1) * Texture^.ry / ny;
-fl:= (Frame div ny) * Texture^.rx / nx;
-fr:= ((Frame div ny) + 1) * Texture^.rx / nx;
+r.y:=(Frame mod ny) * h;
+r.x:=(Frame div ny) * w;
+r.w:=w;
+r.h:=h;
+ComputeTexcoords(Texture, @r, @TextureBuffer);
-glBindTexture(GL_TEXTURE_2D, Texture^.id);
+glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
VertexBuffer[0].X:= -hw;
VertexBuffer[0].Y:= w / -2;
@@ -188,20 +243,11 @@
VertexBuffer[3].X:= -hw;
VertexBuffer[3].Y:= w / 2;
-TextureBuffer[0].X:= fl;
-TextureBuffer[0].Y:= ft;
-TextureBuffer[1].X:= fr;
-TextureBuffer[1].Y:= ft;
-TextureBuffer[2].X:= fr;
-TextureBuffer[2].Y:= fb;
-TextureBuffer[3].X:= fl;
-TextureBuffer[3].Y:= fb;
-
glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-glPopMatrix
+ResetModelview;
end;
procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
@@ -214,19 +260,18 @@
procedure DrawSpriteRotatedF(Sprite: TSprite; X, Y, Frame, Dir: LongInt; Angle: real);
begin
-glPushMatrix;
-glTranslatef(X, Y, 0);
-
+SetOffset(X, Y);
if Dir < 0 then
- glRotatef(Angle, 0, 0, -1)
+ SetRotation(Angle, -1.0)
else
- glRotatef(Angle, 0, 0, 1);
+ SetRotation(Angle, 1.0);
if Dir < 0 then
- glScalef(-1.0, 1.0, 1.0);
+ AddScale(-1.0, 1.0);
+UpdateModelview;
DrawSprite(Sprite, -SpritesData[Sprite].Width div 2, -SpritesData[Sprite].Height div 2, Frame);
-glPopMatrix
+ResetModelview;
end;
procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
@@ -238,19 +283,18 @@
if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then
exit;
-glPushMatrix;
-glTranslatef(X, Y, 0);
+SetOffset(X, Y);
if Dir < 0 then
begin
hw:= - hw;
- glRotatef(Angle, 0, 0, -1);
+ SetRotation(Angle, -1.0);
end
else
- glRotatef(Angle, 0, 0, 1);
+ SetRotation(Angle, 1.0);
+UpdateModelview;
-
-glBindTexture(GL_TEXTURE_2D, Texture^.id);
+glBindTexture(GL_TEXTURE_2D, Texture^.atlas^.id);
VertexBuffer[0].X:= -hw;
VertexBuffer[0].Y:= -hh;
@@ -265,7 +309,7 @@
glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-glPopMatrix
+ResetModelview;
end;
procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt);
@@ -329,8 +373,9 @@
glDisable(GL_TEXTURE_2D);
glEnable(GL_LINE_SMOOTH);
- glPushMatrix;
- glTranslatef(WorldDx, WorldDy, 0);
+ ResetRotation;
+ SetOffset(WorldDx, WorldDy);
+ UpdateModelview;
glLineWidth(Width);
Tint(r, g, b, a);
@@ -343,7 +388,7 @@
glDrawArrays(GL_LINES, 0, Length(VertexBuffer));
Tint($FF, $FF, $FF, $FF);
- glPopMatrix;
+ ResetModelview;
glEnable(GL_TEXTURE_2D);
glDisable(GL_LINE_SMOOTH);
@@ -352,6 +397,10 @@
procedure DrawFillRect(r: TSDL_Rect);
var VertexBuffer: array [0..3] of TVertex2f;
begin
+SetOffset(0, 0);
+ResetRotation;
+UpdateModelview;
+
// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then
exit;
@@ -375,7 +424,9 @@
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
Tint($FF, $FF, $FF, $FF);
-glEnable(GL_TEXTURE_2D)
+glEnable(GL_TEXTURE_2D);
+
+ResetModelview;
end;
procedure DrawCircle(X, Y, Radius, Width: LongInt; r, g, b, a: Byte);
@@ -396,23 +447,29 @@
end;
glDisable(GL_TEXTURE_2D);
glEnable(GL_LINE_SMOOTH);
- glPushMatrix;
+ SetOffset(0, 0);
+ ResetRotation;
+ UpdateModelview;
glLineWidth(Width);
glVertexPointer(2, GL_FLOAT, 0, @CircleVertex[0]);
glDrawArrays(GL_LINE_LOOP, 0, 60);
- glPopMatrix;
glEnable(GL_TEXTURE_2D);
glDisable(GL_LINE_SMOOTH);
+ ResetModelview;
end;
procedure DrawHedgehog(X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
-const VertexBuffer: array [0..3] of TVertex2f = (
- (X: -16; Y: -16),
- (X: 16; Y: -16),
- (X: 16; Y: 16),
- (X: -16; Y: 16));
-var l, r, t, b: real;
+const VertexBuffers: array[0..1] of TVertexRect = (
+ ((x: -16; y: -16),
+ (x: 16; y: -16),
+ (x: 16; y: 16),
+ (x: -16; y: 16)),
+ ((x: 16; y: -16),
+ (x: -16; y: -16),
+ (x: -16; y: 16),
+ (x: 16; y: 16)));
+var r: TSDL_Rect;
TextureBuffer: array [0..3] of TVertex2f;
begin
// do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
@@ -421,41 +478,25 @@
if (abs(Y) > 32) and ((abs(Y - 0.5 * cScreenHeight) - 16) * cScaleFactor > cScreenHeight) then
exit;
- t:= Pos * 32 / HHTexture^.h;
- b:= (Pos + 1) * 32 / HHTexture^.h;
+ r.x:=Step * 32;
+ r.y:=Pos * 32;
+ r.w:=32;
+ r.h:=32;
+ ComputeTexcoords(HHTexture, @r, @TextureBuffer);
- if Dir = -1 then
- begin
- l:= (Step + 1) * 32 / HHTexture^.w;
- r:= Step * 32 / HHTexture^.w
- end
- else
- begin
- l:= Step * 32 / HHTexture^.w;
- r:= (Step + 1) * 32 / HHTexture^.w
- end;
-
+ SetOffset(X, Y);
+ SetRotation(Angle, 1.0);
+ UpdateModelview;
- glPushMatrix();
- glTranslatef(X, Y, 0);
- glRotatef(Angle, 0, 0, 1);
-
- glBindTexture(GL_TEXTURE_2D, HHTexture^.id);
+ glBindTexture(GL_TEXTURE_2D, HHTexture^.atlas^.id);
+ if Dir = -1 then
+ glVertexPointer(2, GL_FLOAT, 0, @VertexBuffers[1][0])
+ else
+ glVertexPointer(2, GL_FLOAT, 0, @VertexBuffers[0][0]);
+ glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- TextureBuffer[0].X:= l;
- TextureBuffer[0].Y:= t;
- TextureBuffer[1].X:= r;
- TextureBuffer[1].Y:= t;
- TextureBuffer[2].X:= r;
- TextureBuffer[2].Y:= b;
- TextureBuffer[3].X:= l;
- TextureBuffer[3].Y:= b;
-
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
- glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
- glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-
- glPopMatrix
+ ResetModelview;
end;
procedure DrawScreenWidget(widget: POnScreenWidget);
--- a/hedgewars/uStore.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uStore.pas Tue Jun 05 22:17:06 2012 +0200
@@ -43,10 +43,15 @@
procedure WarpMouse(x, y: Word); inline;
procedure SwapBuffers; inline;
+procedure UpdateProjection;
+
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+{$ENDIF}
implementation
uses uMisc, uConsole, uMobile, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands,
- uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF};
+ uDebug{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}, uMatrix;
//type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple);
@@ -57,6 +62,10 @@
{$ELSE}
SDLPrimSurface: PSDL_Surface;
{$ENDIF}
+{$IFDEF GL2}
+ Shader: GLuint;
+ uMVPLocation: GLint;
+{$ENDIF}
function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
var w, h: LongInt;
@@ -625,6 +634,106 @@
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); // try to prefer hardware rendering
end;
+{$IFDEF GL2}
+function CompileShader(shaderFile: string; shaderType: GLenum): GLuint;
+var
+ shader: GLuint;
+ f: Textfile;
+ source, line: AnsiString;
+ sourceA: Pchar;
+ lengthA: GLint;
+ compileResult: GLint;
+ logLength: GLint;
+ log: PChar;
+begin
+ Assign(f, Pathz[ptShaders] + '/' + shaderFile);
+ filemode:= 0; // readonly
+ Reset(f);
+ if IOResult <> 0 then
+ begin
+ AddFileLog('Unable to load ' + shaderFile);
+ halt(-1);
+ end;
+
+ source:='';
+ while not eof(f) do
+ begin
+ ReadLn(f, line);
+ source:= source + line + #10;
+ end;
+
+ CloseFile(f);
+
+ writeln('Compiling shader: ' + Pathz[ptShaders] + '/' + shaderFile);
+
+ sourceA:=PChar(source);
+ lengthA:=Length(source);
+
+ shader:=glCreateShader(shaderType);
+ glShaderSource(shader, 1, @sourceA, @lengthA);
+ glCompileShader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, @compileResult);
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, @logLength);
+
+ if logLength > 1 then
+ begin
+ GetMem(log, logLength);
+ glGetShaderInfoLog(shader, logLength, nil, log);
+ writeln('========== Compiler log ==========');
+ writeln(log);
+ writeln('===================================');
+ FreeMem(log, logLength);
+ end;
+
+ if compileResult <> GL_TRUE then
+ begin
+ writeln('Shader compilation failed, halting');
+ halt(-1);
+ end;
+
+ CompileShader:= shader;
+end;
+
+function CompileProgram(shaderName: string): GLuint;
+var
+ program_: GLuint;
+ vs, fs: GLuint;
+ linkResult: GLint;
+ logLength: GLint;
+ log: PChar;
+begin
+ program_:= glCreateProgram();
+ vs:= CompileShader(shaderName + '.vs', GL_VERTEX_SHADER);
+ fs:= CompileShader(shaderName + '.fs', GL_FRAGMENT_SHADER);
+ glAttachShader(program_, vs);
+ glAttachShader(program_, fs);
+ glLinkProgram(program_);
+ glDeleteShader(vs);
+ glDeleteShader(fs);
+
+ glGetProgramiv(program_, GL_LINK_STATUS, @linkResult);
+ glGetProgramiv(program_, GL_INFO_LOG_LENGTH, @logLength);
+
+ if logLength > 1 then
+ begin
+ GetMem(log, logLength);
+ glGetProgramInfoLog(program_, logLength, nil, log);
+ writeln('========== Compiler log ==========');
+ writeln(log);
+ writeln('===================================');
+ FreeMem(log, logLength);
+ end;
+
+ if linkResult <> GL_TRUE then
+ begin
+ writeln('Linking program failed, halting');
+ halt(-1);
+ end;
+
+ CompileProgram:= program_;
+end;
+{$ENDIF}
+
procedure SetupOpenGL;
//var vendor: shortstring = '';
var buf: array[byte] of char;
@@ -682,6 +791,15 @@
AddFileLog(' \----- Extensions: ' + shortstring(pchar(glGetString(GL_EXTENSIONS))));
//TODO: don't have the Extensions line trimmed but slipt it into multiple lines
+{$IFDEF GL2}
+ Load_GL_VERSION_2_0;
+ Shader:= CompileProgram('default');
+ glUseProgram(Shader);
+ glUniform1i(glGetUniformLocation(Shader, 'tex'), 0);
+ uMVPLocation:= glGetUniformLocation(Shader, 'mvp');
+
+{$ENDIF}
+
{$IFNDEF S3D_DISABLED}
if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
begin
@@ -729,9 +847,7 @@
glMatrixMode(GL_MODELVIEW);
// prepare default translation/scaling
- glLoadIdentity();
- glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
- glTranslatef(0, -cScreenHeight / 2, 0);
+ SetScale(2.0);
// enable alpha blending
glEnable(GL_BLEND);
@@ -746,23 +862,43 @@
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
end;
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+var
+ mvp: TMatrix4x4f;
+begin
+ MatrixMultiply(mvp, mProjection, mModelview);
+ glUniformMatrix4fv(uMVPLocation, 1, GL_FALSE, @mvp[0, 0]);
+end;
+{$ENDIF GL2}
+
+procedure UpdateProjection;
+var
+ s: GLfloat;
+begin
+ s:=cScaleFactor;
+ mProjection[0,0]:= s/cScreenWidth; mProjection[0,1]:= 0.0; mProjection[0,2]:=0.0; mProjection[0,3]:= 0.0;
+ mProjection[1,0]:= 0.0; mProjection[1,1]:= -s/cScreenHeight; mProjection[1,2]:=0.0; mProjection[1,3]:= 0.0;
+ mProjection[2,0]:= 0.0; mProjection[2,1]:= 0.0; mProjection[2,2]:=1.0; mProjection[2,3]:= 0.0;
+ mProjection[3,0]:= cStereoDepth; mProjection[3,1]:= s/2; mProjection[3,2]:=0.0; mProjection[3,3]:= 1.0;
+
+ {$IFDEF GL2}
+ UpdateModelviewProjection;
+ {$ELSE}
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(@mProjection[0, 0]);
+ glMatrixMode(GL_MODELVIEW);
+ {$ENDIF}
+end;
+
procedure SetScale(f: GLfloat);
begin
-// leave immediately if scale factor did not change
- if f = cScaleFactor then
- exit;
-
- if f = cDefaultZoomLevel then
- glPopMatrix // "return" to default scaling
- else // other scaling
- begin
- glPushMatrix; // save default scaling
- glLoadIdentity;
- glScalef(f / cScreenWidth, -f / cScreenHeight, 1.0);
- glTranslatef(0, -cScreenHeight / 2, 0);
- end;
-
- cScaleFactor:= f;
+ // This lazy update conflicts with R7103 at the moment, missing the initial SetScale(2.0)
+ //if cScaleFactor <> f then
+ //begin
+ cScaleFactor:=f;
+ UpdateProjection;
+ //end;
end;
////////////////////////////////////////////////////////////////////////////////
@@ -1033,11 +1169,7 @@
// chFullScr is called when there is a rotation event and needs the SetScale and SetupOpenGL to set up the new resolution
// this 6 gl functions are the relevant ones and are hacked together here for optimisation
glMatrixMode(GL_MODELVIEW);
- glPopMatrix;
- glLoadIdentity();
- glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
- glTranslatef(0, -cScreenHeight / 2, 0);
- glViewport(0, 0, cScreenWidth, cScreenHeight);
+ SetScale(2.0);
exit;
{$ELSE}
SetScale(cDefaultZoomLevel);
@@ -1151,6 +1283,9 @@
procedure freeModule;
begin
+{$IFDEF GL2}
+ glDeleteProgram(Shader);
+{$ENDIF}
StoreRelease(false);
TTF_Quit();
{$IFDEF SDL13}
--- a/hedgewars/uTextures.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uTextures.pas Tue Jun 05 22:17:06 2012 +0200
@@ -26,6 +26,7 @@
procedure Surface2GrayScale(surf: PSDL_Surface);
function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture;
procedure FreeTexture(tex: PTexture);
+procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect);
procedure initModule;
procedure freeModule;
@@ -47,10 +48,44 @@
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
end;
+procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect);
+var x0, y0, x1, y1: Real;
+ w, h, aw, ah: LongInt;
+const texelOffset = 0.0;
+begin
+aw:=texture^.atlas^.w;
+ah:=texture^.atlas^.h;
+if texture^.isRotated then
+ begin
+ w:=r^.h;
+ h:=r^.w;
+ end
+else
+ begin
+ w:=r^.w;
+ h:=r^.h;
+ end;
+
+x0:= (r^.x + texelOffset)/aw;
+x1:= (r^.x + w - texelOffset)/aw;
+y0:= (r^.y + texelOffset)/ah;
+y1:= (r^.y + h - texelOffset)/ah;
+
+tb^[0].X:= x0;
+tb^[0].Y:= y0;
+tb^[1].X:= x1;
+tb^[1].Y:= y0;
+tb^[2].X:= x1;
+tb^[2].Y:= y1;
+tb^[3].X:= x0;
+tb^[3].Y:= y1
+end;
+
procedure ResetVertexArrays(texture: PTexture);
+var r: TSDL_Rect;
begin
with texture^ do
- begin
+begin
vb[0].X:= 0;
vb[0].Y:= 0;
vb[1].X:= w;
@@ -59,16 +94,13 @@
vb[2].Y:= h;
vb[3].X:= 0;
vb[3].Y:= h;
+end;
- tb[0].X:= 0;
- tb[0].Y:= 0;
- tb[1].X:= rx;
- tb[1].Y:= 0;
- tb[2].X:= rx;
- tb[2].Y:= ry;
- tb[3].X:= 0;
- tb[3].Y:= ry
- end;
+r.x:= 0;
+r.y:= 0;
+r.w:= texture^.w;
+r.h:= texture^.h;
+ComputeTexcoords(texture, @r, @texture^.tb);
end;
function NewTexture(width, height: Longword; buf: Pointer): PTexture;
@@ -84,16 +116,22 @@
end;
TextureList:= NewTexture;
-NewTexture^.w:= width;
-NewTexture^.h:= height;
-NewTexture^.rx:= 1.0;
-NewTexture^.ry:= 1.0;
+
+// Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite
+new(NewTexture^.atlas);
+NewTexture^.atlas^.w:=width;
+NewTexture^.atlas^.h:=height;
+NewTexture^.x:=0;
+NewTexture^.y:=0;
+NewTexture^.w:=width;
+NewTexture^.h:=height;
+NewTexture^.isRotated:=false;
ResetVertexArrays(NewTexture);
-glGenTextures(1, @NewTexture^.id);
+glGenTextures(1, @NewTexture^.atlas^.id);
-glBindTexture(GL_TEXTURE_2D, NewTexture^.id);
+glBindTexture(GL_TEXTURE_2D, NewTexture^.atlas^.id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
SetTextureParameters(true);
@@ -136,20 +174,27 @@
end;
TextureList:= Surface2Tex;
+// Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite
+new(Surface2Tex^.atlas);
+
Surface2Tex^.w:= surf^.w;
Surface2Tex^.h:= surf^.h;
+Surface2Tex^.x:=0;
+Surface2Tex^.y:=0;
+Surface2Tex^.isRotated:=false;
+
if (surf^.format^.BytesPerPixel <> 4) then
begin
TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true);
- Surface2Tex^.id:= 0;
+ Surface2Tex^.atlas^.id:= 0;
exit
end;
-glGenTextures(1, @Surface2Tex^.id);
+glGenTextures(1, @Surface2Tex^.atlas^.id);
-glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id);
+glBindTexture(GL_TEXTURE_2D, Surface2Tex^.atlas^.id);
if SDL_MustLock(surf) then
SDLTry(SDL_LockSurface(surf) >= 0, true);
@@ -164,8 +209,8 @@
tw:= toPowerOf2(Surf^.w);
th:= toPowerOf2(Surf^.h);
- Surface2Tex^.rx:= Surf^.w / tw;
- Surface2Tex^.ry:= Surf^.h / th;
+ Surface2Tex^.atlas^.w:=tw;
+ Surface2Tex^.atlas^.h:=th;
tmpp:= GetMem(tw * th * surf^.format^.BytesPerPixel);
@@ -195,8 +240,8 @@
end
else
begin
- Surface2Tex^.rx:= 1.0;
- Surface2Tex^.ry:= 1.0;
+ Surface2Tex^.atlas^.w:=Surf^.w;
+ Surface2Tex^.atlas^.h:=Surf^.h;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels);
end;
@@ -214,13 +259,16 @@
begin
if tex <> nil then
begin
+ // Atlas cleanup happens here later on. For now we just free as each sprite has one atlas
+ Dispose(tex^.atlas);
+
if tex^.NextTexture <> nil then
tex^.NextTexture^.PrevTexture:= tex^.PrevTexture;
if tex^.PrevTexture <> nil then
tex^.PrevTexture^.NextTexture:= tex^.NextTexture
else
TextureList:= tex^.NextTexture;
- glDeleteTextures(1, @tex^.id);
+ glDeleteTextures(1, @tex^.atlas^.id);
Dispose(tex);
end
end;
@@ -236,7 +284,7 @@
WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem');
while TextureList <> nil do
begin
- AddFileLog('Texture not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.priority*1000)));
+ AddFileLog('Sprite not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.atlas^.priority*1000)));
FreeTexture(TextureList);
end
end;
--- a/hedgewars/uTypes.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uTypes.pas Tue Jun 05 22:17:06 2012 +0200
@@ -44,7 +44,8 @@
// Different files are stored in different folders, this enumeration is used to tell which folder to use
TPathType = (ptNone, ptData, ptGraphics, ptThemes, ptCurrTheme, ptTeams, ptMaps,
ptMapCurrent, ptDemos, ptSounds, ptGraves, ptFonts, ptForts,
- ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps, ptSuddenDeath, ptButtons);
+ ptLocale, ptAmmoMenu, ptHedgehog, ptVoices, ptHats, ptFlags, ptMissionMaps, ptSuddenDeath, ptButtons,
+ ptShaders);
// Available sprites for displaying stuff
TSprite = (sprWater, sprCloud, sprBomb, sprBigDigit, sprFrame,
@@ -199,13 +200,30 @@
X, Y: GLint;
end;
+ TMatrix4x4f = array[0..3, 0..3] of GLfloat;
+
+ PAtlas = ^TAtlas;
PTexture = ^TTexture;
+
+ TAtlas = record
+ id: GLuint;
+ w, h: LongInt;
+ priority: GLfloat;
+ end;
+
+ PVertexRect = ^TVertexRect;
+ TVertexRect = array[0..3] of TVertex2f;
+
TTexture = record
- id: GLuint;
+ atlas: PAtlas;
w, h, scale: LongInt;
- rx, ry: GLfloat;
- priority: GLfloat;
- vb, tb: array [0..3] of TVertex2f;
+
+ x, y: LongInt; // Offset in the texture atlas
+ isRotated: boolean; // if true sprite is flipped in the atlas taking w pixels along the y and h pixels along the x axis
+
+ // Cached values for texel coordinates and vertex coordinates
+ vb, tb: TVertexRect;
+
PrevTexture, NextTexture: PTexture;
end;
--- a/hedgewars/uVariables.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uVariables.pas Tue Jun 05 22:17:06 2012 +0200
@@ -21,7 +21,7 @@
unit uVariables;
interface
-uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uMobile;
+uses SDLh, uTypes, uFloat, GLunit, uConsts, Math, uMobile, uMatrix;
var
/////// init flags ///////
@@ -225,8 +225,9 @@
'Graphics/Hats', // ptHats
'Graphics/Flags', // ptFlags
'Missions/Maps', // ptMissionMaps
- 'Graphics/SuddenDeath', // ptSuddenDeath
- 'Graphics/Buttons' // ptButton
+ 'Graphics/SuddenDeath', // ptSuddenDeath
+ 'Graphics/Buttons', // ptButton
+ 'Shaders' // ptShaders
);
Fontz: array[THWFont] of THHFont = (
@@ -2425,6 +2426,7 @@
SyncTexture,
ConfirmTexture: PTexture;
cScaleFactor: GLfloat;
+ cStereoDepth: GLfloat;
SupportNPOTT: Boolean;
Step: LongInt;
squaresize : LongInt;
@@ -2463,6 +2465,9 @@
lastTurnChecksum : Longword;
+ mModelview: TMatrix4x4f;
+ mProjection: TMatrix4x4f;
+
var trammo: array[TAmmoStrId] of ansistring; // name of the weapon
trammoc: array[TAmmoStrId] of ansistring; // caption of the weapon
trammod: array[TAmmoStrId] of ansistring; // description of the weapon
@@ -2612,6 +2617,9 @@
GrayScale:= false;
LuaGoals:= '';
+
+ MatrixLoadIdentity(mModelview);
+ MatrixLoadIdentity(mProjection);
end;
procedure freeModule;
--- a/hedgewars/uWorld.pas Tue Jun 05 19:36:07 2012 +0200
+++ b/hedgewars/uWorld.pas Tue Jun 05 22:17:06 2012 +0200
@@ -77,7 +77,6 @@
amSel: TAmmoType = amNothing;
missionTex: PTexture;
missionTimer: LongInt;
- stereoDepth: GLfloat;
isFirstFrame: boolean;
AMAnimType: LongInt;
@@ -819,8 +818,9 @@
procedure DrawWaves(Dir, dX, dY: LongInt; tnt: Byte);
var VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
- lw, waves, shift: GLfloat;
+ lw, waves: GLfloat;
sprite: TSprite;
+ r: TSDL_Rect;
begin
if SuddenDeathDmg then
sprite:= sprSDWater
@@ -830,7 +830,6 @@
cWaveWidth:= SpritesData[sprite].Width;
lw:= cScreenWidth / cScaleFactor;
-waves:= lw * 2 / cWaveWidth;
if SuddenDeathDmg then
Tint(LongInt(tnt) * SDWaterColorArray[2].r div 255 + 255 - tnt,
@@ -845,7 +844,7 @@
255
);
-glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.id);
+glBindTexture(GL_TEXTURE_2D, SpritesData[sprite].Texture^.atlas^.id);
VertexBuffer[0].X:= -lw;
VertexBuffer[0].Y:= cWaterLine + WorldDy + dY;
@@ -856,15 +855,12 @@
VertexBuffer[3].X:= -lw;
VertexBuffer[3].Y:= VertexBuffer[2].Y;
-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;
+// this uses texture repeat mode, when using an atlas rect we need to split to several quads here!
+r.x := -Trunc(lw) + (( - WorldDx + LongInt(RealTicks shr 6) * Dir + dX) mod cWaveWidth);
+r.y:= 0;
+r.w:= Trunc(lw + lw);
+r.h:= SpritesData[sprite].Texture^.h;
+ComputeTexcoords(SpritesData[sprite].Texture, @r, @TextureBuffer);
glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
@@ -1088,10 +1084,8 @@
exit
else if rm = rmLeftEye then
d:= -d;
- stereoDepth:= stereoDepth + d;
- glMatrixMode(GL_PROJECTION);
- glTranslatef(d, 0, 0);
- glMatrixMode(GL_MODELVIEW);
+ cStereoDepth:= cStereoDepth + d;
+ UpdateProjection;
{$ENDIF}
end;
@@ -1103,10 +1097,8 @@
{$ELSE}
if rm = rmDefault then
exit;
- glMatrixMode(GL_PROJECTION);
- glTranslatef(-stereoDepth, 0, 0);
- glMatrixMode(GL_MODELVIEW);
- stereoDepth:= 0;
+ cStereoDepth:= 0;
+ UpdateProjection;
{$ENDIF}
end;
@@ -1827,14 +1819,13 @@
missionTimer:= 0;
missionTex:= nil;
cOffsetY:= 0;
- stereoDepth:= 0;
+ cStereoDepth:= 0;
AMState:= AMHidden;
isFirstFrame:= true;
end;
procedure freeModule;
begin
- stereoDepth:= stereoDepth; // avoid hint
FreeTexture(fpsTexture);
fpsTexture:= nil;
FreeTexture(timeTexture);
--- a/share/hedgewars/Data/CMakeLists.txt Tue Jun 05 19:36:07 2012 +0200
+++ b/share/hedgewars/Data/CMakeLists.txt Tue Jun 05 22:17:06 2012 +0200
@@ -1,3 +1,3 @@
-foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc" "Scripts")
+foreach(dir "Fonts" "Forts" "Graphics" "Locale" "Maps" "Music" "Sounds" "Themes" "Missions" "Names" "misc" "Scripts" "Shaders")
add_subdirectory(${dir})
endforeach(dir)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/CMakeLists.txt Tue Jun 05 22:17:06 2012 +0200
@@ -0,0 +1,5 @@
+file(GLOB BaseShaders *.vs *.fs)
+
+install(FILES
+ ${BaseShaders}
+ DESTINATION ${SHAREPATH}Data/Shaders)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/default.fs Tue Jun 05 22:17:06 2012 +0200
@@ -0,0 +1,9 @@
+// !!!just testing!!!
+// This is not GLSL 1.3+ compatible, as its using the compatibility profile!
+uniform sampler2D tex0;
+varying vec4 tint;
+
+void main()
+{
+ gl_FragColor = texture2D(tex0, gl_TexCoord[0].st) * tint;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/default.vs Tue Jun 05 22:17:06 2012 +0200
@@ -0,0 +1,11 @@
+// !!!just testing!!!
+// This is not GLSL 1.3+ compatible, as its using the compatibility profile!
+uniform mat4 mvp;
+varying vec4 tint;
+
+void main()
+{
+ gl_Position = mvp * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ tint = gl_Color;
+}