Умудрился вынести самому себе мозг, чуть не потярял очки 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 Мб)
Облизываюсь, примеряюсь где буду такое использовать. Она ж без блендинга вообще, и порядок сортировки не важен!
Что если смещение матрицы смещать на пол-периода каждый кадр? Тогда получится отличное темпоральное сглаживание (не говоря уже, что я планирую искривлённый вывод супер-сэмпленного рендер-буфера для получения сферической проекции, что даст дополнительно сглаживание размытием)