Не удается отобразить импортированную текстурированную модель FBX с помощью OpenGL - PullRequest
0 голосов
/ 22 мая 2019

Я пытаюсь визуализировать текстурированную модель, используя данные из файла FBX с OpenGL, но координаты текстуры неверны.

Сводка данных модели, предоставленных файлом FBX, включает UV-координаты для ссылки на текстуру.которые сопоставлены с вершинами модели.

  • Количество вершин: 19895
  • Количество PolygonVertexIndices: 113958

  • КоличествоUVs: 21992

  • Количество UVIndices: 113958

Совершенно очевидно, что модель имеет 113958 интересующих вершин.Насколько я понимаю, «PolygonVertexIndices» указывают на «Вершины», а «UVIndices» указывают на значения «UV».

Я использую glDrawElements с GL_TRIANGLES для визуализации модели, используя «PolygonVertexIndices» в качестве GL_ELEMENT_ARRAY_BUFFER и"Вершины" как GL_ARRAY_BUFFER.Сама модель визуализируется правильно, но текстурирование далеко.

Поскольку я использую «PolygonVertexIndices» для GL_ELEMENT_ARRAY_BUFFER, насколько я понимаю, такая же индексация произойдет для массива атрибутов для UV-координат.Я не думаю, что OpenGL может использовать экспортированные UV-индексы, поэтому я создаю новый буфер для UV-значений размера 113958, который содержит соответствующие UV-значения, соответствующие PolygonVertexIndices.

Т.е. для вершины i в[0: 113958], я делаю

new_UVs[PolygonVertexIndices[i]] = UVs[UVIndices[i]]

и затем связываю new_UVs как массив атрибутов UV-координат.

Тем не менее, текстурирование явно неверно.Мое мышление не так?

Мне кажется, что я неправильно понимаю, как работать с УФ-буферами при использовании индексированного рендеринга OpenGL glDrawElements.Также кажется неправильным расширять мой UV-буфер, чтобы он соответствовал количеству вершин до 113958, поскольку преимущество glDrawElements должно заключаться в том, чтобы сохранять дублирующиеся значения вершин, а UV-буфер, вероятно, будет содержать дубликаты.

Было бы лучше выполнитьиндексирование и расширение «Вершин» и «UV» до размера 113958 и простое использование glDrawArrays с точки зрения производительности?

Любые мысли / идеи / предложения приветствуются.

Ответы [ 2 ]

0 голосов
/ 23 мая 2019

Предыдущий пост относится только к OpenGL до 4.3. Если у вас 4.3+, то вполне возможно использовать несколько индексов для вершин (хотя может не самый эффективный способ визуализации геометрии - это зависит от вашего варианта использования).

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

in int vs_vertexIndex;
in int vs_uvIndex;

Убедитесь, что вы указали эти параметры с помощью glVertexArrayAttribIFormat (ПРИМЕЧАНИЕ: «I» важно !! Также обратите внимание, что glVertexAttribIFormat также будет работать).

Следующий шаг - связать вершины и UV-массивы как SSBO

.
layout(std430, binding = 1) buffer vertexBuffer
{
    float verts[];
};
layout(std430, binding = 2) buffer uvBuffer
{
    float uvs[];
};

И теперь в вашем main () вы можете извлечь правильный vert + uv следующим образом:

vec2 uv = vec2(uvs[2 * vs_uvIndex], 
               uvs[2 * vs_uvIndex + 1]);
vec4 vert = vec4(verts[3 * vs_vertexIndex], 
                 verts[3 * vs_vertexIndex + 1], 
                 verts[3 * vs_vertexIndex + 2], 1.0);

В этот момент пропустите glDrawElements и просто используйте вместо него glDrawArrays (где число вершин - это число индексов в вашей сетке).

Я не говорю, что это самый быстрый подход (построение ваших собственных проиндексированных элементов, вероятно, является наиболее эффективным). Однако есть случаи, когда это может быть полезно - обычно, когда у вас есть данные в таком формате, как FBX / USD / Alembic, и вам необходимо обновить (например) вершины и нормали для каждого кадра.

0 голосов
/ 23 мая 2019

Вы правы, что OpenGL поддерживает только один индексный буфер.

Ваш UV-код назначения неверен.Вы не можете просто скопировать UV, поскольку вершины и массивы UV имеют разные размеры.Что вам нужно сделать, это создать дубликаты вершин для тех, которые имеют несколько UV и назначить UV для каждой копии.

Думайте о UV и координатах вершин как о единой структуре, содержащей и то, и другое, и работайте с этим.Пример:

struct Vertex
{
   float3 position;
   float2 UV;
};

std::vector<Vertex> vertices;
// Fill "vertices" here.

Это также позволяет легко чередовать данные, выгружать весь полученный массив в один VBO и отображать его.

Would it be better to performing the indexing and expand both "Vertices" and "UVs" to be of size 113958 and simply use glDrawArrays in terms of performance?

Это не вопрос производительности,но буквально единственный путь.

...