Cheb's Game Engine

Планы, идеология, архитектура и т.п.

Модератор: Модераторы

Re: Cheb's Game Engine

Сообщение Cheb » 08.06.2017 12:53:26

Какой же я, всё таки, былинный изобретатель велосипедов...
Неожиданно нашёл свой дреееевний диздок от января 2000 года.
6. И последняя идея, довольно спорная. При наличии одного источника света (солнышко), создаём дополнительный буфер - глубины теней, и в нём ещё раз строим всю сцену, наплевав на текстуры и освещённость. Потом, рисуя сцену уже в нормальном буфере, вычисляем глубину и положение каждой точки в координатах буфера теней, и соответственно применяем освещённость - на солнышке / в тени. Естественно, буфер теней - дробный, с уменьшением разрешения по мере удаления от камеры.
В результате должен получиться эффект, как от ray tracing'а, но с меньшими затратами.

Гы :lol:

3.4.1 Минимальные системные требования.

В качестве платформы я выбрал Маздай 95, потому, что моя любимая DOS вымирает. Поддержка DOS режима в Маздае всё хуже, и старым программам приходится всё туже... Сначала были глюки с Sound Blaster, из-за которых замолчали все игры, распознавашие его автоматически. Теперь очередь дошла и до мыши, чувствительность которой параноидально мала, и не регулируется. И чтобы что‑нибудь нарисовать, мне приходится перезагружаться в режиме полной эмуляции MS-DOS, иначе мой любимый De Luxe Paint II просто неработоспособен. Я уже не говорю про Arkanoid, который глючит сам, и завешивает систему намертво (Яркий пример, да ?..).
А в скором времени халтурщики из Майкрософт могут решить, что ради всякого старья не стоит и возиться, и вообще уберут поддержку DOS, чтоб какая‑нибудь там Windows 2005 работала надёжнее.
Итак, с платформой вопрос ясен - Маздай 95. (Другие ОС я даже не рассматриваю, они стоят на 3% компьютеров, и если хотят жить, поддерживают Win32.)
Что же насчёт аппаратной части ?.. Минимум, на чём работает Windows (95‑я, а не 98‑я!) ‑ это 486 с 8Мб ОЗУ. (Знаю, сам два года прожил в такой конфигурации) Но на 486 машине ничего путного не сделаешь. Самый крутой мотор, который тянет этот процессор ‑ это движок Дюка, да и тот иногда притормаживает. К тому же, львиная доля 486 машин снабжена видеокартами ISA, у которых скорость обращения к видеопамяти редко превышает 1 Мбайт/с.
С другой стороны, сейчас на толкучке полно относительно дешёвых Пентиумов, и только совсем бедный не обзавёлся хоть завалящим. Весь вопрос ‑ какую частоту принять за минимальную ?.. 75 и 100 уже сейчас выглядят несерьёзно (и встречаются редко), так что как рабочий вариант я принимаю 166. Эта цифра может измениться в процессе разработки, которая может занять годы. Учитывая скорость технического прогресса, я также принимаю обязательность поддрежки процессором технологии MMX, заметно упрощающей и ускоряющей некоторые алгоритмы.
Что касается памяти: 16 Мбайт - это так мало, что даже говорить не стоит.
32 Мбайт - вопрос спорный, удастся ли втиснуть и графику, и сложный игровой мир в это прокрустово ложе. В любом случае, получится уродливо, но как я уже говорил выше, в хорошей игре графика - не главное.
Не будем рассматривать и тех недальновидных людей, кто поставил Windows 98 на машину с 32 Мб памяти, пусть апградят до 48.
Итак, по состоянию на середину 2001 года...
Будем предполагать, что разработка игры, до первых бет, займёт 3 года ‑ т. е., наметим выпуск на 2004 год. По известной закономерности, возможности "железа" за это время вырастут в 4 раза (или оно во столько же раз подешевеет ‑ как смотреть).
128 Мб памяти сейчас стоят $25 - будут $6, т.е. приспосабливать ядро к машине с памятью с менее, чем 128Мб необязательно.
Третий Пентиум сейчас стоит $130, будет - $30, т.е., приспосабливать ядро к машине медленнее Pentium III-500 тоже необязательно.
Верхним разумным пределом системных требований будут 512Мб памяти, и процессор, выполняющий около 10 миллиардов целочисленных операций в секунду. (или около 3 миллиардов с плавающей запятой).
Microsoft, к тому времени выпустит 64 битную Windows, которая не получит распространения из - за... Ну понятно, почему. И Win32 всё ещё будет самой распространённой платформой.

Гыыыы :lol:
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение скалогрыз » 08.06.2017 16:34:32

Чеборакул!

Cheb писал(а):1. Взял тоннельную пушку, сканер - и вперёд, на геологоразведку. Пушка умеет только длинные трёхметровые тоннели. Сканер видит только на десять метров.

Red Faction
Главной отличительной чертой является полностью разрушаемый мир. Игрок может уничтожить практически любую конструкцию, используя ракеты, огнестрельное оружие, автоматы и другие подручные средства. При этом каждый раз разрушения происходят по реалистичным законам физики, а значит, вы практически не сможете увидеть полностью одинаковых обломков.

Самое интересное, что критические вещи (н.р. дверь, к которой нужно раздобыть ключ), а так же деревянные стены вокруг этой двери, не разрушались... :mrgreen:

Полностью интерактивный мир позволяет игроку проявить фантазию во время прохождения. Например, если героя окружают враги, то можно разрушить ближайшие строения и сделать тайный проход.

когда в неё играл, то мне не хватало фантазии разрушать ближайшие строения и делать тайных проход.
шутер же! стрейф решает :D
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Cheb's Game Engine

Сообщение Cheb » 08.06.2017 17:59:04

Я должен сказать, мой самый запоминающийся опыт - из сетевой командной Ace of Spades
https://youtu.be/1AZlJ-aAakU?list=PLU4i ... rjxY&t=287

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

Туннельная пушка:
https://youtu.be/GZs6e0rgBYw?t=197
https://youtu.be/1AZlJ-aAakU?list=PLU4i ... rjxY&t=559

н.р. дверь, к которой нужно раздобыть ключ

Фтопку. Надо врага куда-то не пустить - окружаешь это место трёхмерным лабиринтом с ловушками и миньонами.
Нет ничего неразрушимого, а-ля Хранитель подземелий 2.

шутер же! стрейф решает

Хмммм... Разрушаемости мало, надо именно возможность делать подкопы, и именно быстро.

Чеборакул!

Гы :lol:

Добавлено спустя 16 часов 29 минут 5 секунд:
надо именно возможность делать подкопы, и именно быстро.

Разовью: поверхность вся простреливается, 90% вражьей команды - окопавшиеся снайперы. Выбираешь класс шахтёра, пару минут махания мегалопатой - и готов тоннель от нашей спавн-зоны до их спавн-зоны. Туннель широкий, 3х3 блока, и по нему устремляются наши коммандо с миниганами. А ты такой вылезаешь у врага в тылу и начинаешь делать ПРЕВЕД! снайперам, словно стеллс-пихот.
Враги, отреспавнившись с баттхёртом, начинают искать ответ на вопрос "какого!" - и, если находят выход тоннеля (а это бывает непросто, если ты хитрый а вокруг уже полно воронок от взрывов), начинают его перекрывать затычками, ставить мины (блок выкопал - мину в ямку засунул - блок поставил, такого же цвета, как соседние, воспользовавшись "пипеткой"), устраивать снайперские засады на прямых участках (вот почему я всегда копаю по синусоиде). Ты такой начинаешь делать обкопы вокруг затычек, подрываться на минах, зарабатывая баттхёрт - в общем, начинается увлекаательная драка бульдогов под ковром.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Cheb » 11.06.2017 23:21:49

Всё упёрлось, не только от того, что на работе завал, но и потому что мнен вдруг вот зачесалось добиться работающей GLES.

И забуксовал я на стадии, когда всё компилируется, всё работает, шейдер цепляется, но упорно рисуется пустой экран.
Единственное, что мне удалось заставить работать - glClear, так что да, буферы создаются и свопятся ОК. А вот отрендерить простейшую загогулину... :(

ЧЯДНТ! Изображение

Добавлено спустя 9 минут 58 секунд:
:cry:
Код: Выделить всё
procedure TDumbUniMesh.Render;
var
  i: integer;
  myib: GLuint;
  mymat: TMatrix4f;
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(3, 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: with Mother^.GAPI.ffpEmul do begin
//CheckGLError;

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

      glGetError();

      glEnableVertexAttribArray( position_attrloc );
      CheckGLError;

      glVertexAttribPointer( position_attrloc, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), @vertices[0]);
      CheckGLError;

      glEnableVertexAttribArray( texCoord_attrloc);
      CheckGLError;

      glVertexAttribPointer( texCoord_attrloc, 2, GL_FLOAT, GL_FALSE, sizeof(texcoords[0]), @texcoords[0]);
      CheckGLError;

      glEnableVertexAttribArray( color_attrloc );
      CheckGLError;

      //mymat:= matrix * TGAPI.matrix;
      glUniformMatrix4fv(matrix_unifloc, 1, GL_FALSE, @TGAPI.matrix);//@mymat);
      CheckGLError;

      glVertexAttribPointer( color_attrloc, 4, GL_FLOAT, GL_FALSE, sizeof(colors[0]), @colors[0]);
      CheckGLError;
      // http://openglbook.com/chapter-3-index-buffer-objects-and-primitive-types.html


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

      glDisableVertexAttribArray(position_attrloc);
      glDisableVertexAttribArray(texCoord_attrloc);
      glDisableVertexAttribArray(color_attrloc);
    end;
  else
    DieUnsupportedGLMode;
  end;
end;




class procedure TGAPI.SwitchToFixedPipeline;
begin
  case Mother^.GAPI.Mode of
    gapi_GL21, gapi_DeprecatedImmediateGL : begin
      if Assigned(glBindFramebuffer)
        then glBindFramebuffer(GL_FRAMEBUFFER, 0); //switch from FBO to the window framebuffer
      if Assigned(glUseProgram)
        then glUseProgram(0); //shut down the shaders
    end;
    gapi_GLES2: begin
      if Assigned(glBindFramebuffer)
        then glBindFramebuffer(GL_FRAMEBUFFER, 0); //switch from FBO to the window framebuffer
       if Assigned(glUseProgram) and Assigned(glUniformMatrix4fv)
         and Assigned(glUniform1i)
       then begin
          glUseProgram(Mother^.GAPI.ffpEmul.prog);

          glUniformMatrix4fv(Mother^.GAPI.ffpEmul.matrix_unifloc, 1, GL_FALSE, @matrix);

          glUniform1i(
            glGetUniformLocation(
              Mother^.GAPI.ffpEmul.prog,
              PAnsiChar(RawByteString('u_texture'#0))
            ),
            0
          );
       end;
    end;
    else
      DieUnsupportedGLMode;
  end;
end;



class procedure TGAPI.OrthoApplicationWindow;
begin
  case  Mother^.GAPI.Mode of
    {$ifndef glesonly}
    gapi_GL21, gapi_DeprecatedImmediateGL :begin
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      //origin in the upper left corner!
      glOrtho(0, Mother^.Display.WindowClientRect.Width, Mother^.Display.WindowClientRect.Height, 0, 0 ,1);
      //gluOrtho2d(0, WindowManager.Display.WindowClientWidth, 0, WindowManager.Display.WindowClientHeight);
    end;
    {$endif glesonly}
    gapi_GLES2: begin
      Self.LoadIdentity;
      Self.Ortho(0, Mother^.Display.WindowClientRect.Width, Mother^.Display.WindowClientRect.Height, 0, 0, 1);
    end;
  else
    DieUnsupportedGLMode;
  end;
end;



class procedure TGAPI.LoadIdentity;
begin
  FillChar(matrix, sizeof(matrix), 0);
  matrix[0,0]:= 1;
  matrix[1,1]:= 1;
  matrix[2,2]:= 1;
  matrix[3,3]:= 1;
end; 


class procedure TGAPI.Ortho(left, right, bottom, top,  nearVal, farVal: GLfloat);
var omat, tmat: TMatrix4f;
begin
  //https://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml
  omat[0, 0]:= 2 / (right - left);
  omat[0, 1]:= 0;
  omat[0, 2]:= 0;
  omat[0, 3]:= 0;

  omat[1, 0]:= 0;
  omat[1, 1]:= 2 / (top - bottom);
  omat[1, 2]:= 0;
  omat[1, 3]:= 0;

  omat[2, 0]:= 0;
  omat[2, 1]:= 1;
  omat[2, 2]:= -2 / (farVal - nearVal);
  omat[2, 3]:= 0;

  omat[3, 0]:= - (right + left) / (right - left);
  omat[3, 1]:= - (top + bottom) / (top - bottom);
  omat[3, 2]:= - (farVal + nearVal) / (farVal - nearVal);
  omat[3, 3]:= 1;

  tmat:= matrix;
  matrix:= tmat * omat;
end;


operator * (a, b: TMatrix4f) c: TMatrix4f;
var i: integer;
begin
  for i:= 0 to 3 do begin
    c[i,0]:= a[i,0] * b[0,0] + a[i,1] * b[1,0] + a[i,2] * b[2,0] + a[i,3] * b[3,0];
    c[i,1]:= a[i,0] * b[0,1] + a[i,1] * b[1,1] + a[i,2] * b[2,1] + a[i,3] * b[3,1];
    c[i,2]:= a[i,0] * b[0,2] + a[i,1] * b[1,2] + a[i,2] * b[2,2] + a[i,3] * b[3,2];
    c[i,3]:= a[i,0] * b[0,3] + a[i,1] * b[1,3] + a[i,2] * b[2,3] + a[i,3] * b[3,3];
  end;
end;



//преамбула
#version 120


//вершинный
{$CHE_GL120_ES100_PREAMBLE}

uniform mat4 u_matrix;

attribute vec3 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord;

varying vec2 v_texCoord;
varying vec4 v_color;
            
void main()
{
   //gl_Position = u_matrix * vec4(a_position[0], a_position[1], a_position[2], 0);
   gl_Position = vec4(a_position[0] * 0.001, a_position[1] * -0.001, -0.5, 0.0);//a_position[2], 0);
   v_texCoord = a_texCoord;
   v_color = a_color;
}

//преамбула
#version 120

//фрагментный
{$CHE_GL120_ES100_PREAMBLE}

uniform sampler2D u_texture;

varying vec2 v_texCoord;
varying vec4 v_color;

void main()
{
   vec4 mytexel = texture2D( u_texture, v_texCoord);
//   if (mytexel[3] < 0.05) {
//      discard;
//   } else {
//      gl_FragColor = v_color * mytexel;
//   }
gl_FragColor = vec4(v_texCoord[0], mytexel[0], v_color[1], 255.0);
}


Добавлено спустя 12 минут 38 секунд:
Кстати, зачем там вектору четвёртая компонента?.. :?
А если... :roll:
[правит в вершинном шейдере на gl_Position = u_matrix * vec4(a_position[0], a_position[1], a_position[2], 1.0);]...

Изображение

... :shock:

... :shock:

... :evil:

[длинная, матерная тирада] :evil:
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение shade » 12.06.2017 00:08:42

Cheb писал(а):Кстати, зачем там вектору четвёртая компонента?.. :?

Извиняюсь если не распознал сарказм и влез не в тему, но если вопрос был прямой, то есть такая штука, называется "Проективная геометрия" и "однородные координаты"

а нужно это всё для того, чтобы реализовать перспективу не какими-то сложными формулами, а обычными операциями с векторами и матрицами.

очень хорошо всё это описано в книге "Интерактивная компьютерная графика", старая книжка, сам когда-то ей зачитывался и пытался делать свой движок. Может щас есть поновее (книжка), может есть новое издание. Но по части проективной геометрии и однородных координат там всё очень хорошо расписано, что, как, зачем и почему =)
Аватара пользователя
shade
энтузиаст
 
Сообщения: 879
Зарегистрирован: 21.02.2006 20:15:48
Откуда: http://shamangrad.net/

Re: Cheb's Game Engine

Сообщение Cheb » 12.06.2017 02:28:58

"Проективная геометрия" и "однородные координаты"

[рукалицо] :oops:
Я - заслуженный вуду-кодер :oops:

Спасибо.

Добавлено спустя 5 минут 22 секунды:
термин "Вуду-программирование"
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение runewalsh » 12.06.2017 05:04:27

>gl_FragColor = vec4(v_texCoord[0], mytexel[0], v_color[1], 255.0);
Учитывая, что w-координата была открытием, возможно, новостью будет и то, что в отсутствие HDR компоненты цвета приводятся к [0.0; 1.0] x)
Аватара пользователя
runewalsh
энтузиаст
 
Сообщения: 578
Зарегистрирован: 27.04.2010 00:15:25

Re: Cheb's Game Engine

Сообщение Cheb » 12.06.2017 08:19:45

и то, что в отсутствие HDR компоненты цвета приводятся к [0.0; 1.0] x)

А, там и была 1. 255 - это уже в порядке биения лбом об стену. :oops:
Цитируя перебинтованного мужика, н-цатый раз наступающего на грабли: "А вдруг?"

Добавлено спустя 58 минут 23 секунды:
Йииии-ха!!! :D

Изображение

:D :D :D

8)

Скриншот можно сделать только фотоаппаратом, на нормальных скриншотах аппаратный сурфейс не виден.
Также, он наклается поверх всех окон, включая курсор мыши :evil:
Также, если подвигать позади него окна (резайситься и следовать за своим окном пока не умеет), то видно, что подложка проглядывает сквозь края букв (там альфа не единичная) - то есть, он ещё и блендится!
FPS ниже плинтуса из-за того, что какой-то быдлодрайвер спамит в консоль "glGetError 0x500". Буду разбираться.

В теории, на малине можно *вообще* без окна. Но движения мыши-то тогда чем ловить? Сачком?
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Лекс Айрин » 12.06.2017 11:28:29

Cheb писал(а):В теории, на малине можно *вообще* без окна. Но движения мыши-то тогда чем ловить? Сачком?


вроде как экран тоже считается окном... да и в той же винде, допустим, есть полноэкранный режим.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Cheb's Game Engine

Сообщение Cheb » 12.06.2017 14:55:06

вроде как экран тоже считается окном...

Не, не, малина рендерит в совершенно отдельный фтагнообъект, на уровне драйвера, который окном не считается.Нормальные Линуксовые механизмы о его существовании вообще не подозревают - например, на скриншотах его просто нет. Приходится брать в зубы фотоаппарат.

да и в той же винде, допустим, есть полноэкранный режим.

Не-а. Только у директикса. В OpenGL "полноэкранный" получают, выключив у окна все рамки и развернув окно на весь экран + поверх всех.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Лекс Айрин » 12.06.2017 15:17:12

Cheb писал(а): В OpenGL "полноэкранный" получают, выключив у окна все рамки и развернув окно на весь экран + поверх всех.


А на малине так низзя?

Cheb писал(а):Не, не, малина рендерит в совершенно отдельный фтагнообъект, на уровне драйвера, который окном не считается.


Т. е. у него нет контекста устройства?
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Cheb's Game Engine

Сообщение Cheb » 12.06.2017 16:23:46

А на малине так низзя?

У меня в линуксе (X11) в целом пока не получается полноэкранный режим, знания подобных древностей редкие и плохо гуглятся.
Хотя в теории можно, и нужно. Но отложено на потом.

Т. е. у него нет контекста устройства?

В смысле, контекста окна? Честного - нет. Специальными функциями Broadcom создаёшь фальшивый контекст окна, и скармливаешь его функции EGL, которая создаёт контекст рендера OpenGL, вместо контекста реального окна.

Добавлено спустя 21 час 52 минуты 54 секунды:
Вот это бесценная штука для hi-end оптимизации:
GL_NV_clip_space_w_scaling
Must have на будущее.

(почему: текущая парадигма - 120 - градусный втюпорт, пост-процесснутый до сферической проекции, НО неравномерность разрешения при этом такая (по краям густо, в центре пусто), что обязателен второй, 60-градусный, вьюпорт, накладенный на середину - иии, сцена фактически рендерится дважды. I'll deal with it, но любые расширения, позволяющие рендерить в два вьюпорта сразу, или, как вышеприведённое, вносящие корректирующее искажение разрешения - просто манна небесная.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Лекс Айрин » 13.06.2017 17:47:54

Cheb писал(а):В смысле, контекста окна? Честного - нет.


Контекст окна это частный случай. Речь идет о контексте графического устройства.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Re: Cheb's Game Engine

Сообщение Cheb » 14.06.2017 10:26:27

Не помню в иксах аналога виндовского контекста устройства. Есть PXVisualInfo, подозрительно похожий на pixel format descriptor. Есть хендл окна. Есть хендл дисплея.
А контекста устройства - не, не слышали.

Проблема в том, что аналогичные вещи могут называться совсем по другому.
Код: Выделить всё
  procedure TX11Framework.InitGLFirstStage;
  var
    depth, a, alpha: cint;
    colordepth: byte;
    num_config: EGLint;
    i, j: integer;
    success: boolean;
  begin
    if GLInitialized then Exit;

    InitOpenGL;
    case Mother^.GAPI.Mode of
      gapi_DeprecatedImmediateGL,
      gapi_GL21: begin
        //just like ZenGL does, but while ZenGL tries to find
        // largest depth buffer, we prefer none at all. FBO rulez.

        if Mother^.Debug.Verbose then AddLog('  First stage of GLX initialization...');

        VisualInfo:= nil;
        for a:= 0 to 1 do begin
          alpha:= a * 8;
          pfd[9]:= alpha;
          depth:= 0;
          while not Assigned(VisualInfo) and (depth <= 32) do begin
            pfd[13]:= depth;
            VisualInfo:= GlXChooseVisual(Display, screen, @(pfd[0]));
            if Mother^.Debug.Verbose then
              if Assigned(VisualInfo)
                then AddLog('  Visual found for alpha=%0, depth=%1',[alpha, depth])
                else AddLog('  No visual found for alpha=%0, depth=%1',[alpha, depth]);
            depth+= 8;
          end;
          if Assigned(VisualInfo) then begin
            assumedpfd.r:= pfd[3];
            assumedpfd.g:= pfd[5];
            assumedpfd.b:= pfd[7];
            assumedpfd.a:= alpha;
            assumedpfd.depth:= depth;
            break;
          end;
        end;
        if not Assigned(VisualInfo) then
          Die(MI_ERROR_CANTINITOPENGL,['glXChooseVisual() returned NULL']);
      end;
      gapi_GLES2: begin

        if Mother^.Debug.Verbose then AddLog('  First stage of EGL initialization...');

        GetMem(VisualInfo, sizeof(TXVisualInfo));
        XMatchVisualInfo(Display, screen, DefaultDepth(Display, screen), TrueColor, VisualInfo);
        if Mother^.Debug.Verbose
          then AddLog('  ..visual matched: depth=%0, bits_per_rgb=%1',[VisualInfo^.depth, VisualInfo^.bits_per_rgb]);

        colordepth:= DefaultDepth(display, screen);
        if Mother^.Debug.Verbose
          then AddLog('  ..default color depth=%0',[colordepth]);


        {$ifdef cpuarm}
        if Assigned(BroadcomHack) then begin
          if Mother^.Debug.Verbose then AddLog('    ..Raspberry Pi detected, postponing to after window creation.');
        end else
        {$endif}
        begin

          eDisplay:= eglGetDisplay(display);
          if eDisplay = EGL_NO_DISPLAY
            then Die(MI_ERROR_CANTINITOPENGL,['eglGetDisplay() returned EGL_NO_DISPLAY']);

          if Mother^.Debug.Verbose
            then AddLog('  ..display %0',[eDisplay]);

          if 0 = eglInitialize( eDisplay, @f_vmajo, @f_vmino )
            then Die(MI_ERROR_CANTINITOPENGL,[EGlErrorCodeToString(eglGetError())]);
          if Mother^.Debug.Verbose
            then AddLog('  ..EGL version %0.%1',[f_vmajo, f_vmino]);


          eglBindAPI(EGL_OPENGL_ES_API);
          CheckEGlError();

          //algorithm borrowed from ZenGL but simplified
          // as we don't need depth buffer nor MSAA
          Attr[ 0 ] := EGL_SURFACE_TYPE;
          Attr[ 1 ] := EGL_WINDOW_BIT;
          Attr[ 2 ] := EGL_DEPTH_SIZE;
          Attr[ 3 ] := 0;
          if colordepth > 16 then begin
            Attr[ 4  ] := EGL_RED_SIZE;
            Attr[ 5  ] := 8;
            Attr[ 6  ] := EGL_GREEN_SIZE;
            Attr[ 7  ] := 8;
            Attr[ 8  ] := EGL_BLUE_SIZE;
            Attr[ 9  ] := 8;
            Attr[ 10 ] := EGL_ALPHA_SIZE;
            Attr[ 11 ] := 0;
          end
          else begin
            Attr[ 4  ] := EGL_RED_SIZE;
            Attr[ 5  ] := 5;
            Attr[ 6  ] := EGL_GREEN_SIZE;
            Attr[ 7  ] := 6;
            Attr[ 8  ] := EGL_BLUE_SIZE;
            Attr[ 9  ] := 5;
            Attr[ 10 ] := EGL_ALPHA_SIZE;
            Attr[ 11 ] := 0;
          end;
          Attr[ 12 ] := EGL_NONE;

          for i:= 0 to 4 do begin
            depth:= i * 8;
            for a:= 0 to 1 do begin
              if (colordepth < 32) and (a > 0) then break;
              alpha := 8 * a;
              Attr[11]:= alpha;
              Attr[3]:= depth;

              if Mother^.Debug.Verbose
                then AddLog('  ..trying r%0 g%1 b%2 alpha%3 depth%4',
                  [Attr[5], Attr[7], Attr[9], alpha, depth]);

              eglChooseConfig(eDisplay, @Attr[0], @eConfig, 1, @num_config);
              success:= num_config = 1;

              if Mother^.Debug.Verbose then begin
                if success
                  then AddLog('    ..OK')
                  else AddLog('    ..nope.');
              end;

              if success then begin
                assumedpfd.r:= Attr[5];
                assumedpfd.g:= Attr[7];
                assumedpfd.b:= Attr[9];
                assumedpfd.a:= alpha;
                assumedpfd.depth:= depth;
                assumedpfd.rect:= Mother^.Display.WindowClientRect;
                break;
              end;
            end;
            if success then break;
          end;

          if not success then Die(MI_ERROR_CANTINITOPENGL, [RuEn(
            'Ни один из испробованных форматов пиксела не подошёл',
            'None of the tried pixel formats matched')]);
        end;
      end;
      else
        DieUnsupportedGLMode;
    end;
  end;

  procedure TX11Framework.InitGL;
  var
    rr, rg, rb, ra, rd, rs,  vhi, vmed: integer;
    num_config: EGLint;
    hr: integer;
    err: Cardinal;
    CtxAttr:array[0..3] of EGLint = (EGL_CONTEXT_CLIENT_VERSION,2,EGL_NONE,EGL_NONE);
  begin

    if GLInitialized then Exit;

    case Mother^.GAPI.Mode of
      gapi_DeprecatedImmediateGL,
      gapi_GL21: begin


        if Mother^.Debug.Verbose then AddLog('  Second stage of OpenGL initialization...');

        {Had we need to support FSAA, the pixel format selection would
         be much more elaborate. But as we use manual oversampling via
         rendering into an oversized texture instead, no FSAA is required.}

        if Mother^.Debug.Verbose then AddLog('    Creating rendering context...');

        RenderingContext:= glXCreateContext(Display, VisualInfo, nil, true);
        if not Assigned(RenderingContext) then begin
          RenderingContext:= glXCreateContext(Display, VisualInfo, nil, false);
          if Assigned(RenderingContext) then AddLog(RuEn(
            '  Не удалось создать контекст с прямым подключением. Возможно, аппаратное ускорение недоступно!',
            '  Failed to create direct rendering context. Hardware acceleration may not be available.'));
        end;
        if not Assigned(RenderingContext)
          then Die(MI_ERROR_CANTINITOPENGL,['glXCreateContext() returned NULL']);

        if Mother^.Debug.Verbose then AddLog('    Making the rendering context current...');

        if not glXMakeCurrent(Display, Windowhandle, RenderingContext)
          then Die(MI_ERROR_CANTINITOPENGL,['glXMakeCurrent() returned FALSE']);

        CheckGLVersion;

        glXGetConfig(Display, VisualInfo, GLX_RED_SIZE, rr);
        glXGetConfig(Display, VisualInfo, GLX_GREEN_SIZE, rg);
        glXGetConfig(Display, VisualInfo, GLX_BLUE_SIZE, rb);
        glXGetConfig(Display, VisualInfo, GLX_ALPHA_SIZE, ra);
        glXGetConfig(Display, VisualInfo, GLX_DEPTH_SIZE, rd);
        glXGetConfig(Display, VisualInfo, GLX_STENCIL_SIZE, rs);
        AddLog(MI_LOG_Screen_format, [
          Mother^.Display.WindowClientRect.Width, Mother^.Display.WindowClientRect.Height,
          rr, rg, rb, ra, rd, rs]);

        LoadOpenGLFunctions;

        GLInitialized:=Yes;

        if Assigned(@glXSwapIntervalSGI) then begin
          if glXSwapIntervalSGI(1) > 0
            then GivePeriodicWarning(1.0, 'unable-to-turn-vsync-off', MI_WARN_WARNING,
                  MI_SWAP_CRAP, [RuEn(
                 'OpenGL отказалась отключить Vsync.'
                ,'OpenGL refused to switch Vsync off.')])
            else
              if Mother^.Debug.Verbose then AddLog('Vsync disabled.');
        end
        else GivePeriodicWarning(7.0, 'unable-to-turn-vsync-off', MI_WARN_WARNING,
                  MI_SWAP_CRAP, [RuEn(
                   'Не поддерживается GLX_SGI_swap_control',
                   'GLX_SGI_swap_control not supported')]);
      end;
      gapi_GLES2: begin
        if Mother^.Debug.Verbose then AddLog('  Second stage of OpenGL ES initialization...');
        {$ifdef cpuarm}
        if Assigned(BroadcomHack) then begin
          BroadcomHack.InitEGL(eDisplay, eConfig, eSurface, eContext, assumedpfd);
        end else
        {$endif}
        begin
          eglGetError();

          eSurface:= eglCreateWindowSurface(eDisplay, eConfig, Windowhandle, @CtxAttr[0]);
            if eSurface = EGL_NO_SURFACE then Die(MI_ERROR_CANTINITOPENGL,['eglCreateWindowSurface() returned EGL_NO_SURFACE']);
          CheckEGlError();
            if Mother^.Debug.Verbose then AddLog('    ..surface %0',[eSurface]);

          eContext:= eglCreateContext(eDisplay, eConfig, nil, @CtxAttr[0]);
            if eContext = EGL_NO_CONTEXT  then Die(MI_ERROR_CANTINITOPENGL,['eglCreateContext() returned EGL_NO_CONTEXT']);
          CheckEGlError();
            if Mother^.Debug.Verbose then AddLog('    ..contexr %0',[eContext]);

        end;

        eglMakeCurrent(eDisplay, eSurface, eSurface, eContext);
        err := eglGetError();
        if err <> EGL_SUCCESS then Die(MI_ERROR_CANTINITOPENGL,[RuEn(
          'Не удалось сделать контекст текущим: ',
          'Failed to make the context current: '
          ) + EGlErrorCodeToString(err)]);

        CheckGLESVersion;

        AddLog(MI_LOG_SCREEN_FORMAT, [
                  assumedpfd.rect.Width, assumedpfd.rect.Height,
                  assumedpfd.r, assumedpfd.g, assumedpfd.b,
                  assumedpfd.a, assumedpfd.depth, 0]);

        CreateESFFPEmulationProgram;

      end;
      else
        DieUnsupportedGLMode;
    end;
  end;


Добавлено спустя 15 минут 1 секунду:
З.Ы. Всё от того, что использование X11 на десктопе слегка напоминает натягивание совы на глобус. API - это привет из дремучих восьмидесятых, и заточен был под удалённое выполнение, чем-то напоминающее виндовый remote desktop. То есть, программа выполняется на одной машине, а рендер происходит на другой, и все команды передаются по сети. Почему оно и называется "X сервером", кстати.

Т.е. в вышеприведённом коде, Display - не устройство или контекст оного, а хендл соединения с X сервером.

Так что первый шаг это
Код: Выделить всё
  procedure TX11Framework.InitDisplay;
  begin
    //Соединяемся с X сервером
    Display:= XOpenDisplay(nil);
    if not Assigned(Display) then Die(MI_CANT_CONNECT_TO_X_SERVER);
    screen:= XDefaultScreen(Display);
  end;

- а соединение может не удасться, например если запустить приложение по удалённому терминалу или из консоли, в кою переходишь по Ctrl + Alt + F1..F4. Чентра подоьбных изысков не поддерживает, естественно.
Аватара пользователя
Cheb
энтузиаст
 
Сообщения: 994
Зарегистрирован: 06.06.2005 15:54:34

Re: Cheb's Game Engine

Сообщение Лекс Айрин » 14.06.2017 10:49:31

Cheb писал(а):Есть хендл окна. Есть хендл дисплея.

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

Cheb писал(а):Проблема в том, что аналогичные вещи могут называться совсем по другому.


С этим приходится мириться((( Как и с тем, что его действительно может не быть.

Cheb писал(а):Т.е. в вышеприведённом коде, Display - не устройство или контекст оного, а хендл соединения с X сервером.

контекст устройства, собственно, есть его программное отображение. И не факт, кстати, что система отдает программисту доступ к нему. Вполне может предоставляться API.
Аватара пользователя
Лекс Айрин
долгожитель
 
Сообщения: 5723
Зарегистрирован: 19.02.2013 16:54:51
Откуда: Волгоград

Пред.След.

Вернуться в Разработки на нашем сайте

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 18

Рейтинг@Mail.ru