Страница 9 из 61

Re: Cheb's Game Engine

СообщениеДобавлено: 28.05.2016 16:35:21
runewalsh
1) Матрица должна быть параметром процедуры рисования, а не полем меша, соответственно, все эти Ortho etc. — функциями, её возвращающими, а не методами левого класса.

2) Не допускаешь, что у некоторых мешей какие-то атрибуты могут отсутствовать? Тем же экранным квадам не нужны нормали, текстурированным в простых случаях (т. е. когда не предрассчитываешь освещение в вершинах) не нужны цвета.

3) У тебя уже и так готовые массивы, поэтому даже в FFP нет причины не использовать [Vertex/TexCoord/etc.]Pointer + DrawElements вместо цикла. А ещё лучше записать данные меша в VBO, которые и так поддерживаются вообще везде (OpenGL 1.4, 1.1 or so). Собственно, рисовать из оперативной памяти = нагружать CPU и шину ерундой.

4) Создавать меш, рисовать и тут же уничтожать — сам понимаешь, неочень.

5) Выставлять стейт перед каждым рисованием тоже неочень, будто сам как программист не знаешь, где у тебя что было включено.

Re: Cheb's Game Engine

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

Re: Cheb's Game Engine

СообщениеДобавлено: 30.05.2016 06:51:43
скалогрыз
runewalsh писал(а):А ещё лучше записать данные меша в VBO

а если данные в меше пересчитываются регулярно (анимированный меш). То есть ли смсыл?

Cheb писал(а):Напомню, производительность классического glVertex3f(x,y,z) держится на вполне приличном уровне вплоть до 20К где-то полигонов, а потом - резко падает. Наверняка ж специальный хак с буфером в юзерспейсе для поддержки старых игр.

какой бы там бестробуфер не был задействован, ты как-минимум потеряешь на стоимости вызова функции.

Т.е. для какого-нить меша на 10К точек, у тебя вызовов с бесполезным перезаполнением стэка будет соотвественно 10*4к (вертекс/нормаль/текстура(ы)/цвет). Это становиться ещё большей бессмыслицей, если учесть, что сам точки в твоём коде хранятся в массиве же.

Кстати о классицизме. glVertex() был придуман в те времена, когда запросы к графике были скромными. И количество этих самых точек будет достаточно низким (да и процессор больше потратит времени на обсчёт сцены... fpu со-процессором :D).
Но даже тогда, понимали, что вызывать тучу процедур, на каждый кадр, это не хорошо, и были придуманы диспленые списки.
Которые в последствии были успешно забракованы свежедобавленной поддержкой поддержкой массивов, ну и VBO, конечно, решает.

Re: Cheb's Game Engine

СообщениеДобавлено: 30.05.2016 16:06:23
Cheb
понимали, что вызывать тучу процедур, на каждый кадр, это не хорошо,

Вот, кстати, себе на заметку: покопаться в потрохах третьего квейка (он же Open Arena) и посмотреть, как это там.

а если данные в меше пересчитываются регулярно (анимированный меш).

По идее, рассчитывать анимацию на CPU - это зло. И это для меня - дальний этап, на после завершения первой игры (собственная нескелетная физикообразная анимация).
Пока же, видов анимированных мешей будет два, и оба укладываются в парадигму закачивания на видеокарту двух ключевых кадров, и смешивания их уже на видеокарте (передачей одного дополнительного коэффициента):
- чанки где что-нибудь течёт или сыплется. По парадигме ленивой физики, они просчитывают своё состояние на 200..4000 милисекунд вперёд, и засыпают. При чтении состояние чанка берётся интерполяцией между прошлой и будущей точками. При модификации внешней силою - актуализует промежуточное состояние и просчитывает заново уже от него.
- модели игроков в формате MD3 (Open Arena), с предрассчитанной, уже запечённой анимацией.

Комбинированый меш окружающих игрока чанков (12 штук) будет пересобираться каждый кадр, и только в его пределах (это где-то радиус 10 метров) будут возможны следующие фичи:
- любая полупрозрачность (воды, задымлённых блоков, партиклов)
- честная трава

Re: Cheb's Game Engine

СообщениеДобавлено: 30.05.2016 23:44:17
Mirage
Cheb писал(а):Облизываюсь, примеряюсь где буду такое использовать. Она ж без блендинга вообще, и порядок сортировки не важен!


Ты смотри, прям как в Анреале (первом) когда тот в софтовом режиме работал!
Еще недавно читал, что в свежем GTA такой прием используется, причем более адекватно смотрится, нежели в ролике.

Cheb писал(а):Что если смещение матрицы смещать на пол-периода каждый кадр? Тогда получится отличное темпоральное сглаживание (не говоря уже, что я планирую искривлённый вывод супер-сэмпленного рендер-буфера для получения сферической проекции, что даст дополнительно сглаживание размытием)


Скорее всего, выглядеть будет жутковато, но почему бы не попробовать...

Cheb писал(а):По парадигме ленивой физики, они просчитывают своё состояние на 200..4000 милисекунд вперёд, и засыпают. При чтении состояние чанка берётся интерполяцией между прошлой и будущей точками. При модификации внешней силою - актуализует промежуточное состояние и просчитывает заново уже от него.


А без внешних сил движение равномерное и прямолинейное?
А вообщше внешние силы практически всегда есть, получается, так будет тратиться куча ресурсов зря, просчитывая наперед.

Re: Cheb's Game Engine

СообщениеДобавлено: 31.05.2016 01:59:33
Cheb
А без внешних сил движение равномерное и прямолинейное?
А вообщше внешние силы практически всегда есть, получается, так будет тратиться куча ресурсов зря, просчитывая наперед.

Прямолинейное и равномерное.
Надо учитывать, что внешние силы - такие же ленивые, просчитывают своё будущее состояние с учётом интерполированного состояния чанка (т.к. в общем случае периоды не совпадают)
Из-за этого вот несовпадения периодов расчёт почти никогда не будет напрасным. Поскольку прерывание сна начинается с блендинга состояний на момент для текущего тика, какая-то часть рассчитанного изменения произойдёт.
Короче, вырожденный случай - обычная физика, рассчитываемая каждый тик.



такой прием используется, причем более адекватно смотрится, нежели в ролике.

Надо учитывать, что:
а) я увеличил видео вдвое чтобы лучше видно было
б) моя GTX460 не дотягивает до минимальных системных требований.



, но почему бы не попробовать...

А с обычной прозрачностью геморрой ещё тот. Меня, лично, бесит, когда при погружении в воду у персонажа исчезают волосы (чем грешат все игры от обливиона и до фолаутньювегаса)

Re: Cheb's Game Engine

СообщениеДобавлено: 07.06.2016 17:08:38
Cheb
Ея финальная форма :roll: :

Код: Выделить всё
procedure TDumbUniMesh.Render;
var i: integer;
begin
  if Length(indices) <= 0 then Exit;
  if maxIndex < High(indices) then maxIndex:= High(indices);
  case  Mother^.GAPI.Mode of
   {$ifndef glesonly}
    gapi_DeprecatedImmediateGL, gapi_GL21: begin
      {
      glBegin(GL_TRIANGLES);
      for i:=0 to maxIndex do begin
        glColor4fv(@colors[indices[i]]);
        glNormal3fv(@normals[indices[i]]);
        glTexCoord3fv(@texcoords[indices[i]]);
        glVertex4fv(@vertices[indices[i]]);
      end;
      glEnd;
      }
     // https://www.opengl.org/wiki/Client-Side_Vertex_Arrays

glGetError(); //***TODO this is a hack for an error state provoked somewhere else. Note to self: find and eliminate

      glEnableClientState(GL_VERTEX_ARRAY);
      glVertexPointer(4, GL_FLOAT, 0, @vertices[0]);
      glEnableClientState(GL_COLOR_ARRAY);
      glColorPointer(4, GL_FLOAT, 0, @colors[0]);
      glClientActiveTexture(GL_TEXTURE0);
      glEnableClientState(GL_TEXTURE_COORD_ARRAY);
      glTexCoordPointer(3, GL_FLOAT, 0, @texcoords[0]);
      glEnableClientState(GL_NORMAL_ARRAY);
      glNormalPointer(GL_FLOAT, 0, @normals[0]);

      glDrawElements(GL_TRIANGLES, maxIndex + 1, GL_UNSIGNED_SHORT, @indices[0]);

      CheckGLError;
    end;
   {$endif glesonly}
    gapi_GLES2: begin
Die('***NotImplementedYet');
    end;
  else
    DieUnsupportedGLMode;
  end;
end;

Re: Cheb's Game Engine

СообщениеДобавлено: 12.06.2016 23:24:52
Cheb
Разгрёб говнокоды до стадии компилируемости игрового модуля.

Теперь самое страшное: найти из-за какого из 100500 перелопаченных мест его развозит до полного выхода в атсрал.

По крайней мере, та часть Чеперси, что отвечает за регистрацию, выполняется без крахов.
Неприятным сюрпризам стало, что экземпляр класса потолстел на размер указателя (причём, втыкается это в конце после всех полей). Предполагаю, что это ссылка на интерфейс.

Грязный хакЪ для обхода:
Код: Выделить всё
  procedure TChepersyObject.RegisterFields;
  begin
    ListFields([
      'CpsMask', @f_cpsmask, typeinfo(dword),
      '{Skipped,NeverClone}f_RefCount', @f_refCount, typeinfo(dword)//typeinfo(longint)
      //Can't use longint as it is not registered yet at this time
      //  while I have NO desire of touching the hard-coded type numbers used by
      //  the backward/forward compatibility mechanism to resolve unknown types

      ,'CpsWTFisThisCrapMaybeInterfacePointer', pointer(@f_refCount) + sizeof(f_refCount), CPS_POINTER
    ]);
  end;


Добавлено спустя 3 часа 28 минут 10 секунд:
Чудом увернулся от нежданчика, который бы мне выел весь мозг в будущем, заставив протрахаться с отладкой неделю, а может, и месяц. Каким чудом? При пробном запуске 64-битной версии модуля стукнула проверка, вставленная мной в Чеперси как бы ещё не в 2007-м, на то, как компилятор размещает в памяти счётчик ссылок массива. Она сама уже не актуальна, но привлекла моё внимание и оказалось:

Все мои ктулхаки мухлежа со счётчиком ссылок в строках не учитывали того факта, что оный счётчик может быть равен минус единице!
А -1 он равен у константных строк - т.е. тех, которые изначально зашиты в екзешник.

См.:
Код: Выделить всё
  s1:= 'phthagn!'; //s1+= 'ы';
  s2:= s1;
addlog('%0 %1', [ptrint(pointer(ptruint(s2) - sizeof(pointer))^), ptrint(pointer(ptruint(s2) - 2 * sizeof(pointer))^)]);
addlog('%0 %1 %2', [s2, pointer(s2), pointer(s2)] );
  s2+= '#';
addlog('%0 %1', [ptrint(pointer(ptruint(s2) - sizeof(pointer))^), ptrint(pointer(ptruint(s2) - 2 * sizeof(pointer))^)]);
addlog('%0 %1 %2', [s2, pointer(s2), pointer(s2)] );
addlog('--');
s1:= 'phthagn!';
s1+= 'ы';
s2:= s1;
addlog('%0 %1', [ptrint(pointer(ptruint(s2) - sizeof(pointer))^), ptrint(pointer(ptruint(s2) - 2 * sizeof(pointer))^)]);
addlog('%0 %1 %2', [s2, pointer(s2), pointer(s2)] );
s2+= '#';
addlog('%0 %1', [ptrint(pointer(ptruint(s2) - sizeof(pointer))^), ptrint(pointer(ptruint(s2) - 2 * sizeof(pointer))^)]);
addlog('%0 %1 %2', [s2, pointer(s2), pointer(s2)] );
addlog('--');
s1:= IntToStr(9);
s2:= s1;
addlog('%0 %1', [ptrint(pointer(ptruint(s2) - sizeof(pointer))^), ptrint(pointer(ptruint(s2) - 2 * sizeof(pointer))^)]);
addlog('%0 %1 %2', [s2, pointer(s2), pointer(s2)] );
s2+= '#';
addlog('%0 %1', [ptrint(pointer(ptruint(s2) - sizeof(pointer))^), ptrint(pointer(ptruint(s2) - 2 * sizeof(pointer))^)]);
addlog('%0 %1 %2', [s2, pointer(s2), pointer(s2)] ); 


Код: Выделить всё
Win32/FPC 2.6.4:
(поток №0) 8 -1
(поток №0) phthagn! 144573F4h 144573F4h
(поток №0) 9 1
(поток №0) phthagn!# 14522070h 14522070h
(поток №0) --
(поток №0) 9 3
(поток №0) phthagn!ы 14522090h 14522090h
(поток №0) 10 1
(поток №0) phthagn!ы# 14522070h 14522070h
(поток №0) --
(поток №0) 1 2
(поток №0) 9 1451A068h 1451A068h
(поток №0) 2 1
(поток №0) 9# 1451A098h 1451A098h

Win64/FPC 2.6.4:
(поток №0) 8 -1
(поток №0) phthagn! 001101011D0h 001101011D0h
(поток №0) 9 1
(поток №0) phthagn!# 00006476BE0h 00006476BE0h
(поток №0) --
(поток №0) 9 3
(поток №0) phthagn!ы 00006476C20h 00006476C20h
(поток №0) 10 1
(поток №0) phthagn!ы# 00006476BE0h 00006476BE0h
(поток №0) --
(поток №0) 1 2
(поток №0) 9 000063F1B80h 000063F1B80h
(поток №0) 2 1
(поток №0) 9# 000063F1B20h 000063F1B20h


Это был бы полный. :(

Re: Cheb's Game Engine

СообщениеДобавлено: 14.06.2016 20:47:42
runewalsh
>if Length(indices) <= 0 then Exit;
Читал (правда, в контексте PS3), что условия, которые в 99% случаев не сработают и при которых код всё равно отработает корректно, не нужны: так, проверка в «if size > 0 then Move(a, b, size)» лишняя. Мол, нужно писать код под наиболее типичный случай, а не граничные. То же касается, например, брейков по маловероятным условиям, когда без брейка всё равно отработает корректно и не сильно медленнее.

Re: Cheb's Game Engine

СообщениеДобавлено: 14.06.2016 21:11:52
скалогрыз
runewalsh писал(а):так, проверка в «if size > 0 then Move(a, b, size)» лишняя

зависит от Move и настроек компилятора.

например:
Код: Выделить всё
...const s : array of byte;
  Move(s[0], b[0], length(s));

вызовет Range Check error, если проверка на Range включена, а length(s)=0.
по-этому для аккуратного паскалиста следует писать именно
Код: Выделить всё
...const s : array of byte;
...
  if length(s)>0 then Move(s[0], b[0], length(s));


неаккуратный паскалист может писать так:
Код: Выделить всё
{$R-}
  ...const s : array of byte;

  Move(s[0], b[0], length(s));


перфекционист напишет так:
Код: Выделить всё
{$ifndef release}
{$R+}
{$endif}
  ...const s : array of byte;

  {$ifdef release}
  Move(s[0], b[0], length(s));
  {$else]
  if length(s)>0 then Move(s[0], b[0], length(s));
  {$endif}

ИМХО: с тех пор, как графика общитывается GPU, а не CPU, на санитарных проверках можно и не экономить.

ЗЫ. к слову об эффективности glVertex и массивах точек. Выяснилось, что ZenGL эмулирует immediate-режим OpenGL-а для OpenGLES 1.0 (в котором этого immediate режима не было изначально)

Добавлено спустя 1 минуту 58 секунд:
runewalsh писал(а): (правда, в контексте PS3)

PlayStation 3?

Re: Cheb's Game Engine

СообщениеДобавлено: 14.06.2016 22:06:38
runewalsh
>вызовет Range Check error
Move(pointer(s)^, pointer(b)^, length(s)). В данном случае pointer(nil)^ легален со всеми проверками, т. к. разворачивается просто в nil.
>PlayStation 3?
https://macton.smugmug.com/Other/2008-0 ... Fi/n-xmKDH — он говорит про Load-Hit-Store и другие специфичные вещи, но вот тот же «statistically common case» я бы даже к преждевременной оптимизации не отнёс, скорее к здравому смыслу.

Re: Cheb's Game Engine

СообщениеДобавлено: 14.06.2016 22:18:04
скалогрыз
runewalsh писал(а):Move(pointer(s)^, pointer(b)^, length(s)). В данном случае pointer(nil)^ легален со всеми проверками, т. к. разворачивается просто в nil.

две заметки:
1) (эстетическая) ну сам же ты так - с приведением к поинтерому - писать не станешь?! ;)
2) (техническая) а я не зря написал const s: array of byte; намекая на то, что "s" может быть и открытым, а не динамическним массивом. С ним такое приведение типов просто не прокатит
Код: Выделить всё
procedure DoStuffOnBitmap( ... const s: array of byte ..)

  Move(pointer(s)^, pointer(b)^, length(s))

Error: Illegal type conversion: "Open Array Of Byte" to "Pointer"

Ну и попытка сделать такое приведение
pointer(@s[0])^
вызовет всё тот же Range Check error :)

Re: Cheb's Game Engine

СообщениеДобавлено: 14.06.2016 22:36:58
Cheb
>if Length(indices) <= 0 then Exit;
Читал (правда, в контексте PS3), что условия, которые в 99% случаев не сработают и при которых код всё равно отработает корректно, не нужны:

Без этого ниже по течению словит AV, так как указатель на нулевой элемент массива скармливается glDrawElements()

Главная радость: запустилося! :D Игровой модуль кряхтит, пердит и высокохудожественнно падает в самых разных местах, но уже жив и даже в основном вменяем. Даже сохранение / загрузка после перезапуска работают.
А вот попытка откатить сессию не прерывая работы, вызвала красный экран смерти (который как синий экран смерти, только красный). Короче, основной поток бомбанул капитально, а поток игровой логики остался крутиться без руля и ветрил в бесконечном грузячем цикле. Однозначно что-то распидорасило в менеджере ассетов.

Основное надругательство над кодом заключалось в массовой замене <чегототам>.Scrape; на <чегототам>:= nil;

Ещё, 64-битная версия игрового модуля *почти* пошла, но Чеперси бычит на неверно рассчитанное выравнивание полей и размер инстансов.

Ещё, Vampyre Imaging в 64-битном варианте таки не читала жпеги. Вылечил, расковыряв ей дефайны, там вместо IMJPEGLIB надо было выбрать PASJPEG.

Re: Cheb's Game Engine

СообщениеДобавлено: 14.06.2016 23:17:30
скалогрыз
Cheb писал(а):там вместо IMJPEGLIB надо было выбрать PASJPEG

я б так не делал, PASJPEG на данный момент будет упорно проигрывать IMJPEGLIB (в скорости и поддержке jpeg-ов).
...ну если бы и делал, то как временное решение, с большим-большим TODO - использовать Си-шную либу.

то же самое касается zlib.

Re: Cheb's Game Engine

СообщениеДобавлено: 14.06.2016 23:41:55
Cheb
на данный момент будет упорно проигрывать IMJPEGLIB (в скорости и поддержке jpeg-ов).

В принципе, поддержка жпегов - это затычка для совместимости с openarena, сам в игре планирую использовать только png и tga.

то же самое касается zlib.

Всё своё ношу с собой (портировал своими руками на использование потоков): un_unzip.pp. Из стандартных юзает только zbase, в котором одни хидеры и объявления типов-записей.