Я следовал этому уроку и смог нарисовать 20 треугольников на экране. Однако в этом примере и данные о положении, и данные о цвете хранятся в одном массиве и передаются как один вызов glBufferSubData. Я не уверен, должен ли я всегда следовать этому подходу или создавать отдельные массивы для хранения атрибутов вершин и вызывать glBufferSubData
для каждого атрибута. Я попытался сохранить положение и цвет отдельно и попал в странную проблему. Вместо того, чтобы нарисовать 20 треугольников на экране, я получаю только 10!
[Я использовал glfw вместо Qt для создания окна.]
Подход 1:
Я определил глобальные переменные следующим образом:
float dx = 0.1f;
unsigned int triangleCount = 0;
const unsigned int TRIANGLE_MAX_COUNT = 20;
const unsigned int TRIANGLE_VERTEX_COUNT = 3;
const unsigned int VERTEX_FLOAT_COUNT = 8;
const unsigned int TRIANGLE_BYTE_SIZE = TRIANGLE_VERTEX_COUNT * VERTEX_FLOAT_COUNT * sizeof(float);
Моя функция рисования треугольника определена как
void sendAnotherTriangle()
{
if (triangleCount == TRIANGLE_MAX_COUNT)
return;
const float x = -1 + triangleCount * dx;
glm::vec4 newTriangle[] = {
glm::vec4(x, +0.0f, +0.0f,1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f,1.0f),
glm::vec4(x + dx, +1.0f, +0.0f,1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f,1.0f),
glm::vec4(x, +1.0f, +0.0f,1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f,1.0f)
};
glBufferSubData(GL_ARRAY_BUFFER, triangleCount * sizeof(newTriangle), sizeof(newTriangle), newTriangle);
triangleCount++;
}
Макет буфера вершин определяется следующим образом:
unsigned int vb;
glGenBuffers(1, &vb);
glBindBuffer(GL_ARRAY_BUFFER, vb);
glBufferData(GL_ARRAY_BUFFER, TRIANGLE_MAX_COUNT*TRIANGLE_BYTE_SIZE, NULL, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, glm::vec4::length(), GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec4), (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, glm::vec4::length(), GL_FLOAT, GL_FALSE, 2 * sizeof(glm::vec4), (const void*)(sizeof(glm::vec4)));
Насколько я понимаю, поскольку атрибуты позиции и цвета чередуются, шаг для обоих атрибутов: 2 * sizeof (glm :: vec4), поскольку каждый атрибут имеет тип glm:: vec4. Поскольку данные позиции начинаются в самом начале, смещение позиции равно 0, а смещение цвета - sizeof (glm :: vec4), поскольку оно начинается после первой позиции вершины.
Наконец, вызов отрисовки выглядит следующим образом:
while (display.isRunning(window))
{
glClear(GL_DEPTH_BUFFER_BIT);
sendAnotherTriangle();
glDrawArrays(GL_TRIANGLES, 0, triangleCount * TRIANGLE_VERTEX_COUNT);
display.update();
}
Это дает мне желаемый результат, то есть 20 красных треугольников, нарисованных на экране.
Подход 2:
После этого я попыталсясделать то же самое, используя несколько вызовов glBufferSubData. В этом подходе модифицированная функция рисования треугольника:
void sendAnotherTriangle()
{
if (triangleCount == TRIANGLE_MAX_COUNT)
return;
const float x = -1 + triangleCount * dx;
glm::vec4 newPositions[] = {
glm::vec4(x, +0.0f, +0.0f, +1.0f),
glm::vec4(x + dx, +1.0f, +0.0f, +1.0f),
glm::vec4(x, +1.0f, +0.0f, +1.0f)
};
glm::vec4 newColors[] = {
glm::vec4(+1.0f, +0.0f, +0.0f, +1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f, +1.0f),
glm::vec4(+1.0f, +0.0f, +0.0f, +1.0f)
};
glBufferSubData(GL_ARRAY_BUFFER, triangleCount*(sizeof(newPositions) + sizeof(newColors)), sizeof(newPositions), newPositions);
glBufferSubData(GL_ARRAY_BUFFER, triangleCount*(sizeof(newPositions) + sizeof(newColors)) + sizeof(newPositions), sizeof(newColors), newColors);
triangleCount++;
}
И макет буфера вершин изменяется следующим образом:
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, glm::vec4::length(), GL_FLOAT, GL_FALSE, 0, (const void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, glm::vec4::length(), GL_FLOAT, GL_FALSE, 0, (const void*)(TRIANGLE_VERTEX_COUNT * sizeof(glm::vec4)));
Поскольку данные о положении и цвете хранятся отдельно, мойпонимание состоит в том, что они плотно упакованы и, следовательно, их шаг равен 0, и поскольку данные о цвете начинаются после данных о положении, смещение цвета равно TRIANGLE_VERTEX_COUNT * sizeof (glm :: vec4).
С этим новым параметром яожидается, что на экране нарисовано 20 треугольников. Тем не менее, я получаю только 10 треугольников, нарисованных на экране. Я предполагаю, что это связано с присвоением неверных значений шагам и смещениям. Тем не менее, я не мог понять это.
Поэтому я хотел бы сначала спросить, какой из них лучше и безопаснее.
Во-вторых, как я могу получить желаемый результат после второго подхода