Я пытаюсь запрограммировать какую-нибудь игру с помощью OpenGL и читаю целую кучу учебников. К сожалению, у меня возникла небольшая проблема, которая просто мешает моему прогрессу.
Я создал класс «Mesh», где я передаю массив GLfloats. Эти поплавки включены VAO и VBO.
Пока я создаю массив внутри конструктора (со всеми функциями инициализации), он работает нормально. Но если я захочу передать массив в качестве аргумента, OpenGL просто не будет рисовать. Я что-то забыл?
Вот мой основной код:
Mesh.cpp
Mesh::Mesh(GLfloat* vertices)
{
glGenVertexArrays(1, &m_vertexArray);
glBindVertexArray(m_vertexArray);
glGenBuffers(1, &m_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
Mesh::~Mesh()
{
glDeleteVertexArrays(1, &m_vertexArray);
}
void Mesh::draw()
{
glBindVertexArray(m_vertexArray);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
}
main.cpp
[...]
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices);
while (!mainWindow->isClosed())
{
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shaders->bind();
// here main functions:
mesh.draw();
mainWindow->update();
}
Я передаю массив GLfloats
Нет, вы не «передаете» массив чего-либо. Вы прошли указатель. Указатели и массивы — это разные вещи в C ++. Самое главное, массивы могут «распадаться» на указатели (это то, что позволяет передавать их функциям, которые принимают указатели), но при этом вся информация о размерах теряется.
sizeof(vertices)
это размер GLfloat*
, По всей вероятности, это либо 4, либо 8. Это наверняка не размер массива, который вы имели в вызывающей функции.
Предпочтительным методом для обработки этого было бы передать указатель и размер этой функции. Тем не мение, sizeof(vertices)
будет количество байтов в массиве, а не количество элементов массива.
Одним из способов справиться с этим было бы получить std::vector
а не массив, через C ++ 11:
std::vector<GLfloat> vertices = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices.data(), vertices.size());
Кроме того, вы можете рассчитать размер с некоторыми умными макросами:
#define ARRAY_COUNT(arr) ( sizeof(arr) / sizeof(arr[0]))
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices, ARRAY_COUNT(vertices));
Или, если вы хотите использовать более умные возможности C ++ 11:
template<typename T, size_t N>
constexpr size_t array_count(T (&arr)[N]) {return N;}
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices, array_count(vertices));
Или вы можете просто пропустить посредника и применить основные принципы C ++ поддержка библиотеки класса span
:
Mesh::Mesh(gsl::span<GLfloat> vertices)
{
glGenVertexArrays(1, &m_vertexArray);
glBindVertexArray(m_vertexArray);
glGenBuffers(1, &m_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size_bytes(), vertices.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
}
GLfloat vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f,
-1.0f, -1.0f, 0.0f,
0.0f, -1.0f, 0.0f,
-0.5f, 0.0f, 0.0f
};
Mesh mesh(vertices);
Других решений пока нет …