许多立方体对象的 OpenGL 绘图元素

OpenGL Drawing Elements for many cube objects

本文关键字:绘图 元素 OpenGL 立方体 对象 许多      更新时间:2023-10-16

我正在构建一个渲染器,它可以接收许多对象并将它们批量渲染到屏幕上。完整的渲染器代码 -> https://github.com/rob-DEV/OpenGL-Model-Viewer/tree/master/OpenGL-Model-Viewer/src/graphics/renderer

在每个帧调用时将对象(都是包含索引顶点 (8) 和 36 个索引的多维数据集)推送到渲染器。 荷载模型 for (int j = 0; j <5; j++) { models.push_back(ObjModel("test-models/box.obj", glm::vec3(i * 5, i, j * 5))); }

renderer.begin();
for (int i = 0; i < models.size(); i++)
{
//add to render call
renderer.submit(models[i]);
}
renderer.end();
renderer.flush();

渲染初始化()

// Enable depth test
glEnable(GL_DEPTH_TEST);
// Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS);
glGenVertexArrays(1, &m_VAO);
glGenBuffers(1, &m_VBO);
glBindVertexArray(m_VAO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER, RENDERER_BUFFER_SIZE, NULL, GL_STATIC_DRAW);
glEnableVertexAttribArray(SHADER_VERTEX_INDEX);
glEnableVertexAttribArray(SHADER_COLOR_INDEX);
glVertexAttribPointer(SHADER_VERTEX_INDEX, 3, GL_FLOAT, GL_FALSE, RENDERER_VERTEX_SIZE, (const GLvoid*)0);
glVertexAttribPointer(SHADER_COLOR_INDEX, 4, GL_UNSIGNED_BYTE, GL_TRUE, RENDERER_VERTEX_SIZE, (const GLvoid*)(offsetof(VertexData, VertexData::colour)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
//setup element
glGenBuffers(1, &m_IBO);
glBindVertexArray(0);

提交对象

void Renderer::submit(ObjModel& object)
{
//a vector of vec3 vertices // these are indexed all objects are cubes so 8 verts per object
std::vector<glm::vec3> vertices = object.get_vertices();
std::vector<unsigned int> indices = object.get_indices();
std::vector<unsigned int> colours = object.get_colours();
//adjust the postion and give each picture a random colour & add to buffer
for (unsigned int i = 0; i < vertices.size(); i++)
{ 
vertices[i] += object.position;
m_VertexBuffer->vertex = vertices[i];
m_VertexBuffer->colour = colours[i];
m_VertexBuffer++;
m_VertexDataCount++;
}
m_IndiceCount += indices.size();
indiceData.insert(indiceData.end(), indices.begin(), indices.end());
}

如您所见,我将每个顶点(添加在世界中的位置)和颜色放入一个简单的结构(VertexData*)中,然后将索引添加到向量中。

这是实际的抽奖

void Renderer::flush()
{
glBindVertexArray(m_VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_IndiceCount * sizeof(unsigned int), &indiceData[0], GL_STATIC_DRAW);
// Draw the triangles !
glDrawElements(
GL_TRIANGLES,      // mode
m_IndiceCount,    // count
GL_UNSIGNED_INT,   // type
(void*)0           // element array buffer offset
);
indiceData.clear();
m_IndiceCount = 0;
m_VertexDataCount = 0;
}

我意识到长度,但我的问题是,为什么该位置仅适用于第一个立方体(要么彼此重叠绘制,要么只绘制第一个立方体)我无法弄清楚这一点。有没有更好的方法我的想法:)

为什么该位置仅适用于第一个立方体(要么彼此重叠绘制,要么仅绘制第一个立方体)

因为您只绘制了这些第一个顶点,只是几次:

在每个

帧调用时将对象(都是包含索引顶点 (8) 和 36 个索引的多维数据集)推送到渲染器。

每次调用submit时,您将这 8 个顶点添加到顶点数组的末尾,您只需将 36 个索引复制到索引数组的末尾:

m_IndiceCount += indices.size();
indiceData.insert(indiceData.end(), indices.begin(), indices.end());

对于第一个多维数据集,所有索引都将在 0 到 7 的范围内,这很好。但对于所有后续多维数据集,您也将只使用索引 0 到 7(因为这是仅本地对象的正确索引)。但是,第二个多维数据集的顶点位于全局顶点数组中的索引 8 到 15。因此,当您一次绘制两个立方体时,它将只重新绘制第一个立方体两次。

因此,解决方案应该很容易看到:您只需要将索引数组中的每个索引偏移量偏移全局顶点数组中顶点的实际基本偏移量。