Я пытаюсь отобразить изоповерхность, построенную с использованием алгоритма движущихся кубов, который, я полагаю, создает набор треугольников. Однако я — полный любитель в графическом программировании, и я борюсь с пониманием нескольких методов их эффективного рисования.
Я хотел нарисовать все это за один вызов, используя что-то вроде конструкции glVertexPointer-glDrawElement. Последнее, однако, требует, чтобы я знал показатели, а я явно не знаю их. Более того, я на самом деле не совсем уверен в их назначении: я думаю, что они являются просто индексом, порядком их использования драйвером, а также способом экономии памяти, исключая одну и ту же вершину, появляющуюся несколько раз. ,
Итак, верно ли мое видение назначения индексов и как правильно решить мою проблему?
Если вам не нужны индексы, тогда … не используйте индексы! Да, они могут быть использованы для повышения эффективности рендеринга, если одна и та же вершина используется несколько раз. Но они совершенно необязательны.
Вызов дро, используемый при рендеринге без индексов, glDrawArrays()
, Это будет использовать вершины в вашем буфере вершин в их естественном порядке, основанном на типе примитива, переданного в вызов отрисовки. Например, с GL_TRIANGLES
, он нарисует треугольник с вершинами в позициях (0, 1, 2) в буфере, треугольник с вершинами (3, 4, 5) и т. д.
Таким образом, в вашем алгоритме изоповерхности вы можете просто вычислять 3 вершины каждый раз, когда вы генерируете треугольник, и добавлять их в список вершин, которые вы в конечном итоге сохраните в буфере вершин. Затем нарисуйте все это с glDrawArrays(GL_TRIANGLES, ...)
и это все, что есть.
Теперь в сетке, которая покрывает поверхность, эта же вершина совместно используется в среднем приблизительно 6 треугольниками (посмотрите на регулярную сетку, чтобы увидеть, как получается это число). Таким образом, если вы генерируете вершины отдельно для каждого треугольника, у вас будет одна и та же вершина примерно 6 раз, что приведет к значительному количеству ненужного использования памяти и времени для обработки вершин.
Вот где приходят индексы. Один из подходов, который вы можете использовать, заключается в том, что для каждого ребра сетки вы отслеживаете, была ли уже создана изоповерхностная вершина на ребре, и сохраняете ее индекс, если он был. Затем в любое время, когда вам требуется вершина для ребра сетки при генерации ваших треугольников, вы создаете новую вершину (с новым индексом), если у ребра еще нет вершины, или используете индекс уже созданной вершины. Затем вы сохраняете полученную последовательность индексов в буфере индекса и рисуете glDrawElements(GL_TRIANGLES, ...)
,
Небольшая вариация вышеописанного состоит в том, что сначала вы перебираете все ребра сетки, вычисляете все вершины для ребер, которые пересекают изоповерхность, и снова сохраняете индекс вершин для каждого из этих ребер. Затем, когда вы перебираете кубы сетки для генерации треугольников, вы можете просто взять индекс вершины с каждого из его пересекающихся ребер.
Если вы хотите нарисовать большую вещь одним вызовом, вы делаете это, предоставляя функцию рисования 2 вещи:
Который является массивом, как вы уже догадались, вершин. Координаты в трехмерном пространстве. Они не должны быть в каком-то определенном порядке.
Который является массивом индексов в массиве вершин.
Этот массив сообщает вашему драйверу порядок вершин (что с чем связано).
Вы должны загрузить все вершины, а затем превратить их в треугольники в массиве индекса.