Как реализовать плоское затенение в OpenGL без дублированных вершин? - PullRequest
3 голосов
/ 02 февраля 2020

Я пытаюсь визуализировать 3D призмы в LWJGL OpenGL с плоским затенением. Например, у меня есть индексированный куб:

enter image description here

У меня есть только 8 вершин в буфере вершин, которые я проиндексировал, как указано выше. Есть ли способ реализовать плоское нормальное затенение на кубе, как показано ниже? Я не хочу переписывать мои буферы вершин и индексов, чтобы включить дубликаты вершин, если это возможно.

1 Ответ

2 голосов
/ 02 февраля 2020

Если вам не нужны какие-либо другие атрибуты (например, координаты текстуры), есть возможность создать куб me sh с векторами нормалей лица, только по 8 вершинам. Используйте flat Interpolation qualifier для вектора нормалей.

Вершинный шейдер:

flat out vec3 surfaceNormal;

Фрагмент sahder:

flat out vec3 surfaceNormal;

При использовании квалификатора flat выходные данные вершинного шейдера не будут интерполированы , Значение, данное фрагментному шейдеру, является одним из атрибутов, связанных с одной вершиной примитива, Провоцирующая вершина .
Для GL_TRINANGLE примитива это либо последний или первая вершина. Это можно выбрать с помощью glProvokingVertex.

Выберите первую вершину:

glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);

Для порядка точек вашего куба me sh (изображение в вопросе)

  front      back

  1     3    7     5
   +---+      +---+
   |   |      |   |
   +---+      +---+
  0     2    6     4

необходимо установить следующие координаты вершины и векторы нормалей:

//  x   y   z   nx, ny, nz
    -1, -1, -1,   0, -1,  0,  // 0, nv front
    -1, -1,  1,   0,  0,  1,  // 1, nv top
     1, -1, -1,   0,  0,  0,  // 2
     1, -1,  1,   1,  0,  0,  // 3, nv right
     1,  1, -1,   0,  1,  0,  // 4, nv back
     1,  1,  1,   0,  0,  0,  // 5
    -1,  1, -1,   0,  0, -1,  // 6, nv bottom
    -1,  1,  1,  -1,  0,  0,  // 7, nv left 

Определить индексы таким образом, чтобы вершины 7, 3, 0, 4, 6, 1 - первая вершина для обоих треугольников слева, справа, спереди, сзади, снизу и сверху куба:

0, 2, 3,   0, 3, 1, // front
4, 6, 7,   4, 7, 5, // back
3, 2, 4,   3, 4, 5, // right
7, 6, 0,   7, 0, 1, // left
6, 4, 2,   6, 2, 0, // bottom 
1, 3, 5,   1, 5, 7  // top

Нарисуйте 12 треугольных примитивов. Например:

glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);

...