V
V
Vladimir Semenyakin2015-10-04 03:49:46
3D
Vladimir Semenyakin, 2015-10-04 03:49:46

How to properly draw game scene in openGL?

Most sensible openGL lessons come down to drawing a colored triangle. The maximum that they tell is how to load the model. Examples of such introductory lessons: here , here is another lesson on Google code and here (the last one is a detailed introductory lesson, alas, however, not going further than the same triangle).
The problem is that as soon as the writing of the renderer of a real game scene with more than one object begins, problems arise and I, for example, could not find normal lessons on this matter.

Lyrics about the question

Примечание: Дальше я буду называть объектом "экземпляр" модели. В случаи с играми, объектом будет то, что игрок видит как юнит. Ясно, что в сцене могут быть несколько юнитов одного типа (соответственно, это будет несколько объектов одной модели).
На текущем уровне понимания openGL я вижу следующие способы нарисовать сцену с более чем одним объектом модели:
1. Неэффективный по скорости. Вызывается draw одного и того же VAO с вершинами модели, но с разными матрицами. Вызов draw, как я понимаю, дорогая операция - требует явной синхронизации чего-то там и прочих неприятных вещей. Если для каждого объекта вызывать draw (которых в RTS, например, могут быть тысячи) - работать такой код может намного дольше, чем код, в который мы скопом передаём все вершины сцены.
Эта техника обсуждалась тут, тут и тут... Везде, короче.
2. Неэффективный по памяти. Можно отправить на видеоустройство громадный VAO, хранящий все вершины мира - с дублированием вершин для каждого объекта модели. Таким образом треугольники всех объектов пойдут на отрисовку одновременно и этот процесс будет легче распараллелить. Но таким образом видеопамять будет забивать по самое не хочу бессмысленно дублируемыми данными. Такой метод, думаю, вообще нигде не используется.
3. Индексирование. В openGL есть возможность индексирования вершин. В случаи использования этого метода, вместо атрибутов, привязываемых через VAO, можно отсылать массив индексов вершин, по которым будут формироваться треугольники объектов. В этом случаи дублирование данных всё равно будет - дублирование элементов индексных массивов (см. картинку, индексы в массиве мировых моделей будут от 0 до N, где N - это количество вершин модели). Но места индексы будут занимать меньше места.
16b1fc7954d7466893d5869989532bb0.png
Ещё одна проблема - отсылка информации о матрицах преобразования для объектов (на картинке - строчка transforms). Ясно что передавать матрицу с каждой вершиной будет избыточно (для каждой вершины одного объекта модели используется одна и та же матрица преобразования). С другой стороны, если опять-таки сделать что-то вроде индексации. То есть отсылать матрицы в большом UBO и к индексам вершин привязывать индекс матрицы преобразования соответствующей модели (не уверен что знаю как это сделать). К тому же, так как объекты могут создаваться и исчезать достаточно активно в течение сцены, использование UBO может тормозить процесс рендера (насколько я понимаю, UBO грузить на видяху дольше чем VAO).

The question itself ... More precisely, questions.
1. Is the draw command really that expensive? Logically, there should be a road - after all, if we draw the scene in small portions of several hundred triangles instead of drawing millions of triangles of the entire scene at once, drawing is more difficult to parallelize.
2. If the answer to the first question is "Yes", then is there a drawing command in openGL that takes an array of index gaps as input (in the format "start index - end index") and calls the pipeline for these gaps in the same way that glDrawArrays is called for one VAO , defined by consecutive vertices not spaced apart in memory?.. Damn, it seems to sound incomprehensible at all... I mean something like this:
The code

// В следующей строчка - код отсылки вершин моделей. Скорее всего, в едином VAO
// или UBO.
. . .
// Смещения вершин на отрисовку и количество вершин в каждом наборе.
int worldObjectRanges[][] = {{0, model1_VertexCount}, {0, model0_VertexCount },
{ model0_VertexCount, model1_VertexCount },
{ model0_VertexCount + model1_VertexCount, model2_VertexCount }};
matrix worldObjectTransforms[] = { obj0Trans, obj1Trans, obj2Trans, obj3Trans };
// В следующей строчке кода идёт отправка трансформаций моделей
// worldObjectTransforms (и, кстати, ещё какой-нибудь уникальной для моделей
// сопроводительной инфы) - предположительно через UBO.
. . .
// Тут делается магия. Пайплайн вызывается для всех вершин, находящихся
// в промежутках заданных через worldObjectRanges. При нужно чтобы в вершинный
// шейдер передавался индекс элемента worldObjectRanges, на основе которого шейдер
// был вызван для данной вершины (фактически, это будет индекс объекта); это нужно
// чтобы по индексу из UBO с трансформациями моделей получить трансформацию
// рисуемой в шейдере модели.
glDrawIndexedRanges(worldObjectRanges);

3. Well, and if all my thoughts are complete garbage - where can I read about techniques for effectively rendering real scenes with many models using openGL?
Lyrics about the super task

P.S.: Планирую поднять ещё несколько тем по openGL. В общем и целом, темы перечисленны в этом вопросе. После того, как чуть разберусь, планирую написать учебную статью (возможно, цикл статей) на хабре. Делать это буду по схеме, при которой комментирование статьи знающими людьми будет приводить к модификации статьи (схему такой работы я описывал в этом вопросе этом вопросе).
Помимо меркантильной пользы "самому разобраться", надеюсь заполнить циклом пробел, который имеется в учебных темах по openGL. Дело в том, что, как упоминалось в начале этого вопроса, есть простые статьи, есть сразу статьи очень сложные (чтобы понять такие нужно курить openGL не один год), а промежуточных нету. Это дело нужно исправлять.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
A
Andryukha, 2015-10-04
@semenyakinVS

triplepointfive.github.io/ogltutor/index.html

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question