Умудрился вынести самому себе мозг, чуть не потярял очки SAN разбирая свой фхтагнокод 2008-го года... В конце концов пришлость снести его на и написать с нуля.

Создавать меш, рисовать и тут же уничтожать — сам понимаешь, неочень.
Для консоли уже оптимизировал, остальные места модуля - матки - не критичны, буду оптимизироватоь на стороне игрового модуля:
- Код: Выделить всё
  procedure TConsole.Draw();
 var
   zoom: glFloat;
   xmax, zms: integer;
   condensed: boolean;
   liT, Red, Green, Blue, Alpha: glFloat;
   currentLineTop, currentYTop: integer;
   //processing from bottom to top until the next line is completely off-screen
   function DrawOneLine() : boolean;
   var
     xp, yp, x, y, c, cc, L2, y2, SubLines, tlen: integer;
     ts, tt: GLfloat;
   begin
     if currentLineTop < 0 then Exit(false);
     tlen:= Length(Self.Strings[currentLineTop]);
     if (tlen > 1)
       then SubLines:= 1 + ((tlen - 1 - 1) div (xmax))
       else SubLines:= 1;
     currentYTop -= Sublines * trunc(ConsoleCharHeight * zoom);
     if (currentYTop + Sublines * ConsoleCharHeight * zoom) < 0 //completely off screen?
       then Exit(false);
     x:=0;
     y:=0;
     c:=1;
     While c < tlen - 1 do begin
       //draw character;
       xp:= trunc(ConsoleBorders) + x * trunc(ConsoleCharWidth * zoom);
       yp:= y * trunc(ConsoleCharHeight * zoom);
       cc:=Ord(Self.Strings[currentLineTop][c]);
       if cc >=32 then begin //ignore special characters
         ts:=((cc mod 16) * ConsoleCharXstep + ConsoleCharOffsetS) / ConsoleImageWidth;
         tt:=((cc div 16) * 16 + ConsoleCharOffsetT) / 256.0;
         f_mesh.AddQuad2d(
           Red, Green, Blue, Alpha,
           xp, yp + currentYTop,
             xp + (ConsoleCharWidth + 1) * zoom, yp + currentYTop + ConsoleCharHeight * zoom,
           ts, tt, ts + (ConsoleCharWidth + 1) / ConsoleImageWidth, tt + ConsoleCharHeight / 256.0 );
       end;
       inc (c);
       inc (x);
       if x > xmax then begin
         x:=1;
         inc(y);
       end;
     end;
     currentLineTop-= 1;
     Result:= true;
   end;
 begin
   if not Mother^.Display.CanRender then Exit;
   zms:= Round((Now() - f_lasttime) * 1000.0 * SECONDS_PER_DAY );
   LastHeartbeatMoment:=Now();
   If not (f_vis
           or (zms < (f_hidetime + f_fadetime)))
   then begin
     f_fadeline:= -1;
     f_fade:= 1.0;
     Exit;
   end;
   if f_vis then liT:=0
   else begin
     if zms < f_hidetime then liT:= - (f_hidetime - zms) / f_hidetime
                         else liT:=(zms - f_hidetime) / f_fadetime;
   end;
   if f_scrolled_back < 0 then f_scrolled_back:=0;
   if not f_vis then f_scrolled_back:=0;
//  f_fade:= 1.0;
   Alpha:= CCLd(liT, 4) * Mother^.Display.FadeIn;
   condensed:= ConsoleUseCondensedFont or (Mother^.Display.WindowClientRect.Width < f_tosquish);
   if not Assigned(f_mesh)
     or f_change.Yes
     or (f_change.lit <> trunc(Alpha * 1000))
     or (f_change.sb <> f_scrolled_back)
     or (f_change.dw <> Mother^.Display.WindowClientRect.Width)
     or (f_change.dh <> Mother^.Display.WindowClientRect.Height)
     or (f_change.condensed <> condensed)
   then begin
     if Assigned(f_mesh) then begin f_mesh.Free; f_mesh:= nil end;
     if Self.Count < 1 then Exit;
     f_change.Yes := No;
     f_change.dw := Mother^.Display.WindowClientRect.Width;
     f_change.dh := Mother^.Display.WindowClientRect.Height;
     f_change.sb := f_scrolled_back;
     f_change.lit := trunc(Alpha * 1000);
     f_change.condensed:= condensed;
      Red:= CCLd(liT, 1);
      Green:= CCLd(liT, 2);
      Blue:= CCLd(liT, 3);
     if condensed then begin
       ConsoleCharWidth:= 4;
       ConsoleCharXstep:= 128 div 16;
       ConsoleImageWidth:= 128.0;
       ConsoleCharOffsetS:= 2;
     end
     else begin
       ConsoleCharWidth:= 9;
       ConsoleCharXstep:= 256 div 16;
       ConsoleImageWidth:= 256.0;
       ConsoleCharOffsetS:= 4;
     end;
      zoom:=1.0;
      if Mother^.Display.WindowClientRect.Width > f_tostretch then zoom:= 2.0;
      xmax := -1 + ((Mother^.Display.WindowClientRect.Width
        - trunc(2 * ConsoleBorders * zoom ) ) div  trunc(zoom * ConsoleCharWidth));
      currentYTop:= Mother^.Display.WindowClientRect.Height - trunc(ConsoleBorders);
      currentLineTop:= max(0, Self.Count - 1 - f_scrolled_back);
      if (currentLineTop < 1) and (f_scrolled_back > 0) then begin
        f_scrolled_back:= max(0, f_scrolled_back - (1 - currentLineTop));
        currentLineTop:= max(0, Self.Count - 1 - f_scrolled_back);
      end;
      f_mesh:= TBasicMesh.Create;
     while DrawOneLine() do;
   end;
   if Assigned(f_mesh) then begin
     SetGLStatesForGUI;
     f_mesh.SetGLStatesForGUI;
     if condensed
       then glBindTexture(GL_TEXTURE_2D, f_halftexture)
       else glBindTexture(GL_TEXTURE_2D, f_texture);
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     f_mesh.Render;
   end;
 end; 
, поэтому даже в FFP нет причины не использовать [Vertex/TexCoord/etc.]Pointer + DrawElements вместо цикла.
Обязательно вернусь к этому когда дойду до стадии непадающей игровой логики.
С наскока ниасилил, получил чёрный экран при молчащей glGetError()
, что у некоторых мешей какие-то атрибуты могут отсутствовать?
Это изначальный базовый для простых вещей.
Понадобится оптимизация - напложу специализированных потомков.
, соответственно, все эти Ortho etc. — функциями, её возвращающими, а не методами левого класса.
В норме да, но я делаю базу для использования старого говнокода с минимумом изменений. 
На работе третий год подобным же занимаюсь, целый эмулятор Joomla! 1.5 написал.
Добавлено спустя 11 часов 30 минут 35 секунд:Всё, разобрался. Это не лыжи не едут, это я... кхм.
Когда шлёшь видяхе четырёхмерные координаты (на... кой?) - четвёртую компоненту надо заполнять единицами. А не то.
FFP зачем-то множит три первые компоненты на 1/четвёртую. 
Чую, предстоит курить матрицы.
По ходу, потестирую потом производительность этой штуки. Если окажется адекватной - буду рендерить ею все места, где надо быстро подмухлевать геометрию на лету, не дожидаясь ленивого обновления. Например, ближние чанки вокруг игрока, где надо шустро по отдельности переключать грани с общего текстурного атласа чанка на индивидуальные текстуры повышенного разрешения, или дорисовывать подстраховочные оболочки за ближними стенками на случай фейла по z-near.
Напомню, производительность классического glVertex3f(x,y,z) держится на вполне приличном уровне вплоть до 20К где-то полигонов, а потом - резко падает. Наверняка ж специальный хак с буфером в юзерспейсе для поддержки старых игр.
Ещё впечатлился реализацией прозрачности в Fallout 4 (на дизеринге).
http://chebmaster.com/_share/fo4-dithering.avi (4 Мб)
Облизываюсь, примеряюсь где буду такое использовать. Она ж без блендинга вообще, и порядок сортировки не важен!
Что если смещение матрицы смещать на пол-периода каждый кадр? Тогда получится отличное темпоральное сглаживание (не говоря уже, что я планирую искривлённый вывод супер-сэмпленного рендер-буфера для получения сферической проекции, что даст дополнительно сглаживание размытием)