Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 顶点数据是按pertex还是按属性排列?_C++_Opengl_Vertex - Fatal编程技术网

C++ 顶点数据是按pertex还是按属性排列?

C++ 顶点数据是按pertex还是按属性排列?,c++,opengl,vertex,C++,Opengl,Vertex,我有一段OpenGL代码来渲染网格。我使用VBO来渲染它们。现在,网格由具有以下属性的顶点组成: glm::vec3 position; glm::vec2 uv; glm::vec4 color; glm::vec3 normal; glm::vec3 tangent; glm::vec3 binormal; 目前,我按每个顶点渲染顶点,如下所示: // Upload a vector of vertices glBindBuffer(GL_ARRAY_BUFFER, &m_vbo)

我有一段OpenGL代码来渲染网格。我使用VBO来渲染它们。现在,网格由具有以下属性的顶点组成:

glm::vec3 position;
glm::vec2 uv;
glm::vec4 color;
glm::vec3 normal;
glm::vec3 tangent;
glm::vec3 binormal;
目前,我按每个顶点渲染顶点,如下所示:

// Upload a vector of vertices
glBindBuffer(GL_ARRAY_BUFFER, &m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex), &m_vertices[0], GL_STATIC_DRAW);

// Set the "layout" of the vertex attributes
// Binormal
glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) * 3 + sizeof(glm::vec2) + sizeof(glm::vec4)));
// Tangent
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) * 2 + sizeof(glm::vec2) + sizeof(glm::vec4)));
// Normal
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) + sizeof(glm::vec2) + sizeof(glm::vec4)));
// Color
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3) + sizeof(glm::vec2)));
// UV
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (sizeof(glm::vec3)));
// Position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) 0);

// Draw
glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_SHORT, 0);
现在,我看到人们做的有点不同。有些人首先上传所有顶点位置,然后上传UV数据,然后上传法线,以此类推。要对数据布局进行粗略的可视化,请执行以下操作:

// P = position, U = uv, N = normal

// Per-vertex layout
PUNPUNPUNPUNPUNPUNPUNPUNPUNPUNPUNPUN

// Per-attribute layout
PPPPPPPPPPPPUUUUUUUUUUUUNNNNNNNNNNNN

这两种布局有什么不同吗?一个或另一个是否会导致性能问题,尤其是在数据不断更新的情况下?

您描述的第一个布局通常称为“交错布局”,通常被认为是有利的。原因是,它会导致更多的本地内存访问模式,这些模式对缓存更友好

使用不同布局的一个很好的理由是,如果某些属性的更新频率比其他属性高得多。在极端情况下,其中一些是静态的,而另一些是频繁更新的,实际上,将静态属性保留在一个VBO中,使用
GL\u static\u DRAW
usage,并对频繁更改的属性使用
GL\u DYNAMIC\u DRAW
usage,这可能是有益的

@leemes在上面的一条评论中提出了另一个有趣的例子:若您经常只使用属性的一个子集进行绘制调用,那个么对它们进行不同的分组也是值得的。在这种情况下,您可以拥有在交错布局中始终使用的属性,并将很少使用的属性分开


综上所述,渲染管道中通常会有更大的瓶颈,因此在目标合成基准之外很难衡量差异。尽管如此,我认为保持一切尽可能精简是非常值得的。尤其是现在大多数计算机/设备都是靠电池供电的,你不想浪费任何东西。

“尤其是数据不断更新的情况下”你真的确定需要吗?大多数计算可以在顶点着色器中完成(变换、动画等)。但是如果你真的需要在每一帧中上传它们,我想这几乎就是你的瓶颈。否则,如果某些着色器不需要所有属性,“每个属性”可能会快一点,即使不是这样,也可能会因为某些对齐/缓存而快一点,但这取决于硬件。对齐/缓存的问题首先让我感到奇怪。如果需要所有属性怎么办?这会不会使逐顶点布局更快,因为当前顶点所需的所有数据都“就在那里”?@manabreak没错。逐顶点布局很快,因为顶点获取单元更容易获取顶点数据。