fix gl2 build, further rendering cleanup WIP, also new chat command: /debugvl
authorsheepluva
Sat, 14 Jun 2014 15:49:44 +0200
changeset 10304 7e40820b7ed6
parent 10303 f726e36c3e24
child 10305 17f3ca06e39a
fix gl2 build, further rendering cleanup WIP, also new chat command: /debugvl
hedgewars/hwengine.pas
hedgewars/uChat.pas
hedgewars/uRender.pas
hedgewars/uStore.pas
hedgewars/uVariables.pas
hedgewars/uWorld.pas
--- a/hedgewars/hwengine.pas	Sat Jun 14 07:12:22 2014 +0200
+++ b/hedgewars/hwengine.pas	Sat Jun 14 15:49:44 2014 +0200
@@ -32,7 +32,7 @@
 uses SDLh, uMisc, uConsole, uGame, uConsts, uLand, uAmmos, uVisualGears, uGears, uStore, uWorld, uInputHandler
      , uSound, uScript, uTeams, uStats, uIO, uLocale, uChat, uAI, uAIMisc, uAILandMarks, uLandTexture, uCollisions
      , SysUtils, uTypes, uVariables, uCommands, uUtils, uCaptions, uDebug, uCommandHandlers, uLandPainted
-     , uPhysFSLayer, uCursor, uRandom, ArgParsers, uVisualGearsHandlers, uTextures
+     , uPhysFSLayer, uCursor, uRandom, ArgParsers, uVisualGearsHandlers, uTextures, uRender
      {$IFDEF USE_VIDEO_RECORDING}, uVideoRec {$ENDIF}
      {$IFDEF USE_TOUCH_INTERFACE}, uTouch {$ENDIF}
      {$IFDEF ANDROID}, GLUnit{$ENDIF}
@@ -479,6 +479,7 @@
         uSound.initModule;
         uStats.initModule;
         uStore.initModule;
+        uRender.initModule;
         uTeams.initModule;
         uVisualGears.initModule;
         uVisualGearsHandlers.initModule;
@@ -507,6 +508,7 @@
         uCollisions.freeModule;     //stub
         uChat.freeModule;
         uAmmos.freeModule;
+        uRender.freeModule;
         uStore.freeModule;          // closes SDL
 {$IFDEF USE_VIDEO_RECORDING}uVideoRec.freeModule;{$ENDIF}
 {$IFDEF USE_TOUCH_INTERFACE}uTouch.freeModule;{$ENDIF}  //stub
--- a/hedgewars/uChat.pas	Sat Jun 14 07:12:22 2014 +0200
+++ b/hedgewars/uChat.pas	Sat Jun 14 15:49:44 2014 +0200
@@ -288,7 +288,7 @@
 if (s[1] = '/') then
     begin
     // These 3 are same as above, only are to make the hedgehog say it on next attack
-    if (copy(s, 1, 5) = '/hsa ') then
+    if (copy(s, 2, 4) = 'hsa ') then
         begin
         if CurrentTeam^.ExtDriven then
             ParseCommand('/say ' + copy(s, 6, Length(s)-5), true)
@@ -297,7 +297,7 @@
         exit
         end;
 
-    if (copy(s, 1, 5) = '/hta ') then
+    if (copy(s, 2, 4) = 'hta ') then
         begin
         if CurrentTeam^.ExtDriven then
             ParseCommand('/say ' + copy(s, 6, Length(s)-5), true)
@@ -306,7 +306,7 @@
         exit
         end;
 
-    if (copy(s, 1, 5) = '/hya ') then
+    if (copy(s, 2, 4) = 'hya ') then
         begin
         if CurrentTeam^.ExtDriven then
             ParseCommand('/say ' + copy(s, 6, Length(s)-5), true)
@@ -315,18 +315,27 @@
         exit
         end;
 
-    if (copy(s, 1, 6) = '/team ') and (length(s) > 6) then
+    if (copy(s, 2, 5) = 'team ') and (length(s) > 6) then
         begin
         ParseCommand(s, true);
         exit
         end;
 
-    if (copy(s, 1, 4) = '/me ') then
+    if (copy(s, 2, 3) = 'me ') then
         begin
         ParseCommand('/say ' + s, true);
         exit
         end;
 
+    // debugging commands
+    if (copy(s, 2, 7) = 'debugvl') then
+        begin
+        cViewLimitsDebug:= (not cViewLimitsDebug);
+        UpdateViewLimits();
+        exit
+        end;
+    end;
+
     if (not CurrentTeam^.ExtDriven) and (CurrentTeam^.Hedgehogs[0].BotLevel = 0) then
         begin
         for i:= Low(TWave) to High(TWave) do
@@ -343,7 +352,6 @@
                 exit
                 end;
         end
-    end
     else
         ParseCommand('/say ' + s, true);
 end;
--- a/hedgewars/uRender.pas	Sat Jun 14 07:12:22 2014 +0200
+++ b/hedgewars/uRender.pas	Sat Jun 14 15:49:44 2014 +0200
@@ -23,7 +23,10 @@
 
 interface
 
-uses SDLh, uTypes, GLunit, uConsts{$IFDEF GL2}, uMatrix{$ENDIF};
+uses SDLh, uTypes, GLunit;
+
+procedure initModule;
+procedure freeModule;
 
 procedure DrawSprite            (Sprite: TSprite; X, Y, Frame: LongInt);
 procedure DrawSprite            (Sprite: TSprite; X, Y, FrameX, FrameY: LongInt);
@@ -48,11 +51,13 @@
 
 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
 procedure DrawLine              (X0, Y0, X1, Y1, Width: Single; r, g, b, a: Byte);
-procedure DrawFillRect          (r: TSDL_Rect);
+procedure DrawRect              (rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
 procedure DrawHedgehog          (X, Y: LongInt; Dir: LongInt; Pos, Step: LongWord; Angle: real);
 procedure DrawScreenWidget      (widget: POnScreenWidget);
 procedure DrawWaterBody         (pVertexBuffer: Pointer);
 
+procedure RenderClear           ();
+procedure RenderSetClearColor      (r, g, b, a: real);
 procedure Tint                  (r, g, b, a: Byte); inline;
 procedure Tint                  (c: Longword); inline;
 procedure untint(); inline;
@@ -67,6 +72,10 @@
 procedure SetScale(f: GLfloat);
 procedure UpdateViewLimits();
 
+procedure RenderSetup();
+
+// TODO everything below this should not need a public interface
+
 procedure EnableTexture(enable:Boolean);
 
 procedure SetTexCoordPointer(p: Pointer;n: Integer);
@@ -86,7 +95,8 @@
 
 
 implementation
-uses uVariables;
+uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}SysUtils, uVariables, uUtils, uConsts
+     {$IFDEF GL2}, uMatrix, uConsole{$ENDIF};
 
 {$IFDEF USE_TOUCH_INTERFACE}
 const
@@ -94,6 +104,12 @@
     MOVE_ANIM_TIME = 500;
 {$ENDIF}
 
+{$IFDEF GL2}
+var
+    shaderMain: GLuint;
+    shaderWater: GLuint;
+{$ENDIF}
+
 var LastTint: LongWord = 0;
 
 function isAreaOffscreen(X, Y, Width, Height: LongInt): boolean; inline;
@@ -115,6 +131,292 @@
     isDyAreaOffscreen:= 0;
 end;
 
+procedure RenderClear();
+begin
+    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+end;
+
+procedure RenderSetClearColor(r, g, b, a: real);
+begin
+    glClearColor(r, g, b, a);
+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 RenderSetup();
+var AuxBufNum: LongInt = 0;
+    tmpstr: ansistring;
+    tmpint: LongInt;
+    tmpn: LongInt;
+begin
+    // suppress hint/warning
+    AuxBufNum:= AuxBufNum;
+
+    // get the max (h and v) size for textures that the gpu can support
+    glGetIntegerv(GL_MAX_TEXTURE_SIZE, @MaxTextureSize);
+    if MaxTextureSize <= 0 then
+        begin
+        MaxTextureSize:= 1024;
+        AddFileLog('OpenGL Warning - driver didn''t provide any valid max texture size; assuming 1024');
+        end
+    else if (MaxTextureSize < 1024) and (MaxTextureSize >= 512) then
+        begin
+        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))));
+    AddFileLog('  |----- Texture Size: ' + inttostr(MaxTextureSize));
+{$IFDEF USE_VIDEO_RECORDING}
+    glGetIntegerv(GL_AUX_BUFFERS, @AuxBufNum);
+    AddFileLog('  |----- Number of auxiliary buffers: ' + inttostr(AuxBufNum));
+{$ENDIF}
+{$IFNDEF PAS2C}
+    AddFileLog('  \----- Extensions: ');
+
+    // fetch extentions and store them in string
+    tmpstr := StrPas(PChar(glGetString(GL_EXTENSIONS)));
+    tmpn := WordCount(tmpstr, [' ']);
+    tmpint := 1;
+
+    repeat
+    begin
+        // print up to 3 extentions per row
+        // ExtractWord will return empty string if index out of range
+        AddFileLog(TrimRight(
+            ExtractWord(tmpint, tmpstr, [' ']) + ' ' +
+            ExtractWord(tmpint+1, tmpstr, [' ']) + ' ' +
+            ExtractWord(tmpint+2, tmpstr, [' '])
+        ));
+        tmpint := tmpint + 3;
+    end;
+    until (tmpint > tmpn);
+{$ENDIF}
+    AddFileLog('');
+
+    defaultFrame:= 0;
+
+{$IFDEF USE_VIDEO_RECORDING}
+    if GameType = gmtRecord then
+    begin
+        if glLoadExtension('GL_EXT_framebuffer_object') then
+        begin
+            CreateFramebuffer(defaultFrame, depthv, texv);
+            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame);
+            AddFileLog('Using framebuffer for video recording.');
+        end
+        else if AuxBufNum > 0 then
+        begin
+            glDrawBuffer(GL_AUX0);
+            glReadBuffer(GL_AUX0);
+            AddFileLog('Using auxiliary buffer for video recording.');
+        end
+        else
+        begin
+            glDrawBuffer(GL_BACK);
+            glReadBuffer(GL_BACK);
+            AddFileLog('Warning: off-screen rendering is not supported; using back buffer but it may not work.');
+        end;
+    end;
+{$ENDIF}
+
+{$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 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
+            begin
+            CreateFramebuffer(framel, depthl, texl);
+            CreateFramebuffer(framer, depthr, texr);
+
+            // reset
+            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame)
+            end
+        else
+            cStereoMode:= smNone;
+    end;
+{$ENDIF}
+
+// 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);
+
+    // disable/lower perspective correction (will not need it anyway)
+    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
+    // disable dithering
+    glDisable(GL_DITHER);
+    // enable common states by default as they save a lot
+    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;
+
 procedure openglLoadIdentity(); inline;
 begin
 {$IFDEF GL2}
@@ -285,11 +587,25 @@
     tmp:= cScreenHeight / cScaleFactor;
     ViewBottomY:= round(tmp) + cScreenHeight div 2; // ceil could make more sense
     ViewTopY:= round(-tmp) + cScreenHeight div 2; // floor could make more sense
+
+    // visual debugging fun :D
+    if cViewLimitsDebug then
+        begin
+        // some margin on each side
+        tmp:= min(cScreenWidth, cScreenHeight) div 2 / cScaleFactor;
+        ViewLeftX  := ViewLeftX   + trunc(tmp);
+        ViewRightX := ViewRightX  - trunc(tmp);
+        ViewBottomY:= ViewBottomY - trunc(tmp);
+        ViewTopY   := ViewTopY    + trunc(tmp);
+        end;
+
+    ViewWidth := ViewRightX  - ViewLeftX + 1;
+    ViewHeight:= ViewBottomY - ViewTopY  + 1;
 end;
 
 procedure SetScale(f: GLfloat);
 begin
-// leave immediately if scale factor did not change
+    // leave immediately if scale factor did not change
     if f = cScaleFactor then
         exit;
 
@@ -303,7 +619,7 @@
         openglPushMatrix; // save default scaling in matrix
         openglLoadIdentity();
         openglScalef(f / cScreenWidth, -f / cScreenHeight, 1.0);
-        openglTranslatef(0, -cScreenHeight / 2, 0);
+        openglTranslatef(0, -cScreenHeight div 2, 0);
         end;
 
     cScaleFactor:= f;
@@ -337,11 +653,16 @@
 if (SourceTexture^.h = 0) or (SourceTexture^.w = 0) then
     exit;
 
+{if isDxAreaOffscreen(X, W) <> 0 then
+    exit;
+if isDyAreaOffscreen(Y, H) <> 0 then
+    exit;}
+
 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
-if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then
+{if (abs(X) > W) and ((abs(X + W / 2) - W / 2) > cScreenWidth / cScaleFactor) then
     exit;
 if (abs(Y) > H) and ((abs(Y + H / 2 - (0.5 * cScreenHeight)) - H / 2) > cScreenHeight / cScaleFactor) then
-    exit;
+    exit;}
 
 rr.x:= X;
 rr.y:= Y;
@@ -357,13 +678,13 @@
 
 if Dir < 0 then
     begin
-    VertexBuffer[0].X:= X + rr.w/2;
+    VertexBuffer[0].X:= X + rr.w div 2;
     VertexBuffer[0].Y:= Y;
-    VertexBuffer[1].X:= X - rr.w/2;
+    VertexBuffer[1].X:= X - rr.w div 2;
     VertexBuffer[1].Y:= Y;
-    VertexBuffer[2].X:= X - rr.w/2;
+    VertexBuffer[2].X:= X - rr.w div 2;
     VertexBuffer[2].Y:= rr.h + Y;
-    VertexBuffer[3].X:= X + rr.w/2;
+    VertexBuffer[3].X:= X + rr.w div 2;
     VertexBuffer[3].Y:= rr.h + Y;
     end
 else
@@ -402,16 +723,16 @@
 
 openglPushMatrix;
 openglTranslatef(X, Y, 0);
-openglScalef(Scale, Scale, 1);
+
+if Scale <> 1.0 then
+    openglScalef(Scale, Scale, 1);
 
 glBindTexture(GL_TEXTURE_2D, Texture^.id);
 
 SetVertexPointer(@Texture^.vb, Length(Texture^.vb));
 SetTexCoordPointer(@Texture^.tb, Length(Texture^.vb));
 
-{$IFDEF GL2}
 UpdateModelviewProjection;
-{$ENDIF}
 
 glDrawArrays(GL_TRIANGLE_FAN, 0, Length(Texture^.vb));
 openglPopMatrix;
@@ -457,11 +778,17 @@
     hw, hh, nx, ny: LongInt;
     VertexBuffer, TextureBuffer: array [0..3] of TVertex2f;
 begin
+
+if isDxAreaOffscreen(X, w) <> 0 then
+    exit;
+if isDyAreaOffscreen(Y, h) <> 0 then
+    exit;
+
 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
-if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then
+{if (abs(X) > W) and ((abs(X + dir * OffsetX) - W / 2) * cScaleFactor > cScreenWidth) then
     exit;
 if (abs(Y) > H) and ((abs(Y + OffsetY - (0.5 * cScreenHeight)) - W / 2) * cScaleFactor > cScreenHeight) then
-    exit;
+    exit;}
 
 openglPushMatrix;
 
@@ -558,11 +885,17 @@
 procedure DrawTextureRotated(Texture: PTexture; hw, hh, X, Y, Dir: LongInt; Angle: real);
 var VertexBuffer: array [0..3] of TVertex2f;
 begin
+
+if isDxAreaOffscreen(X, 2 * hw) <> 0 then
+    exit;
+if isDyAreaOffscreen(Y, 2 * hh) <> 0 then
+    exit;
+
 // do not draw anything outside the visible screen space (first check fixes some sprite drawing, e.g. hedgehogs)
-if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then
+{if (abs(X) > 2 * hw) and ((abs(X) - hw) > cScreenWidth / cScaleFactor) then
     exit;
 if (abs(Y) > 2 * hh) and ((abs(Y - 0.5 * cScreenHeight) - hh) > cScreenHeight / cScaleFactor) then
-    exit;
+    exit;}
 
 openglPushMatrix;
 openglTranslatef(X, Y, 0);
@@ -647,12 +980,20 @@
 
 procedure DrawTextureCentered(X, Top: LongInt; Source: PTexture);
 var scale: GLfloat;
+    left : LongInt;
 begin
+    // scale down if larger than screen
     if (Source^.w + 20) > cScreenWidth then
-        scale:= cScreenWidth / (Source^.w + 20)
+        begin
+        scale:= cScreenWidth / (Source^.w + 20);
+        DrawTexture(X - round(Source^.w * scale) div 2, Top, Source, scale);
+        end
     else
-        scale:= 1.0;
-    DrawTexture(X - round(Source^.w * scale) div 2, Top, Source, scale)
+        begin
+        left:= X - Source^.w div 2;
+        if (not isAreaOffscreen(left, Top, Source^.w, Source^.h)) then
+            DrawTexture(left, Top, Source);
+        end;
 end;
 
 procedure DrawLine(X0, Y0, X1, Y1, Width: Single; color: LongWord); inline;
@@ -690,31 +1031,36 @@
     glDisable(GL_LINE_SMOOTH);
 end;
 
-procedure DrawFillRect(r: TSDL_Rect);
+procedure DrawRect(rect: TSDL_Rect; r, g, b, a: Byte; Fill: boolean);
 var VertexBuffer: array [0..3] of TVertex2f;
 begin
 // 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
+{if (abs(r.x) > r.w) and ((abs(r.x + r.w / 2) - r.w / 2) * cScaleFactor > cScreenWidth) then
     exit;
 if (abs(r.y) > r.h) and ((abs(r.y + r.h / 2 - (0.5 * cScreenHeight)) - r.h / 2) * cScaleFactor > cScreenHeight) then
-    exit;
+    exit;}
 
 EnableTexture(False);
 
-Tint($00, $00, $00, $80);
+Tint(r, g, b, a);
 
-VertexBuffer[0].X:= r.x;
-VertexBuffer[0].Y:= r.y;
-VertexBuffer[1].X:= r.x + r.w;
-VertexBuffer[1].Y:= r.y;
-VertexBuffer[2].X:= r.x + r.w;
-VertexBuffer[2].Y:= r.y + r.h;
-VertexBuffer[3].X:= r.x;
-VertexBuffer[3].Y:= r.y + r.h;
+with rect do
+begin
+    VertexBuffer[0].X:= x;
+    VertexBuffer[0].Y:= y;
+    VertexBuffer[1].X:= x + w;
+    VertexBuffer[1].Y:= y;
+    VertexBuffer[2].X:= x + w;
+    VertexBuffer[2].Y:= y + h;
+    VertexBuffer[3].X:= x;
+    VertexBuffer[3].Y:= y + h;
+end;
 
 SetVertexPointer(@VertexBuffer[0], Length(VertexBuffer));
-glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer));
+if Fill then
+    glDrawArrays(GL_TRIANGLE_FAN, 0, Length(VertexBuffer))
+else
+    glDrawArrays(GL_LINE_LOOP, 0, Length(VertexBuffer));
 
 untint;
 
@@ -953,4 +1299,18 @@
         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 end;
 
+procedure initModule;
+begin
+end;
+
+procedure freeModule;
+begin
+{$IFDEF GL2}
+    glDeleteProgram(shaderMain);
+    glDeleteProgram(shaderWater);
+    glDeleteBuffers(1, @vBuffer);
+    glDeleteBuffers(1, @tBuffer);
+    glDeleteBuffers(1, @cBuffer);
+{$ENDIF}
+end;
 end.
--- a/hedgewars/uStore.pas	Sat Jun 14 07:12:22 2014 +0200
+++ b/hedgewars/uStore.pas	Sat Jun 14 15:49:44 2014 +0200
@@ -21,7 +21,7 @@
 
 unit uStore;
 interface
-uses {$IFNDEF PAS2C} StrUtils, {$ENDIF}SysUtils, uConsts, SDLh, GLunit, uTypes, uLandTexture, uCaptions, uChat;
+uses SysUtils, uConsts, SDLh, GLunit, uTypes, uLandTexture, uCaptions, uChat;
 
 procedure initModule;
 procedure freeModule;
@@ -62,20 +62,13 @@
 procedure SwapBuffers; {$IFDEF USE_VIDEO_RECORDING}cdecl{$ELSE}inline{$ENDIF};
 procedure SetSkyColor(r, g, b: real);
 
-{$IFDEF GL2}
-var
-    shaderMain: GLuint;
-    shaderWater: GLuint;
-{$ENDIF}
-
 implementation
 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};
 
-var MaxTextureSize: LongInt;
+var
 {$IFDEF SDL2}
     SDLwindow: PSDL_Window;
     SDLGLcontext: PSDL_GLContext;
@@ -792,118 +785,8 @@
     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;
-    tmpstr: ansistring;
-    tmpint: LongInt;
-    tmpn: LongInt;
 begin
 
 {$IFDEF SDL2}
@@ -913,8 +796,6 @@
     AddFileLog('Setting up OpenGL (using driver: ' + shortstring(SDL_VideoDriverName(buf, sizeof(buf))) + ')');
 {$ENDIF}
 
-    AuxBufNum:= AuxBufNum;
-
 {$IFDEF MOBILE}
     // TODO: this function creates an opengles1.1 context
     // un-comment below and add proper logic to support opengles2.0
@@ -926,165 +807,7 @@
     SDL_GL_SetSwapInterval(1);
 {$ENDIF}
 
-    // get the max (h and v) size for textures that the gpu can support
-    glGetIntegerv(GL_MAX_TEXTURE_SIZE, @MaxTextureSize);
-    if MaxTextureSize <= 0 then
-        begin
-        MaxTextureSize:= 1024;
-        AddFileLog('OpenGL Warning - driver didn''t provide any valid max texture size; assuming 1024');
-        end
-    else if (MaxTextureSize < 1024) and (MaxTextureSize >= 512) then
-        begin
-        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))));
-    AddFileLog('  |----- Texture Size: ' + inttostr(MaxTextureSize));
-{$IFDEF USE_VIDEO_RECORDING}
-    glGetIntegerv(GL_AUX_BUFFERS, @AuxBufNum);
-    AddFileLog('  |----- Number of auxiliary buffers: ' + inttostr(AuxBufNum));
-{$ENDIF}
-{$IFNDEF PAS2C}
-    AddFileLog('  \----- Extensions: ');
-
-    // fetch extentions and store them in string
-    tmpstr := StrPas(PChar(glGetString(GL_EXTENSIONS)));
-    tmpn := WordCount(tmpstr, [' ']);
-    tmpint := 1;
-
-    repeat
-    begin
-        // print up to 3 extentions per row
-        // ExtractWord will return empty string if index out of range
-        AddFileLog(TrimRight(
-            ExtractWord(tmpint, tmpstr, [' ']) + ' ' +
-            ExtractWord(tmpint+1, tmpstr, [' ']) + ' ' +
-            ExtractWord(tmpint+2, tmpstr, [' '])
-        ));
-        tmpint := tmpint + 3;
-    end;
-    until (tmpint > tmpn);
-{$ENDIF}
-    AddFileLog('');
-
-    defaultFrame:= 0;
-{$IFDEF USE_VIDEO_RECORDING}
-    if GameType = gmtRecord then
-    begin
-        if glLoadExtension('GL_EXT_framebuffer_object') then
-        begin
-            CreateFramebuffer(defaultFrame, depthv, texv);
-            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame);
-            AddFileLog('Using framebuffer for video recording.');
-        end
-        else if AuxBufNum > 0 then
-        begin
-            glDrawBuffer(GL_AUX0);
-            glReadBuffer(GL_AUX0);
-            AddFileLog('Using auxiliary buffer for video recording.');
-        end
-        else
-        begin
-            glDrawBuffer(GL_BACK);
-            glReadBuffer(GL_BACK);
-            AddFileLog('Warning: off-screen rendering is not supported; using back buffer but it may not work.');
-        end;
-    end;
-{$ENDIF}
-
-{$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 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
-            begin
-            CreateFramebuffer(framel, depthl, texl);
-            CreateFramebuffer(framer, depthr, texr);
-
-            // reset
-            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, defaultFrame)
-            end
-        else
-            cStereoMode:= smNone;
-    end;
-{$ENDIF}
-
-// 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);
-
-    // disable/lower perspective correction (will not need it anyway)
-    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
-    // disable dithering
-    glDisable(GL_DITHER);
-    // enable common states by default as they save a lot
-    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)
+    RenderSetup();
 end;
 
 (*
@@ -1133,7 +856,7 @@
 
     TryDo(ProgrTex <> nil, 'Error - Progress Texure is nil!', true);
 
-    glClear(GL_COLOR_BUFFER_BIT);
+    RenderClear();
     if Step < numsquares then
         r.x:= 0
     else
@@ -1370,7 +1093,7 @@
     glutHideWindow();
     // we do not need to set this callback, but it is required for GLUT3 compat
     glutDisplayFunc(@SwapBuffers);
-    SetupOpenGL();
+    SetupRenderer();
 end;
 {$ENDIF} // SDL2
 {$ENDIF} // USE_VIDEO_RECORDING
@@ -1509,7 +1232,7 @@
     if reinit then
         begin
         // clean the window from any previous content
-        glClear(GL_COLOR_BUFFER_BIT);
+        RenderClear();
         if SuddenDeathDmg then
             SetSkyColor(SDSkyColor.r * (SDTint/255) / 255, SDSkyColor.g * (SDTint/255) / 255, SDSkyColor.b * (SDTint/255) / 255)
         else if ((cReducedQuality and rqNoBackground) = 0) then
@@ -1550,7 +1273,7 @@
 
 procedure SetSkyColor(r, g, b: real);
 begin
-    glClearColor(r, g, b, 0.99)
+    RenderSetClearColor(r, g, b, 0.99)
 end;
 
 procedure initModule;
@@ -1586,13 +1309,6 @@
 
 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}
--- a/hedgewars/uVariables.pas	Sat Jun 14 07:12:22 2014 +0200
+++ b/hedgewars/uVariables.pas	Sat Jun 14 15:49:44 2014 +0200
@@ -212,7 +212,10 @@
     WorldDy: LongInt;
 
     // for tracking the limits of the visible grid based on cScaleFactor
-    ViewLeftX, ViewRightX, ViewBottomY, ViewTopY: LongInt;
+    ViewLeftX, ViewRightX, ViewBottomY, ViewTopY, ViewWidth, ViewHeight: LongInt;
+
+    // for debugging the view limits visually
+    cViewLimitsDebug: boolean;
 
     dirtyLandTexCount: LongInt;
 
@@ -226,6 +229,8 @@
 
     mobileRecord: TMobileRecord;
 
+    MaxTextureSize: LongInt;
+
 /////////////////////////////////////
 //Buttons
 {$IFDEF USE_TOUCH_INTERFACE}
@@ -2634,6 +2639,8 @@
 
     UIDisplay:= uiAll;
     LocalMessage:= 0;
+
+    cViewLimitsDebug:= false;
 end;
 
 procedure freeModule;
--- a/hedgewars/uWorld.pas	Sat Jun 14 07:12:22 2014 +0200
+++ b/hedgewars/uWorld.pas	Sat Jun 14 15:49:44 2014 +0200
@@ -1854,6 +1854,16 @@
         end
     end;
 
+// debug stuff
+if cViewLimitsDebug then
+    begin
+    r.x:= ViewLeftX;
+    r.y:= ViewTopY;
+    r.w:= ViewWidth;
+    r.h:= ViewHeight;
+    DrawRect(r, 255, 0, 0, 128, false);
+    end;
+
 isFirstFrame:= false
 end;