--- a/hedgewars/uStore.pas Sun Jan 19 00:18:28 2014 +0400
+++ b/hedgewars/uStore.pas Tue Jan 21 22:38:13 2014 +0100
@@ -21,7 +21,7 @@
unit uStore;
interface
-uses StrUtils, SysUtils, uConsts, SDLh, GLunit, uTypes, uLandTexture, uCaptions, uChat;
+uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}SysUtils, uConsts, SDLh, GLunit, uTypes, uLandTexture, uCaptions, uChat;
procedure initModule;
procedure freeModule;
@@ -59,15 +59,24 @@
procedure SwapBuffers; {$IFDEF USE_VIDEO_RECORDING}cdecl{$ELSE}inline{$ENDIF};
procedure SetSkyColor(r, g, b: real);
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+procedure EnableTexture(enable:Boolean);
+{$ENDIF}
+
+procedure SetTexCoordPointer(p: Pointer;n: Integer);
+procedure SetVertexPointer(p: Pointer;n: Integer);
+procedure SetColorPointer(p: Pointer;n: Integer);
+procedure BeginWater;
+procedure EndWater;
+
implementation
-uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils, uCommands
- , uPhysFSLayer
- , uDebug
+uses uMisc, uConsole, uVariables, uUtils, uTextures, uRender, uRenderUtils,
+ uCommands, uPhysFSLayer, uDebug
+ {$IFDEF GL2}, uMatrix{$ENDIF}
{$IFDEF USE_CONTEXT_RESTORE}, uWorld{$ENDIF}
{$IF NOT DEFINED(SDL2) AND DEFINED(USE_VIDEO_RECORDING)}, glut {$ENDIF};
-//type TGPUVendor = (gvUnknown, gvNVIDIA, gvATI, gvIntel, gvApple);
-
var MaxTextureSize: LongInt;
{$IFDEF SDL2}
SDLwindow: PSDL_Window;
@@ -79,6 +88,13 @@
numsquares : LongInt;
ProgrTex: PTexture;
+{$IFDEF GL2}
+ shaderMain: GLuint;
+ shaderWater: GLuint;
+
+ // attributes
+{$ENDIF}
+
const
cHHFileName = 'Hedgehog';
cCHFileName = 'Crosshair';
@@ -159,7 +175,13 @@
r.x:= 0;
r.y:= 0;
drY:= - 4;
+{$IFNDEF PAS2C}
DecodeDate(Date, year, month, md);
+{$ELSE}
+year:= 0;
+month:= 0;
+md:= 0;
+{$ENDIF}
for t:= 0 to Pred(TeamsCount) do
with TeamsArray[t]^ do
begin
@@ -249,7 +271,7 @@
else if (month = 10) and (md = 31) then
Hat := 'fr_pumpkin'; // Halloween/Hedgewars' birthday
end;
-
+
if Hat <> 'NoHat' then
begin
if (Length(Hat) > 39) and (Copy(Hat,1,8) = 'Reserved') and (Copy(Hat,9,32) = PlayerHash) then
@@ -450,8 +472,10 @@
if not reload then
AddProgress;
IMG_Quit();
+
end;
+{$IFNDEF PAS2C}
{$IF DEFINED(USE_S3D_RENDERING) OR DEFINED(USE_VIDEO_RECORDING)}
procedure CreateFramebuffer(var frame, depth, tex: GLuint);
begin
@@ -476,6 +500,7 @@
glDeleteFramebuffersEXT(1, @frame);
end;
{$ENDIF}
+{$ENDIF}
procedure StoreRelease(reload: boolean);
var ii: TSprite;
@@ -539,6 +564,7 @@
end;
end;
end;
+{$IFNDEF PAS2C}
{$IFDEF USE_VIDEO_RECORDING}
if defaultFrame <> 0 then
DeleteFramebuffer(defaultFrame, depthv, texv);
@@ -550,6 +576,7 @@
DeleteFramebuffer(framer, depthr, texr);
end
{$ENDIF}
+{$ENDIF}
end;
@@ -667,6 +694,8 @@
function glLoadExtension(extension : shortstring) : boolean;
begin
+//TODO: pas2c does not handle {$IF (GLunit = gles11) OR DEFINED(PAS2C)}
+{$IFNDEF PAS2C}
{$IF GLunit = gles11}
// FreePascal doesnt come with OpenGL ES 1.1 Extension headers
extension:= extension; // avoid hint
@@ -679,6 +708,7 @@
else
AddFileLog('OpenGL - "' + extension + '" failed to load');
{$ENDIF}
+{$ENDIF}
end;
procedure SetupOpenGLAttributes;
@@ -701,6 +731,112 @@
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); // prefer hw 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, PathPrefix + cPathz[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;
+
+ Close(f);
+
+ WriteLnToConsole('Compiling shader: ' + PathPrefix + cPathz[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
+ log := GetMem(logLength);
+ glGetShaderInfoLog(shader, logLength, nil, log);
+ WriteLnToConsole('========== Compiler log ==========');
+ WriteLnToConsole(shortstring(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, PChar('vertex'));
+ glBindAttribLocation(program_, aTexCoord, PChar('texcoord'));
+ glBindAttribLocation(program_, aColor, PChar('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
+ log := GetMem(logLength);
+ glGetProgramInfoLog(program_, logLength, nil, log);
+ WriteLnToConsole('========== Compiler log ==========');
+ WriteLnToConsole(shortstring(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 buf: array[byte] of char;
AuxBufNum: LongInt = 0;
@@ -708,6 +844,7 @@
tmpint: LongInt;
tmpn: LongInt;
begin
+
{$IFDEF SDL2}
AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_GetCurrentVideoDriver()) + ')');
{$ELSE}
@@ -740,8 +877,8 @@
cReducedQuality := cReducedQuality or rqNoBackground;
AddFileLog('Texture size too small for backgrounds, disabling.');
end;
-
// everyone loves debugging
+ // find out which gpu we are using (for extension compatibility maybe?)
AddFileLog('OpenGL-- Renderer: ' + shortstring(pchar(glGetString(GL_RENDERER))));
AddFileLog(' |----- Vendor: ' + shortstring(pchar(glGetString(GL_VENDOR))));
AddFileLog(' |----- Version: ' + shortstring(pchar(glGetString(GL_VERSION))));
@@ -750,6 +887,7 @@
glGetIntegerv(GL_AUX_BUFFERS, @AuxBufNum);
AddFileLog(' |----- Number of auxiliary buffers: ' + inttostr(AuxBufNum));
{$ENDIF}
+{$IFNDEF PAS2C}
AddFileLog(' \----- Extensions: ');
// fetch extentions and store them in string
@@ -769,6 +907,7 @@
tmpint := tmpint + 3;
end;
until (tmpint > tmpn);
+{$ENDIF}
AddFileLog('');
defaultFrame:= 0;
@@ -796,8 +935,42 @@
end;
{$ENDIF}
-{$IFDEF USE_S3D_RENDERING}
- if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
+{$IFDEF GL2}
+
+{$IFDEF PAS2C}
+ err := glewInit();
+ if err <> GLEW_OK then
+ begin
+ WriteLnToConsole('Failed to initialize GLEW.');
+ halt;
+ end;
+{$ENDIF}
+
+{$IFNDEF PAS2C}
+ if not Load_GL_VERSION_2_0 then
+ halt;
+{$ENDIF}
+
+ shaderWater:= CompileProgram('water');
+ glUseProgram(shaderWater);
+ glUniform1i(glGetUniformLocation(shaderWater, pchar('tex0')), 0);
+ uWaterMVPLocation:= glGetUniformLocation(shaderWater, pchar('mvp'));
+
+ shaderMain:= CompileProgram('default');
+ glUseProgram(shaderMain);
+ glUniform1i(glGetUniformLocation(shaderMain, pchar('tex0')), 0);
+ uMainMVPLocation:= glGetUniformLocation(shaderMain, pchar('mvp'));
+ uMainTintLocation:= glGetUniformLocation(shaderMain, pchar('tint'));
+
+ uCurrentMVPLocation:= uMainMVPLocation;
+
+ Tint(255, 255, 255, 255);
+ UpdateModelviewProjection;
+{$ENDIF}
+
+{$IFNDEF PAS2C}
+{$IFNDEF USE_S3D_RENDERING}
+ if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
begin
// prepare left and right frame buffers and associated textures
if glLoadExtension('GL_EXT_framebuffer_object') then
@@ -812,19 +985,33 @@
cStereoMode:= smNone;
end;
{$ENDIF}
+{$ENDIF}
- // set view port to whole window
- glViewport(0, 0, cScreenWidth, cScreenHeight);
+// set view port to whole window
+glViewport(0, 0, cScreenWidth, cScreenHeight);
+{$IFDEF GL2}
+ uMatrix.initModule;
+ hglMatrixMode(MATRIX_MODELVIEW);
+ // prepare default translation/scaling
+ hglLoadIdentity();
+ hglScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
+ hglTranslatef(0, -cScreenHeight / 2, 0);
+
+ EnableTexture(True);
+
+ glEnableVertexAttribArray(aVertex);
+ glEnableVertexAttribArray(aTexCoord);
+ glGenBuffers(1, @vBuffer);
+ glGenBuffers(1, @tBuffer);
+ glGenBuffers(1, @cBuffer);
+{$ELSE}
glMatrixMode(GL_MODELVIEW);
// prepare default translation/scaling
glLoadIdentity();
glScalef(2.0 / cScreenWidth, -2.0 / cScreenHeight, 1.0);
glTranslatef(0, -cScreenHeight / 2, 0);
- // enable alpha blending
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
// disable/lower perspective correction (will not need it anyway)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
// disable dithering
@@ -833,8 +1020,97 @@
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+{$ENDIF}
+
+ // enable alpha blending
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ // disable/lower perspective correction (will not need it anyway)
end;
+{$IFDEF GL2}
+procedure EnableTexture(enable:Boolean);
+begin
+ if enable then
+ glUniform1i(glGetUniformLocation(shaderMain, pchar('enableTexture')), 1)
+ else
+ glUniform1i(glGetUniformLocation(shaderMain, pchar('enableTexture')), 0);
+end;
+{$ENDIF}
+
+procedure SetTexCoordPointer(p: Pointer; n: Integer);
+begin
+{$IFDEF GL2}
+ glBindBuffer(GL_ARRAY_BUFFER, tBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * n * 2, p, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(aTexCoord);
+ glVertexAttribPointer(aTexCoord, 2, GL_FLOAT, GL_FALSE, 0, pointer(0));
+{$ELSE}
+ n:= n;
+ glTexCoordPointer(2, GL_FLOAT, 0, p);
+{$ENDIF}
+end;
+
+procedure SetVertexPointer(p: Pointer; n: Integer);
+begin
+{$IFDEF GL2}
+ glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * n * 2, p, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(aVertex);
+ glVertexAttribPointer(aVertex, 2, GL_FLOAT, GL_FALSE, 0, pointer(0));
+{$ELSE}
+ n:= n;
+ glVertexPointer(2, GL_FLOAT, 0, p);
+{$ENDIF}
+end;
+
+procedure SetColorPointer(p: Pointer; n: Integer);
+begin
+{$IFDEF GL2}
+ glBindBuffer(GL_ARRAY_BUFFER, cBuffer);
+ glBufferData(GL_ARRAY_BUFFER, n * 4, p, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(aColor);
+ glVertexAttribPointer(aColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, pointer(0));
+{$ELSE}
+ n:= n;
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, p);
+{$ENDIF}
+end;
+
+{$IFDEF GL2}
+procedure UpdateModelviewProjection;
+var
+ mvp: TMatrix4x4f;
+begin
+ //MatrixMultiply(mvp, mProjection, mModelview);
+{$HINTS OFF}
+ hglMVP(mvp);
+{$HINTS ON}
+ glUniformMatrix4fv(uCurrentMVPLocation, 1, GL_FALSE, @mvp[0, 0]);
+end;
+{$ENDIF}
+
+(*
+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
@@ -842,18 +1118,62 @@
exit;
if f = cDefaultZoomLevel then
- glPopMatrix // return to default scaling
+{$IFDEF GL2}
+ hglPopMatrix // "return" to default scaling
+{$ELSE}
+ glPopMatrix
+{$ENDIF}
else // other scaling
begin
+{$IFDEF GL2}
+ hglPushMatrix; // save default scaling
+ hglLoadIdentity;
+ hglScalef(f / cScreenWidth, -f / cScreenHeight, 1.0);
+ hglTranslatef(0, -cScreenHeight / 2, 0);
+{$ELSE}
glPushMatrix; // save default scaling
glLoadIdentity;
glScalef(f / cScreenWidth, -f / cScreenHeight, 1.0);
glTranslatef(0, -cScreenHeight / 2, 0);
+{$ENDIF}
end;
cScaleFactor:= f;
+
+{$IFDEF GL2}
+ UpdateModelviewProjection;
+{$ENDIF}
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;
+
+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;
+
+
////////////////////////////////////////////////////////////////////////////////
procedure AddProgress;
var r: TSDL_Rect;
@@ -870,10 +1190,11 @@
squaresize:= texsurf^.w shr 1;
numsquares:= texsurf^.h div squaresize;
SDL_FreeSurface(texsurf);
+ {$IFNDEF PAS2C}
with mobileRecord do
if GameLoading <> nil then
GameLoading();
-
+ {$ENDIF}
end;
TryDo(ProgrTex <> nil, 'Error - Progress Texure is nil!', true);
@@ -891,14 +1212,17 @@
DrawTextureFromRect( -squaresize div 2, (cScreenHeight - squaresize) shr 1, @r, ProgrTex);
SwapBuffers;
+
inc(Step);
end;
procedure FinishProgress;
begin
+ {$IFNDEF PAS2C}
with mobileRecord do
if GameLoaded <> nil then
GameLoaded();
+ {$ENDIF}
WriteLnToConsole('Freeing progress surface... ');
FreeTexture(ProgrTex);
ProgrTex:= nil;
@@ -1244,6 +1568,7 @@
{$ENDIF}
SetupOpenGL();
+
if reinit then
begin
// clean the window from any previous content
@@ -1320,6 +1645,13 @@
procedure freeModule;
begin
+{$IFDEF GL2}
+ glDeleteProgram(shaderMain);
+ glDeleteProgram(shaderWater);
+ glDeleteBuffers(1, @vBuffer);
+ glDeleteBuffers(1, @tBuffer);
+ glDeleteBuffers(1, @cBuffer);
+{$ENDIF}
StoreRelease(false);
TTF_Quit();
{$IFDEF SDL2}