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

Попытка переключить режим рисования на GL_LINE, GL_LINE_STRIP или GL_LINE_LOOP, когда данные вершин вашего куба создаются в основном для использования с GL_TRIANGLES, дает некоторые интересные результаты, но ни один из них не дает хорошего каркасного представления куба.

Есть ли способ построить данные вершины и индекса куба, чтобы простое переключение режима рисования между GL_LINES/GL_LINE_STRIP/GL_LINE_LOOP и GL_TRIANGLES давало хорошие результаты? Или это единственный способ получить хороший каркас для воссоздания вершин специально для использования с одним из режимов линий?


person Caustic    schedule 05.09.2014    source источник
comment
Было бы приемлемо иметь два массива индексов? Вам не нужно копировать фактические данные вершин, но у вас есть отдельные массивы индексов, которые вы используете в зависимости от того, рисуете ли вы линии или треугольники.   -  person Reto Koradi    schedule 05.09.2014
comment
Это лучшее решение, чем отсутствие решения вообще.   -  person Caustic    schedule 05.09.2014
comment
Если вы не хотите использовать устаревшие функции, вы можете указать несколько пограничных флагов. :)   -  person genpfault    schedule 05.09.2014


Ответы (1)


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

Чтобы реализовать это, вы можете использовать два разных буфера индекса (GL_ELEMENT_ARRAY_BUFFER). Или, более элегантно, ИМХО, используйте один буфер и храните в нем оба набора индексов. Скажем, вам нужно triIdxCount индексов для рендеринга треугольников и lineIdxCount для рендеринга линий. Затем вы можете настроить индексный буфер с помощью:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
             (triIdxCount + lineIdxCount) * sizeof(GLushort), 0,
             GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
                0, triIdxCount * sizeof(GLushort), triIdxArray);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
                triIdxCount * sizeof(GLushort), lineIdxCount * sizeof(GLushort),
                lineIdxArray);

Затем, когда вы будете готовы рисовать, настройте все свое состояние, включая привязку индексного буфера (в идеале, используя VAO для всех настроек состояния), а затем выполните рендеринг условно:

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
if (renderTri) {
    glDrawElements(GL_TRIANGLES, triIndexCount, GL_UNSIGNED_SHORT, 0);
} else {
    glDrawElements(GL_LINES, lineIdxCount, GL_UNSIGNED_SHORT,
                   triIndexCount * sizeof(GLushort));
}

С точки зрения использования памяти наличие двух наборов индексов требует умеренных затрат. Фактические данные атрибутов вершин обычно намного больше, чем данные индекса, и ключевым моментом здесь является то, что данные атрибутов не реплицируются.

Если вы не хотите рендерить линии строго, а просто нуждаетесь в каркасном рендеринге, есть и другие варианты. Например, есть элегантный подход (сам никогда его не реализовывал, но он выглядит умным), когда вы рисуете пиксели только близко к границе полигонов и отбрасываете внутренние пиксели во фрагментном шейдере на основе расстояния до края полигона. Этот вопрос (где я дал ответ) подробно описывает подход: Каркасный шейдер — проблема с барицентрическими координатами при использовании общих вершин.

person Reto Koradi    schedule 05.09.2014