С наступающим Новым годом! Форум программистов, компьютерный форум, киберфорум
Наши страницы
OpenGL
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.63/8: Рейтинг темы: голосов - 8, средняя оценка - 4.63
snake32
1665 / 1117 / 197
Регистрация: 26.02.2009
Сообщений: 4,136
Записей в блоге: 5
1

Архитектура. Куда прилепить VAO?

05.12.2013, 12:23. Просмотров 1403. Ответов 11
Метки нет (Все метки)

Добра всем!

Ломаю голову над собственной архитектурой недодвижка на OpenGL 3.3.
Есть объект Mesh, который содержит вершины, нормали и прочие VBO. Также этот объект содержит Материал, который состоит из шейдера, текстур, ну и других uniform данных. В относительно новом OpenGL 3.3 вроде как обязательно использовать VAO. Изначально я предположил что VAO должен лежать внутри Mesh'a, так как VAO зависит от VBO и шейдера, который лежит в материале, который в свою очередь уже есть в меше.
Вот упрощённые классы:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TMesh = class
  vbo:TVBO;
  mat:TMaterial;
  vao:TVAO;
  procedure Draw;
end;
 
TMaterial = class
  Unifroms:TUniforms;
  Textures:TTextures;
  Shader:TShader;
end;
 
// отрисовка
for i:=0 to Meshes.Count-1 do
  Meshes[i].Draw();
Но, допустим, я хочу построить тени(shadow maps). Для этого я должен отрисовать один и тот же Mesh 2 раза с разным материалом. Один в буфер глубины от источника света, второй - нормальный вид. Получается я должен изменить Материал, а в месте с ним и VAO 2 раза за кадр для каждого меша который отбрасывает тень. Собственно польза от такого использования VAO нулевая. А хотелось бы не менять его +100500 раз.

Пока придумал следующее.
Вариант 1: Mesh может содержать не единственную копию Material+VAO, а целый сарафан - список/массив таких элементов:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TMatVAO = class // как его адекватно обозвать не знаю
  mat:TMaterial;
  vao:TVAO;
  procedure Draw( mesh:TMesh );
end;
TMesh = class
  vbo:TVBO;
  matvao:TList<TMatVAO>;
  procedure Draw( indexmatvao:integer );
end;
 
// отрисовка в zBuffer для теней
for i:=0 to Meshes.Count-1 do
  Meshes[i].Draw(1);
// нормальная отрисовка
for i:=0 to Meshes.Count-1 do
  Meshes[i].Draw(0);
Вариант 2: Вообще устроить демократию сделать равноправие mat,vao и mesh. И объединить их в объект_для_отрисовки:
TMesh = class
vbo:TVBO;// теперь содержит только буфера(вершины, нормали и тп)
end;

TRenderObject = class
mat:TMaterial;
mesh:TMesh;
vao:TVAO;
procedure Draw;
end;

Shadows:TList<TRenderObject>;
Default:TList<TRenderObject>;
// отрисовка в zBuffer для теней
for i:=0 to Shadows.Count-1 do
Shadows[i].Draw;
// нормальная отрисовка
for i:=0 to Default.Count-1 do
Default[i].Draw;[/DELPHI]
Этот вариант пока ещё толком не продумал. Кажется более универсальным...хотя...
Может ли кто сказать как лучше сделать сточки зрения архитектуры. Или может подсказать как в современных движках это реализовано. Или поделиться своими наработками с OpenGL не ниже 3.3.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
05.12.2013, 12:23
Ответы с готовыми решениями:

Несколько vao в один vao
В общем, как объединить несколько уже существующих вао в один ? У них...

Id вершины + VAO
В общем помню давно читал что есть возможность добавлять вершину к полигону по...

Не рендерится VAO
Имеется простенькая программа, состоящая только из main.cpp: #include...

VAO, фальш-старт
Ребята, не могу запустить, какая то мелочь, ни как не вижу... void...

Не работает vao и vbo
Здравствуйте, собственно вопрос, а почему когда я нахожу примеры с vao и vbo,...

11
SEvg
85 / 85 / 1
Регистрация: 16.10.2012
Сообщений: 305
05.12.2013, 19:57 2
Цитата Сообщение от snake32 Посмотреть сообщение
vbo:TVBO;// теперь содержит только буфера(вершины, нормали и тп)
Вроде во всех движках так и сделано.
Меш - содержит только геометрию.
Материал - текстуры, шейдер и прочее...

На сцене располагаются, узлы сцены, которые содержат в себе меш (или мешы), материал (или материалы), так же матрицы трансформации. Как то так...

Да, для теней во многих случаях используют другой меш, упрощённый...
1
snake32
1665 / 1117 / 197
Регистрация: 26.02.2009
Сообщений: 4,136
Записей в блоге: 5
06.12.2013, 20:52  [ТС] 3
Лады. Выбираем вариант 2. Итого:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TMaterial = class
  Unifrorms:TList<TUniform>;
  Textures:TList<TTexture>;
  Shader:TShader;
end;
 
TMesh = class
  VBOs:TList<TVBO>;
end;
 
TRenderObject = class
  Mesh:TMesh;
  Material:TMaterial;
  VAO:TVAO;
end;
Теперь можно создать класс TPass отвечающий за проход, например отрисовка всей сцены в теневом буфере, или отрисовать в буфер выбора, или нормальная отрисовка. Причём для теней и буфера выбора материал для всех объектов будет один и тот же. Думаю, логично выделить место в классе TPass для ссылки под материал.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
TPass = class
  RObjs: TList<TRenderObject>;// список всех объектов которые должны быть
  Material:TMaterial;// если он nil то материал для отрисовки будет браться из TRenderObject
  FrameBuffer:GLuint;// куда будет идти отрисовка
  procedure Draw;
end;
 
procedure TPass.Draw;
begin
  if( RObjs.Count > 0 )and( Modify )then
  begin
     Modify := false;// не для всех проходов нужно обновлять данные каждый кадр
     glBindFramebuffer( GL_FRAMEBUFFER, FrameBuffer );
     // здесь дополнительные настройки - можно сделать виртуальной ф-ией
     for i:=0 to RObjs.Count-1 do
       RObjs[i].Draw( Material );
  end;
end; 
 
var 
Passes:TList<TPass>;
 
// полная отрисовка кадра( всех проходов )
for i:=0 to Passes.Count-1 do
  Passes[i].Draw;
Но вот что меня беспокоит. Получается что TRenderObject будет создаваться для каждого прохода свой и если у нас используются все N прохода - это на каждый объект придётся создать по N TRenderObject'a. Единственное что утешает это его размер - всего лишь 2 ссылки и GLuint для VAO.

Так, подобрались к T3DObject - базовый класс любого объекта на сцене. Что же он может содержать?:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
T3DObject = class
  BBox:TBBox;
  Node:TOctNode; // какому узлу октодерева принадлежит этот объект
  // Пока у меня нет его
  Mesh:TMesh;
  Material:TMaterial;
  Flags;TFlags32;// думаю в нём разместить флаги, 
  // которые будут говорить какому проходу  
  // может принадлежать конкретный объект.
  Matrix:TMat4; // локальная матрица модели
  procedure Load( engine:TEngine ); virtual;
end;
Загрузка объекта будет происходить в недрах движка, как только потребуется. Всё выше описанное только наброски. Чтобы смотреть куда двигаться при разработке недодвижка. Ещё не ясно куда лепить LODы. И когда и как их выбирать. Пока хотя бы нужно оживить только написанное. Может прояснится в процессе разработки.
Там ещё гемор с юниформами. Стека матриц больше нет - теперь нужно самому придумать альтернативу. Вообщем надеюсь на выходных чтонить более-менее рабочее сварганить.
0
Ух ты!
Ах ты! All we Astronautы
121 / 98 / 1
Регистрация: 20.10.2012
Сообщений: 373
Записей в блоге: 2
10.12.2013, 16:16 4
посмотри в сторону компонентной модели объекта сцены (игры) ближайший аналог - GameObject из юнити, а то что ты делаешь сейчас я так понял это "god object" ?
0
snake32
1665 / 1117 / 197
Регистрация: 26.02.2009
Сообщений: 4,136
Записей в блоге: 5
10.12.2013, 22:49  [ТС] 5
Цитата Сообщение от Ух ты! Посмотреть сообщение
посмотри в сторону компонентной модели объекта сцены (игры) ближайший аналог - GameObject из юнити
Нашёл это: http://docs.unity3d.com/Documentation/ScriptReference/GameObject.html
Описание методов это не то что мне нужно. Мне бы внутренности посмотреть как оно там всё связано.

Цитата Сообщение от Ух ты! Посмотреть сообщение
а то что ты делаешь сейчас я так понял это "god object"
Нет. Это любой может сделать. Хотелось бы распределить обязанности по классам.
0
Ух ты!
Ах ты! All we Astronautы
121 / 98 / 1
Регистрация: 20.10.2012
Сообщений: 373
Записей в блоге: 2
11.12.2013, 16:58 6
>Мне бы внутренности посмотреть как оно там всё связано.
C юнити не получится по понятным причинам ) можно лишь строить версии.

Но из того что можно посмотреть, есть еще один двиг, правда не знаю как там насчет компонентной модели. Но его исходники я как-то качал в полном объеме, он весь как на ладони. К тому же если я ничего не путаю он написан на Delphi / Lazerus. Двиг называется LEAF2 мб это актуальная версия сорсов - http://leafproject.com.sapo.pt/LEAF2-Source.rar

>Хотелось бы распределить обязанности по классам.
Правильно, каждый должен заниматься своим делом, но
в рез-те все эти возможности будет подключать или не подключать к себе в качестве компонентов - базовый игровой класс, на каркасе которого ты и будешь строить новые игровые сущности.
1
snake32
1665 / 1117 / 197
Регистрация: 26.02.2009
Сообщений: 4,136
Записей в блоге: 5
03.02.2014, 15:48  [ТС] 7
Апну темку. На выходных наконец-то сделал менеджер ресурсов(перестал качать борща и е-50 в танках). Сделал на основе двусвязных списков, так как сложность вставки и удаления = O(1). Поиск O(N) - не лучший показатель, но как бы не критично. Используется поиск только при загрузки объекта и то не всегда. Генерация и удаление ID'шников для всех OpenGL объектов (текстуры, семплеры, буфера, ВАО, шейдеры) теперь происходит пачками. То есть за одни вызов сразу n ID. При этом уже не нужные не удаляются а возвращаются в список свободных IDs

С VAO пока тупо определил статичный массив в T3DObject. Который переименовал в TRenderObject. Отрисовал скайбокс и квад с текстурой, выловил утечки памяти. Сейчас код отрисовки объекта таков:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
procedure TRenderObject.Draw( var u:TUniformArray; delta:single; const pass:TPass );
  var i:integer;
      a:TAttribute;
      p:TBufferAttrParam;
      m:TMaterial;
      pe:TPassEnum;
begin
  Bind( u, delta );
  // применяется материал прохода если он есть
  if pass.Material = nil then m := FMaterial
                         else m := pass.Material;
 
  m.Bind( u, delta, FEngine );
  pe := pass.GetEnum; // выбирается индекс VAO для текущего прохода
 
  if FVAOs[pe] = nil then
  begin
    // создаём новый VAO так как он ещё не создан
    FVAOs[pe] := FEngine.Resources.VAOs.Get; //менеджер ресуросов даёт свежий VAO
    FVAOs[pe].Bind;
    for i:=0 to Length( m.Shader.Attributes )-1 do //цикл по всем атрибутам текущего шейдера в материале
    begin
      a := m.Shader.Attributes[i];
      FMesh.GetAttrParam( p, a.enum ); // меш заполняет все характеристики буфера атрибута
      p.buffer.Bind;
      glEnableVertexAttribArray( a.location );
      glVertexAttribPointer( a.location, p.number, p.format, p.normalized, p.stride, PGLvoid( p.offset ) );
    end;
    if FMesh.GetIndexBuffer<>nil then
      FMesh.GetIndexBuffer.Bind;
  end else
    FVAOs[pe].Bind;// если такой VAO есть - просто биндим его
 
  FMesh.Render;
  m.UnBind( u, FEngine );
end;
В планах:
- прикрутить загрузку из 3ds. Сейчас это невозможно так как сам TRenderObject должен иметь структуру дерева. В одном 3дс несколько мешей, которые иерархично связаны между собой.
- запилить наконец проход для теней, отладить, выявить архитектурно кривые места, исправить, и отрисовать красивую сцену с тенями.
0
programina
2053 / 608 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
04.02.2014, 11:42 8
Можно и без. VAO обойтись, я например его вообще не использую.
0
snake32
1665 / 1117 / 197
Регистрация: 26.02.2009
Сообщений: 4,136
Записей в блоге: 5
04.02.2014, 14:27  [ТС] 9
Цитата Сообщение от programina Посмотреть сообщение
Можно и без. VAO обойтись, я например его вообще не использую.
Слышал что в core profile 3.3 он обязателен. Пруфа быстро найти не удалось. Но в любом случае посмотрите сколько заменяет команд отрисовки одного объекта один бинд VAO. Это существенно разгружает CPU.
0
programina
2053 / 608 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
04.02.2014, 17:10 10
Цитата Сообщение от snake32 Посмотреть сообщение
Но в любом случае посмотрите сколько заменяет команд отрисовки одного объекта один бинд VAO
Это разве много?
C++
/* ~ */
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vb[id]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
 
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvb[id]);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
 
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, nb[id]);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eb[id]);
 
glDrawElements(GL_TRIANGLES, m[id], GL_UNSIGNED_INT, (void*)0);
 
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
0
snake32
1665 / 1117 / 197
Регистрация: 26.02.2009
Сообщений: 4,136
Записей в блоге: 5
04.02.2014, 18:27  [ТС] 11
Цитата Сообщение от programina Посмотреть сообщение
Это разве много?
А что сразу не видно?
Ок, 3 атрибута. На каждый из них 4 вызова ф-ии(glEnableVertexAttribArray, glBindBuffer, glVertexAttribPointer, glDisableVertexAttribArray)

То есть 12 вызовов. И ещё один бинд IBO. Итого 13.
Про glDrawElements забыл. 14 вызовов на отрисовку одного объекта. Вроде кажется не много. Но допустим хотим показать 1000 объектов при этом хотим не менее 30 фпс:
14*1000*30 = 420 000 вызовов в секунду должен успеть выдать CPU
Вариант с VAO(vao.Bind; glDrawElements):
2*1000*30 = 60 000

Как бы в 7 раз на стандартном кол-ве атрибутов. ИМХО стоит заморочится.
1
programina
2053 / 608 / 41
Регистрация: 23.10.2011
Сообщений: 4,468
Записей в блоге: 2
05.02.2014, 10:01 12
snake32, если дело в кол-ве, то надо будет посмотреть.
0
05.02.2014, 10:01
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.02.2014, 10:01

VAO, VBO и их правильное применение
Всех с наступившем, в общем меня интересует вопрос как правильно использовать...

Мультитекстуринг с VAO или VBO
Здравствуйте, проблема состоит в том , что не могу совместить мультитекстуринг...

Работа с VAO,VBO и glVertexAttribPointer
Здравствуйте, ЯП C++ Имеется функция рисующая все элементы из vector'a У...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru