Я работаю над Voxel Engine и использую VBO.
Моя проблема в том, что я не знаю, как генерировать вершины.
Мне нужно сгенерировать вершины для порции, поэтому создайте порцию кубов (с одним VBO) из координат X, Y, Z.
Как я могу это сделать?
Сначала вам нужно будет создать / загрузить данные для вокселей. Нечто подобное можно использовать для генерации поля двоичных вокселей размером 10x10x10:
Примечание. Весь код не проверен и, вероятно, не оптимален.
class Field {
bool data[10*10*10];
public:
bool& at(int i, int j, int k) { return data[i*10*10 + j*10 + k]; }
};Field aField;
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
for (int k = 0; k < 10; ++k) {
aField.at(i, j, k) = !(rand() % 2);
}
}
}
Я предполагаю, что вы после Майнкрафт стиль вокселей, в противном случае вы, вероятно, хотите использовать что-то вроде Марширующие кубики обработать двоичное поле вокселей и передать результат в код буфера вершин.
Следующий шаг — для каждого занятого вокселя в поле нарисуйте грани, связанные с кубом. Для этого нам нужно создать список всех вершин и (в данном случае) индексов треугольников.
std::vector< std::array<GLfloat, 3> > vecVerts;
std::vector< std::array<GLuint, 3> > vecTris;
for (int i,j,k from 0 to 10) {
if (aField.at(i,j,k)) {
// Add vertices for eight corners of cube
vecVerts.emplace_back(dWidth*(i ), dWidth*(j ), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j ), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i ), dWidth*(j+1), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j+1), dWidth*(k ));
vecVerts.emplace_back(dWidth*(i ), dWidth*(j ), dWidth*(k+1));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j ), dWidth*(k+1));
vecVerts.emplace_back(dWidth*(i ), dWidth*(j+1), dWidth*(k+1));
vecVerts.emplace_back(dWidth*(i+1), dWidth*(j+1), dWidth*(k+1));
// Add triangle coordinates for each triangle
vecTris.emplace_back(0, 1, 3); vecTris.emplace_back(0, 2, 3);
vecTris.emplace_back(4, 5, 7); vecTris.emplace_back(4, 6, 7);
/* todo: add remaining triangles, should be 8 more */
}
}
Приведенный выше код создаст в памяти два массива, хранящих ваши местоположения вершин и индексы для треугольников. Вы заметите, что код всегда рисует 12 треугольников для каждого вокселя, было бы лучше проверить, есть ли соседний занятый воксел, и удалить грани между такими вокселями, но я оставлю это для вас. Я также рекомендую вам рассмотреть возможность использования GLM :: vec3 для хранения данных вершин, а не просто массив.
Теперь мы можем передать наши массивы в OpenGL:
GLuint unVertexArray;
glGenVertexArrays(1, &unVertexArray);
glBindVertexArray(unVertexArray);
GLuint unVertexBuffer;
glGenBuffers(1, &unVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, unVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, 3*vecVerts.size()*sizeof(GLfloat),
&vecVerts[0][0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
GLuint unIndiciesBuffer;
glGenBuffers(1, &unIndicesBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, unIndicesBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 3*vecTris.size()*sizeof(GLuint),
&vecTris[0][0], GL_STATIC_DRAW);
glBindVertexArray(0);
Затем, наконец, нарисовать наши массивы:
glBindVertexArray(unVertexArray);
glDrawElements(GL_TRIANGLES, 3*vecTris.size(), GL_UNSIGNED_INT, NULL);
glBindVertexArray(0);
Я мог (почти наверняка) забыл кое-что здесь, но это должно дать вам общее представление о том, что вам нужно будет сделать. Для правильного объяснения большинства gl
звонки, используемые выше, есть много онлайн-ссылок, таких как http://arcsynthesis.org/gltut/index.html