Как создать сетку в OpenGL и нарисовать ее линиями - PullRequest
1 голос
/ 22 октября 2019

Мне нужно создать сетку, подобную этой:

  ----------------
  |  |  |  |  |  |
  ----------------
  |  |  |  |  |  |
  ----------------
  |  |  |  |  |  |
  ----------------

и отрисовать ее просто с помощью линий. Вот как я создаю вершины и индексы:

  std::vector<glm::vec3> vertices;
  std::vector<glm::uvec3> indices;

  for(int j=0; j<=slices; ++j) {
    for(int i=0; i<=slices; ++i) {
      float x = (float)i/(float)slices;
      float y = 0;
      float z = (float)j/(float)slices;
      vertices.push_back(glm::vec3(x, y, z));
    }
  }

  for(int j=0; j<slices; ++j) {
    for(int i=0; i<slices; ++i) {

      int row1 = j * (slices+1);
      int row2 = (j+1) * (slices+1);

      indices.push_back(glm::uvec3(row1+i, row1+i+1, row2+i+1));
      indices.push_back(glm::uvec3(row1+i, row2+i+1, row2+i));

    }
  }

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

  GLuint vbo;
  glGenBuffers( 1, &vbo );
  glBindBuffer( GL_ARRAY_BUFFER, vbo );
  glBufferData( GL_ARRAY_BUFFER, vertices.size()*sizeof(glm::vec3), glm::value_ptr(vertices[0]), GL_STATIC_DRAW );
  glEnableVertexAttribArray( 0 );
  glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, nullptr );

  GLuint ibo;
  glGenBuffers( 1, &ibo );
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
  glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(glm::uvec3), glm::value_ptr(indices[0]), GL_STATIC_DRAW );

  glBindVertexArray( 0 );
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
  glBindBuffer( GL_ARRAY_BUFFER, 0 );

  lenght = (GLuint)indices.size()*3;

вот как я отображаю это:

  glBindVertexArray(vao);

  glDrawElements(GL_LINES, lenght, GL_UNSIGNED_INT, NULL);

  glBindVertexArray(0);

Результат не тот, который я хочу. Я также пытаюсь использовать GL_LINE_LOOP и т. Д. Я думаю, что проблема заключается в создании вершин и индексов

ОБНОВЛЕНИЕ:

Я сделал изменения, предложенные Rabbit76, выглядящими идеально! !

enter image description here

Вот финальный код для создания вершин и индексов:

  std::vector<glm::vec3> vertices;
  std::vector<glm::uvec4> indices;

  for(int j=0; j<=slices; ++j) {
    for(int i=0; i<=slices; ++i) {
      float x = (float)i/(float)slices;
      float y = 0;
      float z = (float)j/(float)slices;
      vertices.push_back(glm::vec3(x, y, z));
    }
  }

  for(int j=0; j<slices; ++j) {
    for(int i=0; i<slices; ++i) {

      int row1 =  j    * (slices+1);
      int row2 = (j+1) * (slices+1);

      indices.push_back(glm::uvec4(row1+i, row1+i+1, row1+i+1, row2+i+1));
      indices.push_back(glm::uvec4(row2+i+1, row2+i, row2+i, row1+i));

    }
  }

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

  GLuint vbo;
  glGenBuffers( 1, &vbo );
  glBindBuffer( GL_ARRAY_BUFFER, vbo );
  glBufferData( GL_ARRAY_BUFFER, vertices.size()*sizeof(glm::vec3), glm::value_ptr(vertices[0]), GL_STATIC_DRAW );
  glEnableVertexAttribArray( 0 );
  glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, nullptr );

  GLuint ibo;
  glGenBuffers( 1, &ibo );
  glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
  glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(glm::uvec4), glm::value_ptr(indices[0]), GL_STATIC_DRAW);

  glBindVertexArray(0);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  lenght = (GLuint)indices.size()*4;

это код для рендеринга сетки:

  glEnable(GL_DEPTH_TEST);

  glBindVertexArray(vao);

  glDrawElements(GL_LINES, lenght, GL_UNSIGNED_INT, NULL);

  glBindVertexArray(0);

  glDisable(GL_DEPTH_TEST);

1 Ответ

2 голосов
/ 22 октября 2019

[...] Мне нужно отрисовать линейный растр [...]

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

Изменить тип для индексов:

std::vector<glm::uvec4> indices;

Добавить сегменты линии:

indices.push_back(glm::uvec4(row1+i, row1+i+1, row1+i+1, row2+i+1));
indices.push_back(glm::uvec4(row2+i+1, row2+i, row2+i, row1+i));

Позаботьтесь об измененном типе при создании и инициализации хранилища данных буфера:

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(glm::uvec4),
             indices.data(), GL_STATIC_DRAW);

соответственно (еще более элегантно)

glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(*indices.data()),
             indices.data(), GL_STATIC_DRAW);

Окончательно вычислите правильное количество индексов

lenght = (GLuint)indices.size()*4;

Нарисуйте отрезки линии

glBindVertexArray(vao);
glDrawElements(GL_LINES, lenght, GL_UNSIGNED_INT, NULL);

Другой вариант - визуализировать отрезки линии по всей сетке:

std::vector<glm::uvec2> indices;
int rowLen = slices+1;
int noVert = (int)vertices.size();
for(int j=0; j<slices; ++j) {
    indices.push_back(glm::uvec2(j * rowLen, (j+1) * rowLen - 1));
    indices.push_back(glm::uvec2(j, noVert - rowLen + j));
}
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(*indices.data()),
             indices.data(), GL_STATIC_DRAW);
lenght = (GLuint)indices.size()*2;
...