anchor.diff:  end;
   
   
  -procedure TRenderTerrain.UpdateVBO(aFOW: TKMFogOfWarCommon);
  +procedure TRenderTerrain.UpdateVBO(aAnimStep: Integer; aFOW: TKMFogOfWarCommon);
   var
     Fog: PKMByte2Array;
  -  procedure SetVertex(aI: Integer; aTX, aTY: Word; aIsBottomRow: Boolean; aUTile, aVTile: Single);
  +
  +  procedure SetTileVertex(aH: 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;
  +      fTilesVtx[aH].X := aTX;
  +      fTilesVtx[aH].Y := aTY - Land[aTY+1, aTX+1].Height / CELL_HEIGHT_DIV;
  +      fTilesVtx[aH].Z := aTY - Byte(aIsBottomRow);
  +      fTilesVtx[aH].UTile := aUTile;
  +      fTilesVtx[aH].VTile := aVTile;
  +      fTilesVtx[aH].ULit := Land[aTY+1, aTX+1].Light;
  +      fTilesVtx[aH].UShd := -Land[aTY+1, aTX+1].Light;
         if Fog <> nil then
  -        fTilesVtx[aI].UFow := Fog^[aTY-1, aTX-1] / 256
  +        fTilesVtx[aH].UFow := Fog^[aTY, aTX] shr 8 //  shr 8 = / 256
         else
  -        fTilesVtx[aI].UFow := 255;
  +        fTilesVtx[aH].UFow := 255;
       end;
     end;
  -var
  -  I,K,H: Integer;
  +
  +  procedure SetAnimTileVertex(aQ: Integer; aTX, aTY: Word; aIsBottomRow: Boolean; aUAnimTile, aVAnimTile: Single);
  +  begin
  +    with gTerrain do
  +    begin
  +      fAnimTilesVtx[aQ].X := aTX;
  +      fAnimTilesVtx[aQ].Y := aTY - Land[aTY+1, aTX+1].Height / CELL_HEIGHT_DIV;
  +      fAnimTilesVtx[aQ].Z := aTY - Byte(aIsBottomRow);
  +      fAnimTilesVtx[aQ].UAnim := aUAnimTile;
  +      fAnimTilesVtx[aQ].VAnim := aVAnimTile;
  +    end;
  +  end;
  +
  +  function TryAddAnimTex(var aQ: Integer; aTX, aTY, aTexOffset: Word): Boolean;
  +  var TexAnimC: TUVRect;
  +  begin
  +    Result := False;
  +    with gTerrain do
  +      if (aTexOffset + Land[aTY,aTX].Terrain + 1 <= High(GFXData[rxTiles]))
  +         and (GFXData[rxTiles, aTexOffset + Land[aTY,aTX].Terrain + 1].Tex.ID <> 0)
  +         and (aFOW.CheckTileRevelation(aTX,aTY) > FOG_OF_WAR_ACT) then
  +      begin
  +        TexAnimC := GetTileUV(aTexOffset + Land[aTY,aTX].Terrain, Land[aTY,aTX].Rotation mod 4);
  +
  +        SetAnimTileVertex(aQ,   aTX-1, aTY-1, False, TexAnimC[1][1], TexAnimC[1][2]);
  +        SetAnimTileVertex(aQ+1, aTX-1, aTY,   True,  TexAnimC[2][1], TexAnimC[2][2]);
  +        SetAnimTileVertex(aQ+2, aTX,   aTY,   True,  TexAnimC[3][1], TexAnimC[3][2]);
  +        SetAnimTileVertex(aQ+3, aTX,   aTY-1, False, TexAnimC[4][1], TexAnimC[4][2]);
  +
  +        aQ := aQ + 4;
  +        Result := True;
  +      end;
  +  end;
  +
  +var
  +  I,K,H,Q,AnimCnt: Integer;
     SizeX, SizeY: Word;
     tX, tY: Word;
     Row: Integer;
  -  TexC: TUVRect;
  +  TexTileC: TUVRect;
  +  AL: TAnimLayer;
  +  TexOffsetWater, TexOffsetFalls, TexOffsetSwamp: Word;
   begin
     if not fUseVBO then Exit;
  +
  +  fLastBindVBOArrayType := vat_None;
   
     if aFOW is TKMFogOfWar then
       Fog := @TKMFogOfWar(aFOW).Revelation
  
positive.code:   KM_CommonClasses, KM_CommonTypes, KM_Defaults, KM_FogOfWar, KM_Pics, KM_ResSprites, KM_Points, KM_Terrain;
  
  type
    TUVRect = array [1 .. 4, 1 .. 2] of Single; // Texture UV coordinates
    TTileVertice = record
      X, Y, Z, UTile, VTile, ULit, UShd, UFow: Single;
    end;
    TFOWVertice = record
      X, Y, Z, UFow: Single;
    end;
  
    //Render terrain without sprites
  
negative.code:   //Thus we allow VBO only in 2D
    fUseVBO := VBOSupported and not RENDER_3D;
  
    UpdateVBO(aAnimStep, aFOW);
  
    DoTiles;
    DoOverlays;
  