diff -r 56d2f2d5aad8 -r 4feced261c68 hedgewars/uStore.pas --- 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}