--- a/hedgewars/options.inc Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/options.inc Mon Jun 25 10:44:27 2012 +0200
@@ -30,6 +30,8 @@
{$DEFINE USE_LUA_SCRIPT}
+{$DEFINE GL2}
+
{$IFDEF ANDROID}
{$DEFINE MOBILE}
{$DEFINE USE_SDLTHREADS}
@@ -53,6 +55,10 @@
{$ENDIF}
+{$IFDEF GL2}
+ {$DEFINE S3D_DISABLED}
+{$ENDIF}
+
{$IFDEF WIN32}
{$DEFINE USE_CONTEXT_RESTORE}
{$ENDIF}
--- a/hedgewars/uChat.pas Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uChat.pas Mon Jun 25 10:44:27 2012 +0200
@@ -31,7 +31,7 @@
procedure KeyPressChat(Key: Longword);
implementation
-uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO;
+uses SDLh, uInputHandler, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uStore, uIO;
const MaxStrIndex = 27;
--- a/hedgewars/uGearsRender.pas Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uGearsRender.pas Mon Jun 25 10:44:27 2012 +0200
@@ -37,7 +37,7 @@
end;
implementation
-uses uRender, uUtils, uVariables, uAmmos, Math, uVisualGears;
+uses uRender, uStore, uUtils, uVariables, uAmmos, Math, uVisualGears;
procedure DrawRopeLinesRQ(Gear: PGear);
begin
@@ -54,20 +54,18 @@
glDisable(GL_TEXTURE_2D);
//glEnable(GL_LINE_SMOOTH);
- glPushMatrix;
-
- glTranslatef(WorldDx, WorldDy, 0);
+ ResetRotation;
+ SetOffset(WorldDx, WorldDy);
+ UpdateModelview;
glLineWidth(4.0);
Tint($C0, $C0, $C0, $FF);
- glVertexPointer(2, GL_FLOAT, 0, @RopePoints.rounded[0]);
+ SetVertexPointer(@RopePoints.rounded[0]);
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 Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uLandTexture.pas Mon Jun 25 10:44:27 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 Mon Jun 25 10:44:27 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 Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uRender.pas Mon Jun 25 10:44:27 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);
@@ -48,14 +48,78 @@
procedure DrawHedgehog (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
procedure DrawScreenWidget (widget: POnScreenWidget);
-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;
+
+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;
-var LastTint: LongWord = 0;
+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
@@ -71,8 +135,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 +151,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,17 +164,8 @@
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]);
+SetVertexPointer(@VertexBuffer[0]);
+SetTexCoordPointer(@TextureBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
end;
@@ -125,18 +176,17 @@
procedure DrawTexture(X, Y: LongInt; Texture: PTexture; Scale: GLfloat);
begin
-
-glPushMatrix;
-glTranslatef(X, Y, 0);
-glScalef(Scale, Scale, 1);
+SetOffset(X, Y);
+ResetRotation;
+SetScale(Scale);
+UpdateModelview;
-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);
+SetVertexPointer(@Texture^.vb);
+SetTexCoordPointer(@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 +195,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 +205,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 +221,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 +238,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]);
+SetVertexPointer(@VertexBuffer[0]);
+SetTexCoordPointer(@TextureBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-glPopMatrix
+ResetModelview;
end;
procedure DrawSpriteRotated(Sprite: TSprite; X, Y, Dir: LongInt; Angle: real);
@@ -214,19 +255,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 +278,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;
@@ -261,11 +300,11 @@
VertexBuffer[3].X:= -hw;
VertexBuffer[3].Y:= hh;
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
-glTexCoordPointer(2, GL_FLOAT, 0, @Texture^.tb);
+SetVertexPointer(@VertexBuffer[0]);
+SetTexCoordPointer(@Texture^.tb);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
-glPopMatrix
+ResetModelview;
end;
procedure DrawSprite(Sprite: TSprite; X, Y, Frame: LongInt);
@@ -329,8 +368,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);
@@ -339,11 +379,11 @@
VertexBuffer[1].X:= X1;
VertexBuffer[1].Y:= Y1;
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+ SetVertexPointer(@VertexBuffer[0]);
glDrawArrays(GL_LINES, 0, Length(VertexBuffer));
Tint($FF, $FF, $FF, $FF);
- glPopMatrix;
+ ResetModelview;
glEnable(GL_TEXTURE_2D);
glDisable(GL_LINE_SMOOTH);
@@ -352,6 +392,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;
@@ -371,11 +415,13 @@
VertexBuffer[3].X:= r.x;
VertexBuffer[3].Y:= r.y + r.h;
-glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+SetVertexPointer(@VertexBuffer[0]);
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 +442,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]);
+ SetVertexPointer(@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 +473,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
+ SetVertexPointer(@VertexBuffers[1][0])
+ else
+ SetVertexPointer(@VertexBuffers[0][0]);
+ SetTexCoordPointer(@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);
@@ -505,31 +541,4 @@
{$ENDIF}
end;
-procedure Tint(r, g, b, a: Byte); inline;
-var nc, tw: Longword;
-begin
- nc:= (a shl 24) or (b shl 16) or (g shl 8) or r;
-
- if nc = lastTint then
- exit;
-
- if GrayScale then
- begin
- tw:= round(r * RGB_LUMINANCE_RED + g * RGB_LUMINANCE_GREEN + b * RGB_LUMINANCE_BLUE);
- if tw > 255 then
- tw:= 255;
- r:= tw;
- g:= tw;
- b:= tw
- end;
-
- glColor4ub(r, g, b, a);
- lastTint:= nc;
-end;
-
-procedure Tint(c: Longword); inline;
-begin
- Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
-end;
-
end.
--- a/hedgewars/uStore.pas Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uStore.pas Mon Jun 25 10:44:27 2012 +0200
@@ -43,10 +43,23 @@
procedure WarpMouse(x, y: Word); inline;
procedure SwapBuffers; inline;
+procedure UpdateProjection;
+
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+{$ENDIF}
+
+procedure Tint(r, g, b, a: Byte); inline;
+procedure Tint(c: Longword); inline;
+procedure SetTexCoordPointer(p: Pointer);
+procedure SetVertexPointer(p: Pointer);
+procedure SetColorPointer(p: Pointer);
+procedure BeginWater;
+procedure EndWater;
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 +70,27 @@
{$ELSE}
SDLPrimSurface: PSDL_Surface;
{$ENDIF}
+{$IFDEF GL2}
+ shaderMain: GLuint;
+ shaderWater: GLuint;
+
+ // attributes
+const
+ aVertex: GLint = 0;
+ aTexCoord: GLint = 1;
+ aColor: GLint = 2;
+
+var
+ uCurrentMVPLocation: GLint;
+
+ uMainMVPLocation: GLint;
+ uMainTintLocation: GLint;
+
+ uWaterMVPLocation: GLint;
+
+{$ENDIF}
+ LastTint: LongWord = 0;
+
function WriteInRect(Surface: PSDL_Surface; X, Y: LongInt; Color: LongWord; Font: THWFont; s: ansistring): TSDL_Rect;
var w, h: LongInt;
@@ -625,6 +659,112 @@
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);
+
+ WriteLnToConsole('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);
+ WriteLnToConsole('========== Compiler log ==========');
+ WriteLnToConsole(log);
+ WriteLnToConsole('===================================');
+ FreeMem(log, logLength);
+ end;
+
+ if compileResult <> GL_TRUE then
+ begin
+ WriteLnToConsole('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);
+
+ glBindAttribLocation(program_, aVertex, 'vertex');
+ glBindAttribLocation(program_, aTexCoord, 'texcoord');
+ glBindAttribLocation(program_, aColor, 'color');
+
+ 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);
+ WriteLnToConsole('========== Compiler log ==========');
+ WriteLnToConsole(log);
+ WriteLnToConsole('===================================');
+ FreeMem(log, logLength);
+ end;
+
+ if linkResult <> GL_TRUE then
+ begin
+ WriteLnToConsole('Linking program failed, halting');
+ halt(-1);
+ end;
+
+ CompileProgram:= program_;
+end;
+
+{$ENDIF}
+
procedure SetupOpenGL;
//var vendor: shortstring = '';
var buf: array[byte] of char;
@@ -682,6 +822,26 @@
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;
+
+ shaderWater:= CompileProgram('water');
+ glUseProgram(shaderWater);
+ glUniform1i(glGetUniformLocation(shaderWater, 'tex0'), 0);
+ uWaterMVPLocation:= glGetUniformLocation(shaderWater, 'mvp');
+
+ shaderMain:= CompileProgram('default');
+ glUseProgram(shaderMain);
+ glUniform1i(glGetUniformLocation(shaderMain, 'tex0'), 0);
+ uMainMVPLocation:= glGetUniformLocation(shaderMain, 'mvp');
+ uMainTintLocation:= glGetUniformLocation(shaderMain, 'tint');
+
+ uCurrentMVPLocation:= uMainMVPLocation;
+
+ Tint(255, 255, 255, 255);
+ UpdateModelviewProjection;
+{$ENDIF}
+
{$IFNDEF S3D_DISABLED}
if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
begin
@@ -729,9 +889,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);
@@ -742,27 +900,144 @@
glDisable(GL_DITHER);
// enable common states by default as they save a lot
glEnable(GL_TEXTURE_2D);
+
+{$IFDEF GL2}
+ glEnableVertexAttribArray(aVertex);
+ glEnableVertexAttribArray(aTexCoord);
+{$ELSE}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+{$ENDIF}
+end;
+
+
+procedure Tint(r, g, b, a: Byte); inline;
+var
+ nc, tw: Longword;
+const
+ scale = 1.0/255.0;
+begin
+ nc:= (a shl 24) or (b shl 16) or (g shl 8) or r;
+
+ if nc = lastTint then
+ exit;
+
+ if GrayScale then
+ begin
+ tw:= round(r * RGB_LUMINANCE_RED + g * RGB_LUMINANCE_GREEN + b * RGB_LUMINANCE_BLUE);
+ if tw > 255 then
+ tw:= 255;
+ r:= tw;
+ g:= tw;
+ b:= tw
+ end;
+
+ {$IFDEF GL2}
+ glUniform4f(uMainTintLocation, r*scale, g*scale, b*scale, a*scale);
+ glColor4ub(r, g, b, a);
+ {$ELSE}
+ glColor4ub(r, g, b, a);
+ {$ENDIF}
+ lastTint:= nc;
+end;
+
+procedure Tint(c: Longword); inline;
+begin
+ Tint(((c shr 24) and $FF), ((c shr 16) and $FF), (c shr 8) and $FF, (c and $FF))
+end;
+
+procedure SetTexCoordPointer(p: Pointer);
+begin
+ {$IFDEF GL2}
+ glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, GL_FALSE, 0, p);
+ {$ELSE}
+ glTexCoordPointer(2, GL_FLOAT, 0, p);
+ {$ENDIF}
+end;
+
+procedure SetVertexPointer(p: Pointer);
+begin
+ {$IFDEF GL2}
+ glVertexAttribPointer(aVertex, 2, GL_FLOAT, GL_FALSE, 0, p);
+ {$ELSE}
+ glVertexPointer(2, GL_FLOAT, 0, p);
+ {$ENDIF}
+end;
+
+procedure SetColorPointer(p: Pointer);
+begin
+ {$IFDEF GL2}
+ glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, p);
+ {$ELSE}
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, p);
+ {$ENDIF}
+end;
+
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+var
+ mvp: TMatrix4x4f;
+begin
+ MatrixMultiply(mvp, mProjection, mModelview);
+ glUniformMatrix4fv(uCurrentMVPLocation, 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;
+ // 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;
- 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;
+procedure BeginWater;
+begin
+ {$IFDEF GL2}
+ glUseProgram(shaderWater);
+ uCurrentMVPLocation:=uWaterMVPLocation;
+ UpdateModelviewProjection;
+ glDisableVertexAttribArray(aTexCoord);
+ glEnableVertexAttribArray(aColor);
+ {$ELSE}
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+ {$ENDIF}
+end;
- cScaleFactor:= f;
+procedure EndWater;
+begin
+ {$IFDEF GL2}
+ glUseProgram(shaderMain);
+ uCurrentMVPLocation:=uMainMVPLocation;
+ UpdateModelviewProjection;
+ glDisableVertexAttribArray(aColor);
+ glEnableVertexAttribArray(aTexCoord);
+ {$ELSE}
+ glDisableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ {$ENDIF}
end;
////////////////////////////////////////////////////////////////////////////////
@@ -1033,11 +1308,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 +1422,10 @@
procedure freeModule;
begin
+{$IFDEF GL2}
+ glDeleteProgram(shaderMain);
+ glDeleteProgram(shaderWater);
+{$ENDIF}
StoreRelease(false);
TTF_Quit();
{$IFDEF SDL13}
--- a/hedgewars/uTextures.pas Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uTextures.pas Mon Jun 25 10:44:27 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 Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uTypes.pas Mon Jun 25 10:44:27 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 Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uVariables.pas Mon Jun 25 10:44:27 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 = (
@@ -2427,6 +2428,7 @@
SyncTexture,
ConfirmTexture: PTexture;
cScaleFactor: GLfloat;
+ cStereoDepth: GLfloat;
SupportNPOTT: Boolean;
Step: LongInt;
squaresize : LongInt;
@@ -2465,6 +2467,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
@@ -2614,6 +2619,9 @@
GrayScale:= false;
LuaGoals:= '';
+
+ MatrixLoadIdentity(mModelview);
+ MatrixLoadIdentity(mProjection);
end;
procedure freeModule;
--- a/hedgewars/uWorld.pas Mon Jun 25 10:16:19 2012 +0400
+++ b/hedgewars/uWorld.pas Mon Jun 25 10:44:27 2012 +0200
@@ -77,7 +77,6 @@
amSel: TAmmoType = amNothing;
missionTex: PTexture;
missionTimer: LongInt;
- stereoDepth: GLfloat;
isFirstFrame: boolean;
AMAnimType: LongInt;
@@ -795,28 +794,29 @@
VertexBuffer[3].X:= -lw;
VertexBuffer[3].Y:= lh;
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- glEnableClientState(GL_COLOR_ARRAY);
+ BeginWater;
if SuddenDeathDmg then
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, @SDWaterColorArray[0])
+ SetColorPointer(@SDWaterColorArray[0])
else
- glColorPointer(4, GL_UNSIGNED_BYTE, 0, @WaterColorArray[0]);
+ SetColorPointer(@WaterColorArray[0]);
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+ SetVertexPointer(@VertexBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
- glDisableClientState(GL_COLOR_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ EndWater;
+ {$IFNDEF GL2}
glColor4ub($FF, $FF, $FF, $FF); // must not be Tint() as color array seems to stay active and color reset is required
+ {$ENDIF}
glEnable(GL_TEXTURE_2D);
end;
end;
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
@@ -826,7 +826,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,
@@ -841,7 +840,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;
@@ -852,19 +851,16 @@
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]);
-glTexCoordPointer(2, GL_FLOAT, 0, @TextureBuffer[0]);
+SetVertexPointer(@VertexBuffer[0]);
+SetTexCoordPointer(@TextureBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
Tint($FF, $FF, $FF, $FF);
@@ -1075,35 +1071,17 @@
procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
begin
-{$IFDEF S3D_DISABLED}
- rm:= rm; d:= d; // avoid hint
- exit;
-{$ELSE}
d:= d / 5;
- if rm = rmDefault then
- exit
- else if rm = rmLeftEye then
+ if rm = rmLeftEye then
d:= -d;
- stereoDepth:= stereoDepth + d;
- glMatrixMode(GL_PROJECTION);
- glTranslatef(d, 0, 0);
- glMatrixMode(GL_MODELVIEW);
-{$ENDIF}
+ cStereoDepth:= cStereoDepth + d;
+ UpdateProjection;
end;
procedure ResetDepth(rm: TRenderMode);
begin
-{$IFDEF S3D_DISABLED}
- rm:= rm; // avoid hint
- exit;
-{$ELSE}
- if rm = rmDefault then
- exit;
- glMatrixMode(GL_PROJECTION);
- glTranslatef(-stereoDepth, 0, 0);
- glMatrixMode(GL_MODELVIEW);
- stereoDepth:= 0;
-{$ENDIF}
+ cStereoDepth:= 0;
+ UpdateProjection;
end;
procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
@@ -1556,7 +1534,7 @@
glDisable(GL_TEXTURE_2D);
- glVertexPointer(2, GL_FLOAT, 0, @VertexBuffer[0]);
+ SetVertexPointer(@VertexBuffer[0]);
glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
glEnable(GL_TEXTURE_2D);
@@ -1823,14 +1801,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 Mon Jun 25 10:16:19 2012 +0400
+++ b/share/hedgewars/Data/CMakeLists.txt Mon Jun 25 10:44:27 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 Mon Jun 25 10:44:27 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 Mon Jun 25 10:44:27 2012 +0200
@@ -0,0 +1,13 @@
+#version 130
+
+uniform sampler2D tex0;
+uniform vec4 tint;
+
+in vec2 tex;
+
+out vec4 color;
+
+void main()
+{
+ color = texture(tex0, tex) * tint;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/default.vs Mon Jun 25 10:44:27 2012 +0200
@@ -0,0 +1,16 @@
+#version 130
+
+in vec2 vertex;
+in vec2 texcoord;
+in vec4 colors;
+
+out vec2 tex;
+
+uniform mat4 mvp;
+
+void main()
+{
+ vec4 p = mvp * vec4(vertex, 0.0f, 1.0f);
+ gl_Position = p;
+ tex = texcoord;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/water.fs Mon Jun 25 10:44:27 2012 +0200
@@ -0,0 +1,9 @@
+#version 130
+
+in vec4 vcolor;
+out vec4 color;
+
+void main()
+{
+ color = vcolor;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/share/hedgewars/Data/Shaders/water.vs Mon Jun 25 10:44:27 2012 +0200
@@ -0,0 +1,14 @@
+#version 130
+
+in vec2 vertex;
+in vec4 color;
+out vec4 vcolor;
+
+uniform mat4 mvp;
+
+void main()
+{
+ vec4 p = mvp * vec4(vertex, 0.0f, 1.0f);
+ gl_Position = p;
+ vcolor = color;
+}