anchor.diff:  
     SizeX := Max(fClipRect.Right - fClipRect.Left, 0);
     SizeY := Max(fClipRect.Bottom - fClipRect.Top, 0);
  +
     H := 0;
  -  SetLength(fTilesVtx, (SizeX + 2) * 4 * (SizeY + 1));
  +  Q := 0;
  +
  +  TexOffsetWater := 0;
  +  TexOffsetFalls := 0;
  +  TexOffsetSwamp := 0;
  +
  +  for AL := Low(TAnimLayer) to High(TAnimLayer) do
  +    case AL of
  +      alWater: TexOffsetWater := 300 * (aAnimStep mod 8 + 1);       // 300..2400
  +      alFalls: TexOffsetFalls := 300 * (aAnimStep mod 5 + 1 + 8);   // 2700..3900
  +      alSwamp: TexOffsetSwamp := 300 * ((aAnimStep mod 24) div 8 + 1 + 8 + 5); // 4200..4800
  +    end;
  +
  +  SetLength(fTilesVtx, (SizeX + 1) * 4 * (SizeY + 1));
  +  SetLength(fAnimTilesVtx, (SizeX + 1) * 4 * (SizeY + 1));
     with gTerrain do
  -  if (MapX > 0) and (MapY > 0) then
  -  for I := 0 to SizeY do
  -  for K := 0 to SizeX+1 do
  -  begin
  -    tX := K + fClipRect.Left;
  -    tY := I + fClipRect.Top;
  -    TexC := fTileUVLookup[Land[tY, tX].Terrain, Land[tY, tX].Rotation mod 4];
  -
  -    SetVertex(H, tX, tY, False, TexC[1][1], TexC[1][2]);
  -    SetVertex(H+1, tX, tY+1, True, TexC[2][1], TexC[2][2]);
  -    SetVertex(H+2, tX+1, tY+1, True, TexC[3][1], TexC[3][2]);
  -    SetVertex(H+3, tX+1, tY, False, TexC[4][1], TexC[4][2]);
  -
  -    H := H + 4;
  -  end;
  -
  +    if (MapX > 0) and (MapY > 0) then
  +      for I := 0 to SizeY do
  +        for K := 0 to SizeX do
  +        begin
  +          tX := K + fClipRect.Left;
  +          tY := I + fClipRect.Top;
  +          TexTileC := fTileUVLookup[Land[tY, tX].Terrain, Land[tY, tX].Rotation mod 4];
  +
  +          //Fill Tile vertices array
  +          SetTileVertex(H,   tX-1, tY-1, False, TexTileC[1][1], TexTileC[1][2]);
  +          SetTileVertex(H+1, tX-1, tY,   True,  TexTileC[2][1], TexTileC[2][2]);
  +          SetTileVertex(H+2, tX,   tY,   True,  TexTileC[3][1], TexTileC[3][2]);
  +          SetTileVertex(H+3, tX,   tY-1, False, TexTileC[4][1], TexTileC[4][2]);
  +
  +          //Fill tiles animation vertices array
  +          if not TryAddAnimTex(Q, tX, tY, TexOffsetWater) then  //every tile can have only 1 animation
  +            if not TryAddAnimTex(Q, tX, tY, TexOffsetFalls) then
  +              TryAddAnimTex(Q, tX, tY, TexOffsetSwamp);
  +
  +          H := H + 4;
  +        end;
  +
  +
  +  //Cut animation vertices array to actual size
  +  SetLength(fAnimTilesVtx, Q);
  +
  +  //Fill indexes array for tiles vertices array
     H := 0;
     SetLength(fTilesInd, (SizeX+1) * (SizeY+1) * 6);
     for I := 0 to SizeY do
  -  for K := 0 to SizeX do
  -  begin
  -    Row := I * (SizeX + 2) * 4;
  -    fTilesInd[H+0] := Row + K * 4;
  -    fTilesInd[H+1] := Row + K * 4 + 1;
  -    fTilesInd[H+2] := Row + K * 4 + 2;
  -    fTilesInd[H+3] := Row + K * 4;
  -    fTilesInd[H+4] := Row + K * 4 + 3;
  -    fTilesInd[H+5] := Row + K * 4 + 2;
  +    for K := 0 to SizeX do
  +    begin
  +      Row := (I * (SizeX + 1)) shl 2;
  +      fTilesInd[H+0] := Row + K shl 2; // shl 2 = *4
  +      fTilesInd[H+1] := Row + (K shl 2) + 1;
  +      fTilesInd[H+2] := Row + (K shl 2) + 2;
  +      fTilesInd[H+3] := Row + (K shl 2);
  +      fTilesInd[H+4] := Row + (K shl 2) + 3;
  +      fTilesInd[H+5] := Row + (K shl 2) + 2;
  +      H := H + 6;
  +    end;
  +
  +  AnimCnt := Q div 4;
  +  //Fill indexes array for tiles animation vertices array
  +  H := 0;
  +  I := 0;
  +  SetLength(fAnimTilesInd, AnimCnt*6);
  +  while I < AnimCnt do
  +  begin
  +    fAnimTilesInd[H+0] := I shl 2; // shl 2 = *4
  +    fAnimTilesInd[H+1] := (I shl 2) + 1;
  +    fAnimTilesInd[H+2] := (I shl 2) + 2;
  +    fAnimTilesInd[H+3] := (I shl 2);
  +    fAnimTilesInd[H+4] := (I shl 2) + 3;
  +    fAnimTilesInd[H+5] := (I shl 2) + 2;
       H := H + 6;
  +    Inc(I);
     end;
   end;
   
  
positive.code: end;
  
  
  procedure TRenderTerrain.UpdateVBO(aFOW: TKMFogOfWarCommon);
  var
    Fog: PKMByte2Array;
    procedure SetVertex(aI: Integer; aTX, aTY: Word; aIsBottomRow: Boolean; aUTile, aVTile: Single);
    begin
      with gTerrain do
      begin
        fTilesVtx[aI].X := aTX-1;
        fTilesVtx[aI].Y := aTY-1 - Land[aTY, aTX].Height / CELL_HEIGHT_DIV;
        fTilesVtx[aI].Z := aTY - 1 - Byte(aIsBottomRow);
        fTilesVtx[aI].UTile := aUTile;
        fTilesVtx[aI].VTile := aVTile;
        fTilesVtx[aI].ULit := Land[aTY, aTX].Light;
        fTilesVtx[aI].UShd := -Land[aTY, aTX].Light;
        if Fog <> nil then
          fTilesVtx[aI].UFow := Fog^[aTY-1, aTX-1] / 256
        else
          fTilesVtx[aI].UFow := 255;
      end;
    end;
  var
    I,K,H: Integer;
    SizeX, SizeY: Word;
    tX, tY: Word;
    Row: Integer;
    TexC: TUVRect;
  begin
    if not fUseVBO then Exit;
  
    if aFOW is TKMFogOfWar then
      Fog := @TKMFogOfWar(aFOW).Revelation
  
negative.code:     fTextB: GLuint; //Contrast BW for FOW over color-coder
      fUseVBO: Boolean; //Wherever to render terrain through VBO (faster but needs GL1.5) or DrawCalls (slower but needs only GL1.1)
      fTilesVtx: array of TTileVertice; //Vertice cache for tiles
      fTilesInd: array of Integer;      //Indexes for tiles array
      fAnimTilesVtx: array of TAnimTileVertice; //Vertice cache for tiles animations (water/falls/swamp)
      fAnimTilesInd: array of Integer;          //Indexes for array tiles animation array
      fVtxTilesShd: GLUint;
      fIndTilesShd: GLUint;
      fVtxAnimTilesShd: GLUint;
      fIndAnimTilesShd: GLUint;
      fTileUVLookup: array [0..255, 0..3] of TUVRect;
      fLastBindVBOArrayType: TVBOArrayType;
      function GetTileUV(Index: Word; Rot: Byte): TUVRect;
      procedure BindVBOArray(aVBOArrayType: TVBOArrayType);
      procedure UpdateVBO(aAnimStep: Integer; aFOW: TKMFogOfWarCommon);
      procedure DoTiles;
      procedure DoOverlays;
      procedure DoLighting;
  