2015-06-24 7 views
2

У меня проблема с нормалями OpenGL. Я представляю модель дракона, но у меня есть некоторые странные нормальные узоры.OpenGL: странная нормальная рендеринг

Вот скриншот из моего рендеринга: render_screen

это мои методы создания буфера:

glGenVertexArrays(1, &VAO); 
    glBindVertexArray(VAO); 

    if (has_position) { 
     glGenBuffers(1, &vertex_buffer); 
     glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); 
     glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float), vertices.data(), GL_STATIC_DRAW); 
     glEnableVertexAttribArray(kVertexArray); 
     glVertexAttribPointer(kVertexArray, 3, GL_FLOAT, GL_FALSE, 0, nullptr); 
    } 

    if (has_normal) { 
     glGenBuffers(1, &normal_buffer); 
     glBindBuffer(GL_ARRAY_BUFFER, normal_buffer); 
     glBufferData(GL_ARRAY_BUFFER, normals.size() * 3 * sizeof(float), normals.data(), GL_STATIC_DRAW); 
     glEnableVertexAttribArray(kNormalArray); 
     glVertexAttribPointer(kNormalArray, 3, GL_FLOAT, GL_FALSE, 0, nullptr); 
    } 

    if (has_tex_coord) { 
     glGenBuffers(1, &tex_coord_buffer); 
     glBindBuffer(GL_ARRAY_BUFFER, tex_coord_buffer); 
     glBufferData(GL_ARRAY_BUFFER, tex_coords.size() * 3 * sizeof(float), tex_coords.data(), GL_STATIC_DRAW); 
     glEnableVertexAttribArray(kTexCoordArray); 
     glVertexAttribPointer(kTexCoordArray, 3, GL_FLOAT, GL_FALSE, 0, nullptr); 
    } 

    if (has_index) { 
     glGenBuffers(1, &index_buffer); 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer); 
     glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * 3 * sizeof(unsigned short), indices.data(), GL_STATIC_DRAW); 
     glBindVertexArray(0); 
    } 

и рисовать: glDrawElements(GL_TRIANGLES, indices.size() * 3, GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

Wavefront OBJ метод погрузчик:

bool Loadfs() { 
    CVector3<float> vertex; 
    CVector3<unsigned short> vindex, tindex, nindex; 

    while(file_stream->offset_ < file_stream->size_) { 
     if (file_stream->buffer_[file_stream->offset_] == '#') { 
      char comment[512] = {0}; 
      file_stream->ReadLine(comment); // check return code -> "its local variable return address" 
      file_stream->SkipLine(); 
     } 
     else if (file_stream->buffer_[file_stream->offset_] == 'v') { 
      file_stream->offset_++; 

      if (file_stream->buffer_[file_stream->offset_] == ' ') { 
       has_position = true; 
       file_stream->offset_++; 
       file_stream->SkipWhiteSpace(); 

       vertex.x = file_stream->ReadFloat(); 
       file_stream->SkipWhiteSpace(); 

       vertex.y = file_stream->ReadFloat(); 
       file_stream->SkipWhiteSpace(); 

       vertex.z = file_stream->ReadFloat(); 
       file_stream->SkipLine(); 

       vertices.push_back(vertex); 
      } 
      else if (file_stream->buffer_[file_stream->offset_] == 'n') { 
       has_normal = true; 
       file_stream->offset_++; 
       file_stream->SkipWhiteSpace(); 

       vertex.x = file_stream->ReadFloat(); 
       file_stream->SkipWhiteSpace(); 

       vertex.y = file_stream->ReadFloat(); 
       file_stream->SkipWhiteSpace(); 

       vertex.z = file_stream->ReadFloat(); 
       file_stream->SkipLine(); 

       normals.push_back(vertex); 
      } 
      else if (file_stream->buffer_[file_stream->offset_] == 't') { 
       has_tex_coord = true; 
       file_stream->offset_++; 
       file_stream->SkipWhiteSpace(); 

       vertex.x = file_stream->ReadFloat(); 
       file_stream->SkipWhiteSpace(); 

       vertex.y = file_stream->ReadFloat(); 
       file_stream->SkipWhiteSpace(); 

       vertex.z = file_stream->ReadFloat(); 
       file_stream->SkipLine(); 

       tex_coords.push_back(vertex); 
      } 
     } 
     else if (file_stream->buffer_[file_stream->offset_] == 'f') { 
      has_index = true; 
      file_stream->offset_++; 
      file_stream->SkipWhiteSpace(); 

      // 
      if (has_position) { 
       vindex.x = file_stream->ReadShort(); 
      } 
      if (has_tex_coord) { 
       file_stream->offset_++; 
       tindex.x = file_stream->ReadShort(); 
      } 
      if (has_normal) { 
       file_stream->offset_++; 
       nindex.x = file_stream->ReadShort(); 
      } 
      file_stream->SkipWhile(' '); 

      // 
      if (has_position) { 
       vindex.y = file_stream->ReadShort(); 
      } 
      if (has_tex_coord) { 
       file_stream->offset_++; 
       tindex.y = file_stream->ReadShort(); 
      } 
      if (has_normal) { 
       file_stream->offset_++; 
       nindex.y = file_stream->ReadShort(); 
      } 
      file_stream->SkipWhile(' '); 

      // 
      if (has_position) { 
       vindex.z = file_stream->ReadShort(); 
      } 
      if (has_tex_coord) { 
       file_stream->offset_++; 
       tindex.z = file_stream->ReadShort(); 
      } 
      if (has_normal) { 
       file_stream->offset_++; 
       nindex.z = file_stream->ReadShort(); 
      } 
      vi.push_back(--vindex); 
      ti.push_back(--tindex); 
      ni.push_back(--nindex); 
      //indices.push_back(--vindex); 
     } 
     else file_stream->SkipLine(); 
    } 


    indices.insert(indices.end(), vi.begin(), vi.end()); 
    return true; 
} 

Вот против: GLSL основных методов:

position_ = MV * vec4(vVertex, 1.0); 
normal_ = normalize(N * vNormal); 
texture_ = vTexture; 
//shadow_ = S * M * vec4(vVertex, 1.0); 

gl_Position = MVP * vec4(vVertex, 1.0); 

и fs.glsl основные методы:

vec3 rgb = vec3(1.0, 1.0, 1.0); 
rgb = PhongShade(g_light, g_material, position_, normal_); 
_frag_color = vec4(rgb, 1.0); 

//_frag_color = texel * vec4(ambient + diffuse + specular, 1.0); 

Кто-нибудь получил какие-нибудь мысли?

+0

Это появилось в аналогичной форме много раз. См. Например: http://stackoverflow.com/questions/29718501/c-obj-parser-issue-with-parsing-or-drawing-using-opengl или http://stackoverflow.com/questions/23349080/opengl- Index-буфера-трудность. –

+0

Но один из них использует фиксированную функцию и другие методы использования метода рисования, я думаю. Я использую метод элемента, поэтому я должен оставить файл wavefront? Im также изучает raytraceing.У вас есть предложение для типа файла модели для использования в моем коде? Спасибо. – ADesignersEncyclopedia

+0

Вы можете использовать алгоритм в @RetoKoradi [ответ здесь] (http://stackoverflow.com/questions/23349080/opengl-index-buffers-difficulties), если вы хотите использовать glDrawElements. Логика индексирования работает одинаково для фиксированной функции и программируемого конвейера, поэтому это не будет проблемой. – samgak

ответ

0

Проблема заключается в том, что OpenGL использует единый индексный буфер для индексации положения вершин, координат текстуры и обычных буферов, используя один и тот же индекс для каждого (3 индекса для треугольника), тогда как формат obj Wavefront позволяет каждому лицу указать отдельные индексы для положения вершин, координаты текстуры и нормального независимо (всего 9 индексов для треугольника).

Это не ясно из вашего кода, но, скорее всего, вы на самом деле не используя ti и ni индексных массивов, которые вы читаете в, но создавая свои index_buffer от vi, поэтому индексов вершин используются в качестве индекса в normal_buffer и tex_coord_buffer, давая странные результаты.

Для исправления этой проблемы необходимо создать буферы координат вершин, координаты tex и нормальные координаты с записью для каждой уникальной комбинации индекса вершинной позиции, индекса координаты tex и нормального индекса, который используется в определении лица в obj файл, а затем сделайте индекс индекса индекса в этих массивах таким образом, чтобы конкретная вершина лица имела одинаковый индекс для каждого. В идеале это будет сделано как шаг предварительной обработки, а не во время загрузки.

В качестве альтернативы отказаться от индексированного рендера с помощью glDrawElements и использовать вместо этого glDrawArrays. Выпишите одну запись в каждый из массивов для каждой грани грани, основанный на указателях лицевой вершины для позиции, текс-координаты и нормальный, а затем визуализируйте это. Однако это менее эффективно.

Другим решением (если это возможно) является экспорт obj-файла таким образом, чтобы каждая граничная вершина использовала те же индексы для позиции, tex и normal.

+0

спасибо samgak. Я также вставлял индекс ni и ti в индексы и отображал одно и то же. Я хочу использовать метод элемента для повышения эффективности. У меня есть некоторый obj-файл, который использует тот же индекс v, t, n (такой f 1/1/1 2/2/2 3/3/3 .......) и отображается правильно, но другие файлы имеют разные нормальные, размер texcoord. Что мне делать? (Извините за мой английский :) Я думаю, что понимаю код лучше, чем английский) – ADesignersEncyclopedia

+0

Вы должны использовать формат с теми же индексами, например. 1/1/1 2/2/2 3/3/3, потому что OpenGL не поддерживает отдельную индексацию для позиции/tex/normal. Это меньше памяти, чем файл .obj, но вы ничего не можете с этим поделать, потому что это ограничение OpenGL. Таким образом, вам нужно либо использовать формат файла с индексами в этом формате, либо конвертировать его во время загрузки или на этапе предварительной обработки. – samgak